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

Jeremy Allison jra at samba.org
Mon Mar 21 22:17:32 UTC 2016


On Thu, Mar 17, 2016 at 03:01:17AM +0100, Michael Adam wrote:
> 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

LGTM - pushed !

> 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
> 






More information about the samba-technical mailing list