[SCM] Samba Shared Repository - branch master updated - tevent-0-9-8-362-g033ced6

Stefan Metzmacher metze at samba.org
Wed Sep 16 04:30:01 MDT 2009


The branch, master has been updated
       via  033ced60ac734161686bd3da685f2d7b056e17c8 (commit)
       via  8f482ae663611ee2109395e4d24418e4c4f57160 (commit)
      from  4c5854fc2d8569cdf27fc6af543ad4a25a6f7a0b (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 033ced60ac734161686bd3da685f2d7b056e17c8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Sep 16 02:03:46 2009 +0200

    libcli/auth: rewrite schannel sign/seal code to be more generic
    
    This prepares support for HMAC-SHA256/AES.
    
    metze

commit 8f482ae663611ee2109395e4d24418e4c4f57160
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Sep 16 02:36:49 2009 +0200

    lib/crypto: include aes.h into crypto.h
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 lib/crypto/crypto.h            |    2 +-
 libcli/auth/schannel_proto.h   |   21 +--
 libcli/auth/schannel_sign.c    |  297 ++++++++++++++++++++--------------------
 source3/rpc_client/cli_pipe.c  |   41 ++++---
 source3/rpc_server/srv_pipe.c  |   44 ++++---
 source4/auth/gensec/schannel.c |   89 ++++++++-----
 6 files changed, 264 insertions(+), 230 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/crypto/crypto.h b/lib/crypto/crypto.h
index 0a43cbe..b5ea9c7 100644
--- a/lib/crypto/crypto.h
+++ b/lib/crypto/crypto.h
@@ -24,5 +24,5 @@
 #include "../lib/crypto/sha256.h"
 #include "../lib/crypto/hmacsha256.h"
 #include "../lib/crypto/arcfour.h"
-
+#include "../lib/crypto/aes.h"
 
diff --git a/libcli/auth/schannel_proto.h b/libcli/auth/schannel_proto.h
index d31707d..eee7199 100644
--- a/libcli/auth/schannel_proto.h
+++ b/libcli/auth/schannel_proto.h
@@ -23,20 +23,15 @@
 #ifndef _LIBCLI_AUTH_SCHANNEL_PROTO_H__
 #define _LIBCLI_AUTH_SCHANNEL_PROTO_H__
 
-NTSTATUS schannel_unseal_packet(struct schannel_state *state,
+NTSTATUS netsec_incoming_packet(struct schannel_state *state,
 				TALLOC_CTX *mem_ctx,
+				bool do_unseal,
 				uint8_t *data, size_t length,
 				const DATA_BLOB *sig);
-NTSTATUS schannel_check_packet(struct schannel_state *state,
-			       TALLOC_CTX *mem_ctx,
-			       const uint8_t *data, size_t length,
-			       const DATA_BLOB *sig);
-NTSTATUS schannel_seal_packet(struct schannel_state *state,
-			      TALLOC_CTX *mem_ctx,
-			      uint8_t *data, size_t length,
-			      DATA_BLOB *sig);
-NTSTATUS schannel_sign_packet(struct schannel_state *state,
-			      TALLOC_CTX *mem_ctx,
-			      const uint8_t *data, size_t length,
-			      DATA_BLOB *sig);
+NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
+				TALLOC_CTX *mem_ctx,
+				bool do_seal,
+				uint8_t *data, size_t length,
+				DATA_BLOB *sig);
+
 #endif
diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c
index e60b410..0672f67 100644
--- a/libcli/auth/schannel_sign.c
+++ b/libcli/auth/schannel_sign.c
@@ -24,58 +24,89 @@
 #include "../libcli/auth/schannel.h"
 #include "../lib/crypto/crypto.h"
 
-#define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }
-#define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
+static void netsec_offset_and_sizes(struct schannel_state *state,
+				    bool do_seal,
+				    uint32_t *_min_sig_size,
+				    uint32_t *_used_sig_size,
+				    uint32_t *_checksum_length,
+				    uint32_t *_confounder_ofs)
+{
+	uint32_t min_sig_size = 24;
+	uint32_t used_sig_size = 32;
+	uint32_t checksum_length = 8;
+	uint32_t confounder_ofs = 24;
+
+	if (do_seal) {
+		min_sig_size += 8;
+	}
+
+	if (_min_sig_size) {
+		*_min_sig_size = min_sig_size;
+	}
+
+	if (_used_sig_size) {
+		*_used_sig_size = used_sig_size;
+	}
+
+	if (_checksum_length) {
+		*_checksum_length = checksum_length;
+	}
+
+	if (_confounder_ofs) {
+		*_confounder_ofs = confounder_ofs;
+	}
+}
 
 /*******************************************************************
  Encode or Decode the sequence number (which is symmetric)
  ********************************************************************/
-static void netsec_deal_with_seq_num(struct schannel_state *state,
-				     const uint8_t packet_digest[8],
-				     uint8_t seq_num[8])
+static void netsec_do_seq_num(struct schannel_state *state,
+			      const uint8_t *checksum,
+			      uint32_t checksum_length,
+			      uint8_t seq_num[8])
 {
 	static const uint8_t zeros[4];
 	uint8_t sequence_key[16];
 	uint8_t digest1[16];
 
 	hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1);
-	hmac_md5(digest1, packet_digest, 8, sequence_key);
+	hmac_md5(digest1, checksum, checksum_length, sequence_key);
 	arcfour_crypt(seq_num, sequence_key, 8);
 
 	state->seq_num++;
 }
 
-
-/*******************************************************************
- Calculate the key with which to encode the data payload
- ********************************************************************/
-static void netsec_get_sealing_key(const uint8_t session_key[16],
-				   const uint8_t seq_num[8],
-				   uint8_t sealing_key[16])
+static void netsec_do_seal(struct schannel_state *state,
+			   const uint8_t seq_num[8],
+			   uint8_t confounder[8],
+			   uint8_t *data, uint32_t length)
 {
+	uint8_t sealing_key[16];
 	static const uint8_t zeros[4];
 	uint8_t digest2[16];
 	uint8_t sess_kf0[16];
 	int i;
 
 	for (i = 0; i < 16; i++) {
-		sess_kf0[i] = session_key[i] ^ 0xf0;
+		sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
 	}
 
 	hmac_md5(sess_kf0, zeros, 4, digest2);
 	hmac_md5(digest2, seq_num, 8, sealing_key);
-}
 
+	arcfour_crypt(confounder, sealing_key, 8);
+	arcfour_crypt(data, sealing_key, length);
+}
 
 /*******************************************************************
  Create a digest over the entire packet (including the data), and
  MD5 it with the session key.
  ********************************************************************/
-static void schannel_digest(const uint8_t sess_key[16],
-			    const uint8_t netsec_sig[8],
-			    const uint8_t *confounder,
-			    const uint8_t *data, size_t data_len,
-			    uint8_t digest_final[16])
+static void netsec_do_sign(struct schannel_state *state,
+			   const uint8_t *confounder,
+			   const uint8_t *data, size_t data_len,
+			   uint8_t header[8],
+			   uint8_t *checksum)
 {
 	uint8_t packet_digest[16];
 	static const uint8_t zeros[4];
@@ -83,187 +114,155 @@ static void schannel_digest(const uint8_t sess_key[16],
 
 	MD5Init(&ctx);
 	MD5Update(&ctx, zeros, 4);
-	MD5Update(&ctx, netsec_sig, 8);
 	if (confounder) {
+		SSVAL(header, 0, NL_SIGN_HMAC_MD5);
+		SSVAL(header, 2, NL_SEAL_RC4);
+		SSVAL(header, 4, 0xFFFF);
+		SSVAL(header, 6, 0x0000);
+
+		MD5Update(&ctx, header, 8);
 		MD5Update(&ctx, confounder, 8);
+	} else {
+		SSVAL(header, 0, NL_SIGN_HMAC_MD5);
+		SSVAL(header, 2, NL_SEAL_NONE);
+		SSVAL(header, 4, 0xFFFF);
+		SSVAL(header, 6, 0x0000);
+
+		MD5Update(&ctx, header, 8);
 	}
 	MD5Update(&ctx, data, data_len);
 	MD5Final(packet_digest, &ctx);
 
-	hmac_md5(sess_key, packet_digest, sizeof(packet_digest), digest_final);
+	hmac_md5(state->creds->session_key,
+		 packet_digest, sizeof(packet_digest),
+		 checksum);
 }
 
-
-/*
-  unseal a packet
-*/
-NTSTATUS schannel_unseal_packet(struct schannel_state *state,
+NTSTATUS netsec_incoming_packet(struct schannel_state *state,
 				TALLOC_CTX *mem_ctx,
+				bool do_unseal,
 				uint8_t *data, size_t length,
 				const DATA_BLOB *sig)
 {
-	uint8_t digest_final[16];
-	uint8_t confounder[8];
+	uint32_t min_sig_size = 0;
+	uint8_t header[8];
+	uint8_t checksum[32];
+	uint32_t checksum_length = sizeof(checksum_length);
+	uint8_t _confounder[8];
+	uint8_t *confounder = NULL;
+	uint32_t confounder_ofs = 0;
 	uint8_t seq_num[8];
-	uint8_t sealing_key[16];
-	static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
+	int ret;
+
+	netsec_offset_and_sizes(state,
+				do_unseal,
+				&min_sig_size,
+				NULL,
+				&checksum_length,
+				&confounder_ofs);
 
-	if (sig->length != 32) {
+	if (sig->length < min_sig_size) {
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	memcpy(confounder, sig->data+24, 8);
+	if (do_unseal) {
+		confounder = _confounder;
+		memcpy(confounder, sig->data+confounder_ofs, 8);
+	} else {
+		confounder = NULL;
+	}
 
 	RSIVAL(seq_num, 0, state->seq_num);
 	SIVAL(seq_num, 4, state->initiator?0:0x80);
 
-	netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key);
-	arcfour_crypt(confounder, sealing_key, 8);
-	arcfour_crypt(data, sealing_key, length);
-
-	schannel_digest(state->creds->session_key,
-			netsec_sig, confounder,
-			data, length, digest_final);
-
-	if (memcmp(digest_final, sig->data+16, 8) != 0) {
-		dump_data_pw("calc digest:", digest_final, 8);
-		dump_data_pw("wire digest:", sig->data+16, 8);
-		return NT_STATUS_ACCESS_DENIED;
+	if (do_unseal) {
+		netsec_do_seal(state, seq_num,
+			       confounder,
+			       data, length);
 	}
 
-	netsec_deal_with_seq_num(state, digest_final, seq_num);
-
-	if (memcmp(seq_num, sig->data+8, 8) != 0) {
-		dump_data_pw("calc seq num:", seq_num, 8);
-		dump_data_pw("wire seq num:", sig->data+8, 8);
-		return NT_STATUS_ACCESS_DENIED;
-	}
-
-	return NT_STATUS_OK;
-}
-
-/*
-  check the signature on a packet
-*/
-NTSTATUS schannel_check_packet(struct schannel_state *state,
-			       TALLOC_CTX *mem_ctx,
-			       const uint8_t *data, size_t length,
-			       const DATA_BLOB *sig)
-{
-	uint8_t digest_final[16];
-	uint8_t seq_num[8];
-	static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
+	netsec_do_sign(state, confounder,
+		       data, length,
+		       header, checksum);
 
-	/* w2k sends just 24 bytes and skip the confounder */
-	if (sig->length != 32 && sig->length != 24) {
+	ret = memcmp(checksum, sig->data+16, checksum_length);
+	if (ret != 0) {
+		dump_data_pw("calc digest:", checksum, checksum_length);
+		dump_data_pw("wire digest:", sig->data+16, checksum_length);
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	RSIVAL(seq_num, 0, state->seq_num);
-	SIVAL(seq_num, 4, state->initiator?0:0x80);
-
-	dump_data_pw("seq_num:\n", seq_num, 8);
-	dump_data_pw("sess_key:\n", state->creds->session_key, 16);
+	netsec_do_seq_num(state, checksum, checksum_length, seq_num);
 
-	schannel_digest(state->creds->session_key,
-			netsec_sig, NULL,
-			data, length, digest_final);
-
-	netsec_deal_with_seq_num(state, digest_final, seq_num);
-
-	if (memcmp(seq_num, sig->data+8, 8) != 0) {
+	ret = memcmp(seq_num, sig->data+8, 8);
+	if (ret != 0) {
 		dump_data_pw("calc seq num:", seq_num, 8);
 		dump_data_pw("wire seq num:", sig->data+8, 8);
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	if (memcmp(digest_final, sig->data+16, 8) != 0) {
-		dump_data_pw("calc digest:", digest_final, 8);
-		dump_data_pw("wire digest:", sig->data+16, 8);
-		return NT_STATUS_ACCESS_DENIED;
-	}
-
 	return NT_STATUS_OK;
 }
 
-
-/*
-  seal a packet
-*/
-NTSTATUS schannel_seal_packet(struct schannel_state *state,
-			      TALLOC_CTX *mem_ctx,
-			      uint8_t *data, size_t length,
-			      DATA_BLOB *sig)
+NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
+				TALLOC_CTX *mem_ctx,
+				bool do_seal,
+				uint8_t *data, size_t length,
+				DATA_BLOB *sig)
 {
-	uint8_t digest_final[16];
-	uint8_t confounder[8];
+	uint32_t min_sig_size = 0;
+	uint32_t used_sig_size = 0;
+	uint8_t header[8];
+	uint8_t checksum[32];
+	uint32_t checksum_length = sizeof(checksum_length);
+	uint8_t _confounder[8];
+	uint8_t *confounder = NULL;
+	uint32_t confounder_ofs = 0;
 	uint8_t seq_num[8];
-	uint8_t sealing_key[16];
-	static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
 
-	generate_random_buffer(confounder, 8);
+	netsec_offset_and_sizes(state,
+				do_seal,
+				&min_sig_size,
+				&used_sig_size,
+				&checksum_length,
+				&confounder_ofs);
 
 	RSIVAL(seq_num, 0, state->seq_num);
 	SIVAL(seq_num, 4, state->initiator?0x80:0);
 
-	schannel_digest(state->creds->session_key,
-			netsec_sig, confounder,
-			data, length, digest_final);
-
-	netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key);
-	arcfour_crypt(confounder, sealing_key, 8);
-	arcfour_crypt(data, sealing_key, length);
-
-	netsec_deal_with_seq_num(state, digest_final, seq_num);
-
-	(*sig) = data_blob_talloc(mem_ctx, NULL, 32);
-
-	memcpy(sig->data, netsec_sig, 8);
-	memcpy(sig->data+8, seq_num, 8);
-	memcpy(sig->data+16, digest_final, 8);
-	memcpy(sig->data+24, confounder, 8);
-
-	dump_data_pw("signature:", sig->data+ 0, 8);
-	dump_data_pw("seq_num  :", sig->data+ 8, 8);
-	dump_data_pw("digest   :", sig->data+16, 8);
-	dump_data_pw("confound :", sig->data+24, 8);
-
-	return NT_STATUS_OK;
-}
-
-
-/*
-  sign a packet
-*/
-NTSTATUS schannel_sign_packet(struct schannel_state *state,
-			      TALLOC_CTX *mem_ctx,
-			      const uint8_t *data, size_t length,
-			      DATA_BLOB *sig)
-{
-	uint8_t digest_final[16];
-	uint8_t seq_num[8];
-	static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
+	if (do_seal) {
+		confounder = _confounder;
+		generate_random_buffer(confounder, 8);
+	} else {
+		confounder = NULL;
+	}
 
-	RSIVAL(seq_num, 0, state->seq_num);
-	SIVAL(seq_num, 4, state->initiator?0x80:0);
+	netsec_do_sign(state, confounder,
+		       data, length,
+		       header, checksum);
 
-	schannel_digest(state->creds->session_key,
-			netsec_sig, NULL,
-			data, length, digest_final);
+	if (do_seal) {
+		netsec_do_seal(state, seq_num,
+			       confounder,
+			       data, length);
+	}
 
-	netsec_deal_with_seq_num(state, digest_final, seq_num);
+	netsec_do_seq_num(state, checksum, checksum_length, seq_num);
 
-	(*sig) = data_blob_talloc(mem_ctx, NULL, 32);
+	(*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
 
-	memcpy(sig->data, netsec_sig, 8);
+	memcpy(sig->data, header, 8);
 	memcpy(sig->data+8, seq_num, 8);
-	memcpy(sig->data+16, digest_final, 8);
-	memset(sig->data+24, 0, 8);
+	memcpy(sig->data+16, checksum, checksum_length);
+
+	if (confounder) {
+		memcpy(sig->data+confounder_ofs, confounder, 8);
+	}
 
 	dump_data_pw("signature:", sig->data+ 0, 8);
 	dump_data_pw("seq_num  :", sig->data+ 8, 8);
-	dump_data_pw("digest   :", sig->data+16, 8);
-	dump_data_pw("confound :", sig->data+24, 8);
+	dump_data_pw("digest   :", sig->data+16, checksum_length);
+	dump_data_pw("confound :", sig->data+confounder_ofs, 8);
 
 	return NT_STATUS_OK;
 }
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 393c726..186696f 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -676,6 +676,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p
 	uint32 save_offset = prs_offset(current_pdu);
 	struct schannel_state *schannel_auth =
 		cli->auth->a_u.schannel_auth;
+	uint8_t *data;
 	uint32 data_len;
 	DATA_BLOB blob;
 	NTSTATUS status;
@@ -727,20 +728,24 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p
 		dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
 	}
 
+	data = (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN;
+
 	switch (cli->auth->auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
-		status = schannel_unseal_packet(schannel_auth,
+		status = netsec_incoming_packet(schannel_auth,
 						talloc_tos(),
-						(uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
+						true,
+						data,
 						data_len,
 						&blob);
 		break;
 	case DCERPC_AUTH_LEVEL_INTEGRITY:
-		status = schannel_check_packet(schannel_auth,
-					       talloc_tos(),
-					       (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
-					       data_len,
-					       &blob);
+		status = netsec_incoming_packet(schannel_auth,
+						talloc_tos(),
+						false,
+						data,
+						data_len,
+						&blob);
 		break;
 	default:
 		status = NT_STATUS_INTERNAL_ERROR;
@@ -1948,18 +1953,20 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
 
 	switch (cli->auth->auth_level) {
 	case DCERPC_AUTH_LEVEL_PRIVACY:
-		status = schannel_seal_packet(sas,
-					      talloc_tos(),
-					      (uint8_t *)data_p,
-					      data_and_pad_len,
-					      &blob);
+		status = netsec_outgoing_packet(sas,
+						talloc_tos(),
+						true,
+						(uint8_t *)data_p,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list