diff options
| -rw-r--r-- | selftest/knownfail | 1 | ||||
| -rw-r--r-- | source4/torture/smb2/durable_open.c | 128 | 
2 files changed, 127 insertions, 2 deletions
diff --git a/selftest/knownfail b/selftest/knownfail index 35da8b32c3..f08b4d1586 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -159,6 +159,7 @@  ^samba3.smb2.durable-open.reopen2a  ^samba3.smb2.durable-open.reopen3  ^samba3.smb2.durable-open.reopen4 +^samba3.smb2.durable-open.delete_on_close1  ^samba3.smb2.durable-open.oplock  ^samba3.smb2.durable-v2-open.open-oplock  ^samba3.smb2.durable-v2-open.open-lease diff --git a/source4/torture/smb2/durable_open.c b/source4/torture/smb2/durable_open.c index 0c20f776ea..7e55052a05 100644 --- a/source4/torture/smb2/durable_open.c +++ b/source4/torture/smb2/durable_open.c @@ -30,8 +30,15 @@  #define CHECK_VAL(v, correct) do { \  	if ((v) != (correct)) { \ -		torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \ -				__location__, #v, (int)v, (int)correct); \ +		torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%llx - should be 0x%llx\n", \ +				__location__, #v, (unsigned long long)v, (unsigned long long)correct); \ +		ret = false; \ +	}} while (0) + +#define CHECK_NOT_VAL(v, correct) do { \ +	if ((v) == (correct)) { \ +		torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%llx - should not be 0x%llx\n", \ +				__location__, #v, (unsigned long long)v, (unsigned long long)correct); \  		ret = false; \  	}} while (0) @@ -699,6 +706,121 @@ done:  	return ret;  } +bool test_durable_open_delete_on_close1(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 io1, io2, io3; +	bool ret = true; +	struct smb2_transport *transport; +	struct smb2_session *session2; +	struct smb2_tree *tree2; +	union smb_fileinfo info1, info2; + +	/* Choose a random name in case the state is left a little funky. */ +	snprintf(fname, 256, "durable_open_delete_on_close1_%s.dat", +		 generate_random_str(tctx, 8)); + +	smb2_util_unlink(tree, fname); + +	smb2_oplock_create_share(&io1, fname, +				 smb2_util_share_access(""), +				 smb2_util_oplock_level("b")); +	io1.in.durable_open = true; +	io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE; + +	status = smb2_create(tree, mem_ctx, &io1); +	CHECK_STATUS(status, NT_STATUS_OK); +	_h = io1.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")); + +	ZERO_STRUCT(info1); +	info1.internal_information.level = RAW_FILEINFO_INTERNAL_INFORMATION; +	info1.internal_information.in.file.handle = _h; +	status = smb2_getinfo_file(tree, tree, &info1); +	CHECK_STATUS(status, NT_STATUS_OK); + +	/* +	 * do a session logoff, establish a new session and tree +	 * connect on the same transport, and try a durable reopen +	 */ +	transport = tree->session->transport; +	status = smb2_logoff(tree->session); +	CHECK_STATUS(status, NT_STATUS_OK); + +	if (!torture_smb2_session_setup(tctx, transport, +					0, /* previous_session_id */ +					mem_ctx, &session2)) +	{ +		torture_warning(tctx, "session setup failed.\n"); +		ret = false; +		goto done; +	} + +	/* +	 * the session setup has talloc-stolen the transport, +	 * so we can safely free the old tree+session for clarity +	 */ +	TALLOC_FREE(tree); + +	if (!torture_smb2_tree_connect(tctx, session2, mem_ctx, &tree2)) { +		torture_warning(tctx, "tree connect failed.\n"); +		ret = false; +		goto done; +	} + +	ZERO_STRUCT(io3); +	io3.in.fname = fname; +	io3.in.durable_handle = h; +	h = NULL; + +	smb2_oplock_create_share(&io2, fname, +				 smb2_util_share_access(""), +				 smb2_util_oplock_level("b")); +	io2.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE; + +	status = smb2_create(tree2, mem_ctx, &io2); +	CHECK_STATUS(status, NT_STATUS_OK); +	_h = io2.out.file.handle; +	h = &_h; +	CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE); +	CHECK_VAL(io2.out.durable_open, false); +	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b")); + +	ZERO_STRUCT(info2); +	info2.internal_information.level = RAW_FILEINFO_INTERNAL_INFORMATION; +	info2.internal_information.in.file.handle = _h; +	status = smb2_getinfo_file(tree2, tree2, &info2); +	CHECK_STATUS(status, NT_STATUS_OK); + +	CHECK_NOT_VAL(info1.internal_information.out.file_id, +		      info2.internal_information.out.file_id); + +	status = smb2_create(tree2, mem_ctx, &io3); +	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); + +done: +	if (h != NULL) { +		smb2_util_close(tree2, *h); +	} + +	smb2_util_unlink(tree2, fname); + +	talloc_free(tree); +	talloc_free(tree2); + +	talloc_free(mem_ctx); + +	return ret; +} +  /*     basic testing of SMB2 durable opens     regarding the position information on the handle @@ -1273,6 +1395,8 @@ struct torture_suite *torture_smb2_durable_open_init(void)  	torture_suite_add_1smb2_test(suite, "reopen2a", test_durable_open_reopen2a);  	torture_suite_add_1smb2_test(suite, "reopen3", test_durable_open_reopen3);  	torture_suite_add_1smb2_test(suite, "reopen4", test_durable_open_reopen4); +	torture_suite_add_1smb2_test(suite, "delete_on_close1", +				     test_durable_open_delete_on_close1);  	torture_suite_add_2smb2_test(suite, "file-position",  	    test_durable_open_file_position);  	torture_suite_add_2smb2_test(suite, "oplock", test_durable_open_oplock);  | 
