summaryrefslogtreecommitdiff
path: root/source4/torture/smb2/replay.c
diff options
context:
space:
mode:
authorMichael Adam <obnox@samba.org>2016-03-01 23:03:50 +0100
committerMichael Adam <obnox@samba.org>2016-03-03 13:09:24 +0100
commit2036e1d27b7dde091531c4a8a516212e4b489df2 (patch)
treef3d51f788a8399f9310f445f69a1a9aaa219eff9 /source4/torture/smb2/replay.c
parent6eeabe43a2378a832dc21a1d8acdaf18b0dbc889 (diff)
downloadsamba-2036e1d27b7dde091531c4a8a516212e4b489df2.tar.gz
torture:smb2: add smb2.replay.replay-dhv2-lease-oplock
Open with a lease and replay with an oplock. Signed-off-by: Michael Adam <obnox@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source4/torture/smb2/replay.c')
-rw-r--r--source4/torture/smb2/replay.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c
index 600a8a6f52d..16d97bcc132 100644
--- a/source4/torture/smb2/replay.c
+++ b/source4/torture/smb2/replay.c
@@ -1048,6 +1048,150 @@ done:
}
/**
+ * Test durablity v2 create replay detection on single channel.
+ * Do the original create with a lease, and do the replay
+ * with an oplock.
+ */
+static bool test_replay_dhv2_lease_oplock(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ struct smb2_handle _h1;
+ struct smb2_handle *h1 = NULL;
+ struct smb2_handle _h2;
+ struct smb2_handle *h2 = NULL;
+ struct smb2_create io1, io2, ref1;
+ struct GUID create_guid = GUID_random();
+ bool ret = true;
+ const char *fname = BASEDIR "\\replay2_lease1.dat";
+ struct smb2_transport *transport = tree->session->transport;
+ uint32_t share_capabilities;
+ bool share_is_so;
+ uint32_t server_capabilities;
+ struct smb2_lease ls1, ls2;
+ uint64_t lease_key;
+
+ if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
+ torture_skip(tctx, "SMB 3.X Dialect family required for "
+ "replay tests\n");
+ }
+
+ server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
+ if (!(server_capabilities & SMB2_CAP_LEASING)) {
+ torture_skip(tctx, "leases are not supported");
+ }
+
+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
+
+ ZERO_STRUCT(break_info);
+ break_info.tctx = tctx;
+ tree->session->transport->oplock.handler = torture_oplock_ack_handler;
+ tree->session->transport->oplock.private_data = tree;
+
+ torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
+ "on Single Channel\n");
+ smb2_util_unlink(tree, fname);
+ status = torture_smb2_testdir(tree, BASEDIR, &_h1);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ smb2_util_close(tree, _h1);
+ CHECK_VAL(break_info.count, 0);
+
+ lease_key = random();
+
+ smb2_lease_create(&io1, &ls1, false /* dir */, fname,
+ lease_key, smb2_util_lease_state("RH"));
+ io1.in.durable_open = false;
+ io1.in.durable_open_v2 = true;
+ io1.in.persistent_open = false;
+ io1.in.create_guid = create_guid;
+ io1.in.timeout = UINT32_MAX;
+
+ status = smb2_create(tree, mem_ctx, &io1);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ ref1 = io1;
+ _h1 = io1.out.file.handle;
+ h1 = &_h1;
+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
+ CHECK_VAL(io1.out.durable_open, false);
+ CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
+ CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
+ CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
+ if (share_is_so) {
+ CHECK_VAL(io1.out.lease_response.lease_state,
+ smb2_util_lease_state("R"));
+ CHECK_VAL(io1.out.durable_open_v2, false);
+ CHECK_VAL(io1.out.timeout, 0);
+ } else {
+ CHECK_VAL(io1.out.lease_response.lease_state,
+ smb2_util_lease_state("RH"));
+ CHECK_VAL(io1.out.durable_open_v2, true);
+ CHECK_VAL(io1.out.timeout, io1.in.timeout);
+ }
+
+ /*
+ * Upgrade the lease to RWH
+ */
+ smb2_lease_create(&io2, &ls2, false /* dir */, fname,
+ lease_key, smb2_util_lease_state("RHW"));
+ io2.in.durable_open = false;
+ io2.in.durable_open_v2 = true;
+ io2.in.persistent_open = false;
+ io2.in.create_guid = GUID_random(); /* new guid... */
+ io2.in.timeout = UINT32_MAX;
+
+ status = smb2_create(tree, mem_ctx, &io2);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ _h2 = io2.out.file.handle;
+ h2 = &_h2;
+
+ /*
+ * Replay Durable V2 Create on single channel.
+ * We get the io from open #1 but with the
+ * upgraded lease.
+ */
+
+ smb2_oplock_create_share(&io2, fname,
+ smb2_util_share_access(""),
+ smb2_util_oplock_level("b"));
+ io2.in.durable_open = false;
+ io2.in.durable_open_v2 = true;
+ io2.in.persistent_open = false;
+ io2.in.create_guid = create_guid;
+ io2.in.timeout = UINT32_MAX;
+
+ /* adapt expected lease in response */
+ if (!share_is_so) {
+ ref1.out.lease_response.lease_state =
+ smb2_util_lease_state("RHW");
+ }
+
+ smb2cli_session_start_replay(tree->session->smbXcli);
+ status = smb2_create(tree, mem_ctx, &io1);
+ smb2cli_session_stop_replay(tree->session->smbXcli);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_CREATE_OUT(&io1, &ref1);
+ CHECK_VAL(break_info.count, 0);
+
+done:
+ smb2cli_session_stop_replay(tree->session->smbXcli);
+
+ if (h1 != NULL) {
+ smb2_util_close(tree, *h1);
+ }
+ if (h2 != NULL) {
+ smb2_util_close(tree, *h2);
+ }
+ smb2_deltree(tree, BASEDIR);
+
+ talloc_free(tree);
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+/**
* Test Durablity V2 Create Replay Detection on Multi Channel
*/
static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1)
@@ -1587,6 +1731,7 @@ struct torture_suite *torture_smb2_replay_init(void)
torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3);
torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1", test_replay_dhv2_lease1);
torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2", test_replay_dhv2_lease2);
+ torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock", test_replay_dhv2_lease_oplock);
torture_suite_add_1smb2_test(suite, "replay3", test_replay3);
torture_suite_add_1smb2_test(suite, "replay4", test_replay4);
torture_suite_add_1smb2_test(suite, "replay5", test_replay5);