s4/torture: add a creditting test skipping a SMB2 MID
authorRalph Boehme <slow@samba.org>
Mon, 27 Feb 2017 11:55:04 +0000 (12:55 +0100)
committerJeremy Allison <jra@samba.org>
Sat, 4 Mar 2017 00:54:07 +0000 (01:54 +0100)
This tests that skipping a SMB2 MID the client's usable MID window is

[unused mid, unused mid + 8192]

The test currently fails against Samba as we only grant up to 512
credits. It passes against Windows 2016 as that grants up to 8192
credits by default.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Sat Mar  4 01:54:07 CET 2017 on sn-devel-144

selftest/knownfail
source4/selftest/tests.py
source4/torture/smb2/credits.c

index a5e2dd42ae065d86635356853476947172c70af4..7c5417b6bc18cb04086d67f345304e38671fdb0d 100644 (file)
 ^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_security_descriptor.*
 ^samba3.smb2.credits.session_setup_credits_granted.*
 ^samba3.smb2.credits.single_req_credits_granted.*
+^samba3.smb2.credits.skipped_mid.*
index 80bee039dbaacab4757284e514db46bcc92a9b67..ac601f5f217152509dc29fbcfc8d1eb4170e3489 100755 (executable)
@@ -303,7 +303,7 @@ for t in nbt_tests:
 ntvfsargs = ["--option=torture:sharedelay=100000", "--option=torture:oplocktimeout=3", "--option=torture:writetimeupdatedelay=500000"]
 
 # Filter smb2 tests that should not run against ad_dc_ntvfs
-smb2_s3only = ["smb2.change_notify_disabled", "smb2.dosmode"]
+smb2_s3only = ["smb2.change_notify_disabled", "smb2.dosmode", "smb2.credits"]
 smb2 = [x for x in smbtorture4_testsuites("smb2.") if x not in smb2_s3only]
 
 #The QFILEINFO-IPC test needs to be on ipc$
index d34b1d59d9a996d315430c2bcde5f25bffb4dd0d..43550c370e40de12332a0db57e7145b44fd82f56 100644 (file)
@@ -149,12 +149,118 @@ done:
        return ret;
 }
 
+static bool test_crediting_skipped_mid(struct torture_context *tctx,
+                                      struct smb2_tree *_tree)
+{
+       struct smbcli_options options;
+       struct smb2_transport *transport = NULL;
+       struct smb2_tree *tree = NULL;
+       struct smb2_handle h = {{0}};
+       struct smb2_create create;
+       const char *fname = "skipped_mid.dat";
+       uint64_t mid;
+       uint16_t cur_credits;
+       NTSTATUS status;
+       bool ret = true;
+       int i;
+
+       smb2_util_unlink(_tree, fname);
+
+       transport = _tree->session->transport;
+       options = transport->options;
+
+       status = smb2_logoff(_tree->session);
+       torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_logoff failed\n");
+       TALLOC_FREE(_tree);
+
+       options.max_credits = 8192;
+
+       ret = torture_smb2_connection_ext(tctx, 0, &options, &tree);
+       torture_assert_goto(tctx, ret == true, ret, done, "torture_smb2_connection_ext failed\n");
+
+       transport = tree->session->transport;
+
+       cur_credits = smb2cli_conn_get_cur_credits(transport->conn);
+       if (cur_credits != 8192) {
+               torture_result(tctx, TORTURE_FAIL, "Server only granted %" PRIu16" credits\n", cur_credits);
+               ret = false;
+               goto done;
+       }
+
+       ZERO_STRUCT(create);
+       create.in.impersonation_level   = NTCREATEX_IMPERSONATION_IMPERSONATION;
+       create.in.desired_access        = SEC_RIGHTS_FILE_ALL;
+       create.in.file_attributes       = FILE_ATTRIBUTE_NORMAL;
+       create.in.create_disposition    = NTCREATEX_DISP_OPEN_IF;
+       create.in.fname                 = fname;
+
+       status = smb2_create(tree, tctx, &create);
+       torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
+       h = create.out.file.handle;
+
+       /*
+        * See what happens if we skip a mid. As we want to avoid triggering our
+        * client side mid window check we keep conn->smb2.cur_credits
+        * unchanged so the server keeps granting credits until it's max mid
+        * windows size is reached at which point it will disconnect us:
+        *
+        * o Windows 2016 currently has a maximum mid window size of 8192 by
+        *   default
+        *
+        * o Samba's limit is 512
+        *
+        * o Windows 2008r2 uses some special algorithm (MS-SMB2 3.3.1.1
+        *   footnote <167>) that kicks in once a mid is skipped, resulting in a
+        *   maximum window size of 100-300 depending on the number of granted
+        *   credits at the moment of skipping a mid.
+        */
+
+       mid = smb2cli_conn_get_mid(tree->session->transport->conn);
+       smb2cli_conn_set_mid(tree->session->transport->conn, mid + 1);
+
+       for (i = 0; i < 8191; i++) {
+               status = smb2_util_write(tree, h, "\0", 0, 1);
+               if (!NT_STATUS_IS_OK(status)) {
+                       torture_result(tctx, TORTURE_FAIL, "Server only allowed %d writes\n", i);
+                       ret = false;
+                       goto done;
+               }
+       }
+
+       /*
+        * Now use the skipped mid (the smb2_util_close...), we should
+        * immediately get a full mid window of size 8192.
+        */
+       smb2cli_conn_set_mid(tree->session->transport->conn, mid);
+       status = smb2_util_close(tree, h);
+       torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_close failed\n");
+       ZERO_STRUCT(h);
+
+       cur_credits = smb2cli_conn_get_cur_credits(transport->conn);
+       if (cur_credits != 8192) {
+               torture_result(tctx, TORTURE_FAIL, "Server only granted %" PRIu16" credits\n", cur_credits);
+               ret = false;
+               goto done;
+       }
+
+       smb2cli_conn_set_mid(tree->session->transport->conn, mid + 8192);
+
+done:
+       if (!smb2_util_handle_empty(h)) {
+               smb2_util_close(tree, h);
+       }
+       smb2_util_unlink(tree, fname);
+       TALLOC_FREE(tree);
+       return ret;
+}
+
 struct torture_suite *torture_smb2_crediting_init(void)
 {
        struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "credits");
 
        torture_suite_add_1smb2_test(suite, "session_setup_credits_granted", test_session_setup_credits_granted);
        torture_suite_add_1smb2_test(suite, "single_req_credits_granted", test_single_req_credits_granted);
+       torture_suite_add_1smb2_test(suite, "skipped_mid", test_crediting_skipped_mid);
 
        suite->description = talloc_strdup(suite, "SMB2-CREDITS tests");