[PATCHES] to smb2.durable[-v2]-open tests

Michael Adam obnox at samba.org
Thu Mar 17 02:01:17 UTC 2016


ENOPATCH...

On 2016-03-17 at 02:58 +0100, Michael Adam wrote:
> Hi!
> 
> Attached find a patchset that improves the
> durable-[v2-]open.reopen1a tests and then
> adds variants of these using leases,
> durable-[v2-]open.reopen1a-lease.
> 
> The speciality with leases is, that in contrast
> to oplocks, the client_guid is checked upon
> reconnect. This is the additional aspect that
> these new tests verify. The improvement of the
> original (oplock) reopen1a tests also proves
> that for the oplock case, the client_guid is
> irrelevant.
> 
> Note: The reopen1a-lease tests were the ones that
> had me provoke the smbd crash due to use-after-free
> a patch for which I sent earlier.
> 
> Review appreciated!
> 
> Thanks - Michael


-------------- next part --------------
From 5ea7b1c3f1994dd0154e61efb38aed228f7184b9 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Tue, 15 Mar 2016 09:35:03 +0100
Subject: [PATCH 01/10] torture:smb2: use assert, not warning in error case in
 durable-open.reopen1a

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/torture/smb2/durable_open.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/source4/torture/smb2/durable_open.c b/source4/torture/smb2/durable_open.c
index fe0a326..11388ef 100644
--- a/source4/torture/smb2/durable_open.c
+++ b/source4/torture/smb2/durable_open.c
@@ -464,13 +464,9 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 
 	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
 
-	if (!torture_smb2_connection_ext(tctx, previous_session_id,
-					 &options, &tree2))
-	{
-		torture_warning(tctx, "couldn't reconnect, bailing\n");
-		ret = false;
-		goto done;
-	}
+	ret = torture_smb2_connection_ext(tctx, previous_session_id,
+					  &options, &tree2);
+	torture_assert_goto(tctx, ret, ret, done, "could not reconnect");
 
 	/*
 	 * check that this has deleted the old session
-- 
2.5.0


From cffa315509468b4b48e79e59cede1f7b6df231ec Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 4 Mar 2016 22:55:40 +0100
Subject: [PATCH 02/10] torture:smb2: fix crashes in smb2.durable-open.reopen1a
 test

If the test failed too early, we dereferenced tree2 which
was still NULL.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/torture/smb2/durable_open.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/source4/torture/smb2/durable_open.c b/source4/torture/smb2/durable_open.c
index 11388ef..e8a82c0 100644
--- a/source4/torture/smb2/durable_open.c
+++ b/source4/torture/smb2/durable_open.c
@@ -479,6 +479,8 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 	status = smb2_create(tree, mem_ctx, &io2);
 	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
 
+	TALLOC_FREE(tree);
+
 	/*
 	 * but a durable reconnect on the new session succeeds:
 	 */
@@ -495,15 +497,19 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 	h = &_h;
 
 done:
-	if (h != NULL) {
-		smb2_util_close(tree2, *h);
+	if (tree == NULL) {
+		tree = tree2;
 	}
 
-	smb2_util_unlink(tree2, fname);
-
-	talloc_free(tree2);
+	if (tree != NULL) {
+		if (h != NULL) {
+			smb2_util_close(tree, *h);
+			h = NULL;
+		}
+		smb2_util_unlink(tree, fname);
 
-	talloc_free(tree);
+		talloc_free(tree);
+	}
 
 	talloc_free(mem_ctx);
 
-- 
2.5.0


From 5d1a534782c7a91425e06dfa292b6eabedd3192b Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 17 Mar 2016 02:45:16 +0100
Subject: [PATCH 03/10] torture:smb2: durable-open.reopen1a only needs one io
 struct

Using two is confusing.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/torture/smb2/durable_open.c | 38 ++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/source4/torture/smb2/durable_open.c b/source4/torture/smb2/durable_open.c
index e8a82c0..584f046 100644
--- a/source4/torture/smb2/durable_open.c
+++ b/source4/torture/smb2/durable_open.c
@@ -431,7 +431,7 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 	char fname[256];
 	struct smb2_handle _h;
 	struct smb2_handle *h = NULL;
-	struct smb2_create io1, io2;
+	struct smb2_create io;
 	bool ret = true;
 	struct smb2_tree *tree2 = NULL;
 	uint64_t previous_session_id;
@@ -445,18 +445,18 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 
 	smb2_util_unlink(tree, fname);
 
-	smb2_oplock_create_share(&io1, fname,
+	smb2_oplock_create_share(&io, fname,
 				 smb2_util_share_access(""),
 				 smb2_util_oplock_level("b"));
-	io1.in.durable_open = true;
+	io.in.durable_open = true;
 
-	status = smb2_create(tree, mem_ctx, &io1);
+	status = smb2_create(tree, mem_ctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	_h = io1.out.file.handle;
+	_h = io.out.file.handle;
 	h = &_h;
-	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
-	CHECK_VAL(io1.out.durable_open, true);
-	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
+	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.durable_open, true);
+	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
 
 	/*
 	 * a session reconnect on a second tcp connection
@@ -472,11 +472,11 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 	 * check that this has deleted the old session
 	 */
 
-	ZERO_STRUCT(io2);
-	io2.in.fname = fname;
-	io2.in.durable_handle = h;
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle = h;
 
-	status = smb2_create(tree, mem_ctx, &io2);
+	status = smb2_create(tree, mem_ctx, &io);
 	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
 
 	TALLOC_FREE(tree);
@@ -485,15 +485,15 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 	 * but a durable reconnect on the new session succeeds:
 	 */
 
-	ZERO_STRUCT(io2);
-	io2.in.fname = fname;
-	io2.in.durable_handle = h;
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle = h;
 
-	status = smb2_create(tree2, mem_ctx, &io2);
+	status = smb2_create(tree2, mem_ctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
-	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
-	_h = io2.out.file.handle;
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
+	_h = io.out.file.handle;
 	h = &_h;
 
 done:
-- 
2.5.0


From 0c5b17916f7da0d90b2f6b40b449f0247b781f80 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Tue, 15 Mar 2016 08:59:53 +0100
Subject: [PATCH 04/10] torture:smb2: for oplocks, durable reconnect works with
 different client guid

in durabble-open.reopen1a test

Try both original and a different client guid.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/torture/smb2/durable_open.c | 51 +++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/source4/torture/smb2/durable_open.c b/source4/torture/smb2/durable_open.c
index 584f046..b74b5c5 100644
--- a/source4/torture/smb2/durable_open.c
+++ b/source4/torture/smb2/durable_open.c
@@ -434,10 +434,13 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 	struct smb2_create io;
 	bool ret = true;
 	struct smb2_tree *tree2 = NULL;
+	struct smb2_tree *tree3 = NULL;
 	uint64_t previous_session_id;
 	struct smbcli_options options;
+	struct GUID orig_client_guid;
 
 	options = tree->session->transport->options;
+	orig_client_guid = options.client_guid;
 
 	/* Choose a random name in case the state is left a little funky. */
 	snprintf(fname, 256, "durable_open_reopen1a_%s.dat",
@@ -464,6 +467,9 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 
 	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
 
+	/* for oplocks, the client guid can be different: */
+	options.client_guid = GUID_random();
+
 	ret = torture_smb2_connection_ext(tctx, previous_session_id,
 					  &options, &tree2);
 	torture_assert_goto(tctx, ret, ret, done, "could not reconnect");
@@ -496,11 +502,56 @@ static bool test_durable_open_reopen1a(struct torture_context *tctx,
 	_h = io.out.file.handle;
 	h = &_h;
 
+	/*
+	 * a session reconnect on a second tcp connection
+	 */
+
+	previous_session_id = smb2cli_session_current_id(tree2->session->smbXcli);
+
+	/* the original client_guid works just the same */
+	options.client_guid = orig_client_guid;
+
+	ret = torture_smb2_connection_ext(tctx, previous_session_id,
+					  &options, &tree3);
+	torture_assert_goto(tctx, ret, ret, done, "could not reconnect");
+
+	/*
+	 * check that this has deleted the old session
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle = h;
+
+	status = smb2_create(tree2, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
+
+	TALLOC_FREE(tree2);
+
+	/*
+	 * but a durable reconnect on the new session succeeds:
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle = h;
+
+	status = smb2_create(tree3, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
+	_h = io.out.file.handle;
+	h = &_h;
+
 done:
 	if (tree == NULL) {
 		tree = tree2;
 	}
 
+	if (tree == NULL) {
+		tree = tree3;
+	}
+
 	if (tree != NULL) {
 		if (h != NULL) {
 			smb2_util_close(tree, *h);
-- 
2.5.0


From 77f668434c5522255e361ee8852956a253e336fc Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Tue, 15 Mar 2016 10:02:14 +0100
Subject: [PATCH 05/10] torture:smb2: add durable-open.reopen1a-lease

Lease variant of the reopen1a test which tests the
relevance of the client guid.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 selftest/knownfail                  |   1 +
 source4/torture/smb2/durable_open.c | 170 ++++++++++++++++++++++++++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/selftest/knownfail b/selftest/knownfail
index c15d263..8f2f139 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -193,6 +193,7 @@
 ^samba3.smb2.notify.rec
 ^samba3.smb2.durable-open.delete_on_close2
 ^samba3.smb2.durable-v2-open.app-instance
+^samba3.smb2.durable-open.reopen1a-lease\(ad_dc\)$
 ^samba4.smb2.ioctl.req_resume_key\(ad_dc_ntvfs\) # not supported by s4 ntvfs server
 ^samba4.smb2.ioctl.copy_chunk_\w*\(ad_dc_ntvfs\)	# not supported by s4 ntvfs server
 ^samba3.smb2.dir.one
diff --git a/source4/torture/smb2/durable_open.c b/source4/torture/smb2/durable_open.c
index b74b5c5..7b59566 100644
--- a/source4/torture/smb2/durable_open.c
+++ b/source4/torture/smb2/durable_open.c
@@ -568,6 +568,175 @@ done:
 }
 
 /**
+ * lease variant of reopen1a
+ *
+ * Basic test for doing a durable open and doing a session
+ * reconnect while the first session is still active and the
+ * handle is still open in the client.
+ * This closes the original session and  a durable reconnect on
+ * the new session succeeds depending on the client guid:
+ *
+ * Durable reconnect on a session with a different client guid fails.
+ * Durable reconnect on a session with the original client guid succeeds.
+ */
+bool test_durable_open_reopen1a_lease(struct torture_context *tctx,
+				      struct smb2_tree *tree)
+{
+	NTSTATUS status;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	char fname[256];
+	struct smb2_handle _h;
+	struct smb2_handle *h = NULL;
+	struct smb2_create io;
+	struct smb2_lease ls;
+	uint64_t lease_key;
+	bool ret = true;
+	struct smb2_tree *tree2 = NULL;
+	struct smb2_tree *tree3 = NULL;
+	uint64_t previous_session_id;
+	struct smbcli_options options;
+	struct GUID orig_client_guid;
+
+	options = tree->session->transport->options;
+	orig_client_guid = options.client_guid;
+
+	/* Choose a random name in case the state is left a little funky. */
+	snprintf(fname, 256, "durable_v2_open_reopen1a_lease_%s.dat",
+		 generate_random_str(tctx, 8));
+
+	smb2_util_unlink(tree, fname);
+
+	lease_key = random();
+	smb2_lease_create(&io, &ls, false /* dir */, fname,
+			  lease_key, smb2_util_lease_state("RWH"));
+	io.in.durable_open = true;
+
+	status = smb2_create(tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	_h = io.out.file.handle;
+	h = &_h;
+	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.durable_open, true);
+	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
+	CHECK_VAL(io.out.lease_response.lease_key.data[0], lease_key);
+	CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease_key);
+	CHECK_VAL(io.out.lease_response.lease_state,
+		  smb2_util_lease_state("RWH"));
+	CHECK_VAL(io.out.lease_response.lease_flags, 0);
+	CHECK_VAL(io.out.lease_response.lease_duration, 0);
+
+	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
+
+	/*
+	 * a session reconnect on a second tcp connection
+	 * with a different client_guid does not allow
+	 * the durable reconnect.
+	 */
+
+	options.client_guid = GUID_random();
+
+	ret = torture_smb2_connection_ext(tctx, previous_session_id,
+					  &options, &tree2);
+	torture_assert_goto(tctx, ret, ret, done, "couldn't reconnect");
+
+	/*
+	 * check that this has deleted the old session
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle = h;
+	io.in.lease_request = &ls;
+	status = smb2_create(tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
+	TALLOC_FREE(tree);
+
+
+	/*
+	 * but a durable reconnect on the new session with the wrong
+	 * client guid fails
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle = h;
+	io.in.lease_request = &ls;
+	status = smb2_create(tree2, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+	/*
+	 * now a session reconnect on a second tcp connection
+	 * with original client_guid allows the durable reconnect.
+	 */
+
+	options.client_guid = orig_client_guid;
+
+	ret = torture_smb2_connection_ext(tctx, previous_session_id,
+					  &options, &tree3);
+	torture_assert_goto(tctx, ret, ret, done, "couldn't reconnect");
+
+	/*
+	 * check that this has deleted the old session
+	 * In this case, a durable reconnect attempt with the
+	 * correct client_guid yields a different error code.
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle = h;
+	io.in.lease_request = &ls;
+	status = smb2_create(tree2, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+	TALLOC_FREE(tree2);
+
+	/*
+	 * but a durable reconnect on the new session succeeds:
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle = h;
+	io.in.lease_request = &ls;
+	status = smb2_create(tree3, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.durable_open, false); /* no dh response context... */
+	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
+	CHECK_VAL(io.out.lease_response.lease_key.data[0], lease_key);
+	CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease_key);
+	CHECK_VAL(io.out.lease_response.lease_state,
+		  smb2_util_lease_state("RWH"));
+	CHECK_VAL(io.out.lease_response.lease_flags, 0);
+	CHECK_VAL(io.out.lease_response.lease_duration, 0);
+	_h = io.out.file.handle;
+	h = &_h;
+
+done:
+	if (tree == NULL) {
+		tree = tree2;
+	}
+
+	if (tree == NULL) {
+		tree = tree3;
+	}
+
+	if (tree != NULL) {
+		if (h != NULL) {
+			smb2_util_close(tree, *h);
+		}
+
+		smb2_util_unlink(tree, fname);
+
+		talloc_free(tree);
+	}
+
+	talloc_free(mem_ctx);
+
+	return ret;
+}
+
+
+/**
  * basic test for doing a durable open
  * tcp disconnect, reconnect, do a durable reopen (succeeds)
  */
@@ -2589,6 +2758,7 @@ struct torture_suite *torture_smb2_durable_open_init(void)
 	torture_suite_add_1smb2_test(suite, "open-lease", test_durable_open_open_lease);
 	torture_suite_add_1smb2_test(suite, "reopen1", test_durable_open_reopen1);
 	torture_suite_add_1smb2_test(suite, "reopen1a", test_durable_open_reopen1a);
+	torture_suite_add_1smb2_test(suite, "reopen1a-lease", test_durable_open_reopen1a_lease);
 	torture_suite_add_1smb2_test(suite, "reopen2", test_durable_open_reopen2);
 	torture_suite_add_1smb2_test(suite, "reopen2-lease", test_durable_open_reopen2_lease);
 	torture_suite_add_1smb2_test(suite, "reopen2-lease-v2", test_durable_open_reopen2_lease_v2);
-- 
2.5.0


From c112967ab6036b0788f7e8d8805257bb569db77f Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Tue, 15 Mar 2016 09:39:43 +0100
Subject: [PATCH 06/10] torture:smb2: use assert, not warning in error case in
 durable-v2-open.reopen1a

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/torture/smb2/durable_v2_open.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c
index f3ec344..a80506a 100644
--- a/source4/torture/smb2/durable_v2_open.c
+++ b/source4/torture/smb2/durable_v2_open.c
@@ -629,13 +629,9 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 
 	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
 
-	if (!torture_smb2_connection_ext(tctx, previous_session_id,
-					 &options, &tree2))
-	{
-		torture_warning(tctx, "couldn't reconnect, bailing\n");
-		ret = false;
-		goto done;
-	}
+	ret = torture_smb2_connection_ext(tctx, previous_session_id,
+					  &options, &tree2);
+	torture_assert_goto(tctx, ret, ret, done, "couldn't reconnect");
 
 	/*
 	 * check that this has deleted the old session
-- 
2.5.0


From cd936d1fce36d91235a482a1de6598649fa8f828 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Tue, 15 Mar 2016 09:44:06 +0100
Subject: [PATCH 07/10] torture:smb2: fix crashes in
 smb2.durable-v2-open.reopen1a test

If the test failed too early, we dereferenced tree2 which
was still NULL.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/torture/smb2/durable_v2_open.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c
index a80506a..de24c8f 100644
--- a/source4/torture/smb2/durable_v2_open.c
+++ b/source4/torture/smb2/durable_v2_open.c
@@ -644,6 +644,8 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	status = smb2_create(tree, mem_ctx, &io);
 	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
 
+	TALLOC_FREE(tree);
+
 	/*
 	 * but a durable reconnect on the new session succeeds:
 	 */
@@ -664,13 +666,19 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	h = &_h;
 
 done:
-	if (h != NULL) {
-		smb2_util_close(tree, *h);
+	if (tree == NULL) {
+		tree = tree2;
 	}
 
-	smb2_util_unlink(tree, fname);
+	if (tree != NULL) {
+		if (h != NULL) {
+			smb2_util_close(tree, *h);
+		}
 
-	talloc_free(tree);
+		smb2_util_unlink(tree, fname);
+
+		talloc_free(tree);
+	}
 
 	talloc_free(mem_ctx);
 
-- 
2.5.0


From 6dd86cb2ee81e3c629bc87cc0c9cd050b3977f2f Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 17 Mar 2016 02:35:35 +0100
Subject: [PATCH 08/10] torture:smb2: get rid of supefluous io2 var in
 durable-v2-open.reopen1a

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/torture/smb2/durable_v2_open.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c
index de24c8f..2528187 100644
--- a/source4/torture/smb2/durable_v2_open.c
+++ b/source4/torture/smb2/durable_v2_open.c
@@ -588,7 +588,7 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	char fname[256];
 	struct smb2_handle _h;
 	struct smb2_handle *h = NULL;
-	struct smb2_create io, io2;
+	struct smb2_create io;
 	struct GUID create_guid = GUID_random();
 	bool ret = true;
 	struct smb2_tree *tree2 = NULL;
@@ -650,19 +650,19 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	 * but a durable reconnect on the new session succeeds:
 	 */
 
-	ZERO_STRUCT(io2);
-	io2.in.fname = "";
-	io2.in.durable_handle_v2 = h;
-	io2.in.create_guid = create_guid;
-	status = smb2_create(tree2, mem_ctx, &io2);
+	ZERO_STRUCT(io);
+	io.in.fname = "";
+	io.in.durable_handle_v2 = h;
+	io.in.create_guid = create_guid;
+	status = smb2_create(tree2, mem_ctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
-	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
-	CHECK_VAL(io2.out.durable_open, false);
-	CHECK_VAL(io2.out.durable_open_v2, false); /* no dh2q response blob */
-	CHECK_VAL(io2.out.persistent_open, false);
-	CHECK_VAL(io2.out.timeout, io.in.timeout);
-	_h = io2.out.file.handle;
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
+	CHECK_VAL(io.out.durable_open, false);
+	CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */
+	CHECK_VAL(io.out.persistent_open, false);
+	CHECK_VAL(io.out.timeout, io.in.timeout);
+	_h = io.out.file.handle;
 	h = &_h;
 
 done:
-- 
2.5.0


From 784c6440f45cba1ca4c6cbecd2219f959ac9e8d7 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Tue, 15 Mar 2016 09:02:28 +0100
Subject: [PATCH 09/10] torture:smb2: for oplocks, durable reconnect works with
 different client-guid

for durable-v2-open.reopen1a

Try both different and original client guid.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/torture/smb2/durable_v2_open.c | 54 ++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c
index 2528187..e48fb9b 100644
--- a/source4/torture/smb2/durable_v2_open.c
+++ b/source4/torture/smb2/durable_v2_open.c
@@ -592,10 +592,13 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	struct GUID create_guid = GUID_random();
 	bool ret = true;
 	struct smb2_tree *tree2 = NULL;
+	struct smb2_tree *tree3 = NULL;
 	uint64_t previous_session_id;
 	struct smbcli_options options;
+	struct GUID orig_client_guid;
 
 	options = tree->session->transport->options;
+	orig_client_guid = options.client_guid;
 
 	/* Choose a random name in case the state is left a little funky. */
 	snprintf(fname, 256, "durable_v2_open_reopen1a_%s.dat",
@@ -629,6 +632,9 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 
 	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
 
+	/* for oplocks, the client guid can be different: */
+	options.client_guid = GUID_random();
+
 	ret = torture_smb2_connection_ext(tctx, previous_session_id,
 					  &options, &tree2);
 	torture_assert_goto(tctx, ret, ret, done, "couldn't reconnect");
@@ -665,11 +671,59 @@ bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
 	_h = io.out.file.handle;
 	h = &_h;
 
+	/*
+	 * a session reconnect on a second tcp connection
+	 */
+
+	previous_session_id = smb2cli_session_current_id(tree2->session->smbXcli);
+
+	/* it works the same with the original guid */
+	options.client_guid = orig_client_guid;
+
+	ret = torture_smb2_connection_ext(tctx, previous_session_id,
+					  &options, &tree3);
+	torture_assert_goto(tctx, ret, ret, done, "couldn't reconnect");
+
+	/*
+	 * check that this has deleted the old session
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = "";
+	io.in.durable_handle_v2 = h;
+	io.in.create_guid = create_guid;
+	status = smb2_create(tree2, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
+	TALLOC_FREE(tree2);
+
+	/*
+	 * but a durable reconnect on the new session succeeds:
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = "";
+	io.in.durable_handle_v2 = h;
+	io.in.create_guid = create_guid;
+	status = smb2_create(tree3, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
+	CHECK_VAL(io.out.durable_open, false);
+	CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */
+	CHECK_VAL(io.out.persistent_open, false);
+	CHECK_VAL(io.out.timeout, io.in.timeout);
+	_h = io.out.file.handle;
+	h = &_h;
+
 done:
 	if (tree == NULL) {
 		tree = tree2;
 	}
 
+	if (tree == NULL) {
+		tree = tree3;
+	}
+
 	if (tree != NULL) {
 		if (h != NULL) {
 			smb2_util_close(tree, *h);
-- 
2.5.0


From 55564b164a2bd24dff0c594315393b7ed9f3abba Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Tue, 15 Mar 2016 09:06:56 +0100
Subject: [PATCH 10/10] torture:smb2: add durable-v2-open.reopen1a-lease

Lease variant of the reopen1a test which tests the
relevance of the client guid.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 selftest/knownfail                     |   1 +
 source4/torture/smb2/durable_v2_open.c | 183 +++++++++++++++++++++++++++++++++
 2 files changed, 184 insertions(+)

diff --git a/selftest/knownfail b/selftest/knownfail
index 8f2f139..c296c0e 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -194,6 +194,7 @@
 ^samba3.smb2.durable-open.delete_on_close2
 ^samba3.smb2.durable-v2-open.app-instance
 ^samba3.smb2.durable-open.reopen1a-lease\(ad_dc\)$
+^samba3.smb2.durable-v2-open.reopen1a-lease\(ad_dc\)$
 ^samba4.smb2.ioctl.req_resume_key\(ad_dc_ntvfs\) # not supported by s4 ntvfs server
 ^samba4.smb2.ioctl.copy_chunk_\w*\(ad_dc_ntvfs\)	# not supported by s4 ntvfs server
 ^samba3.smb2.dir.one
diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c
index e48fb9b..b7d8920 100644
--- a/source4/torture/smb2/durable_v2_open.c
+++ b/source4/torture/smb2/durable_v2_open.c
@@ -740,6 +740,188 @@ done:
 }
 
 /**
+ * lease variant of reopen1a
+ *
+ * Basic test for doing a durable open and doing a session
+ * reconnect while the first session is still active and the
+ * handle is still open in the client.
+ * This closes the original session and  a durable reconnect on
+ * the new session succeeds depending on the client guid:
+ *
+ * Durable reconnect on a session with a different client guid fails.
+ * Durable reconnect on a session with the original client guid succeeds.
+ */
+bool test_durable_v2_open_reopen1a_lease(struct torture_context *tctx,
+					 struct smb2_tree *tree)
+{
+	NTSTATUS status;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	char fname[256];
+	struct smb2_handle _h;
+	struct smb2_handle *h = NULL;
+	struct smb2_create io;
+	struct GUID create_guid = GUID_random();
+	struct smb2_lease ls;
+	uint64_t lease_key;
+	bool ret = true;
+	struct smb2_tree *tree2 = NULL;
+	struct smb2_tree *tree3 = NULL;
+	uint64_t previous_session_id;
+	struct smbcli_options options;
+	struct GUID orig_client_guid;
+
+	options = tree->session->transport->options;
+	orig_client_guid = options.client_guid;
+
+	/* Choose a random name in case the state is left a little funky. */
+	snprintf(fname, 256, "durable_v2_open_reopen1a_lease_%s.dat",
+		 generate_random_str(tctx, 8));
+
+	smb2_util_unlink(tree, fname);
+
+	lease_key = random();
+	smb2_lease_create(&io, &ls, false /* dir */, fname,
+			  lease_key, smb2_util_lease_state("RWH"));
+	io.in.durable_open = false;
+	io.in.durable_open_v2 = true;
+	io.in.persistent_open = false;
+	io.in.create_guid = create_guid;
+	io.in.timeout = UINT32_MAX;
+
+	status = smb2_create(tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	_h = io.out.file.handle;
+	h = &_h;
+	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.durable_open, false);
+	CHECK_VAL(io.out.durable_open_v2, true);
+	CHECK_VAL(io.out.persistent_open, false);
+	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
+	CHECK_VAL(io.out.lease_response.lease_key.data[0], lease_key);
+	CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease_key);
+	CHECK_VAL(io.out.lease_response.lease_state,
+		  smb2_util_lease_state("RWH"));
+	CHECK_VAL(io.out.lease_response.lease_flags, 0);
+	CHECK_VAL(io.out.lease_response.lease_duration, 0);
+
+	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);
+
+	/*
+	 * a session reconnect on a second tcp connection
+	 * with a different client_guid does not allow
+	 * the durable reconnect.
+	 */
+
+	options.client_guid = GUID_random();
+
+	ret = torture_smb2_connection_ext(tctx, previous_session_id,
+					  &options, &tree2);
+	torture_assert_goto(tctx, ret, ret, done, "couldn't reconnect");
+
+	/*
+	 * check that this has deleted the old session
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle_v2 = h;
+	io.in.create_guid = create_guid;
+	io.in.lease_request = &ls;
+	status = smb2_create(tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
+	TALLOC_FREE(tree);
+
+	/*
+	 * but a durable reconnect on the new session with the wrong
+	 * client guid fails
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle_v2 = h;
+	io.in.create_guid = create_guid;
+	io.in.lease_request = &ls;
+	status = smb2_create(tree2, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+
+	/*
+	 * now a session reconnect on a second tcp connection
+	 * with original client_guid allows the durable reconnect.
+	 */
+
+	options.client_guid = orig_client_guid;
+	//options.client_guid = GUID_random();
+
+	ret = torture_smb2_connection_ext(tctx, previous_session_id,
+					  &options, &tree3);
+	torture_assert_goto(tctx, ret, ret, done, "couldn't reconnect");
+
+	/*
+	 * check that this has deleted the old session
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle_v2 = h;
+	io.in.create_guid = create_guid;
+	io.in.lease_request = &ls;
+	status = smb2_create(tree2, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+	TALLOC_FREE(tree2);
+
+	/*
+	 * but a durable reconnect on the new session succeeds:
+	 */
+
+	ZERO_STRUCT(io);
+	io.in.fname = fname;
+	io.in.durable_handle_v2 = h;
+	io.in.create_guid = create_guid;
+	io.in.lease_request = &ls;
+	status = smb2_create(tree3, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
+	CHECK_VAL(io.out.durable_open, false);
+	CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */
+	CHECK_VAL(io.out.persistent_open, false);
+	CHECK_VAL(io.out.timeout, io.in.timeout);
+	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
+	CHECK_VAL(io.out.lease_response.lease_key.data[0], lease_key);
+	CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease_key);
+	CHECK_VAL(io.out.lease_response.lease_state,
+		  smb2_util_lease_state("RWH"));
+	CHECK_VAL(io.out.lease_response.lease_flags, 0);
+	CHECK_VAL(io.out.lease_response.lease_duration, 0);
+	_h = io.out.file.handle;
+	h = &_h;
+
+done:
+	if (tree == NULL) {
+		tree = tree2;
+	}
+
+	if (tree == NULL) {
+		tree = tree3;
+	}
+
+	if (tree != NULL) {
+		if (h != NULL) {
+			smb2_util_close(tree, *h);
+		}
+
+		smb2_util_unlink(tree, fname);
+
+		talloc_free(tree);
+	}
+
+	talloc_free(mem_ctx);
+
+	return ret;
+}
+
+/**
  * basic test for doing a durable open
  * tcp disconnect, reconnect, do a durable reopen (succeeds)
  */
@@ -1832,6 +2014,7 @@ struct torture_suite *torture_smb2_durable_v2_open_init(void)
 	torture_suite_add_1smb2_test(suite, "open-lease", test_durable_v2_open_lease);
 	torture_suite_add_1smb2_test(suite, "reopen1", test_durable_v2_open_reopen1);
 	torture_suite_add_1smb2_test(suite, "reopen1a", test_durable_v2_open_reopen1a);
+	torture_suite_add_1smb2_test(suite, "reopen1a-lease", test_durable_v2_open_reopen1a_lease);
 	torture_suite_add_1smb2_test(suite, "reopen2", test_durable_v2_open_reopen2);
 	torture_suite_add_1smb2_test(suite, "reopen2b", test_durable_v2_open_reopen2b);
 	torture_suite_add_1smb2_test(suite, "reopen2c", test_durable_v2_open_reopen2c);
-- 
2.5.0

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


More information about the samba-technical mailing list