[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Mon Jul 23 12:15:02 MDT 2012


The branch, master has been updated
       via  4b64ec5 libcli/smb: set should_encrypt = true if we got SMB2_SESSION_FLAG_ENCRYPT_DATA
       via  6b93210 libcli/smb: encrypt SMB2 traffic if nedded/desired.
       via  6e651df libcli/smb: increment nbt_len, when we have the fully created the SMB2 PDU
       via  f08adbb libcli/smb: maintain smb2.should_sign on smbXcli_req_state
       via  92811c6 libcli/smb: make use of SMB2_HDR_BODY as header size
       via  be8e33e libcli/smb: parse the SMB2_TRANSFORM header and decrypt the SMB2 pdu
       via  c2b0a48 libcli/smb: create 4 iovecs per request in smb2cli_inbuf_parse_compound()
       via  5863107 libcli/smb: prepare [en|de]cryption_key for SMB3
       via  d333edb libcli/smb: copy the application_key in smb2cli_session_create_channel()
       via  077eb57 libcli/smb: check the buffer length in smbXcli_negprot_dispatch_incoming()
       via  1c144b0 libcli/smb: only pass the smb2 buffer to smb2cli_inbuf_parse_compound()
       via  fd736f7 libcli/smb: add smb2_signing_[en|e]crypt_pdu()
       via  7e09824 libcli/smb: construct the signing_key before forming the message
       via  5adf63f lib/crypto: add aes_ccm_128
       via  4628e28 libcli/smb: add SMB2_SESSION_FLAG_ENCRYPT_DATA
       via  d728567 libcli/smb: add SMB2_TRANSFORM macros
       via  a41a1d1 s3:test_smb2: copy the session_channel from the primary channel.
       via  88f326a s3:smb2_tcon: reject access to shares mark as "smb encrypt = required"
      from  3fe601a s3-winbind: Fix idmap initialization debug message.

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


- Log -----------------------------------------------------------------
commit 4b64ec546f0cb982866b1f66aa8f8844f25c91c9
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 11:38:31 2012 +0200

    libcli/smb: set should_encrypt = true if we got SMB2_SESSION_FLAG_ENCRYPT_DATA
    
    metze
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Mon Jul 23 20:14:07 CEST 2012 on sn-devel-104

commit 6b9321071c97f740689a36ecf48d9d66f4a19e8e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 10:14:53 2012 +0200

    libcli/smb: encrypt SMB2 traffic if nedded/desired.
    
    metze

commit 6e651dfdc0af9805827ad2ea7fc29675ab6fe74b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 10:07:19 2012 +0200

    libcli/smb: increment nbt_len, when we have the fully created the SMB2 PDU
    
    metze

commit f08adbb4d63f2cb50de29aff44e7539e76bb87cc
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 10:00:50 2012 +0200

    libcli/smb: maintain smb2.should_sign on smbXcli_req_state
    
    metze

commit 92811c6f5f3d3807ab70a8acfd25795c7c0556b1
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 09:44:06 2012 +0200

    libcli/smb: make use of SMB2_HDR_BODY as header size
    
    metze

commit be8e33ec5416ebc57114dd2c1472ed0faffd05bb
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 09:16:05 2012 +0200

    libcli/smb: parse the SMB2_TRANSFORM header and decrypt the SMB2 pdu
    
    metze

commit c2b0a485136925ba8c9661d2b97b69dfeed5d5de
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 08:11:59 2012 +0200

    libcli/smb: create 4 iovecs per request in smb2cli_inbuf_parse_compound()
    
    The first one might hold the SMB2_TRANSFORM Header later.
    
    metze

commit 5863107cd3a37585272ee2186a0103f94932b063
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jul 20 09:30:05 2012 +0200

    libcli/smb: prepare [en|de]cryption_key for SMB3
    
    metze

commit d333edbe14a35bc1b0c2a0518c2e412f56ffda70
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jul 20 09:22:17 2012 +0200

    libcli/smb: copy the application_key in smb2cli_session_create_channel()
    
    metze

commit 077eb578be1bc9865fc5b32816f8230737e76100
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jul 20 09:20:43 2012 +0200

    libcli/smb: check the buffer length in smbXcli_negprot_dispatch_incoming()
    
    metze

commit 1c144b07f658723a9ae28c61b2e66c33630b573a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jul 20 09:19:24 2012 +0200

    libcli/smb: only pass the smb2 buffer to smb2cli_inbuf_parse_compound()
    
    We should hide the transport as much as possible.
    
    metze

commit fd736f7f18294aa1589aacd495b2a48bbaf8715c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jul 20 09:16:08 2012 +0200

    libcli/smb: add smb2_signing_[en|e]crypt_pdu()
    
    metze

commit 7e0982421b1e8b6a73ef67cdb085ffc60cd3b59b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jul 19 11:16:16 2012 +0200

    libcli/smb: construct the signing_key before forming the message
    
    metze

commit 5adf63fe301e812f5776448f9560af9d6d842554
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jul 20 07:37:48 2012 +0200

    lib/crypto: add aes_ccm_128
    
    metze

commit 4628e2878f844ea95fb678a07dcb017edd46cc1f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 10:46:21 2012 +0200

    libcli/smb: add SMB2_SESSION_FLAG_ENCRYPT_DATA
    
    metze

commit d7285672b4990696a61fef3d1129d7ee45e530a2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jul 20 09:11:30 2012 +0200

    libcli/smb: add SMB2_TRANSFORM macros
    
    metze

commit a41a1d176f31cbbd011309041c6865487a7be9c6
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 13:34:05 2012 +0200

    s3:test_smb2: copy the session_channel from the primary channel.
    
    metze

commit 88f326a2c0be88bf1eb6fb7ae5348c69544815de
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jul 23 13:47:24 2012 +0200

    s3:smb2_tcon: reject access to shares mark as "smb encrypt = required"
    
    We do not support SMB2 transport encryption yet.
    
    metze

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

Summary of changes:
 lib/crypto/aes_ccm_128.c    |  170 ++++++++++++++++++++
 lib/crypto/aes_ccm_128.h    |   54 +++++++
 lib/crypto/crypto.h         |    1 +
 lib/crypto/wscript_build    |    2 +-
 libcli/smb/smb2_constants.h |   16 ++
 libcli/smb/smb2_signing.c   |  132 ++++++++++++++++
 libcli/smb/smb2_signing.h   |    9 +
 libcli/smb/smbXcli_base.c   |  363 ++++++++++++++++++++++++++++++++++--------
 source3/Makefile.in         |    2 +-
 source3/smbd/smb2_tcon.c    |    8 +
 source3/torture/test_smb2.c |    2 +-
 11 files changed, 687 insertions(+), 72 deletions(-)
 create mode 100644 lib/crypto/aes_ccm_128.c
 create mode 100644 lib/crypto/aes_ccm_128.h


Changeset truncated at 500 lines:

diff --git a/lib/crypto/aes_ccm_128.c b/lib/crypto/aes_ccm_128.c
new file mode 100644
index 0000000..ac8e01f
--- /dev/null
+++ b/lib/crypto/aes_ccm_128.c
@@ -0,0 +1,170 @@
+/*
+   AES-CCM-128 (rfc 3610)
+
+   Copyright (C) Stefan Metzmacher 2012
+
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "../lib/crypto/crypto.h"
+#include "lib/util/byteorder.h"
+
+#define M_ ((AES_CCM_128_M - 2) / 2)
+#define L_ (AES_CCM_128_L - 1)
+
+static inline void aes_ccm_128_xor(const uint8_t in1[AES_BLOCK_SIZE],
+				   const uint8_t in2[AES_BLOCK_SIZE],
+				   uint8_t out[AES_BLOCK_SIZE])
+{
+	uint8_t i;
+
+	for (i = 0; i < AES_BLOCK_SIZE; i++) {
+		out[i] = in1[i] ^ in2[i];
+	}
+}
+
+void aes_ccm_128_init(struct aes_ccm_128_context *ctx,
+		      const uint8_t K[AES_BLOCK_SIZE],
+		      const uint8_t N[AES_CCM_128_NONCE_SIZE],
+		      size_t a_total, size_t m_total)
+{
+	uint8_t B_0[AES_BLOCK_SIZE];
+
+	ZERO_STRUCTP(ctx);
+
+	AES_set_encrypt_key(K, 128, &ctx->aes_key);
+	memcpy(ctx->nonce, N, AES_CCM_128_NONCE_SIZE);
+	ctx->a_remain = a_total;
+	ctx->m_remain = m_total;
+
+	/*
+	 * prepare B_0
+	 */
+	B_0[0]  = L_;
+	B_0[0] += 8 * M_;
+	if (a_total > 0) {
+		B_0[0] += 64;
+	}
+	memcpy(&B_0[1], ctx->nonce, AES_CCM_128_NONCE_SIZE);
+	RSIVAL(B_0, (AES_BLOCK_SIZE - AES_CCM_128_L), m_total);
+
+	/*
+	 * prepare X_1
+	 */
+	AES_encrypt(B_0, ctx->X_i, &ctx->aes_key);
+
+	/*
+	 * prepare B_1
+	 */
+	if (a_total >= UINT32_MAX) {
+		RSSVAL(ctx->B_i, 0, 0xFFFF);
+		RSBVAL(ctx->B_i, 2, a_total);
+		ctx->B_i_ofs = 10;
+	} else if (a_total >= 0xFF00) {
+		RSSVAL(ctx->B_i, 0, 0xFFFE);
+		RSIVAL(ctx->B_i, 2, a_total);
+		ctx->B_i_ofs = 6;
+	} else if (a_total > 0) {
+		RSSVAL(ctx->B_i, 0, a_total);
+		ctx->B_i_ofs = 2;
+	}
+
+	ctx->S_i_ofs = AES_BLOCK_SIZE;
+}
+
+void aes_ccm_128_update(struct aes_ccm_128_context *ctx,
+			const uint8_t *v, size_t v_len)
+{
+	size_t *remain;
+
+	if (ctx->a_remain > 0) {
+		remain = &ctx->a_remain;
+	} else {
+		remain = &ctx->m_remain;
+	}
+
+	while (v_len > 0) {
+		size_t n = MIN(AES_BLOCK_SIZE - ctx->B_i_ofs, v_len);
+		bool more = true;
+
+		memcpy(&ctx->B_i[ctx->B_i_ofs], v, n);
+		v += n;
+		v_len -= n;
+		ctx->B_i_ofs += n;
+		*remain -= n;
+
+		if (ctx->B_i_ofs == AES_BLOCK_SIZE) {
+			more = false;
+		} else if (*remain == 0) {
+			more = false;
+		}
+
+		if (more) {
+			continue;
+		}
+
+		aes_ccm_128_xor(ctx->X_i, ctx->B_i, ctx->B_i);
+		AES_encrypt(ctx->B_i, ctx->X_i, &ctx->aes_key);
+
+		ZERO_STRUCT(ctx->B_i);
+		ctx->B_i_ofs = 0;
+	}
+}
+
+static void aes_ccm_128_S_i(struct aes_ccm_128_context *ctx,
+			    uint8_t S_i[AES_BLOCK_SIZE],
+			    size_t i)
+{
+	uint8_t A_i[AES_BLOCK_SIZE];
+
+	A_i[0]  = L_;
+	memcpy(&A_i[1], ctx->nonce, AES_CCM_128_NONCE_SIZE);
+	RSIVAL(A_i, (AES_BLOCK_SIZE - AES_CCM_128_L), i);
+
+	AES_encrypt(A_i, S_i, &ctx->aes_key);
+}
+
+void aes_ccm_128_crypt(struct aes_ccm_128_context *ctx,
+		       uint8_t *m, size_t m_len)
+{
+	while (m_len > 0) {
+		if (ctx->S_i_ofs == AES_BLOCK_SIZE) {
+			ctx->S_i_ctr += 1;
+			aes_ccm_128_S_i(ctx, ctx->S_i, ctx->S_i_ctr);
+			ctx->S_i_ofs = 0;
+		}
+
+		m[0] ^= ctx->S_i[ctx->S_i_ofs];
+		m += 1;
+		m_len -= 1;
+		ctx->S_i_ofs += 1;
+	}
+}
+
+void aes_ccm_128_digest(struct aes_ccm_128_context *ctx,
+			uint8_t digest[AES_BLOCK_SIZE])
+{
+	uint8_t S_0[AES_BLOCK_SIZE];
+
+	aes_ccm_128_S_i(ctx, S_0, 0);
+
+	/*
+	 * note X_i is T here
+	 */
+	aes_ccm_128_xor(ctx->X_i, S_0, digest);
+
+	ZERO_STRUCT(S_0);
+	ZERO_STRUCTP(ctx);
+}
diff --git a/lib/crypto/aes_ccm_128.h b/lib/crypto/aes_ccm_128.h
new file mode 100644
index 0000000..a98c754
--- /dev/null
+++ b/lib/crypto/aes_ccm_128.h
@@ -0,0 +1,54 @@
+/*
+   AES-CCM-128 (rfc 3610)
+
+   Copyright (C) Stefan Metzmacher 2012
+
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef LIB_CRYPTO_AES_CCM_128_H
+#define LIB_CRYPTO_AES_CCM_128_H
+
+#define AES_CCM_128_M 16
+#define AES_CCM_128_L 4
+#define AES_CCM_128_NONCE_SIZE (15 - AES_CCM_128_L)
+
+struct aes_ccm_128_context {
+	AES_KEY aes_key;
+	uint8_t nonce[AES_CCM_128_NONCE_SIZE];
+
+	size_t a_remain;
+	size_t m_remain;
+
+	uint8_t X_i[AES_BLOCK_SIZE];
+	uint8_t B_i[AES_BLOCK_SIZE];
+	size_t B_i_ofs;
+
+	uint8_t S_i[AES_BLOCK_SIZE];
+	size_t S_i_ofs;
+	size_t S_i_ctr;
+};
+
+void aes_ccm_128_init(struct aes_ccm_128_context *ctx,
+		      const uint8_t K[AES_BLOCK_SIZE],
+		      const uint8_t N[AES_CCM_128_NONCE_SIZE],
+		      size_t a_total, size_t m_total);
+void aes_ccm_128_update(struct aes_ccm_128_context *ctx,
+			const uint8_t *v, size_t v_len);
+void aes_ccm_128_crypt(struct aes_ccm_128_context *ctx,
+			 uint8_t *m, size_t m_len);
+void aes_ccm_128_digest(struct aes_ccm_128_context *ctx,
+			uint8_t digest[AES_BLOCK_SIZE]);
+
+#endif /* LIB_CRYPTO_AES_CCM_128_H */
diff --git a/lib/crypto/crypto.h b/lib/crypto/crypto.h
index c0d85c8..1f5a1b7 100644
--- a/lib/crypto/crypto.h
+++ b/lib/crypto/crypto.h
@@ -26,4 +26,5 @@
 #include "../lib/crypto/arcfour.h"
 #include "../lib/crypto/aes.h"
 #include "../lib/crypto/aes_cmac_128.h"
+#include "../lib/crypto/aes_ccm_128.h"
 
diff --git a/lib/crypto/wscript_build b/lib/crypto/wscript_build
index 849bf16..cd7a466 100644
--- a/lib/crypto/wscript_build
+++ b/lib/crypto/wscript_build
@@ -9,7 +9,7 @@ elif not bld.CONFIG_SET('HAVE_COMMONCRYPTO_COMMONDIGEST_H'):
 
 bld.SAMBA_SUBSYSTEM('LIBCRYPTO',
         source='''crc32.c hmacmd5.c md4.c arcfour.c sha256.c hmacsha256.c
-        aes.c rijndael-alg-fst.c aes_cmac_128.c
+        aes.c rijndael-alg-fst.c aes_cmac_128.c aes_ccm_128.c
         ''' + extra_source,
         deps='talloc' + extra_deps
         )
diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h
index 9b60345..f2f28f8 100644
--- a/libcli/smb/smb2_constants.h
+++ b/libcli/smb/smb2_constants.h
@@ -22,6 +22,21 @@
 #ifndef __LIBCLI_SMB2_SMB2_CONSTANTS_H__
 #define __LIBCLI_SMB2_SMB2_CONSTANTS_H__
 
+/* offsets into SMB2_TRANSFORM header elements */
+#define SMB2_TF_PROTOCOL_ID	0x00 /*  4 bytes */
+#define SMB2_TF_SIGNATURE	0x04 /* 16 bytes */
+#define SMB2_TF_NONCE		0x14 /* 16 bytes */
+#define SMB2_TF_MSG_SIZE	0x24 /*  4 bytes */
+#define SMB2_TF_RESERVED	0x28 /*  2 bytes */
+#define SMB2_TF_ALGORITHM	0x2A /*  2 bytes */
+#define SMB2_TF_SESSION_ID	0x2C /*  8 bytes */
+
+#define SMB2_TF_HDR_SIZE	0x34 /* 52 bytes */
+
+#define SMB2_TF_MAGIC 0x424D53FD /* 0xFD 'S' 'M' 'B' */
+
+#define SMB2_ENCRYPTION_AES128_CCM	0x0001
+
 /* offsets into header elements for a sync SMB2 request */
 #define SMB2_HDR_PROTOCOL_ID    0x00
 #define SMB2_HDR_LENGTH		0x04
@@ -109,6 +124,7 @@
 /* SMB2 session flags */
 #define SMB2_SESSION_FLAG_IS_GUEST       0x0001
 #define SMB2_SESSION_FLAG_IS_NULL        0x0002
+#define SMB2_SESSION_FLAG_ENCRYPT_DATA   0x0004 /* in dialect >= 0x224 */
 
 /* SMB2 sharetype flags */
 #define SMB2_SHARE_TYPE_DISK		0x1
diff --git a/libcli/smb/smb2_signing.c b/libcli/smb/smb2_signing.c
index 43c9ba5..bb621fd 100644
--- a/libcli/smb/smb2_signing.c
+++ b/libcli/smb/smb2_signing.c
@@ -207,3 +207,135 @@ void smb2_key_derivation(const uint8_t *KI, size_t KI_len,
 
 	memcpy(KO, digest, 16);
 }
+
+NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key,
+				  enum protocol_types protocol,
+				  struct iovec *vector,
+				  int count)
+{
+	uint8_t *tf;
+	uint16_t alg;
+	uint8_t sig[16];
+	int i;
+	size_t a_total;
+	size_t m_total = 0;
+	struct aes_ccm_128_context ctx;
+	uint8_t key[AES_BLOCK_SIZE];
+
+	if (count < 1) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	tf = (uint8_t *)vector[0].iov_base;
+
+	if (encryption_key.length == 0) {
+		DEBUG(2,("Wrong encryption key length %u for SMB2 signing\n",
+			 (unsigned)encryption_key.length));
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	alg = SMB2_ENCRYPTION_AES128_CCM;
+	SSVAL(tf, SMB2_TF_ALGORITHM, alg);
+
+	a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
+	for (i=1; i < count; i++) {
+		m_total += vector[i].iov_len;
+	}
+	ZERO_STRUCT(key);
+	memcpy(key, encryption_key.data,
+	       MIN(encryption_key.length, AES_BLOCK_SIZE));
+	aes_ccm_128_init(&ctx, key,
+			 tf + SMB2_TF_NONCE,
+			 a_total, m_total);
+	aes_ccm_128_update(&ctx, tf + SMB2_TF_NONCE, a_total);
+	for (i=1; i < count; i++) {
+		aes_ccm_128_update(&ctx,
+				(const uint8_t *)vector[i].iov_base,
+				vector[i].iov_len);
+	}
+	for (i=1; i < count; i++) {
+		aes_ccm_128_crypt(&ctx,
+				(uint8_t *)vector[i].iov_base,
+				vector[i].iov_len);
+	}
+	aes_ccm_128_digest(&ctx, sig);
+
+	memcpy(tf + SMB2_TF_SIGNATURE, sig, 16);
+
+	DEBUG(5,("encrypt SMB2 message\n"));
+
+	return NT_STATUS_OK;
+}
+
+NTSTATUS smb2_signing_decrypt_pdu(DATA_BLOB decryption_key,
+				  enum protocol_types protocol,
+				  struct iovec *vector,
+				  int count)
+{
+	uint8_t *tf;
+	uint16_t alg;
+	uint8_t *sig_ptr = NULL;
+	uint8_t sig[16];
+	int i;
+	size_t a_total;
+	size_t m_total = 0;
+	struct aes_ccm_128_context ctx;
+	uint8_t key[AES_BLOCK_SIZE];
+
+	if (count < 1) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	tf = (uint8_t *)vector[0].iov_base;
+
+	if (decryption_key.length == 0) {
+		DEBUG(2,("Wrong decryption key length %u for SMB2 signing\n",
+			 (unsigned)decryption_key.length));
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	alg = SVAL(tf, SMB2_TF_ALGORITHM);
+	if (alg != SMB2_ENCRYPTION_AES128_CCM) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
+	for (i=1; i < count; i++) {
+		m_total += vector[i].iov_len;
+	}
+	ZERO_STRUCT(key);
+	memcpy(key, decryption_key.data,
+	       MIN(decryption_key.length, AES_BLOCK_SIZE));
+	aes_ccm_128_init(&ctx, key,
+			 tf + SMB2_TF_NONCE,
+			 a_total, m_total);
+	for (i=1; i < count; i++) {
+		aes_ccm_128_crypt(&ctx,
+				(uint8_t *)vector[i].iov_base,
+				vector[i].iov_len);
+	}
+	aes_ccm_128_update(&ctx, tf + SMB2_TF_NONCE, a_total);
+	for (i=1; i < count; i++) {
+		aes_ccm_128_update(&ctx,
+				( uint8_t *)vector[i].iov_base,
+				vector[i].iov_len);
+	}
+	aes_ccm_128_digest(&ctx, sig);
+
+	sig_ptr = tf + SMB2_TF_SIGNATURE;
+	if (memcmp(sig_ptr, sig, 16) != 0) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	DEBUG(5,("decrypt SMB2 message\n"));
+
+	return NT_STATUS_OK;
+}
diff --git a/libcli/smb/smb2_signing.h b/libcli/smb/smb2_signing.h
index 200274b..e8e2e6a 100644
--- a/libcli/smb/smb2_signing.h
+++ b/libcli/smb/smb2_signing.h
@@ -38,4 +38,13 @@ void smb2_key_derivation(const uint8_t *KI, size_t KI_len,
 			 const uint8_t *Context, size_t Context_len,
 			 uint8_t KO[16]);
 
+NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key,
+				  enum protocol_types protocol,
+				  struct iovec *vector,
+				  int count);
+NTSTATUS smb2_signing_decrypt_pdu(DATA_BLOB decryption_key,
+				  enum protocol_types protocol,
+				  struct iovec *vector,
+				  int count);
+
 #endif /* _LIBCLI_SMB_SMB2_SIGNING_H_ */
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index eb9e7d5..326a43d 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -137,6 +137,11 @@ struct smbXcli_session {
 		DATA_BLOB application_key;
 		DATA_BLOB signing_key;
 		bool should_sign;
+		bool should_encrypt;
+		DATA_BLOB encryption_key;
+		DATA_BLOB decryption_key;
+		uint64_t channel_nonce;
+		uint64_t channel_next;
 		DATA_BLOB channel_signing_key;
 	} smb2;
 };
@@ -188,14 +193,23 @@ struct smbXcli_req_state {
 		const uint8_t *dyn;
 		uint32_t dyn_len;
 
-		uint8_t hdr[64];
+		uint8_t transform[SMB2_TF_HDR_SIZE];
+		uint8_t hdr[SMB2_HDR_BODY];
 		uint8_t pad[7];	/* padding space for compounding */
 
-		/* always an array of 3 talloc elements */
+		/*
+		 * always an array of 3 talloc elements
+		 * (without a SMB2_TRANSFORM header!)
+		 *
+		 * HDR, BODY, DYN
+		 */
 		struct iovec *recv_iov;
 
 		uint16_t credit_charge;
 
+		bool should_sign;
+		bool should_encrypt;
+
 		bool signing_skipped;
 		bool notify_async;
 		bool got_async;
@@ -2402,6 +2416,25 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
 
 	if (session) {
 		uid = session->smb2.session_id;
+
+		state->smb2.should_sign = session->smb2.should_sign;
+		state->smb2.should_encrypt = session->smb2.should_encrypt;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list