[PATCH] smbd: Fix snapshot query on shares with DFS enabled

Uri Simchoni uri at samba.org
Wed Aug 17 18:10:59 UTC 2016


On 08/17/2016 08:32 PM, Jeremy Allison wrote:
> On Wed, Aug 17, 2016 at 10:18:21AM -0700, Christof Schmitt wrote:
>>
>> If cli_set_previous_version(cli, time_t t) already registers the
>> timestamp that should be used for opens, then the cli code could create
>> the twrp context from that for SMB2, or in the SMB1 case insert the @GMT
>> token in the path. That way the protocol differences between SMB1 and
>> SMB2 would be hidden from the application using the cli.
> 
> It's the 'insert the @GMT token in the path' for SMB1 part that is
> hard. It would touch a *LOT* of client code :-(.
> 
>>>> For the time being, I think we should apply your shadow_copy_data()
>>>> patches and not my patch that puts the @GMT at the end. That would make
>>>> "allinfo" properly list previous versions against all (reasonably
>>>> recent) versions of samba in SMB2 mode, at the expense of providing a
>>>> not-quite-realistic test for vfs_shadow_copy2.
>>>
>>> I need to fix the source3/modules/vfs_snapper.c code first :-).
>>>
>>> I'll send a patch to review soon !
>>
>> Should we push the fixes you have for shadowcopy2, or do you want to wait
>> until everything is complete, including snapper and tests?
> 
> Already pushed the shadowcopy2 fixes with your reviewed-by.
> 
> I'm working on the snapper fix right now which I'll propose
> for review today, and then the tests.
> 

IMHO, the @GMT parsing (if at all) should be outside the client libs. It
is an application issue (smbclient), how you represent a previous
version of a file. The client lib needs to expose an API that allows its
user to define create contexts in an easy to use way.

To implement that, I was thinking of "stealing" code from source4 -
moving it into libcli, and thus make it available for source3/libsmb to
use. That would affect only the SMB2 code, and indeed touch a lot of
files due the extra parameter (the added pointer to create contexts on open.

The attached patch is a not-tested-but-compiling first step in that
direction.

Once we have that, and we add the capability to add create contexts to
source3/libsmb, then we can start by just having "allinfo" use that, and
continue with either a modal variable in smbclient, or path parsing, or
both.

How does that sound?

Thanks,
Uri.

-------------- next part --------------
From f56814b13b5345106e82451f721ce894b4bde929 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Wed, 17 Aug 2016 20:39:28 +0300
Subject: [PATCH 1/2] libcli: higher-level request create context

Add a structure that represents common create
contexts, and functions that transform this
structure to/from the create contexts buffer
of the SMB2 CREATE request

Refactor source4 into using this, as we'll
move more and more source4 code into this,
and then it will be available for source3
to use.

Following patches will add "meat" to this.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 libcli/smb/smb2_create_blob.c    | 50 ++++++++++++++++++++++++++++
 libcli/smb/smb2_create_blob.h    | 20 ++++++++++++
 source4/libcli/raw/interfaces.h  |  3 +-
 source4/libcli/smb2/create.c     | 15 +++------
 source4/smb_server/smb2/fileio.c | 58 ++++++++++++++++++++-------------
 source4/torture/smb2/create.c    | 70 ++++++++++++++++++++--------------------
 source4/torture/vfs/fruit.c      |  9 ++++--
 7 files changed, 151 insertions(+), 74 deletions(-)

diff --git a/libcli/smb/smb2_create_blob.c b/libcli/smb/smb2_create_blob.c
index c6b2e1e..b7558df 100644
--- a/libcli/smb/smb2_create_blob.c
+++ b/libcli/smb/smb2_create_blob.c
@@ -206,6 +206,56 @@ NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b,
 	return NT_STATUS_OK;
 }
 
+NTSTATUS smb2_add_open_req_cc(TALLOC_CTX *mem_ctx, struct smb_cc_in *in,
+			      struct smb2_create_blobs *b)
+{
+	uint32_t i;
+	NTSTATUS status;
+
+	/* Add additional, non-SMB-level or third-party blobs */
+	for (i = 0; i < in->extra_blobs.num_blobs; ++i) {
+		status = smb2_create_blob_add(mem_ctx, b,
+					      in->extra_blobs.blobs[i].tag,
+					      in->extra_blobs.blobs[i].data);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+NTSTATUS smb2_parse_open_req_cc(TALLOC_CTX *mem_ctx, DATA_BLOB buffer,
+				struct smb_cc_in *cc)
+{
+	uint32_t i;
+	NTSTATUS status;
+	struct smb2_create_blobs *b = &cc->extra_blobs;
+
+	ZERO_STRUCTP(cc);
+
+	status = smb2_create_blob_parse(mem_ctx, buffer, b);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	i = b->num_blobs;
+	while (i > 0) {
+		bool parsed = false;
+		--i;
+
+		if (parsed) {
+			talloc_free(discard_const(b->blobs[i].tag));
+			data_blob_free(&b->blobs[i].data);
+			memmove(&b->blobs[i], &b->blobs[i + 1],
+				(b->num_blobs - i - 1) * sizeof(b->blobs[0]));
+			b->num_blobs--;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
 /*
  * return the first blob with the given tag
  */
diff --git a/libcli/smb/smb2_create_blob.h b/libcli/smb/smb2_create_blob.h
index 90697a7..f619c30 100644
--- a/libcli/smb/smb2_create_blob.h
+++ b/libcli/smb/smb2_create_blob.h
@@ -33,6 +33,14 @@ struct smb2_create_blobs {
 	struct smb2_create_blob *blobs;
 };
 
+/* Create contexts provided by the client
+ * when opening a file.
+ */
+struct smb_cc_in {
+	/* and any additional blobs the caller wants */
+	struct smb2_create_blobs extra_blobs;
+};
+
 struct smb_create_returns {
 	uint8_t oplock_level;
 	uint32_t create_action;
@@ -61,6 +69,18 @@ NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b,
 			      const char *tag, DATA_BLOB data);
 
 /*
+ * Add create contexts for open request
+ */
+NTSTATUS smb2_add_open_req_cc(TALLOC_CTX *mem_ctx, struct smb_cc_in *in,
+			      struct smb2_create_blobs *b);
+
+/*
+ * Parse create context for open request
+ */
+NTSTATUS smb2_parse_open_req_cc(TALLOC_CTX *mem_ctx, DATA_BLOB buffer,
+				struct smb_cc_in *in);
+
+/*
  * return the first blob with the given tag
  */
 struct smb2_create_blob *smb2_create_blob_find(const struct smb2_create_blobs *b,
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index 7e8258e..c71b164 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -1753,8 +1753,7 @@ union smb_open {
 
 			struct GUID *app_instance_id;
 
-			/* and any additional blobs the caller wants */
-			struct smb2_create_blobs blobs;
+			struct smb_cc_in cc;
 		} in;
 		struct {
 			union smb_handle file;
diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c
index 550069a..e98bcde 100644
--- a/source4/libcli/smb2/create.c
+++ b/source4/libcli/smb2/create.c
@@ -35,7 +35,6 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
 	NTSTATUS status;
 	DATA_BLOB blob;
 	struct smb2_create_blobs blobs;
-	int i;
 
 	ZERO_STRUCT(blobs);
 
@@ -270,18 +269,12 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
 		}
 	}
 
-	/* and any custom blobs */
-	for (i=0;i<io->in.blobs.num_blobs;i++) {
-		status = smb2_create_blob_add(req, &blobs,
-					      io->in.blobs.blobs[i].tag, 
-					      io->in.blobs.blobs[i].data);
-		if (!NT_STATUS_IS_OK(status)) {
-			talloc_free(req);
-			return NULL;
-		}
+	status = smb2_add_open_req_cc(req, &io->in.cc, &blobs);
+	if (!NT_STATUS_IS_OK(status)) {
+		talloc_free(req);
+		return NULL;
 	}
 
-
 	status = smb2_create_blob_push(req, &blob, blobs);
 	if (!NT_STATUS_IS_OK(status)) {
 		talloc_free(req);
diff --git a/source4/smb_server/smb2/fileio.c b/source4/smb_server/smb2/fileio.c
index f6460e0..a9cc2b6 100644
--- a/source4/smb_server/smb2/fileio.c
+++ b/source4/smb_server/smb2/fileio.c
@@ -93,35 +93,41 @@ void smb2srv_create_recv(struct smb2srv_request *req)
 	io->smb2.in.create_options	= IVAL(req->in.body, 0x28);
 	SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, io, req->in.body+0x2C, &io->smb2.in.fname));
 	SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x30, &blob));
-	SMB2SRV_CHECK(smb2_create_blob_parse(io, blob, &io->smb2.in.blobs));
+	SMB2SRV_CHECK(smb2_parse_open_req_cc(io, blob, &io->smb2.in.cc));
 
 	/* interpret the parsed tags that a server needs to respond to */
-	for (i=0;i<io->smb2.in.blobs.num_blobs;i++) {
-		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_EXTA) == 0) {
-			SMB2SRV_CHECK(ea_pull_list_chained(&io->smb2.in.blobs.blobs[i].data, io, 
-							   &io->smb2.in.eas.num_eas,
-							   &io->smb2.in.eas.eas));
+	for (i = 0; i < io->smb2.in.cc.extra_blobs.num_blobs; i++) {
+		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag,
+			   SMB2_CREATE_TAG_EXTA) == 0) {
+			SMB2SRV_CHECK(ea_pull_list_chained(
+			    &io->smb2.in.cc.extra_blobs.blobs[i].data, io,
+			    &io->smb2.in.eas.num_eas, &io->smb2.in.eas.eas));
 		}
-		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_SECD) == 0) {
+		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag,
+			   SMB2_CREATE_TAG_SECD) == 0) {
 			enum ndr_err_code ndr_err;
 			io->smb2.in.sec_desc = talloc(io, struct security_descriptor);
 			if (io->smb2.in.sec_desc == NULL) {
 				smb2srv_send_error(req,  NT_STATUS_NO_MEMORY);
 				return;
 			}
-			ndr_err = ndr_pull_struct_blob(&io->smb2.in.blobs.blobs[i].data, io, 
-						       io->smb2.in.sec_desc,
-						       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+			ndr_err = ndr_pull_struct_blob(
+			    &io->smb2.in.cc.extra_blobs.blobs[i].data, io,
+			    io->smb2.in.sec_desc,
+			    (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
 			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 				smb2srv_send_error(req,  ndr_map_error2ntstatus(ndr_err));
 				return;
 			}
 		}
-		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNQ) == 0) {
+		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag,
+			   SMB2_CREATE_TAG_DHNQ) == 0) {
 			io->smb2.in.durable_open = true;
 		}
-		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNC) == 0) {
-			if (io->smb2.in.blobs.blobs[i].data.length != 16) {
+		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag,
+			   SMB2_CREATE_TAG_DHNC) == 0) {
+			if (io->smb2.in.cc.extra_blobs.blobs[i].data.length !=
+			    16) {
 				smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
 				return;				
 			}
@@ -130,26 +136,32 @@ void smb2srv_create_recv(struct smb2srv_request *req)
 				smb2srv_send_error(req,  NT_STATUS_NO_MEMORY);
 				return;
 			}
-			smb2_pull_handle(io->smb2.in.blobs.blobs[i].data.data, io->smb2.in.durable_handle);
+			smb2_pull_handle(
+			    io->smb2.in.cc.extra_blobs.blobs[i].data.data,
+			    io->smb2.in.durable_handle);
 		}
-		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_ALSI) == 0) {
-			if (io->smb2.in.blobs.blobs[i].data.length != 8) {
+		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag,
+			   SMB2_CREATE_TAG_ALSI) == 0) {
+			if (io->smb2.in.cc.extra_blobs.blobs[i].data.length !=
+			    8) {
 				smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
 				return;				
 			}
-			io->smb2.in.alloc_size = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);
+			io->smb2.in.alloc_size = BVAL(
+			    io->smb2.in.cc.extra_blobs.blobs[i].data.data, 0);
 		}
-		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
+		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag,
+			   SMB2_CREATE_TAG_MXAC) == 0) {
 			io->smb2.in.query_maximal_access = true;
 		}
-		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_TWRP) == 0) {
-			if (io->smb2.in.blobs.blobs[i].data.length != 8) {
+		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag, SMB2_CREATE_TAG_TWRP) == 0) {
+			if (io->smb2.in.cc.extra_blobs.blobs[i].data.length != 8) {
 				smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
 				return;				
 			}
-			io->smb2.in.timewarp = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);			
-		}
-		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
+			io->smb2.in.timewarp = BVAL(io->smb2.in.cc.extra_blobs.blobs[i].data.data, 0);
+		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag,
+			   SMB2_CREATE_TAG_QFID) == 0) {
 			io->smb2.in.query_on_disk_id = true;
 		}
 	}
diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c
index 7e6be8d..b42d9ad 100644
--- a/source4/torture/smb2/create.c
+++ b/source4/torture/smb2/create.c
@@ -438,8 +438,8 @@ static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tre
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing unknown tag\n");
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "FooO", data_blob(NULL, 0));
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "FooO",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	status = smb2_create(tree, tctx, &io);
@@ -449,96 +449,96 @@ static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tre
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing bad tag length 0\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "x", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "x",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
 
 	torture_comment(tctx, "Testing bad tag length 1\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "x", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "x",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
 
 	torture_comment(tctx, "Testing bad tag length 2\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "xx", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "xx",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
 
 	torture_comment(tctx, "Testing bad tag length 3\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "xxx", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "xxx",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
 
 	torture_comment(tctx, "Testing tag length 4\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "xxxx", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "xxxx",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing tag length 5\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "xxxxx", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "xxxxx",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing tag length 6\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "xxxxxx", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "xxxxxx",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing tag length 7\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "xxxxxxx", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "xxxxxxx",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing tag length 8\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
-				      "xxxxxxxx", data_blob(NULL, 0));
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "xxxxxxxx",
+				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing tag length 16\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs,
 				      "xxxxxxxxxxxxxxxx", data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing tag length 17\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs,
 				      "xxxxxxxxxxxxxxxxx", data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing tag length 34\n");
-	ZERO_STRUCT(io.in.blobs);
-	status = smb2_create_blob_add(tctx, &io.in.blobs,
+	ZERO_STRUCT(io.in.cc.extra_blobs);
+	status = smb2_create_blob_add(tctx, &io.in.cc.extra_blobs,
 				      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
 				      data_blob(NULL, 0));
 	CHECK_STATUS(status, NT_STATUS_OK);
diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index 020bd1f..ddf83e3 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -1233,7 +1233,8 @@ static bool enable_aapl(struct torture_context *tctx,
 			      SMB2_CRTCTX_AAPL_UNIX_BASED |
 			      SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
 
-	status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
+	status =
+	    smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "AAPL", data);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
 
 	status = smb2_create(tree, tctx, &io);
@@ -1920,7 +1921,8 @@ static bool test_aapl(struct torture_context *tctx,
 			      SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
 
 	torture_comment(tctx, "Testing SMB2 create context AAPL\n");
-	status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
+	status =
+	    smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "AAPL", data);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	status = smb2_create(tree, tctx, &io);
@@ -2385,7 +2387,8 @@ static bool neg_aapl_copyfile(struct torture_context *tctx,
 	SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
 	SBVAL(data.data, 16, flags);
 
-	status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
+	status =
+	    smb2_create_blob_add(tctx, &io.in.cc.extra_blobs, "AAPL", data);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	status = smb2_create(tree, tctx, &io);
-- 
2.5.5


From 23c2dc5cf3425c8cb4f9507437977761bcc2facf Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Wed, 17 Aug 2016 20:44:32 +0300
Subject: [PATCH 2/2] libcli: move twrp request handling from source4 to libcli

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 libcli/smb/smb2_create_blob.c    | 21 ++++++++++++++++++++-
 libcli/smb/smb2_create_blob.h    |  1 +
 source4/libcli/raw/interfaces.h  |  1 -
 source4/libcli/smb2/create.c     | 11 -----------
 source4/ntvfs/ntvfs_generic.c    |  2 +-
 source4/smb_server/smb2/fileio.c |  6 ------
 source4/torture/gentest.c        |  2 +-
 source4/torture/smb2/create.c    |  4 ++--
 8 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/libcli/smb/smb2_create_blob.c b/libcli/smb/smb2_create_blob.c
index b7558df..008c4d2 100644
--- a/libcli/smb/smb2_create_blob.c
+++ b/libcli/smb/smb2_create_blob.c
@@ -212,6 +212,16 @@ NTSTATUS smb2_add_open_req_cc(TALLOC_CTX *mem_ctx, struct smb_cc_in *in,
 	uint32_t i;
 	NTSTATUS status;
 
+	if (in->timewarp) {
+		uint8_t data[8];
+		SBVAL(data, 0, in->timewarp);
+		status = smb2_create_blob_add(mem_ctx, b, SMB2_CREATE_TAG_TWRP,
+					      data_blob_const(data, 8));
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+	}
+
 	/* Add additional, non-SMB-level or third-party blobs */
 	for (i = 0; i < in->extra_blobs.num_blobs; ++i) {
 		status = smb2_create_blob_add(mem_ctx, b,
@@ -241,9 +251,18 @@ NTSTATUS smb2_parse_open_req_cc(TALLOC_CTX *mem_ctx, DATA_BLOB buffer,
 
 	i = b->num_blobs;
 	while (i > 0) {
-		bool parsed = false;
+		bool parsed = true;
 		--i;
 
+		if (strcmp(b->blobs[i].tag, SMB2_CREATE_TAG_TWRP) == 0) {
+			if (b->blobs[i].data.length != 8) {
+				return NT_STATUS_INVALID_PARAMETER;
+			}
+			cc->timewarp = BVAL(b->blobs[i].data.data, 0);
+		} else {
+			parsed = false;
+		}
+
 		if (parsed) {
 			talloc_free(discard_const(b->blobs[i].tag));
 			data_blob_free(&b->blobs[i].data);
diff --git a/libcli/smb/smb2_create_blob.h b/libcli/smb/smb2_create_blob.h
index f619c30..792b24d 100644
--- a/libcli/smb/smb2_create_blob.h
+++ b/libcli/smb/smb2_create_blob.h
@@ -37,6 +37,7 @@ struct smb2_create_blobs {
  * when opening a file.
  */
 struct smb_cc_in {
+	NTTIME timewarp;
 	/* and any additional blobs the caller wants */
 	struct smb2_create_blobs extra_blobs;
 };
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index c71b164..5a690c1 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -1746,7 +1746,6 @@ union smb_open {
 			struct smb2_handle *durable_handle_v2;
 
 			bool   query_maximal_access;
-			NTTIME timewarp;
 			bool   query_on_disk_id;
 			struct smb2_lease *lease_request;
 			struct smb2_lease *lease_request_v2;
diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c
index e98bcde..b009d49 100644
--- a/source4/libcli/smb2/create.c
+++ b/source4/libcli/smb2/create.c
@@ -171,17 +171,6 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
 		}
 	}
 
-	if (io->in.timewarp) {
-		uint8_t data[8];
-		SBVAL(data, 0, io->in.timewarp);		
-		status = smb2_create_blob_add(req, &blobs,
-					      SMB2_CREATE_TAG_TWRP, data_blob_const(data, 8));
-		if (!NT_STATUS_IS_OK(status)) {
-			talloc_free(req);
-			return NULL;
-		}
-	}
-
 	if (io->in.sec_desc) {
 		enum ndr_err_code ndr_err;
 		DATA_BLOB sd_blob;
diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c
index 4edc31c..5ac8258 100644
--- a/source4/ntvfs/ntvfs_generic.c
+++ b/source4/ntvfs/ntvfs_generic.c
@@ -532,7 +532,7 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
 		io2->generic.in.private_flags	= 0;
 
 		/* we don't support timewarp yet */
-		if (io->smb2.in.timewarp != 0) {
+		if (io->smb2.in.cc.timewarp != 0) {
 			status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
 			break;
 		}
diff --git a/source4/smb_server/smb2/fileio.c b/source4/smb_server/smb2/fileio.c
index a9cc2b6..588e0ec 100644
--- a/source4/smb_server/smb2/fileio.c
+++ b/source4/smb_server/smb2/fileio.c
@@ -154,12 +154,6 @@ void smb2srv_create_recv(struct smb2srv_request *req)
 			   SMB2_CREATE_TAG_MXAC) == 0) {
 			io->smb2.in.query_maximal_access = true;
 		}
-		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag, SMB2_CREATE_TAG_TWRP) == 0) {
-			if (io->smb2.in.cc.extra_blobs.blobs[i].data.length != 8) {
-				smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
-				return;				
-			}
-			io->smb2.in.timewarp = BVAL(io->smb2.in.cc.extra_blobs.blobs[i].data.data, 0);
 		if (strcmp(io->smb2.in.cc.extra_blobs.blobs[i].tag,
 			   SMB2_CREATE_TAG_QFID) == 0) {
 			io->smb2.in.query_on_disk_id = true;
diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c
index 4cd2258..c31a9bd 100644
--- a/source4/torture/gentest.c
+++ b/source4/torture/gentest.c
@@ -2554,7 +2554,7 @@ static bool handler_smb2_create(int instance)
 	parm[0].in.alloc_size		      = gen_alloc_size();
 	parm[0].in.durable_open		      = gen_bool();
 	parm[0].in.query_maximal_access	      = gen_bool();
-	parm[0].in.timewarp		      = gen_timewarp();
+	parm[0].in.cc.timewarp = gen_timewarp();
 	parm[0].in.query_on_disk_id	      = gen_bool();
 	parm[0].in.sec_desc		      = gen_sec_desc();
 
diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c
index b42d9ad..bec0fc8 100644
--- a/source4/torture/smb2/create.c
+++ b/source4/torture/smb2/create.c
@@ -424,10 +424,10 @@ static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tre
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	torture_comment(tctx, "Testing timewarp\n");
-	io.in.timewarp = 10000;
+	io.in.cc.timewarp = 10000;
 	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
-	io.in.timewarp = 0;
+	io.in.cc.timewarp = 0;
 
 	torture_comment(tctx, "Testing query_on_disk\n");
 	io.in.query_on_disk_id = true;
-- 
2.5.5



More information about the samba-technical mailing list