summaryrefslogtreecommitdiff
path: root/source4/auth/gensec/ntlmssp_sign.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth/gensec/ntlmssp_sign.c')
-rw-r--r--source4/auth/gensec/ntlmssp_sign.c172
1 files changed, 139 insertions, 33 deletions
diff --git a/source4/auth/gensec/ntlmssp_sign.c b/source4/auth/gensec/ntlmssp_sign.c
index 347a85da77..dba3dbee29 100644
--- a/source4/auth/gensec/ntlmssp_sign.c
+++ b/source4/auth/gensec/ntlmssp_sign.c
@@ -3,7 +3,7 @@
* Version 3.0
* NTLMSSP Signing routines
* Copyright (C) Luke Kenneth Casson Leighton 1996-2001
- * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
+ * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2005
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,16 +32,10 @@
/**
* Some notes on then NTLM2 code:
*
- * This code works correctly for the sealing part of the problem. If
- * we disable the check for valid client signatures, then we see that
- * the output of a rpcecho 'sinkdata' at smbd is correct. We get the
- * valid data, and it is validly decrypted.
- *
- * This means that the quantity of data passing though the RC4 sealing
- * pad is correct.
- *
- * This code also correctly matches test values that I have obtained,
- * claiming to be the correct output of NTLM2 signature generation.
+ * NTLM2 is a AEAD system. This means that the data encrypted is not
+ * all the data that is signed. In DCE-RPC case, the headers of the
+ * DCE-RPC packets are also signed. This prevents some of the
+ * fun-and-games one might have by changing them.
*
*/
@@ -128,12 +122,15 @@ static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_stat
return NT_STATUS_OK;
}
-NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
- TALLOC_CTX *sig_mem_ctx,
- const uint8_t *data, size_t length,
- const uint8_t *whole_pdu, size_t pdu_length,
- DATA_BLOB *sig)
+NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security,
+ TALLOC_CTX *sig_mem_ctx,
+ const uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ DATA_BLOB *sig)
{
+ struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+ struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
+
if (!ntlmssp_state->session_key.length) {
DEBUG(3, ("NO session key, cannot check sign packet\n"));
return NT_STATUS_NO_USER_SESSION_KEY;
@@ -155,12 +152,15 @@ NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
- TALLOC_CTX *sig_mem_ctx,
- const uint8_t *data, size_t length,
- const uint8_t *whole_pdu, size_t pdu_length,
- const DATA_BLOB *sig)
+NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security,
+ TALLOC_CTX *sig_mem_ctx,
+ const uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ const DATA_BLOB *sig)
{
+ struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+ struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
+
DATA_BLOB local_sig;
NTSTATUS nt_status;
@@ -222,12 +222,14 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
- TALLOC_CTX *sig_mem_ctx,
- uint8_t *data, size_t length,
- const uint8_t *whole_pdu, size_t pdu_length,
- DATA_BLOB *sig)
-{
+NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security,
+ TALLOC_CTX *sig_mem_ctx,
+ uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ DATA_BLOB *sig)
+{
+ struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+ struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
NTSTATUS nt_status;
if (!ntlmssp_state->session_key.length) {
DEBUG(3, ("NO session key, cannot seal packet\n"));
@@ -284,12 +286,17 @@ NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state,
- TALLOC_CTX *sig_mem_ctx,
- uint8_t *data, size_t length,
- const uint8_t *whole_pdu, size_t pdu_length,
- DATA_BLOB *sig)
+/*
+ wrappers for the ntlmssp_*() functions
+*/
+NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security,
+ TALLOC_CTX *sig_mem_ctx,
+ uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ const DATA_BLOB *sig)
{
+ struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+ struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
DATA_BLOB local_sig;
NTSTATUS nt_status;
if (!ntlmssp_state->session_key.length) {
@@ -327,7 +334,7 @@ NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state,
} else {
arcfour_crypt_sbox(ntlmssp_state->ntlmssp_hash, data, length);
dump_data_pw("ntlmssp clear data\n", data, length);
- return ntlmssp_check_packet(ntlmssp_state, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig);
+ return gensec_ntlmssp_check_packet(gensec_security, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig);
}
}
@@ -447,3 +454,102 @@ NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
return NT_STATUS_OK;
}
+
+size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security)
+{
+ return NTLMSSP_SIG_SIZE;
+}
+
+NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security,
+ TALLOC_CTX *sig_mem_ctx,
+ const DATA_BLOB *in,
+ DATA_BLOB *out)
+{
+ struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+ DATA_BLOB sig;
+ NTSTATUS nt_status;
+
+ if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+
+ *out = data_blob_talloc(sig_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
+ memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
+
+ nt_status = gensec_ntlmssp_seal_packet(gensec_security, sig_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);
+ }
+ return nt_status;
+
+ } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
+ || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
+
+ *out = data_blob_talloc(sig_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
+ memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
+
+ nt_status = gensec_ntlmssp_sign_packet(gensec_security, sig_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);
+ }
+ return nt_status;
+
+ } else {
+ *out = *in;
+ return NT_STATUS_OK;
+ }
+}
+
+
+NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security,
+ TALLOC_CTX *sig_mem_ctx,
+ const DATA_BLOB *in,
+ DATA_BLOB *out)
+{
+ struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+ DATA_BLOB sig;
+
+ if (gensec_ntlmssp_state->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(sig_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
+
+ return gensec_ntlmssp_unseal_packet(gensec_security, sig_mem_ctx,
+ out->data, out->length,
+ out->data, out->length,
+ &sig);
+
+ } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
+ || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
+ if (in->length < NTLMSSP_SIG_SIZE) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ sig.data = in->data;
+ sig.length = NTLMSSP_SIG_SIZE;
+
+ *out = data_blob_talloc(sig_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
+
+ return gensec_ntlmssp_check_packet(gensec_security, sig_mem_ctx,
+ out->data, out->length,
+ out->data, out->length,
+ &sig);
+ } else {
+ *out = *in;
+ return NT_STATUS_OK;
+ }
+}
+