diff options
Diffstat (limited to 'libcli/auth/ntlmssp_sign.c')
-rw-r--r-- | libcli/auth/ntlmssp_sign.c | 139 |
1 files changed, 139 insertions, 0 deletions
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. */ |