ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / smb2 / credits.c
blobb06bae720504b4d4814ee1d92855eac05821accb
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 credits
6 Copyright (C) Ralph Boehme 2017
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "torture/torture.h"
26 #include "torture/smb2/proto.h"
27 #include "../libcli/smb/smbXcli_base.h"
28 #include "lib/param/param.h"
30 /**
31 * Request 64k credits in negprot/sessionsetup and require at least 8k
33 * This passes against Windows 2016
34 **/
35 static bool test_session_setup_credits_granted(struct torture_context *tctx,
36 struct smb2_tree *_tree)
38 struct smbcli_options options;
39 struct smb2_transport *transport = NULL;
40 struct smb2_tree *tree = NULL;
41 uint16_t cur_credits;
42 NTSTATUS status;
43 bool ret = true;
45 transport = _tree->session->transport;
46 options = transport->options;
48 status = smb2_logoff(_tree->session);
49 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
50 "smb2_logoff failed\n");
51 TALLOC_FREE(_tree);
53 options.max_credits = 65535;
55 ret = torture_smb2_connection_ext(tctx, 0, &options, &tree);
56 torture_assert_goto(tctx, ret == true, ret, done,
57 "torture_smb2_connection_ext failed\n");
59 transport = tree->session->transport;
61 cur_credits = smb2cli_conn_get_cur_credits(transport->conn);
62 if (cur_credits < 8192) {
63 torture_result(tctx, TORTURE_FAIL,
64 "Server only granted %" PRIu16" credits\n",
65 cur_credits);
66 ret = false;
67 goto done;
70 done:
71 TALLOC_FREE(tree);
72 return ret;
75 /**
76 * Request 64K credits in a single SMB2 request and requite at least 8192
78 * This passes against Windows 2016
79 **/
80 static bool test_single_req_credits_granted(struct torture_context *tctx,
81 struct smb2_tree *_tree)
83 struct smbcli_options options;
84 struct smb2_transport *transport = NULL;
85 struct smb2_tree *tree = NULL;
86 struct smb2_handle h = {{0}};
87 struct smb2_create create;
88 const char *fname = "single_req_credits_granted.dat";
89 uint16_t cur_credits;
90 NTSTATUS status;
91 bool ret = true;
93 smb2_util_unlink(_tree, fname);
95 transport = _tree->session->transport;
96 options = transport->options;
98 status = smb2_logoff(_tree->session);
99 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
100 "smb2_logoff failed\n");
101 TALLOC_FREE(_tree);
103 options.max_credits = 1;
105 ret = torture_smb2_connection_ext(tctx, 0, &options, &tree);
106 torture_assert_goto(tctx, ret == true, ret, done,
107 "torture_smb2_connection_ext failed\n");
109 transport = tree->session->transport;
111 cur_credits = smb2cli_conn_get_cur_credits(transport->conn);
112 if (cur_credits != 1) {
113 torture_result(tctx, TORTURE_FAIL,
114 "Only wanted 1 credit but server granted %" PRIu16"\n",
115 cur_credits);
116 ret = false;
117 goto done;
120 smb2cli_conn_set_max_credits(transport->conn, 65535);
122 ZERO_STRUCT(create);
123 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
124 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
125 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
126 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
127 create.in.fname = fname;
129 status = smb2_create(tree, tctx, &create);
130 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
131 "smb2_create failed\n");
132 h = create.out.file.handle;
134 cur_credits = smb2cli_conn_get_cur_credits(transport->conn);
135 if (cur_credits < 8192) {
136 torture_result(tctx, TORTURE_FAIL,
137 "Server only granted %" PRIu16" credits\n",
138 cur_credits);
139 ret = false;
140 goto done;
143 done:
144 if (!smb2_util_handle_empty(h)) {
145 smb2_util_close(tree, h);
147 smb2_util_unlink(tree, fname);
148 TALLOC_FREE(tree);
149 return ret;
152 static bool test_crediting_skipped_mid(struct torture_context *tctx,
153 struct smb2_tree *_tree)
155 struct smbcli_options options;
156 struct smb2_transport *transport = NULL;
157 struct smb2_tree *tree = NULL;
158 struct smb2_handle h = {{0}};
159 struct smb2_create create;
160 const char *fname = "skipped_mid.dat";
161 uint64_t mid;
162 uint16_t cur_credits;
163 NTSTATUS status;
164 bool ret = true;
165 int i;
167 smb2_util_unlink(_tree, fname);
169 transport = _tree->session->transport;
170 options = transport->options;
172 status = smb2_logoff(_tree->session);
173 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_logoff failed\n");
174 TALLOC_FREE(_tree);
176 options.max_credits = 8192;
178 ret = torture_smb2_connection_ext(tctx, 0, &options, &tree);
179 torture_assert_goto(tctx, ret == true, ret, done, "torture_smb2_connection_ext failed\n");
181 transport = tree->session->transport;
183 cur_credits = smb2cli_conn_get_cur_credits(transport->conn);
184 if (cur_credits != 8192) {
185 torture_result(tctx, TORTURE_FAIL, "Server only granted %" PRIu16" credits\n", cur_credits);
186 ret = false;
187 goto done;
190 ZERO_STRUCT(create);
191 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
192 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
193 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
194 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
195 create.in.fname = fname;
197 status = smb2_create(tree, tctx, &create);
198 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
199 h = create.out.file.handle;
202 * See what happens if we skip a mid. As we want to avoid triggering our
203 * client side mid window check we keep conn->smb2.cur_credits
204 * unchanged so the server keeps granting credits until it's max mid
205 * windows size is reached at which point it will disconnect us:
207 * o Windows 2016 currently has a maximum mid window size of 8192 by
208 * default
210 * o Samba's limit is 512
212 * o Windows 2008r2 uses some special algorithm (MS-SMB2 3.3.1.1
213 * footnote <167>) that kicks in once a mid is skipped, resulting in a
214 * maximum window size of 100-300 depending on the number of granted
215 * credits at the moment of skipping a mid.
218 mid = smb2cli_conn_get_mid(tree->session->transport->conn);
219 smb2cli_conn_set_mid(tree->session->transport->conn, mid + 1);
221 for (i = 0; i < 8191; i++) {
222 status = smb2_util_write(tree, h, "\0", 0, 1);
223 if (!NT_STATUS_IS_OK(status)) {
224 torture_result(tctx, TORTURE_FAIL, "Server only allowed %d writes\n", i);
225 ret = false;
226 goto done;
231 * Now use the skipped mid (the smb2_util_close...), we should
232 * immediately get a full mid window of size 8192.
234 smb2cli_conn_set_mid(tree->session->transport->conn, mid);
235 status = smb2_util_close(tree, h);
236 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_close failed\n");
237 ZERO_STRUCT(h);
239 cur_credits = smb2cli_conn_get_cur_credits(transport->conn);
240 if (cur_credits != 8192) {
241 torture_result(tctx, TORTURE_FAIL, "Server only granted %" PRIu16" credits\n", cur_credits);
242 ret = false;
243 goto done;
246 smb2cli_conn_set_mid(tree->session->transport->conn, mid + 8192);
248 done:
249 if (!smb2_util_handle_empty(h)) {
250 smb2_util_close(tree, h);
252 smb2_util_unlink(tree, fname);
253 TALLOC_FREE(tree);
254 return ret;
257 struct torture_suite *torture_smb2_crediting_init(TALLOC_CTX *ctx)
259 struct torture_suite *suite = torture_suite_create(ctx, "credits");
261 torture_suite_add_1smb2_test(suite, "session_setup_credits_granted", test_session_setup_credits_granted);
262 torture_suite_add_1smb2_test(suite, "single_req_credits_granted", test_single_req_credits_granted);
263 torture_suite_add_1smb2_test(suite, "skipped_mid", test_crediting_skipped_mid);
265 suite->description = talloc_strdup(suite, "SMB2-CREDITS tests");
267 return suite;