[PATCHES] add basic support for smb 3.0.2, 3.1.0, and 3.1.1

Michael Adam obnox at samba.org
Wed May 6 23:31:52 MDT 2015


Hi,

I have worked with metze to complete basic support of
the SMB protocol versions 3.0.2, 3.1.0 and 3.1.1 to server
and client.

3.1.0 was an interim protocol version that was available
in one of the previews of windows 10 and matching server.
This (and earlier interim versions like smb 2.2.2.) can
be removed at a later time when the smb 3.1 is finally
officially released.

The patches already have enough review/signoff, but I
wanted to present them to the list anyways.

Michael
-------------- next part --------------
From b0debc31573241957e9512bd3658cb5b8d821bea Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 11:40:04 +0200
Subject: [PATCH 01/18] libcli: add missing printable form of
 NT_STATUS_VHD_SHARED

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 libcli/util/nterr.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcli/util/nterr.c b/libcli/util/nterr.c
index dbf399b..6791b45 100644
--- a/libcli/util/nterr.c
+++ b/libcli/util/nterr.c
@@ -1852,6 +1852,7 @@ const nt_err_code_struct nt_errs[] =
 	{ "NT_STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH", NT_STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH },
 	{ "NT_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED", NT_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED },
 	{ "NT_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT", NT_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT },
+	{ "NT_STATUS_VHD_SHARED", NT_STATUS_VHD_SHARED },
 
 	DOS_CODE(ERRDOS, ERRsuccess),
 	DOS_CODE(ERRDOS, ERRbadfunc),
-- 
2.1.0


From 1108b5b571cdb9f235c00829f7c33a95e05093a9 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 11:40:45 +0200
Subject: [PATCH 02/18] libcli: add new NTSTATUS codes from SMB 3.1

NT_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP
NT_STATUS_SMB_BAD_CLUSTER_DIALECT

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 libcli/util/nterr.c    | 2 ++
 libcli/util/ntstatus.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/libcli/util/nterr.c b/libcli/util/nterr.c
index 6791b45..8f2de99 100644
--- a/libcli/util/nterr.c
+++ b/libcli/util/nterr.c
@@ -1853,6 +1853,8 @@ const nt_err_code_struct nt_errs[] =
 	{ "NT_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED", NT_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED },
 	{ "NT_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT", NT_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT },
 	{ "NT_STATUS_VHD_SHARED", NT_STATUS_VHD_SHARED },
+	{ "NT_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP", NT_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP },
+	{ "NT_STATUS_SMB_BAD_CLUSTER_DIALECT", NT_STATUS_SMB_BAD_CLUSTER_DIALECT },
 
 	DOS_CODE(ERRDOS, ERRsuccess),
 	DOS_CODE(ERRDOS, ERRbadfunc),
diff --git a/libcli/util/ntstatus.h b/libcli/util/ntstatus.h
index 325930f..572093b 100644
--- a/libcli/util/ntstatus.h
+++ b/libcli/util/ntstatus.h
@@ -1892,6 +1892,8 @@ typedef uint32_t NTSTATUS;
 #define NT_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED   NT_STATUS(0xC03A0018)
 #define NT_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT  NT_STATUS(0xC03A0019)
 #define NT_STATUS_VHD_SHARED				  NT_STATUS(0xC05CFF0A)
+#define NT_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP	  NT_STATUS(0xC05D0000)
+#define NT_STATUS_SMB_BAD_CLUSTER_DIALECT		  NT_STATUS(0xC05D0001)
 
 /* I use NT_STATUS_FOOBAR when I have no idea what error code to use -
  * this means we need a torture test */
-- 
2.1.0


From 8e50080d0bead3aa07d12302b559831356dbbc87 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 4 Mar 2015 07:02:38 +0100
Subject: [PATCH 03/18] libcli/smb: add PROTOCOL_SMB3_11 and
 SMB3_DIALECT_REVISION_311

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 docs-xml/manpages/smb.conf.5.xml                   | 7 +++++--
 docs-xml/smbdotconf/protocol/clientmaxprotocol.xml | 5 ++++-
 lib/param/param_table.c                            | 1 +
 libcli/smb/smb2_constants.h                        | 1 +
 libcli/smb/smbXcli_base.c                          | 1 +
 libcli/smb/smb_constants.h                         | 5 +++--
 6 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/docs-xml/manpages/smb.conf.5.xml b/docs-xml/manpages/smb.conf.5.xml
index e98d183..cb2f40b 100644
--- a/docs-xml/manpages/smb.conf.5.xml
+++ b/docs-xml/manpages/smb.conf.5.xml
@@ -470,8 +470,11 @@ chmod 1770 /usr/local/samba/lib/usershares
 		
 		<varlistentry>
 		<term>%R</term>
-		<listitem><para>the selected protocol level after protocol negotiation. It can be one of CORE, COREPLUS, 
-			LANMAN1, LANMAN2, NT1, SMB2_02, SMB2_10, SMB2_22, SMB2_24, SMB3_00, SMB3_02, SMB3_10 or SMB2_FF.</para></listitem>
+		<listitem><para>the selected protocol level after protocol negotiation. It can be one of
+			CORE, COREPLUS, LANMAN1, LANMAN2, NT1,
+			SMB2_02, SMB2_10, SMB2_22, SMB2_24,
+			SMB3_00, SMB3_02, SMB3_10, SMB3_11
+			or SMB2_FF.</para></listitem>
 		</varlistentry>
 
 		<varlistentry>
diff --git a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
index 1b16814..1ca9b93 100644
--- a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
@@ -64,7 +64,10 @@
 		    <para><constant>SMB3_02</constant>: Windows 8.1 SMB3 version.</para>
 		</listitem>
 		<listitem>
-		    <para><constant>SMB3_10</constant>: Windows 10 technical preview SMB3 version.</para>
+		    <para><constant>SMB3_10</constant>: early Windows 10 technical preview SMB3 version.</para>
+		</listitem>
+		<listitem>
+		    <para><constant>SMB3_11</constant>: Windows 10 technical preview SMB3 version (maybe final).</para>
 		</listitem>
 	    </itemizedlist>
 	    <para>By default SMB3 selects the SMB3_00 variant.</para>
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index eede823..9b80639 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -41,6 +41,7 @@ static const struct enum_list enum_protocol[] = {
 	{PROTOCOL_DEFAULT, "default"}, /* the caller decides what this means */
 	{PROTOCOL_SMB2_10, "SMB2"}, /* for now keep PROTOCOL_SMB2_10 */
 	{PROTOCOL_SMB3_00, "SMB3"}, /* for now keep PROTOCOL_SMB3_00 */
+	{PROTOCOL_SMB3_11, "SMB3_11"},
 	{PROTOCOL_SMB3_10, "SMB3_10"},
 	{PROTOCOL_SMB3_02, "SMB3_02"},
 	{PROTOCOL_SMB3_00, "SMB3_00"},
diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h
index baee847..1e4248d 100644
--- a/libcli/smb/smb2_constants.h
+++ b/libcli/smb/smb2_constants.h
@@ -98,6 +98,7 @@
 #define SMB3_DIALECT_REVISION_300       0x0300
 #define SMB3_DIALECT_REVISION_302       0x0302
 #define SMB3_DIALECT_REVISION_310       0x0310
+#define SMB3_DIALECT_REVISION_311       0x0311
 #define SMB2_DIALECT_REVISION_2FF       0x02FF
 
 /* SMB2 negotiate security_mode */
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 9f73566..90c1473 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -3805,6 +3805,7 @@ static const struct {
 	{PROTOCOL_SMB3_00,	SMB3_DIALECT_REVISION_300},
 	{PROTOCOL_SMB3_02,	SMB3_DIALECT_REVISION_302},
 	{PROTOCOL_SMB3_10,	SMB3_DIALECT_REVISION_310},
+	{PROTOCOL_SMB3_11,	SMB3_DIALECT_REVISION_311},
 };
 
 struct smbXcli_negprot_state {
diff --git a/libcli/smb/smb_constants.h b/libcli/smb/smb_constants.h
index 5d494f4..bfbde74 100644
--- a/libcli/smb/smb_constants.h
+++ b/libcli/smb/smb_constants.h
@@ -89,9 +89,10 @@ enum protocol_types {
 	PROTOCOL_SMB2_24,
 	PROTOCOL_SMB3_00,
 	PROTOCOL_SMB3_02,
-	PROTOCOL_SMB3_10
+	PROTOCOL_SMB3_10,
+	PROTOCOL_SMB3_11
 };
-#define PROTOCOL_LATEST PROTOCOL_SMB3_10
+#define PROTOCOL_LATEST PROTOCOL_SMB3_11
 
 enum smb_signing_setting {
 	SMB_SIGNING_DEFAULT = -1,
-- 
2.1.0


From 63b872df72e9acfb6f04e1766c025557f0ca1ea0 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 4 Mar 2015 07:03:44 +0100
Subject: [PATCH 04/18] s3:torture: handle PROTOCOL_SMB3_11

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 source3/torture/test_smb2.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source3/torture/test_smb2.c b/source3/torture/test_smb2.c
index 301c6e7..6871f4c 100644
--- a/source3/torture/test_smb2.c
+++ b/source3/torture/test_smb2.c
@@ -268,6 +268,9 @@ bool run_smb2_negprot(int dummy)
 	case PROTOCOL_SMB3_10:
 		name = "SMB3_10";
 		break;
+	case PROTOCOL_SMB3_11:
+		name = "SMB3_11";
+		break;
 	default:
 		break;
 	}
-- 
2.1.0


From ec9831319aed6b3b810fab72a0c7a125168dfa4a Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 00:16:34 +0200
Subject: [PATCH 05/18] libcli/smb: SMB 3.0.2: define
 SMB2_READFLAG_READ_UNBUFFERED

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 libcli/smb/smb2_constants.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h
index 1e4248d..aeb7cdb 100644
--- a/libcli/smb/smb2_constants.h
+++ b/libcli/smb/smb2_constants.h
@@ -257,6 +257,8 @@
 
 #define SMB2_CLOSE_FLAGS_FULL_INFORMATION (0x01)
 
+#define SMB2_READFLAG_READ_UNBUFFERED	0x01
+
 #define SMB2_WRITEFLAG_WRITE_THROUGH	0x00000001
 
 /* 2.2.31 SMB2 IOCTL Request */
-- 
2.1.0


From 7ee4606cfdfa187ebe11f8c76867a980b8ccd3f2 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 00:18:16 +0200
Subject: [PATCH 06/18] libcli/smb: SMB 3.0.2: define
 SMB2_WRITEFLAG_WRITE_UNBUFFERED

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 libcli/smb/smb2_constants.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h
index aeb7cdb..0c7be0e 100644
--- a/libcli/smb/smb2_constants.h
+++ b/libcli/smb/smb2_constants.h
@@ -260,6 +260,7 @@
 #define SMB2_READFLAG_READ_UNBUFFERED	0x01
 
 #define SMB2_WRITEFLAG_WRITE_THROUGH	0x00000001
+#define SMB2_WRITEFLAG_WRITE_UNBUFFERED	0x00000002
 
 /* 2.2.31 SMB2 IOCTL Request */
 #define SMB2_IOCTL_FLAG_IS_FSCTL		0x00000001
-- 
2.1.0


From 687d4548a599ad3175f700d7dc5f4ff91a88fc51 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 00:55:27 +0200
Subject: [PATCH 07/18] libcli/smb: SMB 3.0.2: define
 FSCTL_SVHDX_SYNC_TUNNEL_REQUEST

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 libcli/smb/smb_constants.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcli/smb/smb_constants.h b/libcli/smb/smb_constants.h
index bfbde74..842618a 100644
--- a/libcli/smb/smb_constants.h
+++ b/libcli/smb/smb_constants.h
@@ -529,6 +529,7 @@ enum csc_policy {
 #define FSCTL_SET_INTEGRITY_INFORMATION (FSCTL_FILESYSTEM | FSCTL_ACCESS_READ \
 							  | FSCTL_ACCESS_WRITE | 0x0280 | FSCTL_METHOD_BUFFERED)
 #define FSCTL_DUP_EXTENTS_TO_FILE	(FSCTL_FILESYSTEM | FSCTL_ACCESS_WRITE | 0x0344 | FSCTL_METHOD_BUFFERED)
+#define FSCTL_SVHDX_SYNC_TUNNEL_REQUEST	(FSCTL_FILESYSTEM | FSCTL_ACCESS_ANY | 0x0304 | FSCTL_METHOD_BUFFERED)
 
 #define FSCTL_NAMED_PIPE		0x00110000
 #define FSCTL_PIPE_PEEK			(FSCTL_NAMED_PIPE | FSCTL_ACCESS_READ | 0x000C | FSCTL_METHOD_BUFFERED)
-- 
2.1.0


From fffd32c153efc8982e22b055a315d4f10ff32b07 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 00:56:34 +0200
Subject: [PATCH 08/18] libcli/smb: SMB 3.0.2: define
 FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 libcli/smb/smb_constants.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcli/smb/smb_constants.h b/libcli/smb/smb_constants.h
index 842618a..589b1a63 100644
--- a/libcli/smb/smb_constants.h
+++ b/libcli/smb/smb_constants.h
@@ -530,6 +530,7 @@ enum csc_policy {
 							  | FSCTL_ACCESS_WRITE | 0x0280 | FSCTL_METHOD_BUFFERED)
 #define FSCTL_DUP_EXTENTS_TO_FILE	(FSCTL_FILESYSTEM | FSCTL_ACCESS_WRITE | 0x0344 | FSCTL_METHOD_BUFFERED)
 #define FSCTL_SVHDX_SYNC_TUNNEL_REQUEST	(FSCTL_FILESYSTEM | FSCTL_ACCESS_ANY | 0x0304 | FSCTL_METHOD_BUFFERED)
+#define FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT	(FSCTL_FILESYSTEM | FSCTL_ACCESS_ANY | 0x0300 | FSCTL_METHOD_BUFFERED)
 
 #define FSCTL_NAMED_PIPE		0x00110000
 #define FSCTL_PIPE_PEEK			(FSCTL_NAMED_PIPE | FSCTL_ACCESS_READ | 0x000C | FSCTL_METHOD_BUFFERED)
-- 
2.1.0


From e540ad00cec7313305b9cacccbc51ca2dd3830b5 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 00:28:19 +0200
Subject: [PATCH 09/18] libcli/smb: SMB 3.0.2: define SVHDX_OPEN_DEVICE_CONTEXT

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 libcli/smb/smb2_constants.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h
index 0c7be0e..cd80346 100644
--- a/libcli/smb/smb2_constants.h
+++ b/libcli/smb/smb2_constants.h
@@ -225,6 +225,7 @@
 #define SMB2_CREATE_TAG_DH2C "DH2C"
 #define SMB2_CREATE_TAG_AAPL "AAPL"
 #define SMB2_CREATE_TAG_APP_INSTANCE_ID "\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74"
+#define SVHDX_OPEN_DEVICE_CONTEXT "\x9C\xCB\xCF\x9E\x04\xC1\xE6\x43\x98\x0E\x15\x8D\xA1\xF6\xEC\x83"
 
 /* SMB2 notify flags */
 #define SMB2_WATCH_TREE 0x0001
-- 
2.1.0


From 3f27dac1a336602dfc8cca8277f25bed8ca89645 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 00:38:55 +0200
Subject: [PATCH 10/18] s3:smb2_create: treat the SVHDX_OPEN_DEVICE_CONTEXT in
 smb2_create (not supported)

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>

Signed-off-by: Michael Adam <obnox at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/smb2_create.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index c9cc9bd..880ceee 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -675,6 +675,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 		struct smb2_lease lease;
 		struct smb2_lease *lease_ptr = NULL;
 		ssize_t lease_len = -1;
+		struct smb2_create_blob *svhdx = NULL;
 
 		exta = smb2_create_blob_find(&in_context_blobs,
 					     SMB2_CREATE_TAG_EXTA);
@@ -688,6 +689,13 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 					     SMB2_CREATE_TAG_TWRP);
 		qfid = smb2_create_blob_find(&in_context_blobs,
 					     SMB2_CREATE_TAG_QFID);
+		if (smb2req->xconn->protocol >= PROTOCOL_SMB3_02) {
+			/*
+			 * This was introduced with SMB3_02
+			 */
+			svhdx = smb2_create_blob_find(&in_context_blobs,
+						      SVHDX_OPEN_DEVICE_CONTEXT);
+		}
 
 		fname = talloc_strdup(state, in_name);
 		if (tevent_req_nomem(fname, req)) {
@@ -902,6 +910,13 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 			}
 		}
 
+		if (svhdx != NULL) {
+			/* SharedVHD is not yet supported */
+			tevent_req_nterror(
+				req, NT_STATUS_INVALID_DEVICE_REQUEST);
+			return tevent_req_post(req, ev);
+		}
+
 		/* these are ignored for SMB2 */
 		in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
 		in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
-- 
2.1.0


From 3bd34aff6742757d6fe2089e1ded5f0afc6dd0f5 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 6 May 2015 10:42:29 +0200
Subject: [PATCH 11/18] s3:smb2_write: add simplified support for
 SMB2_WRITEFLAG_WRITE_UNBUFFERED

TODO: we should add alignment checks.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 source3/smbd/smb2_write.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c
index 508c0b3..da583c9 100644
--- a/source3/smbd/smb2_write.c
+++ b/source3/smbd/smb2_write.c
@@ -275,6 +275,11 @@ static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 	state->smb2req = smb2req;
+	if (smb2req->xconn->protocol >= PROTOCOL_SMB3_02) {
+		if (in_flags & SMB2_WRITEFLAG_WRITE_UNBUFFERED) {
+			state->write_through = true;
+		}
+	}
 	if (in_flags & SMB2_WRITEFLAG_WRITE_THROUGH) {
 		state->write_through = true;
 	}
-- 
2.1.0


From 6459db80b9603c6802b41a941cb94db75da2ca6f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Wed, 6 May 2015 10:52:57 +0200
Subject: [PATCH 12/18] s3:smb2_read: pass in_flags to smbd_smb2_read_send()

For now we still ignore the flags.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 source3/smbd/smb2_read.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c
index 4e974a2..03cd54b 100644
--- a/source3/smbd/smb2_read.c
+++ b/source3/smbd/smb2_read.c
@@ -32,6 +32,7 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
 					      struct tevent_context *ev,
 					      struct smbd_smb2_request *smb2req,
 					      struct files_struct *in_fsp,
+					      uint8_t in_flags,
 					      uint32_t in_length,
 					      uint64_t in_offset,
 					      uint32_t in_minimum,
@@ -47,6 +48,7 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
 	struct smbXsrv_connection *xconn = req->xconn;
 	NTSTATUS status;
 	const uint8_t *inbody;
+	uint8_t in_flags;
 	uint32_t in_length;
 	uint64_t in_offset;
 	uint64_t in_file_id_persistent;
@@ -62,6 +64,11 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
 	}
 	inbody = SMBD_SMB2_IN_BODY_PTR(req);
 
+	if (xconn->protocol >= PROTOCOL_SMB3_02) {
+		in_flags		= CVAL(inbody, 0x03);
+	} else {
+		in_flags		= 0;
+	}
 	in_length		= IVAL(inbody, 0x04);
 	in_offset		= BVAL(inbody, 0x08);
 	in_file_id_persistent	= BVAL(inbody, 0x10);
@@ -89,6 +96,7 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
 
 	subreq = smbd_smb2_read_send(req, req->sconn->ev_ctx,
 				     req, in_fsp,
+				     in_flags,
 				     in_length,
 				     in_offset,
 				     in_minimum_count,
@@ -165,6 +173,7 @@ struct smbd_smb2_read_state {
 	struct smbd_smb2_request *smb2req;
 	struct smb_request *smbreq;
 	files_struct *fsp;
+	uint8_t in_flags;
 	uint32_t in_length;
 	uint64_t in_offset;
 	uint32_t in_minimum;
@@ -422,6 +431,7 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
 					      struct tevent_context *ev,
 					      struct smbd_smb2_request *smb2req,
 					      struct files_struct *fsp,
+					      uint8_t in_flags,
 					      uint32_t in_length,
 					      uint64_t in_offset,
 					      uint32_t in_minimum,
@@ -442,6 +452,7 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 	state->smb2req = smb2req;
+	state->in_flags = in_flags;
 	state->in_length = in_length;
 	state->in_offset = in_offset;
 	state->in_minimum = in_minimum;
-- 
2.1.0


From 20cddbb37a83e9ef56dfc974374921962ded8c1f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 13 Oct 2014 11:01:59 +0200
Subject: [PATCH 13/18] s3:smb2_negprot: add support for negotiating SMB 3.0.2

Pair-Programmed-With: Michael Adam <obnox at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
---
 docs-xml/smbdotconf/protocol/servermaxprotocol.xml | 3 +++
 source3/smbd/smb2_negprot.c                        | 1 +
 2 files changed, 4 insertions(+)

diff --git a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
index 41532a9..dcc78f2 100644
--- a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
@@ -49,6 +49,9 @@
 		<listitem>
 		    <para><constant>SMB3_00</constant>: Windows 8 SMB3 version. (mostly the same as SMB2_24)</para>
 		</listitem>
+		<listitem>
+		    <para><constant>SMB3_02</constant>: Windows 8.1 SMB3 version.</para>
+		</listitem>
 	    </itemizedlist>
 	    <para>By default SMB3 selects the SMB3_00 variant.</para>
 	</listitem>
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
index 9987967..ae2f3f7 100644
--- a/source3/smbd/smb2_negprot.c
+++ b/source3/smbd/smb2_negprot.c
@@ -91,6 +91,7 @@ enum protocol_types smbd_smb2_protocol_dialect_match(const uint8_t *indyn,
 		enum protocol_types proto;
 		uint16_t dialect;
 	} pd[] = {
+		{ PROTOCOL_SMB3_02, SMB3_DIALECT_REVISION_302 },
 		{ PROTOCOL_SMB3_00, SMB3_DIALECT_REVISION_300 },
 		{ PROTOCOL_SMB2_24, SMB2_DIALECT_REVISION_224 },
 		{ PROTOCOL_SMB2_22, SMB2_DIALECT_REVISION_222 },
-- 
2.1.0


From 9b4e96e1a0469ec1e12b1473ca99828bddd900e9 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 6 May 2015 11:30:11 +0200
Subject: [PATCH 14/18] smbd: offer SMB 3.0.2 by default.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 docs-xml/smbdotconf/protocol/clientmaxprotocol.xml | 2 +-
 docs-xml/smbdotconf/protocol/servermaxprotocol.xml | 2 +-
 lib/param/param_table.c                            | 2 +-
 source3/param/loadparm.c                           | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
index 1ca9b93..b6dae59 100644
--- a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
@@ -70,7 +70,7 @@
 		    <para><constant>SMB3_11</constant>: Windows 10 technical preview SMB3 version (maybe final).</para>
 		</listitem>
 	    </itemizedlist>
-	    <para>By default SMB3 selects the SMB3_00 variant.</para>
+	    <para>By default SMB3 selects the SMB3_02 variant.</para>
 	</listitem>
     </itemizedlist>
 
diff --git a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
index dcc78f2..66bc3f8 100644
--- a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
@@ -53,7 +53,7 @@
 		    <para><constant>SMB3_02</constant>: Windows 8.1 SMB3 version.</para>
 		</listitem>
 	    </itemizedlist>
-	    <para>By default SMB3 selects the SMB3_00 variant.</para>
+	    <para>By default SMB3 selects the SMB3_02 variant.</para>
 	</listitem>
     </itemizedlist>
 
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index 9b80639..78ea80b 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -40,7 +40,7 @@
 static const struct enum_list enum_protocol[] = {
 	{PROTOCOL_DEFAULT, "default"}, /* the caller decides what this means */
 	{PROTOCOL_SMB2_10, "SMB2"}, /* for now keep PROTOCOL_SMB2_10 */
-	{PROTOCOL_SMB3_00, "SMB3"}, /* for now keep PROTOCOL_SMB3_00 */
+	{PROTOCOL_SMB3_02, "SMB3"}, /* for now keep PROTOCOL_SMB3_02 */
 	{PROTOCOL_SMB3_11, "SMB3_11"},
 	{PROTOCOL_SMB3_10, "SMB3_10"},
 	{PROTOCOL_SMB3_02, "SMB3_02"},
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index a81a20a..d5b6b81 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -643,7 +643,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.large_readwrite = true;
 	Globals.max_log_size = 5000;
 	Globals.max_open_files = max_open_files();
-	Globals.server_max_protocol = PROTOCOL_SMB3_00;
+	Globals.server_max_protocol = PROTOCOL_SMB3_02;
 	Globals.server_min_protocol = PROTOCOL_LANMAN1;
 	Globals._client_max_protocol = PROTOCOL_DEFAULT;
 	Globals.client_min_protocol = PROTOCOL_CORE;
-- 
2.1.0


From 1f3bca8dd28633b3476546ab46592511149c13ff Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 8 Oct 2014 19:25:15 +0200
Subject: [PATCH 15/18] s3:smb2_negprot.c: add support SMB 3.1 negotiate
 contexts

Used for:
- preauthentication validation
- negotiation of ciphers for sigingn and encryprtion

Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/globals.h      |   7 ++
 source3/smbd/smb2_negprot.c | 243 +++++++++++++++++++++++++++++++++++++++++++-
 source3/smbd/smb2_server.c  |  28 +++++
 3 files changed, 274 insertions(+), 4 deletions(-)

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 22cf5d6..3ddafaf 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -344,6 +344,10 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
 
 struct smbXsrv_client;
 
+struct smbXsrv_preauth {
+	uint8_t sha512_value[64];
+};
+
 struct smbXsrv_connection {
 	struct smbXsrv_connection *prev, *next;
 
@@ -516,6 +520,8 @@ struct smbXsrv_connection {
 			uint16_t cipher;
 		} server;
 
+		struct smbXsrv_preauth preauth;
+
 		struct smbd_smb2_request *requests;
 	} smb2;
 };
@@ -662,6 +668,7 @@ struct smbd_smb2_request {
 	 * request/response of a compound chain
 	 */
 	DATA_BLOB last_key;
+	struct smbXsrv_preauth *preauth;
 
 	struct timeval request_time;
 
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
index ae2f3f7..199dc14 100644
--- a/source3/smbd/smb2_negprot.c
+++ b/source3/smbd/smb2_negprot.c
@@ -22,6 +22,7 @@
 #include "smbd/smbd.h"
 #include "smbd/globals.h"
 #include "../libcli/smb/smb_common.h"
+#include "../libcli/smb/smb2_negotiate_context.h"
 #include "../lib/tsocket/tsocket.h"
 #include "../librpc/ndr/libndr.h"
 
@@ -140,6 +141,13 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	uint32_t in_capabilities;
 	DATA_BLOB in_guid_blob;
 	struct GUID in_guid;
+	struct smb2_negotiate_contexts in_c = { .num_contexts = 0, };
+	struct smb2_negotiate_context *in_preauth = NULL;
+	struct smb2_negotiate_context *in_cipher = NULL;
+	struct smb2_negotiate_contexts out_c = { .num_contexts = 0, };
+	DATA_BLOB out_negotiate_context_blob = data_blob_null;
+	uint32_t out_negotiate_context_offset = 0;
+	uint16_t out_negotiate_context_count = 0;
 	uint16_t dialect = 0;
 	uint32_t capabilities;
 	DATA_BLOB out_guid_blob;
@@ -201,6 +209,53 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_NOT_SUPPORTED);
 	}
 
+	if (protocol >= PROTOCOL_SMB3_10) {
+		uint32_t in_negotiate_context_offset = 0;
+		uint16_t in_negotiate_context_count = 0;
+		DATA_BLOB in_negotiate_context_blob = data_blob_null;
+		size_t ofs;
+
+		in_negotiate_context_offset = IVAL(inbody, 0x1C);
+		in_negotiate_context_count = SVAL(inbody, 0x20);
+
+		ofs = SMB2_HDR_BODY;
+		ofs += SMBD_SMB2_IN_BODY_LEN(req);
+		ofs += expected_dyn_size;
+		if ((ofs % 8) != 0) {
+			ofs += 8 - (ofs % 8);
+		}
+
+		if (in_negotiate_context_offset != ofs) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		ofs -= SMB2_HDR_BODY;
+		ofs -= SMBD_SMB2_IN_BODY_LEN(req);
+
+		if (SMBD_SMB2_IN_DYN_LEN(req) < ofs) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		in_negotiate_context_blob = data_blob_const(indyn,
+						SMBD_SMB2_IN_DYN_LEN(req));
+
+		in_negotiate_context_blob.data += ofs;
+		in_negotiate_context_blob.length -= ofs;
+
+		status = smb2_negotiate_context_parse(req,
+					in_negotiate_context_blob, &in_c);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
+
+		if (in_negotiate_context_count != in_c.num_contexts) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+	}
+
 	if (get_remote_arch() != RA_SAMBA) {
 		set_remote_arch(RA_VISTA);
 	}
@@ -211,6 +266,14 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	reload_services(req->sconn, conn_snum_used, true);
 	DEBUG(3,("Selected protocol %s\n", remote_proto));
 
+	in_preauth = smb2_negotiate_context_find(&in_c,
+					SMB2_PREAUTH_INTEGRITY_CAPABILITIES);
+	if (protocol >= PROTOCOL_SMB3_10 && in_preauth == NULL) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+	in_cipher = smb2_negotiate_context_find(&in_c,
+					SMB2_ENCRYPTION_CAPABILITIES);
+
 	/* negprot_spnego() returns a the server guid in the first 16 bytes */
 	negprot_spnego_blob = negprot_spnego(req, xconn);
 	if (negprot_spnego_blob.data == NULL) {
@@ -285,6 +348,131 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	max_read = MIN(max_limit, lp_smb2_max_read());
 	max_write = MIN(max_limit, lp_smb2_max_write());
 
+	if (in_preauth != NULL) {
+		size_t needed = 4;
+		uint16_t hash_count;
+		uint16_t salt_length;
+		uint16_t selected_preauth = 0;
+		const uint8_t *p;
+		uint8_t buf[38];
+		DATA_BLOB b;
+		size_t i;
+
+		if (in_preauth->data.length < needed) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		hash_count = SVAL(in_preauth->data.data, 0);
+		salt_length = SVAL(in_preauth->data.data, 2);
+
+		if (hash_count == 0) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		p = in_preauth->data.data + needed;
+		needed += hash_count * 2;
+		needed += salt_length;
+
+		if (in_preauth->data.length < needed) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		for (i=0; i < hash_count; i++) {
+			uint16_t v;
+
+			v = SVAL(p, 0);
+			p += 2;
+
+			if (v == SMB2_PREAUTH_INTEGRITY_SHA512) {
+				selected_preauth = v;
+				break;
+			}
+		}
+
+		if (selected_preauth == 0) {
+			return smbd_smb2_request_error(req,
+				NT_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP);
+		}
+
+		SSVAL(buf, 0,  1); /* HashAlgorithmCount */
+		SSVAL(buf, 2, 32); /* SaltLength */
+		SSVAL(buf, 4, selected_preauth);
+		generate_random_buffer(buf + 6, 32);
+
+		b = data_blob_const(buf, sizeof(buf));
+		status = smb2_negotiate_context_add(req, &out_c,
+					SMB2_PREAUTH_INTEGRITY_CAPABILITIES, b);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
+
+		req->preauth = &req->xconn->smb2.preauth;
+	}
+
+	if (!(capabilities & SMB2_CAP_ENCRYPTION)) {
+		in_cipher = NULL;
+	}
+
+	if (in_cipher != NULL) {
+		size_t needed = 2;
+		uint16_t cipher_count;
+		const uint8_t *p;
+		uint8_t buf[4];
+		DATA_BLOB b;
+		size_t i;
+
+		capabilities &= ~SMB2_CAP_ENCRYPTION;
+
+		if (in_cipher->data.length < needed) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		cipher_count = SVAL(in_cipher->data.data, 0);
+
+		if (cipher_count == 0) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		p = in_cipher->data.data + needed;
+		needed += cipher_count * 2;
+
+		if (in_cipher->data.length < needed) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		for (i=0; i < cipher_count; i++) {
+			uint16_t v;
+
+			v = SVAL(p, 0);
+			p += 2;
+
+			if (v == SMB2_ENCRYPTION_AES128_GCM) {
+				xconn->smb2.server.cipher = v;
+				break;
+			}
+			if (v == SMB2_ENCRYPTION_AES128_CCM) {
+				xconn->smb2.server.cipher = v;
+				break;
+			}
+		}
+
+		SSVAL(buf, 0, 1); /* ChiperCount */
+		SSVAL(buf, 2, xconn->smb2.server.cipher);
+
+		b = data_blob_const(buf, sizeof(buf));
+		status = smb2_negotiate_context_add(req, &out_c,
+					SMB2_ENCRYPTION_CAPABILITIES, b);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
+	}
+
 	if (capabilities & SMB2_CAP_ENCRYPTION) {
 		xconn->smb2.server.cipher = SMB2_ENCRYPTION_AES128_CCM;
 	}
@@ -300,6 +488,53 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	security_buffer = data_blob_const(NULL, 0);
 #endif
 
+	if (out_c.num_contexts != 0) {
+		status = smb2_negotiate_context_push(req,
+						&out_negotiate_context_blob,
+						out_c);
+		if (!NT_STATUS_IS_OK(status)) {
+			return smbd_smb2_request_error(req, status);
+		}
+	}
+
+	if (out_negotiate_context_blob.length != 0) {
+		static const uint8_t zeros[8];
+		size_t pad = 0;
+		size_t ofs;
+		bool ok;
+
+		outdyn = data_blob_dup_talloc(req, security_buffer);
+		if (outdyn.length != security_buffer.length) {
+			return smbd_smb2_request_error(req,
+						NT_STATUS_NO_MEMORY);
+		}
+
+		ofs = security_offset + security_buffer.length;
+		if ((ofs % 8) != 0) {
+			pad = 8 - (ofs % 8);
+		}
+		ofs += pad;
+
+		ok = data_blob_append(req, &outdyn, zeros, pad);
+		if (!ok) {
+			return smbd_smb2_request_error(req,
+						NT_STATUS_NO_MEMORY);
+		}
+
+		ok = data_blob_append(req, &outdyn,
+				      out_negotiate_context_blob.data,
+				      out_negotiate_context_blob.length);
+		if (!ok) {
+			return smbd_smb2_request_error(req,
+						NT_STATUS_NO_MEMORY);
+		}
+
+		out_negotiate_context_offset = ofs;
+		out_negotiate_context_count = out_c.num_contexts;
+	} else {
+		outdyn = security_buffer;
+	}
+
 	out_guid_blob = data_blob_const(negprot_spnego_blob.data, 16);
 	status = GUID_from_ndr_blob(&out_guid_blob, &out_guid);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -315,7 +550,8 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	SSVAL(outbody.data, 0x02,
 	      security_mode);			/* security mode */
 	SSVAL(outbody.data, 0x04, dialect);	/* dialect revision */
-	SSVAL(outbody.data, 0x06, 0);		/* reserved */
+	SSVAL(outbody.data, 0x06,
+	      out_negotiate_context_count);	/* reserved/NegotiateContextCount */
 	memcpy(outbody.data + 0x08,
 	       out_guid_blob.data, 16);	/* server guid */
 	SIVAL(outbody.data, 0x18,
@@ -329,9 +565,8 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
 	      security_offset);			/* security buffer offset */
 	SSVAL(outbody.data, 0x3A,
 	      security_buffer.length);		/* security buffer length */
-	SIVAL(outbody.data, 0x3C, 0);		/* reserved */
-
-	outdyn = security_buffer;
+	SIVAL(outbody.data, 0x3C,
+	      out_negotiate_context_offset);	/* reserved/NegotiateContextOffset */
 
 	req->sconn->using_smb2 = true;
 
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 42a809b..d1ada92 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -30,6 +30,7 @@
 #include "../librpc/gen_ndr/krb5pac.h"
 #include "lib/util/iov_buf.h"
 #include "auth.h"
+#include "lib/crypto/sha512.h"
 
 static void smbd_smb2_connection_handler(struct tevent_context *ev,
 					 struct tevent_fd *fde,
@@ -2515,6 +2516,33 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
 		data_blob_clear_free(&req->first_key);
 	}
 
+	if (req->preauth != NULL) {
+		struct hc_sha512state sctx;
+		int i;
+
+		samba_SHA512_Init(&sctx);
+		samba_SHA512_Update(&sctx, req->preauth->sha512_value,
+				    sizeof(req->preauth->sha512_value));
+		for (i = 1; i < req->in.vector_count; i++) {
+			samba_SHA512_Update(&sctx,
+					    req->in.vector[i].iov_base,
+					    req->in.vector[i].iov_len);
+		}
+		samba_SHA512_Final(req->preauth->sha512_value, &sctx);
+
+		samba_SHA512_Init(&sctx);
+		samba_SHA512_Update(&sctx, req->preauth->sha512_value,
+				    sizeof(req->preauth->sha512_value));
+		for (i = 1; i < req->out.vector_count; i++) {
+			samba_SHA512_Update(&sctx,
+					    req->out.vector[i].iov_base,
+					    req->out.vector[i].iov_len);
+		}
+		samba_SHA512_Final(req->preauth->sha512_value, &sctx);
+
+		req->preauth = NULL;
+	}
+
 	/* I am a sick, sick man... :-). Sendfile hack ... JRA. */
 	if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
 	    outdyn->iov_base == NULL && outdyn->iov_len != 0) {
-- 
2.1.0


From 572ddda850c2ae5b3ea686c24f14a1ec43851454 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 10 Oct 2014 14:04:25 +0200
Subject: [PATCH 16/18] s3:smb2_sesssetup.c: For SMB >= 3.1, derive crypto keys
 from preauth

This protects the full connection setup including
a posteriori verification of the negotiate messages,
by signing the final session setup response with a signing key
derived from the preauth hash and the authentication session key.

Pair-Programmed-With: Michael Adam <obnox at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/librpc/idl/smbXsrv.idl |  1 +
 source3/smbd/smb2_sesssetup.c  | 98 +++++++++++++++++++++++++++++++++++-------
 source3/smbd/smbXsrv_session.c | 11 +++++
 3 files changed, 94 insertions(+), 16 deletions(-)

diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index ec6d0ea..b3a24a5 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -190,6 +190,7 @@ interface smbXsrv
 		[ignore] gensec_security		*gensec;
 		[ignore] user_struct			*compat;
 		[ignore] smbXsrv_tcon_table		*tcon_table;
+		[ignore] smbXsrv_preauth		*preauth;
 	} smbXsrv_session;
 
 	typedef union {
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index c56e480..28707ff 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -28,6 +28,7 @@
 #include "../lib/tsocket/tsocket.h"
 #include "../libcli/security/security.h"
 #include "../lib/util/tevent_ntstatus.h"
+#include "lib/crypto/sha512.h"
 
 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
 					struct tevent_context *ev,
@@ -184,6 +185,74 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 	uint8_t session_key[16];
 	struct smbXsrv_session *x = session;
 	struct smbXsrv_connection *xconn = smb2req->xconn;
+	struct _derivation {
+		DATA_BLOB label;
+		DATA_BLOB context;
+	};
+	struct {
+		struct _derivation signing;
+		struct _derivation encryption;
+		struct _derivation decryption;
+		struct _derivation application;
+	} derivation = { };
+
+	if (xconn->protocol >= PROTOCOL_SMB3_10) {
+		struct smbXsrv_preauth *preauth;
+		struct _derivation *d;
+		DATA_BLOB p;
+		struct hc_sha512state sctx;
+		size_t i;
+
+		preauth = talloc_move(smb2req, &session->preauth);
+
+		samba_SHA512_Init(&sctx);
+		samba_SHA512_Update(&sctx, preauth->sha512_value,
+				    sizeof(preauth->sha512_value));
+		for (i = 1; i < smb2req->in.vector_count; i++) {
+			samba_SHA512_Update(&sctx,
+					    smb2req->in.vector[i].iov_base,
+					    smb2req->in.vector[i].iov_len);
+		}
+		samba_SHA512_Final(preauth->sha512_value, &sctx);
+
+		p = data_blob_const(preauth->sha512_value,
+				    sizeof(preauth->sha512_value));
+
+		d = &derivation.signing;
+		d->label = data_blob_string_const_null("SMBSigningKey");
+		d->context = p;
+
+		d = &derivation.decryption;
+		d->label = data_blob_string_const_null("SMBC2SCipherKey");
+		d->context = p;
+
+		d = &derivation.encryption;
+		d->label = data_blob_string_const_null("SMBS2CCipherKey");
+		d->context = p;
+
+		d = &derivation.application;
+		d->label = data_blob_string_const_null("SMBAppKey");
+		d->context = p;
+
+	} else if (xconn->protocol >= PROTOCOL_SMB2_24) {
+		struct _derivation *d;
+
+		d = &derivation.signing;
+		d->label = data_blob_string_const_null("SMB2AESCMAC");
+		d->context = data_blob_string_const_null("SmbSign");
+
+		d = &derivation.decryption;
+		d->label = data_blob_string_const_null("SMB2AESCCM");
+		d->context = data_blob_string_const_null("ServerIn ");
+
+		d = &derivation.encryption;
+		d->label = data_blob_string_const_null("SMB2AESCCM");
+		d->context = data_blob_string_const_null("ServerOut");
+
+		d = &derivation.application;
+		d->label = data_blob_string_const_null("SMB2APP");
+		d->context = data_blob_string_const_null("SmbRpc");
+	}
 
 	if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
 	    lp_server_signing() == SMB_SIGNING_REQUIRED) {
@@ -239,18 +308,16 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 	}
 
 	if (xconn->protocol >= PROTOCOL_SMB2_24) {
-		const DATA_BLOB label = data_blob_string_const_null("SMB2AESCMAC");
-		const DATA_BLOB context = data_blob_string_const_null("SmbSign");
+		struct _derivation *d = &derivation.signing;
 
 		smb2_key_derivation(session_key, sizeof(session_key),
-				    label.data, label.length,
-				    context.data, context.length,
+				    d->label.data, d->label.length,
+				    d->context.data, d->context.length,
 				    x->global->signing_key.data);
 	}
 
 	if (xconn->protocol >= PROTOCOL_SMB2_24) {
-		const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM");
-		const DATA_BLOB context = data_blob_string_const_null("ServerIn ");
+		struct _derivation *d = &derivation.decryption;
 
 		x->global->decryption_key = data_blob_talloc(x->global,
 							     session_key,
@@ -261,14 +328,13 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 		}
 
 		smb2_key_derivation(session_key, sizeof(session_key),
-				    label.data, label.length,
-				    context.data, context.length,
+				    d->label.data, d->label.length,
+				    d->context.data, d->context.length,
 				    x->global->decryption_key.data);
 	}
 
 	if (xconn->protocol >= PROTOCOL_SMB2_24) {
-		const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM");
-		const DATA_BLOB context = data_blob_string_const_null("ServerOut");
+		struct _derivation *d = &derivation.encryption;
 
 		x->global->encryption_key = data_blob_talloc(x->global,
 							     session_key,
@@ -279,8 +345,8 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 		}
 
 		smb2_key_derivation(session_key, sizeof(session_key),
-				    label.data, label.length,
-				    context.data, context.length,
+				    d->label.data, d->label.length,
+				    d->context.data, d->context.length,
 				    x->global->encryption_key.data);
 
 		generate_random_buffer((uint8_t *)&x->nonce_high, sizeof(x->nonce_high));
@@ -295,12 +361,11 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
 	}
 
 	if (xconn->protocol >= PROTOCOL_SMB2_24) {
-		const DATA_BLOB label = data_blob_string_const_null("SMB2APP");
-		const DATA_BLOB context = data_blob_string_const_null("SmbRpc");
+		struct _derivation *d = &derivation.application;
 
 		smb2_key_derivation(session_key, sizeof(session_key),
-				    label.data, label.length,
-				    context.data, context.length,
+				    d->label.data, d->label.length,
+				    d->context.data, d->context.length,
 				    x->global->application_key.data);
 	}
 	ZERO_STRUCT(session_key);
@@ -579,6 +644,7 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
 
 	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 		state->out_session_id = state->session->global->session_wire_id;
+		state->smb2req->preauth = state->session->preauth;
 		tevent_req_nterror(req, status);
 		return;
 	}
diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
index 07375d8..3201670 100644
--- a/source3/smbd/smbXsrv_session.c
+++ b/source3/smbd/smbXsrv_session.c
@@ -1118,6 +1118,7 @@ static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session
 			 */
 			preq->do_signing = false;
 			preq->do_encryption = false;
+			preq->preauth = NULL;
 		}
 	}
 
@@ -1167,6 +1168,15 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
 	session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
 	session->client = conn->client;
 
+	if (conn->protocol >= PROTOCOL_SMB3_10) {
+		session->preauth = talloc(session, struct smbXsrv_preauth);
+		if (session->preauth == NULL) {
+			TALLOC_FREE(session);
+			return NT_STATUS_NO_MEMORY;
+		}
+		*session->preauth = conn->smb2.preauth;
+	}
+
 	status = smbXsrv_session_global_allocate(table->global.db_ctx,
 						 session,
 						 &global);
@@ -1420,6 +1430,7 @@ struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
 				 */
 				preq->do_signing = false;
 				preq->do_encryption = false;
+				preq->preauth = NULL;
 
 				if (preq->subreq != NULL) {
 					tevent_req_cancel(preq->subreq);
-- 
2.1.0


From f78de02195d48fc74ff531a823f29e68c6ee8a0e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 13 Oct 2014 11:01:59 +0200
Subject: [PATCH 17/18] s3:smb2_negprot: add support for negotiating SMB 3.1.0
 and SMB 3.1.1

Note: SMB 3.1.0 was used in a early preview versions of Windows 10.
Was later superseded by 3.1.1.

Pair-Programmed-With: Michael Adam <obnox at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
---
 docs-xml/smbdotconf/protocol/servermaxprotocol.xml | 6 ++++++
 source3/smbd/smb2_negprot.c                        | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
index 66bc3f8..33a49cc 100644
--- a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
@@ -52,6 +52,12 @@
 		<listitem>
 		    <para><constant>SMB3_02</constant>: Windows 8.1 SMB3 version.</para>
 		</listitem>
+		<listitem>
+		    <para><constant>SMB3_10</constant>: early Windows 10 technical preview SMB3 version.</para>
+		</listitem>
+		<listitem>
+		    <para><constant>SMB3_11</constant>: Windows 10 technical preview SMB3 version (maybe final).</para>
+		</listitem>
 	    </itemizedlist>
 	    <para>By default SMB3 selects the SMB3_02 variant.</para>
 	</listitem>
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
index 199dc14..63bac9e 100644
--- a/source3/smbd/smb2_negprot.c
+++ b/source3/smbd/smb2_negprot.c
@@ -92,6 +92,8 @@ enum protocol_types smbd_smb2_protocol_dialect_match(const uint8_t *indyn,
 		enum protocol_types proto;
 		uint16_t dialect;
 	} pd[] = {
+		{ PROTOCOL_SMB3_11, SMB3_DIALECT_REVISION_311 },
+		{ PROTOCOL_SMB3_10, SMB3_DIALECT_REVISION_310 },
 		{ PROTOCOL_SMB3_02, SMB3_DIALECT_REVISION_302 },
 		{ PROTOCOL_SMB3_00, SMB3_DIALECT_REVISION_300 },
 		{ PROTOCOL_SMB2_24, SMB2_DIALECT_REVISION_224 },
-- 
2.1.0


From 43a5da6bdd48c2f5b871eeac0b8e3e9b5730c00e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 10 Oct 2014 15:24:55 +0200
Subject: [PATCH 18/18] smbd: Offer SMB 3.1.1 by default.

Pair-Programmed-With: Michael Adam <obnox at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
---
 docs-xml/smbdotconf/protocol/clientmaxprotocol.xml | 2 +-
 docs-xml/smbdotconf/protocol/servermaxprotocol.xml | 2 +-
 lib/param/param_table.c                            | 2 +-
 source3/param/loadparm.c                           | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
index b6dae59..e68226f 100644
--- a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml
@@ -70,7 +70,7 @@
 		    <para><constant>SMB3_11</constant>: Windows 10 technical preview SMB3 version (maybe final).</para>
 		</listitem>
 	    </itemizedlist>
-	    <para>By default SMB3 selects the SMB3_02 variant.</para>
+	    <para>By default SMB3 selects the SMB3_11 variant.</para>
 	</listitem>
     </itemizedlist>
 
diff --git a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
index 33a49cc..7321d22 100644
--- a/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
+++ b/docs-xml/smbdotconf/protocol/servermaxprotocol.xml
@@ -59,7 +59,7 @@
 		    <para><constant>SMB3_11</constant>: Windows 10 technical preview SMB3 version (maybe final).</para>
 		</listitem>
 	    </itemizedlist>
-	    <para>By default SMB3 selects the SMB3_02 variant.</para>
+	    <para>By default SMB3 selects the SMB3_11 variant.</para>
 	</listitem>
     </itemizedlist>
 
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index 78ea80b..287839f 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -40,7 +40,7 @@
 static const struct enum_list enum_protocol[] = {
 	{PROTOCOL_DEFAULT, "default"}, /* the caller decides what this means */
 	{PROTOCOL_SMB2_10, "SMB2"}, /* for now keep PROTOCOL_SMB2_10 */
-	{PROTOCOL_SMB3_02, "SMB3"}, /* for now keep PROTOCOL_SMB3_02 */
+	{PROTOCOL_SMB3_11, "SMB3"}, /* for now keep PROTOCOL_SMB3_11 */
 	{PROTOCOL_SMB3_11, "SMB3_11"},
 	{PROTOCOL_SMB3_10, "SMB3_10"},
 	{PROTOCOL_SMB3_02, "SMB3_02"},
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index d5b6b81..6f8e145 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -643,7 +643,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.large_readwrite = true;
 	Globals.max_log_size = 5000;
 	Globals.max_open_files = max_open_files();
-	Globals.server_max_protocol = PROTOCOL_SMB3_02;
+	Globals.server_max_protocol = PROTOCOL_SMB3_11;
 	Globals.server_min_protocol = PROTOCOL_LANMAN1;
 	Globals._client_max_protocol = PROTOCOL_DEFAULT;
 	Globals.client_min_protocol = PROTOCOL_CORE;
-- 
2.1.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20150507/1ba97474/attachment.pgp>


More information about the samba-technical mailing list