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 <[email protected]>
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 <[email protected]>
    Autobuild-Date(master): Mon Jul 23 20:14:07 CEST 2012 on sn-devel-104

commit 6b9321071c97f740689a36ecf48d9d66f4a19e8e
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Jul 23 10:14:53 2012 +0200

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

commit 6e651dfdc0af9805827ad2ea7fc29675ab6fe74b
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
Date:   Fri Jul 20 09:30:05 2012 +0200

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

commit d333edbe14a35bc1b0c2a0518c2e412f56ffda70
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
Date:   Fri Jul 20 09:16:08 2012 +0200

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

commit 7e0982421b1e8b6a73ef67cdb085ffc60cd3b59b
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
Date:   Fri Jul 20 07:37:48 2012 +0200

    lib/crypto: add aes_ccm_128
    
    metze

commit 4628e2878f844ea95fb678a07dcb017edd46cc1f
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Jul 23 10:46:21 2012 +0200

    libcli/smb: add SMB2_SESSION_FLAG_ENCRYPT_DATA
    
    metze

commit d7285672b4990696a61fef3d1129d7ee45e530a2
Author: Stefan Metzmacher <[email protected]>
Date:   Fri Jul 20 09:11:30 2012 +0200

    libcli/smb: add SMB2_TRANSFORM macros
    
    metze

commit a41a1d176f31cbbd011309041c6865487a7be9c6
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
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

Reply via email to