diff options
author | Andrew Bartlett <abartlet@samba.org> | 2011-01-20 16:37:04 +1100 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2011-01-20 23:44:05 +0100 |
commit | 084b4e235e2f500614638cb9c023a5ae8c2e531d (patch) | |
tree | cf62ba3dd52756abf5f016fa84ca8fa7ff0096b4 /libcli/auth | |
parent | 039dd96be236ab0ed1656bd854f407d26e8d3433 (diff) | |
download | samba-084b4e235e2f500614638cb9c023a5ae8c2e531d.tar.gz samba-084b4e235e2f500614638cb9c023a5ae8c2e531d.tar.bz2 samba-084b4e235e2f500614638cb9c023a5ae8c2e531d.zip |
libcli/auth move ntlmssp_wrap() and ntlmssp_unwrap() into common code.
The idea here is to allow the source3/libads/sasl.c code to call this
instead of the lower level ntlmssp_* functions.
Andrew Bartlett
Diffstat (limited to 'libcli/auth')
-rw-r--r-- | libcli/auth/ntlmssp.h | 8 | ||||
-rw-r--r-- | libcli/auth/ntlmssp_sign.c | 139 |
2 files changed, 147 insertions, 0 deletions
diff --git a/libcli/auth/ntlmssp.h b/libcli/auth/ntlmssp.h index dead412c99..495d94f6a0 100644 --- a/libcli/auth/ntlmssp.h +++ b/libcli/auth/ntlmssp.h @@ -160,4 +160,12 @@ NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state, uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, const DATA_BLOB *sig); +NTSTATUS ntlmssp_wrap(struct ntlmssp_state *ntlmssp_state, + TALLOC_CTX *out_mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out); +NTSTATUS ntlmssp_unwrap(struct ntlmssp_state *ntlmssp_stae, + TALLOC_CTX *out_mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out); NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state); diff --git a/libcli/auth/ntlmssp_sign.c b/libcli/auth/ntlmssp_sign.c index 3cf1ed75a7..0e57c07a8d 100644 --- a/libcli/auth/ntlmssp_sign.c +++ b/libcli/auth/ntlmssp_sign.c @@ -388,6 +388,145 @@ NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state, return status; } +NTSTATUS ntlmssp_wrap(struct ntlmssp_state *ntlmssp_state, + TALLOC_CTX *out_mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + NTSTATUS nt_status; + DATA_BLOB sig; + + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + *out = data_blob_talloc(out_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); + if (!out->data) { + return NT_STATUS_NO_MEMORY; + } + memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); + + nt_status = ntlmssp_seal_packet(ntlmssp_state, out_mem_ctx, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + &sig); + + if (NT_STATUS_IS_OK(nt_status)) { + memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); + talloc_free(sig.data); + } + return nt_status; + + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { + + *out = data_blob_talloc(out_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); + if (!out->data) { + return NT_STATUS_NO_MEMORY; + } + memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); + + nt_status = ntlmssp_sign_packet(ntlmssp_state, out_mem_ctx, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + &sig); + + if (NT_STATUS_IS_OK(nt_status)) { + memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); + talloc_free(sig.data); + } + return nt_status; + } else { + *out = data_blob_talloc(out_mem_ctx, in->data, in->length); + if (!out->data) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; + } +} + +NTSTATUS ntlmssp_unwrap(struct ntlmssp_state *ntlmssp_state, + TALLOC_CTX *out_mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + DATA_BLOB sig; + + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + if (in->length < NTLMSSP_SIG_SIZE) { + return NT_STATUS_INVALID_PARAMETER; + } + sig.data = in->data; + sig.length = NTLMSSP_SIG_SIZE; + + *out = data_blob_talloc(out_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); + + return ntlmssp_unseal_packet(ntlmssp_state, + out->data, out->length, + out->data, out->length, + &sig); + + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { + NTSTATUS status; + struct ntlmssp_crypt_direction save_direction; + + if (in->length < NTLMSSP_SIG_SIZE) { + return NT_STATUS_INVALID_PARAMETER; + } + sig.data = in->data; + sig.length = NTLMSSP_SIG_SIZE; + *out = data_blob_talloc(out_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); + + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + save_direction = ntlmssp_state->crypt->ntlm2.receiving; + } else { + save_direction = ntlmssp_state->crypt->ntlm; + } + + status = ntlmssp_check_packet(ntlmssp_state, + out->data, out->length, + out->data, out->length, + &sig); + if (!NT_STATUS_IS_OK(status)) { + NTSTATUS check_status = status; + /* + * The Windows LDAP libraries seems to have a bug + * and always use sealing even if only signing was + * negotiated. So we need to fallback. + */ + + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + ntlmssp_state->crypt->ntlm2.receiving = save_direction; + } else { + ntlmssp_state->crypt->ntlm = save_direction; + } + + status = ntlmssp_unseal_packet(ntlmssp_state, + out->data, + out->length, + out->data, + out->length, + &sig); + if (NT_STATUS_IS_OK(status)) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; + } else { + status = check_status; + } + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("NTLMSSP packet check for unwrap failed due to invalid signature\n")); + } + return status; + } else { + *out = data_blob_talloc(out_mem_ctx, in->data, in->length); + if (!out->data) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; + } +} + /** Initialise the state for NTLMSSP signing. */ |