[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Fri Aug 17 08:35:03 MDT 2012


The branch, master has been updated
       via  1b487ad s3:selftest: add some tests against a share the requires encryption
       via  45471f4 s3:smb2_negprot: annouce/negotiate SMB3 encryption support
       via  9397d67 s3:smb2_server: add SMB3 encryption support
       via  9f1dfd8 s3:smbd: don't disconnect the client when a share has "smb encrypt = required"
       via  e5d4e8d s3:smbd: lp_smb_encrypt() returns SMB_SIGNING_* values
       via  8b3da9a s3:smbd: make use of ENCRYPTION_REQUIRED()
       via  abf018e libcli/smb: make sure the SMB2_TRANSFORM pdu is complete
       via  e2b07c0 s4:libcli/smb2: reset trsnport->compound.related when a compound chain is finished
      from  6ce362a build: Ensure -Werror=format works with -Wformat=2 on NULL format strings

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


- Log -----------------------------------------------------------------
commit 1b487ad3d7f709b0a100ccdc6fc30dcf7d0b778c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 17 08:50:21 2012 +0200

    s3:selftest: add some tests against a share the requires encryption
    
    metze
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Fri Aug 17 16:34:26 CEST 2012 on sn-devel-104

commit 45471f4d8f80d80c01197536bcf47d932dcd38e0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Aug 8 07:07:53 2012 +0200

    s3:smb2_negprot: annouce/negotiate SMB3 encryption support
    
    metze

commit 9397d6709f79f2e8837401d32cd7ac584b6c5b24
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Aug 8 07:07:03 2012 +0200

    s3:smb2_server: add SMB3 encryption support
    
    metze

commit 9f1dfd8facaa59370afd93e89cc729de5cc3d9ba
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 17 09:42:27 2012 +0200

    s3:smbd: don't disconnect the client when a share has "smb encrypt = required"
    
    It's not the client fault, if he doesn't know that encryption is required.
    We should just return ACCESS_DENIED and let the client work on other
    shares and open files on the current SMB connection.
    
    metze

commit e5d4e8df6b8186b71aa72dd7817f5579b44fee2f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 17 09:40:52 2012 +0200

    s3:smbd: lp_smb_encrypt() returns SMB_SIGNING_* values
    
    metze

commit 8b3da9a1f400040eef14b63ed0b7884a9e82d907
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 17 09:41:42 2012 +0200

    s3:smbd: make use of ENCRYPTION_REQUIRED()
    
    metze

commit abf018e8b64b237aa029978c20bd418524fff3d0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 17 08:31:52 2012 +0200

    libcli/smb: make sure the SMB2_TRANSFORM pdu is complete
    
    metze

commit e2b07c0adca680d73f20744fd8dbbcb8be818ca3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Aug 17 08:25:08 2012 +0200

    s4:libcli/smb2: reset trsnport->compound.related when a compound chain is finished
    
    metze

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

Summary of changes:
 libcli/smb/smbXcli_base.c       |   15 ++-
 selftest/knownfail              |    5 +
 selftest/target/Samba3.pm       |    4 +
 selftest/target/Samba4.pm       |    4 +
 source3/include/smb_macros.h    |    2 +-
 source3/param/loadparm.c        |    2 +-
 source3/selftest/tests.py       |    9 +-
 source3/smbd/globals.h          |   52 ++++--
 source3/smbd/process.c          |   10 +-
 source3/smbd/smb2_negprot.c     |    8 +
 source3/smbd/smb2_server.c      |  350 +++++++++++++++++++++++++++++++++++----
 source3/smbd/trans2.c           |   20 +--
 source4/libcli/smb2/transport.c |    1 +
 13 files changed, 412 insertions(+), 70 deletions(-)


Changeset truncated at 500 lines:

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index a9adcbb..02d0227 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -3041,6 +3041,7 @@ static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn,
 			struct smbXcli_session *s;
 			uint64_t uid;
 			struct iovec tf_iov[2];
+			size_t enc_len;
 			NTSTATUS status;
 
 			if (len < SMB2_TF_HDR_SIZE) {
@@ -3053,9 +3054,16 @@ static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn,
 			taken += tf_len;
 
 			hdr = first_hdr + taken;
-			len = IVAL(tf, SMB2_TF_MSG_SIZE);
+			enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
 			uid = BVAL(tf, SMB2_TF_SESSION_ID);
 
+			if (len < SMB2_TF_HDR_SIZE + enc_len) {
+				DEBUG(10, ("%d bytes left, expected at least %d\n",
+					   (int)len,
+					   (int)(SMB2_TF_HDR_SIZE + enc_len)));
+				goto inval;
+			}
+
 			s = conn->sessions;
 			for (; s; s = s->next) {
 				if (s->smb2->session_id != uid) {
@@ -3073,7 +3081,7 @@ static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn,
 			tf_iov[0].iov_base = (void *)tf;
 			tf_iov[0].iov_len = tf_len;
 			tf_iov[1].iov_base = (void *)hdr;
-			tf_iov[1].iov_len = len;
+			tf_iov[1].iov_len = enc_len;
 
 			status = smb2_signing_decrypt_pdu(s->smb2->decryption_key,
 							  conn->protocol,
@@ -3083,7 +3091,8 @@ static NTSTATUS smb2cli_inbuf_parse_compound(struct smbXcli_conn *conn,
 				return status;
 			}
 
-			verified_buflen = taken + len;
+			verified_buflen = taken + enc_len;
+			len = enc_len;
 		}
 
 		/*
diff --git a/selftest/knownfail b/selftest/knownfail
index da3d93c..9376264 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -21,6 +21,11 @@
 ^samba3.smbtorture_s3.plain\(dc\).BAD-NBT-SESSION # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(dc\).SMB2-SESSION-REAUTH # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(dc\).SMB2-SESSION-RECONNECT # Fails against the s4 ntvfs server
+ ^samba3.smbtorture_s3.crypt_server\(s3dc\).SMB2-SESSION-REAUTH # expected to give ACCESS_DENIED SMB2.1 doesn't have encryption
+^samba3.smbtorture_s3.crypt_server\(s3dc\).SMB2-SESSION-RECONNECT # expected to give CONNECTION_DISCONNECTED, we need to fix the test
+^samba3.smb2.session enc.reconnect # expected to give CONNECTION_DISCONNECTED, we need to fix the test
+^samba3.raw.session enc # expected to give ACCESS_DENIED as SMB1 encryption isn't used
+^samba3.smbtorture_s3.crypt_server # expected to give ACCESS_DENIED as SMB1 encryption isn't used
 ^samba3.nbt.dgram.*netlogon2\(s3dc\)
 ^samba3.*rap.sam.*.useradd # Not provided by Samba 3
 ^samba3.*rap.sam.*.userdelete # Not provided by Samba 3
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 149a31e..72b9c19 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -939,6 +939,10 @@ sub provision($$$$$$)
 [tmp]
 	path = $shrdir
         comment = smb username is [%U]
+[tmpenc]
+	path = $shrdir
+	comment = encrypt smb username is [%U]
+	smb encrypt = required
 [tmpguest]
 	path = $shrdir
         guest ok = yes
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index b1998a6..17afab2 100644
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1385,6 +1385,10 @@ sub provision_plugin_s4_dc($$)
 
 	my $extra_smbconf_shares = "
 
+[tmpenc]
+	copy = tmp
+	smb encrypt = required
+
 [tmpcase]
 	copy = tmp
 	case sensitive = yes
diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h
index 73f8fb3..8b9d941 100644
--- a/source3/include/smb_macros.h
+++ b/source3/include/smb_macros.h
@@ -139,7 +139,7 @@
 #define smb_len_large(buf) smb_len_tcp(buf)
 #define _smb_setlen_large(buf, len) _smb_setlen_tcp(buf, len)
 
-#define ENCRYPTION_REQUIRED(conn) ((conn) ? ((conn)->encrypt_level == Required) : false)
+#define ENCRYPTION_REQUIRED(conn) ((conn) ? ((conn)->encrypt_level == SMB_SIGNING_REQUIRED) : false)
 #define IS_CONN_ENCRYPTED(conn) ((conn) ? (conn)->encrypted_tid : false)
 
 /****************************************************************************
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index d7141ae..bce1c5b 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -281,7 +281,7 @@ static struct loadparm_service sDefault =
 #else
 	.iDirectoryNameCacheSize = 100,
 #endif
-	.ismb_encrypt = Auto,
+	.ismb_encrypt = SMB_SIGNING_DEFAULT,
 	.param_opt = NULL,
 	.dummy = ""
 };
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 00ecd6c..f9f2e22 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -95,7 +95,11 @@ tests=[ "FDPASS", "LOCK1", "LOCK2", "LOCK3", "LOCK4", "LOCK5", "LOCK6", "LOCK7",
 
 for t in tests:
     plantestsuite("samba3.smbtorture_s3.plain(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
-    plantestsuite("samba3.smbtorture_s3.crypt(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "-e", "-l $LOCAL_PATH"])
+    plantestsuite("samba3.smbtorture_s3.crypt_client(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "-e", "-l $LOCAL_PATH"])
+    if t == "TORTURE":
+        # this is a negative test to verify that the server rejects
+        # access without encryption
+        plantestsuite("samba3.smbtorture_s3.crypt_server(s3dc).%s" % t, "s3dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmpenc', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
     plantestsuite("samba3.smbtorture_s3.plain(dc).%s" % t, "dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/tmp', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
 
 posix_tests=[ "POSIX", "POSIX-APPEND"]
@@ -333,7 +337,8 @@ for t in tests:
         plansmbtorturetestsuite(t, "secshare", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
         plansmbtorturetestsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
     elif t == "raw.session" or t == "smb2.session":
-        plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
+        plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD', 'plain')
+        plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmpenc -U$USERNAME%$PASSWORD', 'enc')
         plansmbtorturetestsuite(t, "plugin_s4_dc", '//$SERVER/tmp -k no -U$USERNAME%$PASSWORD', 'ntlm')
         plansmbtorturetestsuite(t, "plugin_s4_dc", '//$SERVER/tmp -k yes -U$USERNAME%$PASSWORD', 'krb5')
     elif t == "rpc.lsa":
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index ac8a1b2..b024fb3 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -462,7 +462,12 @@ struct smbd_smb2_request {
 	bool compound_related;
 
 	/*
-	 * the signing/encryption key for the last
+	 * the encryption key for the whole
+	 * compound chain
+	 */
+	DATA_BLOB first_key;
+	/*
+	 * the signing key for the last
 	 * request/response of a compound chain
 	 */
 	DATA_BLOB last_key;
@@ -481,15 +486,18 @@ struct smbd_smb2_request {
 	 */
 	struct tevent_req *subreq;
 
-#define SMBD_SMB2_HDR_IOV_OFS 0
-#define SMBD_SMB2_BODY_IOV_OFS 1
-#define SMBD_SMB2_DYN_IOV_OFS 2
+#define SMBD_SMB2_TF_IOV_OFS 0
+#define SMBD_SMB2_HDR_IOV_OFS 1
+#define SMBD_SMB2_BODY_IOV_OFS 2
+#define SMBD_SMB2_DYN_IOV_OFS 3
 
-#define SMBD_SMB2_NUM_IOV_PER_REQ 3
+#define SMBD_SMB2_NUM_IOV_PER_REQ 4
 
 #define SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,ofs) \
 	(&req->dir.vector[(idx)+(ofs)])
 
+#define SMBD_SMB2_IDX_TF_IOV(req,dir,idx) \
+	SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_TF_IOV_OFS)
 #define SMBD_SMB2_IDX_HDR_IOV(req,dir,idx) \
 	SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_HDR_IOV_OFS)
 #define SMBD_SMB2_IDX_BODY_IOV(req,dir,idx) \
@@ -497,6 +505,8 @@ struct smbd_smb2_request {
 #define SMBD_SMB2_IDX_DYN_IOV(req,dir,idx) \
 	SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_DYN_IOV_OFS)
 
+#define SMBD_SMB2_IN_TF_IOV(req)    SMBD_SMB2_IDX_TF_IOV(req,in,req->current_idx)
+#define SMBD_SMB2_IN_TF_PTR(req)    (uint8_t *)(SMBD_SMB2_IN_TF_IOV(req)->iov_base)
 #define SMBD_SMB2_IN_HDR_IOV(req)    SMBD_SMB2_IDX_HDR_IOV(req,in,req->current_idx)
 #define SMBD_SMB2_IN_HDR_PTR(req)    (uint8_t *)(SMBD_SMB2_IN_HDR_IOV(req)->iov_base)
 #define SMBD_SMB2_IN_BODY_IOV(req)   SMBD_SMB2_IDX_BODY_IOV(req,in,req->current_idx)
@@ -506,6 +516,8 @@ struct smbd_smb2_request {
 #define SMBD_SMB2_IN_DYN_PTR(req)    (uint8_t *)(SMBD_SMB2_IN_DYN_IOV(req)->iov_base)
 #define SMBD_SMB2_IN_DYN_LEN(req)    (SMBD_SMB2_IN_DYN_IOV(req)->iov_len)
 
+#define SMBD_SMB2_OUT_TF_IOV(req)   SMBD_SMB2_IDX_TF_IOV(req,out,req->current_idx)
+#define SMBD_SMB2_OUT_TF_PTR(req)   (uint8_t *)(SMBD_SMB2_OUT_TF_IOV(req)->iov_base)
 #define SMBD_SMB2_OUT_HDR_IOV(req)   SMBD_SMB2_IDX_HDR_IOV(req,out,req->current_idx)
 #define SMBD_SMB2_OUT_HDR_PTR(req)   (uint8_t *)(SMBD_SMB2_OUT_HDR_IOV(req)->iov_base)
 #define SMBD_SMB2_OUT_BODY_IOV(req)  SMBD_SMB2_IDX_BODY_IOV(req,out,req->current_idx)
@@ -517,17 +529,19 @@ struct smbd_smb2_request {
 
 	struct {
 		/*
-		 * vector[0] TRANSPORT HEADER
+		 * vector[0] TRANSPORT HEADER (empty)
 		 * .
-		 * vector[1] SMB2
-		 * vector[2] fixed body
-		 * vector[3] dynamic body
+		 * vector[1] SMB2_TRANSFORM (optional)
+		 * vector[2] SMB2
+		 * vector[3] fixed body
+		 * vector[4] dynamic body
 		 * .
 		 * .
 		 * .
-		 * vector[4] SMB2
-		 * vector[5] fixed body
-		 * vector[6] dynamic body
+		 * vector[5] SMB2_TRANSFORM (optional)
+		 * vector[6] SMB2
+		 * vector[7] fixed body
+		 * vector[8] dynamic body
 		 * .
 		 * .
 		 * .
@@ -541,15 +555,17 @@ struct smbd_smb2_request {
 		/*
 		 * vector[0] TRANSPORT HEADER
 		 * .
-		 * vector[1] SMB2
-		 * vector[2] fixed body
-		 * vector[3] dynamic body
+		 * vector[1] SMB2_TRANSFORM (optional)
+		 * vector[2] SMB2
+		 * vector[3] fixed body
+		 * vector[4] dynamic body
 		 * .
 		 * .
 		 * .
-		 * vector[4] SMB2
-		 * vector[5] fixed body
-		 * vector[6] dynamic body
+		 * vector[5] SMB2_TRANSFORM (empty)
+		 * vector[6] SMB2
+		 * vector[7] fixed body
+		 * vector[8] dynamic body
 		 * .
 		 * .
 		 * .
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index dd26a27..fd2c6a4 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1492,11 +1492,15 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req)
 		if (req->encrypted) {
 			conn->encrypted_tid = true;
 			/* encrypted required from now on. */
-			conn->encrypt_level = Required;
+			conn->encrypt_level = SMB_SIGNING_REQUIRED;
 		} else if (ENCRYPTION_REQUIRED(conn)) {
 			if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
-				exit_server_cleanly("encryption required "
-					"on connection");
+				DEBUG(1,("service[%s] requires encryption"
+					"%s ACCESS_DENIED. mid=%llu\n",
+					lp_servicename(talloc_tos(), SNUM(conn)),
+					smb_fn_name(type),
+					(unsigned long long)req->mid));
+				reply_nterror(req, NT_STATUS_ACCESS_DENIED);
 				return conn;
 			}
 		}
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
index d086566..11ec2a5 100644
--- a/source3/smbd/smb2_negprot.c
+++ b/source3/smbd/smb2_negprot.c
@@ -254,6 +254,14 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 		capabilities |= SMB2_CAP_DFS;
 	}
 
+	if ((protocol >= PROTOCOL_SMB2_24) &&
+	    (lp_smb_encrypt(-1) != SMB_SIGNING_OFF))
+	{
+		if (in_capabilities & SMB2_CAP_ENCRYPTION) {
+			capabilities |= SMB2_CAP_ENCRYPTION;
+		}
+	}
+
 	/*
 	 * 0x10000 (65536) is the maximum allowed message size
 	 * for SMB 2.0
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index ff4ee60..106e6ac 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -256,6 +256,7 @@ static void smb2_setup_nbt_length(struct iovec *vector, int count)
 
 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
 {
+	data_blob_clear_free(&req->first_key);
 	data_blob_clear_free(&req->last_key);
 	return 0;
 }
@@ -303,6 +304,9 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
 	int num_iov = 1;
 	size_t taken = 0;
 	uint8_t *first_hdr = buf;
+	size_t verified_buflen = 0;
+	uint8_t *tf = NULL;
+	size_t tf_len = 0;
 
 	/*
 	 * Note: index '0' is reserved for the transport protocol
@@ -324,6 +328,87 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
 		uint8_t *dyn = NULL;
 		struct iovec *iov_tmp;
 
+		if (verified_buflen > taken) {
+			len = verified_buflen - taken;
+		} else {
+			tf = NULL;
+			tf_len = 0;
+		}
+
+		if (len < 4) {
+			DEBUG(10, ("%d bytes left, expected at least %d\n",
+				   (int)len, 4));
+			goto inval;
+		}
+		if (IVAL(hdr, 0) == SMB2_TF_MAGIC) {
+			struct smbXsrv_session *s = NULL;
+			uint64_t uid;
+			struct iovec tf_iov[2];
+			NTSTATUS status;
+			size_t enc_len;
+
+			if (conn->protocol < PROTOCOL_SMB2_24) {
+				DEBUG(10, ("Got SMB2_TRANSFORM header, "
+					   "but dialect[0x%04X] is used\n",
+					   conn->smb2.server.dialect));
+				goto inval;
+			}
+
+			if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
+				DEBUG(10, ("Got SMB2_TRANSFORM header, "
+					   "but not negotiated "
+					   "client[0x%08X] server[0x%08X]\n",
+					   conn->smb2.client.capabilities,
+					   conn->smb2.server.capabilities));
+				goto inval;
+			}
+
+			if (len < SMB2_TF_HDR_SIZE) {
+				DEBUG(1, ("%d bytes left, expected at least %d\n",
+					   (int)len, SMB2_TF_HDR_SIZE));
+				goto inval;
+			}
+			tf = hdr;
+			tf_len = SMB2_TF_HDR_SIZE;
+			taken += tf_len;
+
+			hdr = first_hdr + taken;
+			enc_len = IVAL(tf, SMB2_TF_MSG_SIZE);
+			uid = BVAL(tf, SMB2_TF_SESSION_ID);
+
+			if (len < SMB2_TF_HDR_SIZE + enc_len) {
+				DEBUG(1, ("%d bytes left, expected at least %d\n",
+					   (int)len,
+					   (int)(SMB2_TF_HDR_SIZE + enc_len)));
+				goto inval;
+			}
+
+			status = smb2srv_session_lookup(conn, uid, now, &s);
+			if (s == NULL) {
+				DEBUG(1, ("invalid session[%llu] in "
+					  "SMB2_TRANSFORM header\n",
+					   (unsigned long long)uid));
+				TALLOC_FREE(iov);
+				return NT_STATUS_USER_SESSION_DELETED;
+			}
+
+			tf_iov[0].iov_base = (void *)tf;
+			tf_iov[0].iov_len = tf_len;
+			tf_iov[1].iov_base = (void *)hdr;
+			tf_iov[1].iov_len = enc_len;
+
+			status = smb2_signing_decrypt_pdu(s->global->decryption_key,
+							  conn->protocol,
+							  tf_iov, 2);
+			if (!NT_STATUS_IS_OK(status)) {
+				TALLOC_FREE(iov);
+				return status;
+			}
+
+			verified_buflen = taken + enc_len;
+			len = enc_len;
+		}
+
 		/*
 		 * We need the header plus the body length field
 		 */
@@ -382,6 +467,8 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
 		cur = &iov[num_iov];
 		num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
 
+		cur[SMBD_SMB2_TF_IOV_OFS].iov_base   = tf;
+		cur[SMBD_SMB2_TF_IOV_OFS].iov_len    = tf_len;
 		cur[SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
 		cur[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
 		cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
@@ -891,6 +978,12 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 
 		outbody = outhdr + SMB2_HDR_BODY;
 
+		/*
+		 * SMBD_SMB2_TF_IOV_OFS might be used later
+		 */
+		current[SMBD_SMB2_TF_IOV_OFS].iov_base   = NULL;
+		current[SMBD_SMB2_TF_IOV_OFS].iov_len    = 0;
+
 		current[SMBD_SMB2_HDR_IOV_OFS].iov_base  = (void *)outhdr;
 		current[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
 
@@ -949,10 +1042,12 @@ void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
 	exit_server_cleanly(reason);
 }
 
-static bool dup_smb2_vec3(TALLOC_CTX *ctx,
+static bool dup_smb2_vec4(TALLOC_CTX *ctx,
 			struct iovec *outvec,
 			const struct iovec *srcvec)
 {
+	const uint8_t *srctf;
+	size_t srctf_len;
 	const uint8_t *srchdr;
 	size_t srchdr_len;
 	const uint8_t *srcbody;
@@ -961,10 +1056,13 @@ static bool dup_smb2_vec3(TALLOC_CTX *ctx,
 	const uint8_t *srcdyn;
 	size_t srcdyn_len;
 	const uint8_t *expected_srcdyn;
+	uint8_t *dsttf;
 	uint8_t *dsthdr;
 	uint8_t *dstbody;
 	uint8_t *dstdyn;
 
+	srctf  = (const uint8_t *)srcvec[SMBD_SMB2_TF_IOV_OFS].iov_base;
+	srctf_len = srcvec[SMBD_SMB2_TF_IOV_OFS].iov_len;
 	srchdr  = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base;
 	srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len;
 	srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base;
@@ -974,10 +1072,25 @@ static bool dup_smb2_vec3(TALLOC_CTX *ctx,
 	srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len;
 	expected_srcdyn = srcbody + 8;
 
+	if ((srctf_len != SMB2_TF_HDR_SIZE) && (srctf_len != 0)) {
+		return false;
+	}
+
 	if (srchdr_len != SMB2_HDR_BODY) {
 		return false;
 	}
 
+	if (srctf_len == SMB2_TF_HDR_SIZE) {
+		dsttf = talloc_memdup(ctx, srctf, SMB2_TF_HDR_SIZE);
+		if (dsttf == NULL) {
+			return false;
+		}
+	} else {
+		dsttf = NULL;
+	}
+	outvec[SMBD_SMB2_TF_IOV_OFS].iov_base = (void *)dsttf;
+	outvec[SMBD_SMB2_TF_IOV_OFS].iov_len = srctf_len;
+
 	/* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must
 	 * be allocated with size OUTVEC_ALLOC_SIZE. */
 
@@ -1061,7 +1174,7 @@ static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *re
 
 	/* Setup the vectors identically to the ones in req. */
 	for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
-		if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
+		if (!dup_smb2_vec4(outvec, &outvec[i], &req->out.vector[i])) {
 			break;
 		}
 	}
@@ -1083,6 +1196,8 @@ static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
 static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request *req)
 {
 	struct smbXsrv_connection *conn = req->sconn->conn;
+	int first_idx = 1;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list