Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : test suite for SMB2 replay
5 :
6 : Copyright (C) Anubhav Rakshit 2014
7 : Copyright (C) Stefan Metzmacher 2014
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "libcli/smb2/smb2.h"
25 : #include "libcli/smb2/smb2_calls.h"
26 : #include "torture/torture.h"
27 : #include "torture/smb2/proto.h"
28 : #include "../libcli/smb/smbXcli_base.h"
29 : #include "lib/cmdline/cmdline.h"
30 : #include "auth/credentials/credentials.h"
31 : #include "libcli/security/security.h"
32 : #include "libcli/resolve/resolve.h"
33 : #include "lib/param/param.h"
34 : #include "lib/events/events.h"
35 : #include "oplock_break_handler.h"
36 : #include "lease_break_handler.h"
37 :
38 : #define CHECK_VAL(v, correct) do { \
39 : if ((v) != (correct)) { \
40 : torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
41 : __location__, #v, (int)v, (int)correct); \
42 : ret = false; \
43 : goto done; \
44 : }} while (0)
45 :
46 : #define CHECK_STATUS(status, correct) do { \
47 : if (!NT_STATUS_EQUAL(status, correct)) { \
48 : torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
49 : nt_errstr(status), nt_errstr(correct)); \
50 : ret = false; \
51 : goto done; \
52 : }} while (0)
53 :
54 : #define CHECK_CREATED(__io, __created, __attribute) \
55 : do { \
56 : CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
57 : CHECK_VAL((__io)->out.size, 0); \
58 : CHECK_VAL((__io)->out.file_attr, (__attribute)); \
59 : CHECK_VAL((__io)->out.reserved2, 0); \
60 : } while(0)
61 :
62 : #define CHECK_HANDLE(__h1, __h2) \
63 : do { \
64 : CHECK_VAL((__h1)->data[0], (__h2)->data[0]); \
65 : CHECK_VAL((__h1)->data[1], (__h2)->data[1]); \
66 : } while(0)
67 :
68 : #define __IO_OUT_VAL(__io1, __io2, __m) \
69 : CHECK_VAL((__io1)->out.__m, (__io2)->out.__m)
70 :
71 : #define CHECK_CREATE_OUT(__io1, __io2) \
72 : do { \
73 : CHECK_HANDLE(&(__io1)->out.file.handle, \
74 : &(__io2)->out.file.handle); \
75 : __IO_OUT_VAL(__io1, __io2, oplock_level); \
76 : __IO_OUT_VAL(__io1, __io2, create_action); \
77 : __IO_OUT_VAL(__io1, __io2, create_time); \
78 : __IO_OUT_VAL(__io1, __io2, access_time); \
79 : __IO_OUT_VAL(__io1, __io2, write_time); \
80 : __IO_OUT_VAL(__io1, __io2, change_time); \
81 : __IO_OUT_VAL(__io1, __io2, alloc_size); \
82 : __IO_OUT_VAL(__io1, __io2, size); \
83 : __IO_OUT_VAL(__io1, __io2, file_attr); \
84 : __IO_OUT_VAL(__io1, __io2, durable_open); \
85 : __IO_OUT_VAL(__io1, __io2, durable_open_v2); \
86 : __IO_OUT_VAL(__io1, __io2, persistent_open); \
87 : __IO_OUT_VAL(__io1, __io2, timeout); \
88 : __IO_OUT_VAL(__io1, __io2, blobs.num_blobs); \
89 : if ((__io1)->out.oplock_level == SMB2_OPLOCK_LEVEL_LEASE) { \
90 : __IO_OUT_VAL(__io1, __io2, lease_response.lease_state);\
91 : __IO_OUT_VAL(__io1, __io2, lease_response.lease_key.data[0]);\
92 : __IO_OUT_VAL(__io1, __io2, lease_response.lease_key.data[1]);\
93 : } \
94 : } while(0)
95 :
96 : #define WAIT_FOR_ASYNC_RESPONSE(__tctx, __req) do { \
97 : torture_comment((__tctx), "Waiting for async response: %s\n", #__req); \
98 : while (!(__req)->cancel.can_cancel && (__req)->state <= SMB2_REQUEST_RECV) { \
99 : if (tevent_loop_once((__tctx)->ev) != 0) { \
100 : break; \
101 : } \
102 : } \
103 : } while(0)
104 :
105 : #define BASEDIR "replaytestdir"
106 :
107 : /**
108 : * Test what happens when SMB2_FLAGS_REPLAY_OPERATION is enabled for various
109 : * commands. We want to verify if the server returns an error code or not.
110 : */
111 5 : static bool test_replay_commands(struct torture_context *tctx, struct smb2_tree *tree)
112 : {
113 5 : bool ret = true;
114 0 : NTSTATUS status;
115 0 : struct smb2_handle h;
116 0 : uint8_t buf[200];
117 0 : struct smb2_read rd;
118 0 : union smb_setfileinfo sfinfo;
119 0 : union smb_fileinfo qfinfo;
120 0 : union smb_ioctl ioctl;
121 0 : struct smb2_lock lck;
122 0 : struct smb2_lock_element el[2];
123 0 : struct smb2_flush f;
124 5 : TALLOC_CTX *tmp_ctx = talloc_new(tree);
125 5 : const char *fname = BASEDIR "\\replay_commands.dat";
126 5 : struct smb2_transport *transport = tree->session->transport;
127 :
128 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
129 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
130 : "Replay tests\n");
131 : }
132 :
133 4 : torture_reset_break_info(tctx, &break_info);
134 4 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
135 4 : tree->session->transport->oplock.private_data = tree;
136 :
137 4 : status = torture_smb2_testdir(tree, BASEDIR, &h);
138 4 : CHECK_STATUS(status, NT_STATUS_OK);
139 4 : smb2_util_close(tree, h);
140 :
141 4 : smb2cli_session_start_replay(tree->session->smbXcli);
142 :
143 4 : torture_comment(tctx, "Try Commands with Replay Flags Enabled\n");
144 :
145 4 : torture_comment(tctx, "Trying create\n");
146 4 : status = torture_smb2_testfile(tree, fname, &h);
147 4 : CHECK_STATUS(status, NT_STATUS_OK);
148 4 : CHECK_VAL(break_info.count, 0);
149 : /*
150 : * Wireshark shows that the response has SMB2_FLAGS_REPLAY_OPERATION
151 : * flags set. The server should ignore this flag.
152 : */
153 :
154 4 : torture_comment(tctx, "Trying write\n");
155 4 : status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
156 4 : CHECK_STATUS(status, NT_STATUS_OK);
157 :
158 4 : f = (struct smb2_flush) {
159 : .in.file.handle = h
160 : };
161 4 : torture_comment(tctx, "Trying flush\n");
162 4 : status = smb2_flush(tree, &f);
163 4 : CHECK_STATUS(status, NT_STATUS_OK);
164 :
165 4 : rd = (struct smb2_read) {
166 : .in.file.handle = h,
167 : .in.length = 10,
168 : .in.offset = 0,
169 : .in.min_count = 1
170 : };
171 4 : torture_comment(tctx, "Trying read\n");
172 4 : status = smb2_read(tree, tmp_ctx, &rd);
173 4 : CHECK_STATUS(status, NT_STATUS_OK);
174 4 : CHECK_VAL(rd.out.data.length, 10);
175 :
176 4 : sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
177 4 : sfinfo.position_information.in.file.handle = h;
178 4 : sfinfo.position_information.in.position = 0x1000;
179 4 : torture_comment(tctx, "Trying setinfo\n");
180 4 : status = smb2_setinfo_file(tree, &sfinfo);
181 4 : CHECK_STATUS(status, NT_STATUS_OK);
182 :
183 4 : qfinfo = (union smb_fileinfo) {
184 : .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
185 : .generic.in.file.handle = h
186 : };
187 4 : torture_comment(tctx, "Trying getinfo\n");
188 4 : status = smb2_getinfo_file(tree, tmp_ctx, &qfinfo);
189 4 : CHECK_STATUS(status, NT_STATUS_OK);
190 4 : CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
191 :
192 4 : ioctl = (union smb_ioctl) {
193 : .smb2.level = RAW_IOCTL_SMB2,
194 : .smb2.in.file.handle = h,
195 : .smb2.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID,
196 : .smb2.in.max_output_response = 64,
197 : .smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL
198 : };
199 4 : torture_comment(tctx, "Trying ioctl\n");
200 4 : status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
201 4 : CHECK_STATUS(status, NT_STATUS_OK);
202 :
203 4 : lck = (struct smb2_lock) {
204 : .in.locks = el,
205 : .in.lock_count = 0x0001,
206 : .in.lock_sequence = 0x00000000,
207 : .in.file.handle = h
208 : };
209 4 : el[0].reserved = 0x00000000;
210 4 : el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
211 : SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
212 :
213 4 : torture_comment(tctx, "Trying lock\n");
214 4 : el[0].offset = 0x0000000000000000;
215 4 : el[0].length = 0x0000000000000100;
216 4 : status = smb2_lock(tree, &lck);
217 4 : CHECK_STATUS(status, NT_STATUS_OK);
218 :
219 4 : lck.in.file.handle = h;
220 4 : el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
221 4 : status = smb2_lock(tree, &lck);
222 4 : CHECK_STATUS(status, NT_STATUS_OK);
223 :
224 4 : CHECK_VAL(break_info.count, 0);
225 4 : done:
226 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
227 4 : smb2_util_close(tree, h);
228 4 : smb2_deltree(tree, BASEDIR);
229 :
230 4 : talloc_free(tmp_ctx);
231 :
232 4 : return ret;
233 : }
234 :
235 : /**
236 : * Test replay detection without create GUID on single channel.
237 : * Regular creates can not be replayed.
238 : * The return code is unaffected of the REPLAY_OPERATION flag.
239 : */
240 5 : static bool test_replay_regular(struct torture_context *tctx,
241 : struct smb2_tree *tree)
242 : {
243 0 : NTSTATUS status;
244 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
245 0 : struct smb2_handle _h;
246 5 : struct smb2_handle *h = NULL;
247 0 : struct smb2_create io;
248 5 : uint32_t perms = 0;
249 5 : bool ret = true;
250 5 : const char *fname = BASEDIR "\\replay_regular.dat";
251 5 : struct smb2_transport *transport = tree->session->transport;
252 :
253 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
254 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
255 : "replay tests\n");
256 : }
257 :
258 4 : torture_reset_break_info(tctx, &break_info);
259 4 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
260 4 : tree->session->transport->oplock.private_data = tree;
261 :
262 4 : smb2_util_unlink(tree, fname);
263 4 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
264 4 : CHECK_STATUS(status, NT_STATUS_OK);
265 4 : smb2_util_close(tree, _h);
266 4 : CHECK_VAL(break_info.count, 0);
267 :
268 4 : torture_comment(tctx, "No replay detection for regular create\n");
269 :
270 4 : perms = SEC_STD_SYNCHRONIZE | SEC_STD_READ_CONTROL | SEC_STD_DELETE |
271 : SEC_DIR_WRITE_ATTRIBUTE | SEC_DIR_READ_ATTRIBUTE |
272 : SEC_DIR_WRITE_EA | SEC_FILE_APPEND_DATA |
273 : SEC_FILE_WRITE_DATA;
274 :
275 4 : io = (struct smb2_create) {
276 : .in.desired_access = perms,
277 : .in.file_attributes = 0,
278 : .in.create_disposition = NTCREATEX_DISP_CREATE,
279 : .in.share_access = NTCREATEX_SHARE_ACCESS_DELETE,
280 : .in.create_options = 0x0,
281 : .in.fname = fname
282 : };
283 :
284 4 : status = smb2_create(tree, tctx, &io);
285 4 : CHECK_STATUS(status, NT_STATUS_OK);
286 4 : CHECK_VAL(break_info.count, 0);
287 4 : _h = io.out.file.handle;
288 4 : h = &_h;
289 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
290 :
291 4 : smb2cli_session_start_replay(tree->session->smbXcli);
292 4 : status = smb2_create(tree, tctx, &io);
293 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
294 4 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
295 4 : CHECK_VAL(break_info.count, 0);
296 :
297 4 : smb2_util_close(tree, *h);
298 4 : h = NULL;
299 4 : smb2_util_unlink(tree, fname);
300 :
301 : /*
302 : * Same experiment with different create disposition.
303 : */
304 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
305 4 : status = smb2_create(tree, tctx, &io);
306 4 : CHECK_STATUS(status, NT_STATUS_OK);
307 4 : CHECK_VAL(break_info.count, 0);
308 4 : _h = io.out.file.handle;
309 4 : h = &_h;
310 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
311 :
312 4 : smb2cli_session_start_replay(tree->session->smbXcli);
313 4 : status = smb2_create(tree, tctx, &io);
314 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
315 4 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
316 4 : CHECK_VAL(break_info.count, 0);
317 :
318 4 : smb2_util_close(tree, *h);
319 4 : h = NULL;
320 4 : smb2_util_unlink(tree, fname);
321 :
322 : /*
323 : * Now with more generous share mode.
324 : */
325 4 : io.in.share_access = smb2_util_share_access("RWD");
326 4 : status = smb2_create(tree, tctx, &io);
327 4 : CHECK_STATUS(status, NT_STATUS_OK);
328 4 : CHECK_VAL(break_info.count, 0);
329 4 : _h = io.out.file.handle;
330 4 : h = &_h;
331 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
332 :
333 4 : smb2cli_session_start_replay(tree->session->smbXcli);
334 4 : status = smb2_create(tree, tctx, &io);
335 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
336 4 : CHECK_STATUS(status, NT_STATUS_OK);
337 4 : CHECK_VAL(break_info.count, 0);
338 :
339 4 : done:
340 4 : if (h != NULL) {
341 4 : smb2_util_close(tree, *h);
342 : }
343 4 : smb2_deltree(tree, BASEDIR);
344 :
345 4 : talloc_free(tree);
346 4 : talloc_free(mem_ctx);
347 :
348 4 : return ret;
349 : }
350 :
351 : /**
352 : * Test Durability V2 Create Replay Detection on Single Channel.
353 : */
354 5 : static bool test_replay_dhv2_oplock1(struct torture_context *tctx,
355 : struct smb2_tree *tree)
356 : {
357 0 : NTSTATUS status;
358 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
359 0 : struct smb2_handle _h;
360 5 : struct smb2_handle *h = NULL;
361 0 : struct smb2_create io, ref1;
362 5 : struct GUID create_guid = GUID_random();
363 5 : bool ret = true;
364 5 : const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat";
365 5 : struct smb2_transport *transport = tree->session->transport;
366 0 : uint32_t share_capabilities;
367 0 : bool share_is_so;
368 :
369 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
370 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
371 : "replay tests\n");
372 : }
373 :
374 4 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
375 4 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
376 :
377 4 : torture_reset_break_info(tctx, &break_info);
378 4 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
379 4 : tree->session->transport->oplock.private_data = tree;
380 :
381 4 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
382 : "Channel\n");
383 4 : smb2_util_unlink(tree, fname);
384 4 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
385 4 : CHECK_STATUS(status, NT_STATUS_OK);
386 4 : smb2_util_close(tree, _h);
387 4 : CHECK_VAL(break_info.count, 0);
388 :
389 4 : smb2_oplock_create_share(&io, fname,
390 : smb2_util_share_access(""),
391 4 : smb2_util_oplock_level("b"));
392 4 : io.in.durable_open = false;
393 4 : io.in.durable_open_v2 = true;
394 4 : io.in.persistent_open = false;
395 4 : io.in.create_guid = create_guid;
396 4 : io.in.timeout = UINT32_MAX;
397 :
398 4 : status = smb2_create(tree, mem_ctx, &io);
399 4 : CHECK_STATUS(status, NT_STATUS_OK);
400 4 : ref1 = io;
401 4 : _h = io.out.file.handle;
402 4 : h = &_h;
403 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
404 4 : CHECK_VAL(io.out.durable_open, false);
405 4 : if (share_is_so) {
406 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
407 0 : CHECK_VAL(io.out.durable_open_v2, false);
408 0 : CHECK_VAL(io.out.timeout, 0);
409 : } else {
410 4 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
411 4 : CHECK_VAL(io.out.durable_open_v2, true);
412 4 : CHECK_VAL(io.out.timeout, 300*1000);
413 : }
414 :
415 : /*
416 : * Replay Durable V2 Create on single channel
417 : */
418 4 : smb2cli_session_start_replay(tree->session->smbXcli);
419 4 : status = smb2_create(tree, mem_ctx, &io);
420 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
421 4 : CHECK_STATUS(status, NT_STATUS_OK);
422 4 : CHECK_CREATE_OUT(&io, &ref1);
423 4 : CHECK_VAL(break_info.count, 0);
424 :
425 4 : done:
426 4 : if (h != NULL) {
427 4 : smb2_util_close(tree, *h);
428 : }
429 4 : smb2_deltree(tree, BASEDIR);
430 :
431 4 : talloc_free(tree);
432 4 : talloc_free(mem_ctx);
433 :
434 4 : return ret;
435 : }
436 :
437 : /**
438 : * Test Durability V2 Create Replay Detection on Single Channel.
439 : * Hand in a different oplock level in the replay.
440 : * Server responds with the handed in oplock level and
441 : * corresponding durable status, but does not change the
442 : * oplock level or durable status of the opened file.
443 : */
444 5 : static bool test_replay_dhv2_oplock2(struct torture_context *tctx,
445 : struct smb2_tree *tree)
446 : {
447 0 : NTSTATUS status;
448 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
449 0 : struct smb2_handle _h;
450 5 : struct smb2_handle *h = NULL;
451 0 : struct smb2_create io, ref1, ref2;
452 5 : struct GUID create_guid = GUID_random();
453 5 : bool ret = true;
454 5 : const char *fname = BASEDIR "\\replay_dhv2_oplock2.dat";
455 5 : struct smb2_transport *transport = tree->session->transport;
456 0 : uint32_t share_capabilities;
457 0 : bool share_is_so;
458 :
459 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
460 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
461 : "replay tests\n");
462 : }
463 :
464 4 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
465 4 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
466 :
467 4 : torture_reset_break_info(tctx, &break_info);
468 4 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
469 4 : tree->session->transport->oplock.private_data = tree;
470 :
471 4 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
472 : "Channel\n");
473 4 : smb2_util_unlink(tree, fname);
474 4 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
475 4 : CHECK_STATUS(status, NT_STATUS_OK);
476 4 : smb2_util_close(tree, _h);
477 4 : CHECK_VAL(break_info.count, 0);
478 :
479 4 : smb2_oplock_create_share(&io, fname,
480 : smb2_util_share_access(""),
481 4 : smb2_util_oplock_level("b"));
482 4 : io.in.durable_open = false;
483 4 : io.in.durable_open_v2 = true;
484 4 : io.in.persistent_open = false;
485 4 : io.in.create_guid = create_guid;
486 4 : io.in.timeout = UINT32_MAX;
487 :
488 4 : status = smb2_create(tree, mem_ctx, &io);
489 4 : CHECK_STATUS(status, NT_STATUS_OK);
490 4 : ref1 = io;
491 4 : _h = io.out.file.handle;
492 4 : h = &_h;
493 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
494 4 : CHECK_VAL(io.out.durable_open, false);
495 4 : if (share_is_so) {
496 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
497 0 : CHECK_VAL(io.out.durable_open_v2, false);
498 0 : CHECK_VAL(io.out.timeout, 0);
499 : } else {
500 4 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
501 4 : CHECK_VAL(io.out.durable_open_v2, true);
502 4 : CHECK_VAL(io.out.timeout, 300*1000);
503 : }
504 :
505 : /*
506 : * Replay durable v2 create on single channel:
507 : *
508 : * Replay the create with a different oplock (none).
509 : * The server replies with the requested oplock level
510 : * and also only replies with durable handle based
511 : * on whether it could have been granted based on
512 : * the requested oplock type.
513 : */
514 4 : smb2_oplock_create_share(&io, fname,
515 : smb2_util_share_access(""),
516 4 : smb2_util_oplock_level(""));
517 4 : io.in.durable_open = false;
518 4 : io.in.durable_open_v2 = true;
519 4 : io.in.persistent_open = false;
520 4 : io.in.create_guid = create_guid;
521 4 : io.in.timeout = UINT32_MAX;
522 :
523 : /*
524 : * Adapt the response to the expected values
525 : */
526 4 : ref2 = ref1;
527 4 : ref2.out.oplock_level = smb2_util_oplock_level("");
528 4 : ref2.out.durable_open_v2 = false;
529 4 : ref2.out.timeout = 0;
530 4 : ref2.out.blobs.num_blobs = 0;
531 :
532 4 : smb2cli_session_start_replay(tree->session->smbXcli);
533 4 : status = smb2_create(tree, mem_ctx, &io);
534 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
535 4 : CHECK_STATUS(status, NT_STATUS_OK);
536 4 : CHECK_CREATE_OUT(&io, &ref2);
537 4 : CHECK_VAL(break_info.count, 0);
538 :
539 : /*
540 : * Prove that the open file still has a batch oplock
541 : * by breaking it with another open.
542 : */
543 4 : smb2_oplock_create_share(&io, fname,
544 : smb2_util_share_access(""),
545 4 : smb2_util_oplock_level("b"));
546 4 : io.in.durable_open = false;
547 4 : io.in.durable_open_v2 = true;
548 4 : io.in.persistent_open = false;
549 4 : io.in.create_guid = GUID_random();
550 4 : io.in.timeout = UINT32_MAX;
551 4 : status = smb2_create(tree, mem_ctx, &io);
552 4 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
553 :
554 4 : if (!share_is_so) {
555 4 : CHECK_VAL(break_info.count, 1);
556 4 : CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle);
557 4 : CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
558 4 : torture_reset_break_info(tctx, &break_info);
559 : }
560 :
561 0 : done:
562 4 : if (h != NULL) {
563 4 : smb2_util_close(tree, *h);
564 : }
565 4 : smb2_deltree(tree, BASEDIR);
566 :
567 4 : talloc_free(tree);
568 4 : talloc_free(mem_ctx);
569 :
570 4 : return ret;
571 : }
572 :
573 : /**
574 : * Test Durability V2 Create Replay Detection on Single Channel.
575 : * Replay with a different share mode. The share mode of
576 : * the opened file is not changed by this.
577 : */
578 5 : static bool test_replay_dhv2_oplock3(struct torture_context *tctx,
579 : struct smb2_tree *tree)
580 : {
581 0 : NTSTATUS status;
582 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
583 0 : struct smb2_handle _h;
584 5 : struct smb2_handle *h = NULL;
585 0 : struct smb2_create io, ref1;
586 5 : struct GUID create_guid = GUID_random();
587 5 : bool ret = true;
588 5 : const char *fname = BASEDIR "\\replay_dhv2_oplock3.dat";
589 5 : struct smb2_transport *transport = tree->session->transport;
590 0 : uint32_t share_capabilities;
591 0 : bool share_is_so;
592 :
593 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
594 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
595 : "replay tests\n");
596 : }
597 :
598 4 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
599 4 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
600 :
601 4 : torture_reset_break_info(tctx, &break_info);
602 4 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
603 4 : tree->session->transport->oplock.private_data = tree;
604 :
605 4 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
606 : "Channel\n");
607 4 : smb2_util_unlink(tree, fname);
608 4 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
609 4 : CHECK_STATUS(status, NT_STATUS_OK);
610 4 : smb2_util_close(tree, _h);
611 4 : CHECK_VAL(break_info.count, 0);
612 :
613 4 : smb2_oplock_create_share(&io, fname,
614 : smb2_util_share_access(""),
615 4 : smb2_util_oplock_level("b"));
616 4 : io.in.durable_open = false;
617 4 : io.in.durable_open_v2 = true;
618 4 : io.in.persistent_open = false;
619 4 : io.in.create_guid = create_guid;
620 4 : io.in.timeout = UINT32_MAX;
621 :
622 4 : status = smb2_create(tree, mem_ctx, &io);
623 4 : CHECK_STATUS(status, NT_STATUS_OK);
624 4 : ref1 = io;
625 4 : _h = io.out.file.handle;
626 4 : h = &_h;
627 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
628 4 : CHECK_VAL(io.out.durable_open, false);
629 4 : if (share_is_so) {
630 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
631 0 : CHECK_VAL(io.out.durable_open_v2, false);
632 0 : CHECK_VAL(io.out.timeout, 0);
633 : } else {
634 4 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
635 4 : CHECK_VAL(io.out.durable_open_v2, true);
636 4 : CHECK_VAL(io.out.timeout, 300*1000);
637 : }
638 :
639 : /*
640 : * Replay durable v2 create on single channel:
641 : *
642 : * Replay the create with a different share mode.
643 : * The server replies with the requested share
644 : * mode instead of that which is associated to
645 : * the handle.
646 : */
647 4 : smb2_oplock_create_share(&io, fname,
648 : smb2_util_share_access("RWD"),
649 4 : smb2_util_oplock_level("b"));
650 4 : io.in.durable_open = false;
651 4 : io.in.durable_open_v2 = true;
652 4 : io.in.persistent_open = false;
653 4 : io.in.create_guid = create_guid;
654 4 : io.in.timeout = UINT32_MAX;
655 :
656 4 : smb2cli_session_start_replay(tree->session->smbXcli);
657 4 : status = smb2_create(tree, mem_ctx, &io);
658 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
659 4 : CHECK_STATUS(status, NT_STATUS_OK);
660 4 : CHECK_CREATE_OUT(&io, &ref1);
661 4 : CHECK_VAL(break_info.count, 0);
662 :
663 : /*
664 : * In order to prove that the different share mode in the
665 : * replayed create had no effect on the open file handle,
666 : * show that a new create yields NT_STATUS_SHARING_VIOLATION.
667 : */
668 4 : smb2_oplock_create_share(&io, fname,
669 : smb2_util_share_access(""),
670 4 : smb2_util_oplock_level("b"));
671 4 : io.in.durable_open = false;
672 4 : io.in.durable_open_v2 = true;
673 4 : io.in.persistent_open = false;
674 4 : io.in.create_guid = GUID_random();
675 4 : io.in.timeout = UINT32_MAX;
676 4 : status = smb2_create(tree, mem_ctx, &io);
677 4 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
678 :
679 4 : if (!share_is_so) {
680 4 : CHECK_VAL(break_info.count, 1);
681 4 : CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle);
682 4 : CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
683 4 : torture_reset_break_info(tctx, &break_info);
684 : }
685 :
686 0 : done:
687 4 : if (h != NULL) {
688 4 : smb2_util_close(tree, *h);
689 : }
690 4 : smb2_deltree(tree, BASEDIR);
691 :
692 4 : talloc_free(tree);
693 4 : talloc_free(mem_ctx);
694 :
695 4 : return ret;
696 : }
697 :
698 : /**
699 : * Test Durability V2 Create Replay Detection on Single Channel.
700 : * Create with an oplock, and replay with a lease.
701 : */
702 5 : static bool test_replay_dhv2_oplock_lease(struct torture_context *tctx,
703 : struct smb2_tree *tree)
704 : {
705 0 : NTSTATUS status;
706 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
707 0 : struct smb2_handle _h;
708 5 : struct smb2_handle *h = NULL;
709 0 : struct smb2_create io;
710 5 : struct GUID create_guid = GUID_random();
711 5 : bool ret = true;
712 5 : const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat";
713 5 : struct smb2_transport *transport = tree->session->transport;
714 0 : uint32_t share_capabilities;
715 0 : bool share_is_so;
716 0 : uint32_t server_capabilities;
717 0 : struct smb2_lease ls;
718 0 : uint64_t lease_key;
719 :
720 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
721 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
722 : "replay tests\n");
723 : }
724 :
725 4 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
726 4 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
727 2 : torture_skip(tctx, "leases are not supported");
728 : }
729 :
730 2 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
731 2 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
732 :
733 2 : torture_reset_break_info(tctx, &break_info);
734 2 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
735 2 : tree->session->transport->oplock.private_data = tree;
736 :
737 2 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
738 : "Channel\n");
739 2 : smb2_util_unlink(tree, fname);
740 2 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
741 2 : CHECK_STATUS(status, NT_STATUS_OK);
742 2 : smb2_util_close(tree, _h);
743 2 : CHECK_VAL(break_info.count, 0);
744 :
745 2 : smb2_oplock_create_share(&io, fname,
746 : smb2_util_share_access(""),
747 2 : smb2_util_oplock_level("b"));
748 2 : io.in.durable_open = false;
749 2 : io.in.durable_open_v2 = true;
750 2 : io.in.persistent_open = false;
751 2 : io.in.create_guid = create_guid;
752 2 : io.in.timeout = UINT32_MAX;
753 :
754 2 : status = smb2_create(tree, mem_ctx, &io);
755 2 : CHECK_STATUS(status, NT_STATUS_OK);
756 2 : _h = io.out.file.handle;
757 2 : h = &_h;
758 2 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
759 2 : CHECK_VAL(io.out.durable_open, false);
760 2 : if (share_is_so) {
761 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
762 0 : CHECK_VAL(io.out.durable_open_v2, false);
763 0 : CHECK_VAL(io.out.timeout, 0);
764 : } else {
765 2 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
766 2 : CHECK_VAL(io.out.durable_open_v2, true);
767 2 : CHECK_VAL(io.out.timeout, 300*1000);
768 : }
769 :
770 : /*
771 : * Replay Durable V2 Create on single channel
772 : * but replay it with a lease instead of an oplock.
773 : */
774 2 : lease_key = random();
775 2 : smb2_lease_create(&io, &ls, false /* dir */, fname,
776 : lease_key, smb2_util_lease_state("RH"));
777 2 : io.in.durable_open = false;
778 2 : io.in.durable_open_v2 = true;
779 2 : io.in.persistent_open = false;
780 2 : io.in.create_guid = create_guid;
781 2 : io.in.timeout = UINT32_MAX;
782 :
783 2 : smb2cli_session_start_replay(tree->session->smbXcli);
784 2 : status = smb2_create(tree, mem_ctx, &io);
785 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
786 2 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
787 :
788 2 : done:
789 2 : if (h != NULL) {
790 2 : smb2_util_close(tree, *h);
791 : }
792 2 : smb2_deltree(tree, BASEDIR);
793 :
794 2 : talloc_free(tree);
795 2 : talloc_free(mem_ctx);
796 :
797 2 : return ret;
798 : }
799 :
800 :
801 : /**
802 : * Test durability v2 create replay detection on single channel.
803 : * Variant with leases instead of oplocks:
804 : * - open a file with a rh lease
805 : * - upgrade to a rwh lease with a second create
806 : * - replay the first create.
807 : * ==> it gets back the upgraded lease level
808 : */
809 5 : static bool test_replay_dhv2_lease1(struct torture_context *tctx,
810 : struct smb2_tree *tree)
811 : {
812 0 : NTSTATUS status;
813 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
814 0 : struct smb2_handle _h1;
815 5 : struct smb2_handle *h1 = NULL;
816 0 : struct smb2_handle _h2;
817 5 : struct smb2_handle *h2 = NULL;
818 0 : struct smb2_create io1, io2, ref1;
819 5 : struct GUID create_guid = GUID_random();
820 5 : bool ret = true;
821 5 : const char *fname = BASEDIR "\\replay2_lease1.dat";
822 5 : struct smb2_transport *transport = tree->session->transport;
823 0 : uint32_t share_capabilities;
824 0 : bool share_is_so;
825 0 : uint32_t server_capabilities;
826 0 : struct smb2_lease ls1, ls2;
827 0 : uint64_t lease_key;
828 :
829 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
830 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
831 : "replay tests\n");
832 : }
833 :
834 4 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
835 4 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
836 2 : torture_skip(tctx, "leases are not supported");
837 : }
838 :
839 2 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
840 2 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
841 :
842 2 : torture_reset_break_info(tctx, &break_info);
843 2 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
844 2 : tree->session->transport->oplock.private_data = tree;
845 :
846 2 : torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
847 : "on Single Channel\n");
848 2 : smb2_util_unlink(tree, fname);
849 2 : status = torture_smb2_testdir(tree, BASEDIR, &_h1);
850 2 : CHECK_STATUS(status, NT_STATUS_OK);
851 2 : smb2_util_close(tree, _h1);
852 2 : CHECK_VAL(break_info.count, 0);
853 :
854 2 : lease_key = random();
855 :
856 2 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
857 : lease_key, smb2_util_lease_state("RH"));
858 2 : io1.in.durable_open = false;
859 2 : io1.in.durable_open_v2 = true;
860 2 : io1.in.persistent_open = false;
861 2 : io1.in.create_guid = create_guid;
862 2 : io1.in.timeout = UINT32_MAX;
863 :
864 2 : status = smb2_create(tree, mem_ctx, &io1);
865 2 : CHECK_STATUS(status, NT_STATUS_OK);
866 2 : ref1 = io1;
867 2 : _h1 = io1.out.file.handle;
868 2 : h1 = &_h1;
869 2 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
870 2 : CHECK_VAL(io1.out.durable_open, false);
871 2 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
872 2 : CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
873 2 : CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
874 2 : if (share_is_so) {
875 0 : CHECK_VAL(io1.out.lease_response.lease_state,
876 : smb2_util_lease_state("R"));
877 0 : CHECK_VAL(io1.out.durable_open_v2, false);
878 0 : CHECK_VAL(io1.out.timeout, 0);
879 : } else {
880 2 : CHECK_VAL(io1.out.lease_response.lease_state,
881 : smb2_util_lease_state("RH"));
882 2 : CHECK_VAL(io1.out.durable_open_v2, true);
883 2 : CHECK_VAL(io1.out.timeout, 300*1000);
884 : }
885 :
886 : /*
887 : * Upgrade the lease to RWH
888 : */
889 2 : smb2_lease_create(&io2, &ls2, false /* dir */, fname,
890 : lease_key, smb2_util_lease_state("RHW"));
891 2 : io2.in.durable_open = false;
892 2 : io2.in.durable_open_v2 = true;
893 2 : io2.in.persistent_open = false;
894 2 : io2.in.create_guid = GUID_random(); /* new guid... */
895 2 : io2.in.timeout = UINT32_MAX;
896 :
897 2 : status = smb2_create(tree, mem_ctx, &io2);
898 2 : CHECK_STATUS(status, NT_STATUS_OK);
899 2 : _h2 = io2.out.file.handle;
900 2 : h2 = &_h2;
901 :
902 : /*
903 : * Replay Durable V2 Create on single channel.
904 : * We get the io from open #1 but with the
905 : * upgraded lease.
906 : */
907 :
908 : /* adapt expected lease in response */
909 2 : if (!share_is_so) {
910 2 : ref1.out.lease_response.lease_state =
911 2 : smb2_util_lease_state("RHW");
912 : }
913 :
914 2 : smb2cli_session_start_replay(tree->session->smbXcli);
915 2 : status = smb2_create(tree, mem_ctx, &io1);
916 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
917 2 : CHECK_STATUS(status, NT_STATUS_OK);
918 2 : CHECK_CREATE_OUT(&io1, &ref1);
919 2 : CHECK_VAL(break_info.count, 0);
920 :
921 2 : done:
922 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
923 :
924 2 : if (h1 != NULL) {
925 2 : smb2_util_close(tree, *h1);
926 : }
927 2 : if (h2 != NULL) {
928 2 : smb2_util_close(tree, *h2);
929 : }
930 2 : smb2_deltree(tree, BASEDIR);
931 :
932 2 : talloc_free(tree);
933 2 : talloc_free(mem_ctx);
934 :
935 2 : return ret;
936 : }
937 :
938 : /**
939 : * Test durability v2 create replay detection on single channel.
940 : * Variant with leases instead of oplocks, where the
941 : * replay does not specify the original lease level but
942 : * just a "R" lease. This still gives the upgraded lease
943 : * level in the reply.
944 : * - open a file with a rh lease
945 : * - upgrade to a rwh lease with a second create
946 : * - replay the first create.
947 : * ==> it gets back the upgraded lease level
948 : */
949 5 : static bool test_replay_dhv2_lease2(struct torture_context *tctx,
950 : struct smb2_tree *tree)
951 : {
952 0 : NTSTATUS status;
953 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
954 0 : struct smb2_handle _h1;
955 5 : struct smb2_handle *h1 = NULL;
956 0 : struct smb2_handle _h2;
957 5 : struct smb2_handle *h2 = NULL;
958 0 : struct smb2_create io1, io2, ref1;
959 5 : struct GUID create_guid = GUID_random();
960 5 : bool ret = true;
961 5 : const char *fname = BASEDIR "\\replay2_lease2.dat";
962 5 : struct smb2_transport *transport = tree->session->transport;
963 0 : uint32_t share_capabilities;
964 0 : bool share_is_so;
965 0 : uint32_t server_capabilities;
966 0 : struct smb2_lease ls1, ls2;
967 0 : uint64_t lease_key;
968 :
969 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
970 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
971 : "replay tests\n");
972 : }
973 :
974 4 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
975 4 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
976 2 : torture_skip(tctx, "leases are not supported");
977 : }
978 :
979 2 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
980 2 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
981 :
982 2 : torture_reset_break_info(tctx, &break_info);
983 2 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
984 2 : tree->session->transport->oplock.private_data = tree;
985 :
986 2 : torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
987 : "on Single Channel\n");
988 2 : smb2_util_unlink(tree, fname);
989 2 : status = torture_smb2_testdir(tree, BASEDIR, &_h1);
990 2 : CHECK_STATUS(status, NT_STATUS_OK);
991 2 : smb2_util_close(tree, _h1);
992 2 : CHECK_VAL(break_info.count, 0);
993 :
994 2 : lease_key = random();
995 :
996 2 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
997 : lease_key, smb2_util_lease_state("RH"));
998 2 : io1.in.durable_open = false;
999 2 : io1.in.durable_open_v2 = true;
1000 2 : io1.in.persistent_open = false;
1001 2 : io1.in.create_guid = create_guid;
1002 2 : io1.in.timeout = UINT32_MAX;
1003 :
1004 2 : status = smb2_create(tree, mem_ctx, &io1);
1005 2 : CHECK_STATUS(status, NT_STATUS_OK);
1006 2 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1007 2 : CHECK_VAL(io1.out.durable_open, false);
1008 2 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1009 2 : CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1010 2 : CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1011 2 : if (share_is_so) {
1012 0 : CHECK_VAL(io1.out.lease_response.lease_state,
1013 : smb2_util_lease_state("R"));
1014 0 : CHECK_VAL(io1.out.durable_open_v2, false);
1015 0 : CHECK_VAL(io1.out.timeout, 0);
1016 : } else {
1017 2 : CHECK_VAL(io1.out.lease_response.lease_state,
1018 : smb2_util_lease_state("RH"));
1019 2 : CHECK_VAL(io1.out.durable_open_v2, true);
1020 2 : CHECK_VAL(io1.out.timeout, 300*1000);
1021 : }
1022 2 : ref1 = io1;
1023 2 : _h1 = io1.out.file.handle;
1024 2 : h1 = &_h1;
1025 :
1026 : /*
1027 : * Upgrade the lease to RWH
1028 : */
1029 2 : smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1030 : lease_key, smb2_util_lease_state("RHW"));
1031 2 : io2.in.durable_open = false;
1032 2 : io2.in.durable_open_v2 = true;
1033 2 : io2.in.persistent_open = false;
1034 2 : io2.in.create_guid = GUID_random(); /* new guid... */
1035 2 : io2.in.timeout = UINT32_MAX;
1036 :
1037 2 : status = smb2_create(tree, mem_ctx, &io2);
1038 2 : CHECK_STATUS(status, NT_STATUS_OK);
1039 2 : _h2 = io2.out.file.handle;
1040 2 : h2 = &_h2;
1041 :
1042 : /*
1043 : * Replay Durable V2 Create on single channel.
1044 : * Changing the requested lease level to "R"
1045 : * does not change the response:
1046 : * We get the reply from open #1 but with the
1047 : * upgraded lease.
1048 : */
1049 :
1050 : /* adapt the expected response */
1051 2 : if (!share_is_so) {
1052 2 : ref1.out.lease_response.lease_state =
1053 2 : smb2_util_lease_state("RHW");
1054 : }
1055 :
1056 2 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1057 : lease_key, smb2_util_lease_state("R"));
1058 2 : io1.in.durable_open = false;
1059 2 : io1.in.durable_open_v2 = true;
1060 2 : io1.in.persistent_open = false;
1061 2 : io1.in.create_guid = create_guid;
1062 2 : io1.in.timeout = UINT32_MAX;
1063 :
1064 2 : smb2cli_session_start_replay(tree->session->smbXcli);
1065 2 : status = smb2_create(tree, mem_ctx, &io1);
1066 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
1067 2 : CHECK_STATUS(status, NT_STATUS_OK);
1068 2 : CHECK_CREATE_OUT(&io1, &ref1);
1069 2 : CHECK_VAL(break_info.count, 0);
1070 :
1071 2 : done:
1072 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
1073 :
1074 2 : if (h1 != NULL) {
1075 2 : smb2_util_close(tree, *h1);
1076 : }
1077 2 : if (h2 != NULL) {
1078 2 : smb2_util_close(tree, *h2);
1079 : }
1080 2 : smb2_deltree(tree, BASEDIR);
1081 :
1082 2 : talloc_free(tree);
1083 2 : talloc_free(mem_ctx);
1084 :
1085 2 : return ret;
1086 : }
1087 :
1088 : /**
1089 : * Test durability v2 create replay detection on single channel.
1090 : * create with a lease, and replay with a different lease key
1091 : */
1092 5 : static bool test_replay_dhv2_lease3(struct torture_context *tctx,
1093 : struct smb2_tree *tree)
1094 : {
1095 0 : NTSTATUS status;
1096 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1097 0 : struct smb2_handle _h1;
1098 5 : struct smb2_handle *h1 = NULL;
1099 0 : struct smb2_handle _h2;
1100 5 : struct smb2_handle *h2 = NULL;
1101 0 : struct smb2_create io1, io2;
1102 5 : struct GUID create_guid = GUID_random();
1103 5 : bool ret = true;
1104 5 : const char *fname = BASEDIR "\\replay2_lease2.dat";
1105 5 : struct smb2_transport *transport = tree->session->transport;
1106 0 : uint32_t share_capabilities;
1107 0 : bool share_is_so;
1108 0 : uint32_t server_capabilities;
1109 0 : struct smb2_lease ls1, ls2;
1110 0 : uint64_t lease_key;
1111 :
1112 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
1113 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
1114 : "replay tests\n");
1115 : }
1116 :
1117 4 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
1118 4 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
1119 2 : torture_skip(tctx, "leases are not supported");
1120 : }
1121 :
1122 2 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
1123 2 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1124 :
1125 2 : torture_reset_break_info(tctx, &break_info);
1126 2 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
1127 2 : tree->session->transport->oplock.private_data = tree;
1128 :
1129 2 : torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
1130 : "on Single Channel\n");
1131 2 : smb2_util_unlink(tree, fname);
1132 2 : status = torture_smb2_testdir(tree, BASEDIR, &_h1);
1133 2 : CHECK_STATUS(status, NT_STATUS_OK);
1134 2 : smb2_util_close(tree, _h1);
1135 2 : CHECK_VAL(break_info.count, 0);
1136 :
1137 2 : lease_key = random();
1138 :
1139 2 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1140 : lease_key, smb2_util_lease_state("RH"));
1141 2 : io1.in.durable_open = false;
1142 2 : io1.in.durable_open_v2 = true;
1143 2 : io1.in.persistent_open = false;
1144 2 : io1.in.create_guid = create_guid;
1145 2 : io1.in.timeout = UINT32_MAX;
1146 :
1147 2 : status = smb2_create(tree, mem_ctx, &io1);
1148 2 : CHECK_STATUS(status, NT_STATUS_OK);
1149 2 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1150 2 : CHECK_VAL(io1.out.durable_open, false);
1151 2 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1152 2 : CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1153 2 : CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1154 2 : if (share_is_so) {
1155 0 : CHECK_VAL(io1.out.lease_response.lease_state,
1156 : smb2_util_lease_state("R"));
1157 0 : CHECK_VAL(io1.out.durable_open_v2, false);
1158 0 : CHECK_VAL(io1.out.timeout, 0);
1159 : } else {
1160 2 : CHECK_VAL(io1.out.lease_response.lease_state,
1161 : smb2_util_lease_state("RH"));
1162 2 : CHECK_VAL(io1.out.durable_open_v2, true);
1163 2 : CHECK_VAL(io1.out.timeout, 300*1000);
1164 : }
1165 2 : _h1 = io1.out.file.handle;
1166 2 : h1 = &_h1;
1167 :
1168 : /*
1169 : * Upgrade the lease to RWH
1170 : */
1171 2 : smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1172 : lease_key, smb2_util_lease_state("RHW"));
1173 2 : io2.in.durable_open = false;
1174 2 : io2.in.durable_open_v2 = true;
1175 2 : io2.in.persistent_open = false;
1176 2 : io2.in.create_guid = GUID_random(); /* new guid... */
1177 2 : io2.in.timeout = UINT32_MAX;
1178 :
1179 2 : status = smb2_create(tree, mem_ctx, &io2);
1180 2 : CHECK_STATUS(status, NT_STATUS_OK);
1181 2 : _h2 = io2.out.file.handle;
1182 2 : h2 = &_h2;
1183 :
1184 : /*
1185 : * Replay Durable V2 Create on single channel.
1186 : * use a different lease key.
1187 : */
1188 :
1189 4 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1190 2 : random() /* lease key */,
1191 : smb2_util_lease_state("RH"));
1192 2 : io1.in.durable_open = false;
1193 2 : io1.in.durable_open_v2 = true;
1194 2 : io1.in.persistent_open = false;
1195 2 : io1.in.create_guid = create_guid;
1196 2 : io1.in.timeout = UINT32_MAX;
1197 :
1198 2 : smb2cli_session_start_replay(tree->session->smbXcli);
1199 2 : status = smb2_create(tree, mem_ctx, &io1);
1200 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
1201 2 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1202 :
1203 2 : done:
1204 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
1205 :
1206 2 : if (h1 != NULL) {
1207 2 : smb2_util_close(tree, *h1);
1208 : }
1209 2 : if (h2 != NULL) {
1210 2 : smb2_util_close(tree, *h2);
1211 : }
1212 2 : smb2_deltree(tree, BASEDIR);
1213 :
1214 2 : talloc_free(tree);
1215 2 : talloc_free(mem_ctx);
1216 :
1217 2 : return ret;
1218 : }
1219 :
1220 : /**
1221 : * Test durability v2 create replay detection on single channel.
1222 : * Do the original create with a lease, and do the replay
1223 : * with an oplock.
1224 : */
1225 5 : static bool test_replay_dhv2_lease_oplock(struct torture_context *tctx,
1226 : struct smb2_tree *tree)
1227 : {
1228 0 : NTSTATUS status;
1229 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1230 0 : struct smb2_handle _h1;
1231 5 : struct smb2_handle *h1 = NULL;
1232 0 : struct smb2_handle _h2;
1233 5 : struct smb2_handle *h2 = NULL;
1234 0 : struct smb2_create io1, io2, ref1;
1235 5 : struct GUID create_guid = GUID_random();
1236 5 : bool ret = true;
1237 5 : const char *fname = BASEDIR "\\replay2_lease1.dat";
1238 5 : struct smb2_transport *transport = tree->session->transport;
1239 0 : uint32_t share_capabilities;
1240 0 : bool share_is_so;
1241 0 : uint32_t server_capabilities;
1242 0 : struct smb2_lease ls1, ls2;
1243 0 : uint64_t lease_key;
1244 :
1245 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
1246 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
1247 : "replay tests\n");
1248 : }
1249 :
1250 4 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
1251 4 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
1252 2 : torture_skip(tctx, "leases are not supported");
1253 : }
1254 :
1255 2 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
1256 2 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1257 :
1258 2 : torture_reset_break_info(tctx, &break_info);
1259 2 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
1260 2 : tree->session->transport->oplock.private_data = tree;
1261 :
1262 2 : torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
1263 : "on Single Channel\n");
1264 2 : smb2_util_unlink(tree, fname);
1265 2 : status = torture_smb2_testdir(tree, BASEDIR, &_h1);
1266 2 : CHECK_STATUS(status, NT_STATUS_OK);
1267 2 : smb2_util_close(tree, _h1);
1268 2 : CHECK_VAL(break_info.count, 0);
1269 :
1270 2 : lease_key = random();
1271 :
1272 2 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1273 : lease_key, smb2_util_lease_state("RH"));
1274 2 : io1.in.durable_open = false;
1275 2 : io1.in.durable_open_v2 = true;
1276 2 : io1.in.persistent_open = false;
1277 2 : io1.in.create_guid = create_guid;
1278 2 : io1.in.timeout = UINT32_MAX;
1279 :
1280 2 : status = smb2_create(tree, mem_ctx, &io1);
1281 2 : CHECK_STATUS(status, NT_STATUS_OK);
1282 2 : ref1 = io1;
1283 2 : _h1 = io1.out.file.handle;
1284 2 : h1 = &_h1;
1285 2 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1286 2 : CHECK_VAL(io1.out.durable_open, false);
1287 2 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1288 2 : CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1289 2 : CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1290 2 : if (share_is_so) {
1291 0 : CHECK_VAL(io1.out.lease_response.lease_state,
1292 : smb2_util_lease_state("R"));
1293 0 : CHECK_VAL(io1.out.durable_open_v2, false);
1294 0 : CHECK_VAL(io1.out.timeout, 0);
1295 : } else {
1296 2 : CHECK_VAL(io1.out.lease_response.lease_state,
1297 : smb2_util_lease_state("RH"));
1298 2 : CHECK_VAL(io1.out.durable_open_v2, true);
1299 2 : CHECK_VAL(io1.out.timeout, 300*1000);
1300 : }
1301 :
1302 : /*
1303 : * Upgrade the lease to RWH
1304 : */
1305 2 : smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1306 : lease_key, smb2_util_lease_state("RHW"));
1307 2 : io2.in.durable_open = false;
1308 2 : io2.in.durable_open_v2 = true;
1309 2 : io2.in.persistent_open = false;
1310 2 : io2.in.create_guid = GUID_random(); /* new guid... */
1311 2 : io2.in.timeout = UINT32_MAX;
1312 :
1313 2 : status = smb2_create(tree, mem_ctx, &io2);
1314 2 : CHECK_STATUS(status, NT_STATUS_OK);
1315 2 : _h2 = io2.out.file.handle;
1316 2 : h2 = &_h2;
1317 :
1318 : /*
1319 : * Replay Durable V2 Create on single channel.
1320 : * We get the io from open #1 but with the
1321 : * upgraded lease.
1322 : */
1323 :
1324 2 : smb2_oplock_create_share(&io2, fname,
1325 : smb2_util_share_access(""),
1326 2 : smb2_util_oplock_level("b"));
1327 2 : io2.in.durable_open = false;
1328 2 : io2.in.durable_open_v2 = true;
1329 2 : io2.in.persistent_open = false;
1330 2 : io2.in.create_guid = create_guid;
1331 2 : io2.in.timeout = UINT32_MAX;
1332 :
1333 : /* adapt expected lease in response */
1334 2 : if (!share_is_so) {
1335 2 : ref1.out.lease_response.lease_state =
1336 2 : smb2_util_lease_state("RHW");
1337 : }
1338 :
1339 2 : smb2cli_session_start_replay(tree->session->smbXcli);
1340 2 : status = smb2_create(tree, mem_ctx, &io1);
1341 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
1342 2 : CHECK_STATUS(status, NT_STATUS_OK);
1343 2 : CHECK_CREATE_OUT(&io1, &ref1);
1344 2 : CHECK_VAL(break_info.count, 0);
1345 :
1346 2 : done:
1347 2 : smb2cli_session_stop_replay(tree->session->smbXcli);
1348 :
1349 2 : if (h1 != NULL) {
1350 2 : smb2_util_close(tree, *h1);
1351 : }
1352 2 : if (h2 != NULL) {
1353 2 : smb2_util_close(tree, *h2);
1354 : }
1355 2 : smb2_deltree(tree, BASEDIR);
1356 :
1357 2 : talloc_free(tree);
1358 2 : talloc_free(mem_ctx);
1359 :
1360 2 : return ret;
1361 : }
1362 :
1363 : /**
1364 : * This tests replay with a pending open on a single
1365 : * channel. It tests the case where the client2 open
1366 : * is deferred because it conflicts with a HANDLE lease,
1367 : * which is broken because the operation should otherwise
1368 : * return NT_STATUS_SHARING_VIOLATION.
1369 : *
1370 : * With a durablev2 request containing a create_guid:
1371 : * - client2_level = NONE:
1372 : * but without asking for an oplock nor a lease.
1373 : * - client2_level = BATCH:
1374 : * and asking for a batch oplock.
1375 : * - client2_level = LEASE
1376 : * and asking for an RWH lease.
1377 : *
1378 : * While another client holds a batch oplock or
1379 : * RWH lease. (client1_level => LEASE or BATCH).
1380 : *
1381 : * There are two modes of this test one, with releaseing
1382 : * the oplock/lease of client1 via close or ack.
1383 : * (release_op SMB2_OP_CLOSE/SMB2_OP_BREAK).
1384 : *
1385 : * Windows doesn't detect replays in this case and
1386 : * always result in NT_STATUS_SHARING_VIOLATION.
1387 : *
1388 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1389 : */
1390 20 : static bool _test_dhv2_pending1_vs_violation(struct torture_context *tctx,
1391 : const char *testname,
1392 : struct smb2_tree *tree1,
1393 : uint8_t client1_level,
1394 : uint8_t release_op,
1395 : struct smb2_tree *tree2,
1396 : uint8_t client2_level,
1397 : NTSTATUS orig21_reject_status,
1398 : NTSTATUS replay22_reject_status,
1399 : NTSTATUS replay23_reject_status)
1400 : {
1401 0 : NTSTATUS status;
1402 20 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1403 0 : struct smb2_handle _h1;
1404 20 : struct smb2_handle *h1 = NULL;
1405 20 : struct smb2_handle *h2f = NULL;
1406 0 : struct smb2_handle _h21;
1407 20 : struct smb2_handle *h21 = NULL;
1408 0 : struct smb2_handle _h23;
1409 20 : struct smb2_handle *h23 = NULL;
1410 0 : struct smb2_handle _h24;
1411 20 : struct smb2_handle *h24 = NULL;
1412 0 : struct smb2_create io1, io21, io22, io23, io24;
1413 20 : struct GUID create_guid1 = GUID_random();
1414 20 : struct GUID create_guid2 = GUID_random();
1415 20 : struct smb2_request *req21 = NULL;
1416 20 : struct smb2_request *req22 = NULL;
1417 20 : bool ret = true;
1418 0 : char fname[256];
1419 20 : struct smb2_transport *transport1 = tree1->session->transport;
1420 0 : uint32_t server_capabilities;
1421 0 : uint32_t share_capabilities;
1422 0 : struct smb2_lease ls1;
1423 0 : uint64_t lease_key1;
1424 20 : uint16_t lease_epoch1 = 0;
1425 0 : struct smb2_break op_ack1;
1426 0 : struct smb2_lease_break_ack lb_ack1;
1427 0 : struct smb2_lease ls2;
1428 0 : uint64_t lease_key2;
1429 20 : uint16_t lease_epoch2 = 0;
1430 0 : bool share_is_so;
1431 20 : struct smb2_transport *transport2 = tree2->session->transport;
1432 20 : int request_timeout2 = transport2->options.request_timeout;
1433 20 : struct smb2_session *session2 = tree2->session;
1434 20 : const char *hold_name = NULL;
1435 :
1436 20 : switch (client1_level) {
1437 20 : case SMB2_OPLOCK_LEVEL_LEASE:
1438 20 : hold_name = "RWH Lease";
1439 20 : break;
1440 0 : case SMB2_OPLOCK_LEVEL_BATCH:
1441 0 : hold_name = "BATCH Oplock";
1442 0 : break;
1443 0 : default:
1444 0 : smb_panic(__location__);
1445 0 : break;
1446 : }
1447 :
1448 20 : if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
1449 4 : torture_skip(tctx, "SMB 3.X Dialect family required for "
1450 : "replay tests\n");
1451 : }
1452 :
1453 16 : server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
1454 16 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
1455 8 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
1456 0 : client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
1457 8 : torture_skip(tctx, "leases are not supported");
1458 : }
1459 : }
1460 :
1461 8 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
1462 8 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1463 8 : if (share_is_so) {
1464 0 : torture_skip(tctx, talloc_asprintf(tctx,
1465 : "%s not supported on SCALEOUT share",
1466 : hold_name));
1467 : }
1468 :
1469 : /* Add some random component to the file name. */
1470 8 : snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
1471 : BASEDIR, testname, generate_random_str(tctx, 8));
1472 :
1473 8 : torture_reset_break_info(tctx, &break_info);
1474 8 : break_info.oplock_skip_ack = true;
1475 8 : ZERO_STRUCT(op_ack1);
1476 8 : torture_reset_lease_break_info(tctx, &lease_break_info);
1477 8 : lease_break_info.lease_skip_ack = true;
1478 8 : ZERO_STRUCT(lb_ack1);
1479 8 : transport1->oplock.handler = torture_oplock_ack_handler;
1480 8 : transport1->oplock.private_data = tree1;
1481 8 : transport1->lease.handler = torture_lease_handler;
1482 8 : transport1->lease.private_data = tree1;
1483 8 : smb2_keepalive(transport1);
1484 8 : transport2->oplock.handler = torture_oplock_ack_handler;
1485 8 : transport2->oplock.private_data = tree2;
1486 8 : transport2->lease.handler = torture_lease_handler;
1487 8 : transport2->lease.private_data = tree2;
1488 8 : smb2_keepalive(transport2);
1489 :
1490 8 : smb2_util_unlink(tree1, fname);
1491 8 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
1492 8 : CHECK_STATUS(status, NT_STATUS_OK);
1493 8 : smb2_util_close(tree1, _h1);
1494 8 : CHECK_VAL(break_info.count, 0);
1495 :
1496 8 : lease_key1 = random();
1497 8 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1498 8 : smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
1499 8 : lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
1500 : } else {
1501 0 : smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
1502 : }
1503 8 : io1.in.share_access = 0;
1504 8 : io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
1505 8 : io1.in.durable_open = false;
1506 8 : io1.in.durable_open_v2 = true;
1507 8 : io1.in.persistent_open = false;
1508 8 : io1.in.create_guid = create_guid1;
1509 8 : io1.in.timeout = UINT32_MAX;
1510 :
1511 8 : status = smb2_create(tree1, mem_ctx, &io1);
1512 8 : CHECK_STATUS(status, NT_STATUS_OK);
1513 8 : _h1 = io1.out.file.handle;
1514 8 : h1 = &_h1;
1515 8 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1516 8 : CHECK_VAL(io1.out.durable_open, false);
1517 8 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1518 8 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1519 8 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
1520 8 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
1521 8 : CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
1522 8 : CHECK_VAL(io1.out.lease_response_v2.lease_state,
1523 : smb2_util_lease_state("RWH"));
1524 : } else {
1525 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
1526 : }
1527 8 : CHECK_VAL(io1.out.durable_open_v2, true);
1528 8 : CHECK_VAL(io1.out.timeout, 300*1000);
1529 :
1530 8 : lease_key2 = random();
1531 8 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
1532 0 : smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
1533 0 : lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
1534 : } else {
1535 8 : smb2_oplock_create(&io21, fname, client2_level);
1536 : }
1537 8 : io21.in.share_access = 0;
1538 8 : io21.in.desired_access = SEC_RIGHTS_FILE_ALL;
1539 8 : io21.in.desired_access = SEC_RIGHTS_FILE_READ;
1540 8 : io21.in.durable_open = false;
1541 8 : io21.in.durable_open_v2 = true;
1542 8 : io21.in.persistent_open = false;
1543 8 : io21.in.create_guid = create_guid2;
1544 8 : io21.in.timeout = UINT32_MAX;
1545 8 : io24 = io23 = io22 = io21;
1546 :
1547 8 : req21 = smb2_create_send(tree2, &io21);
1548 8 : torture_assert(tctx, req21 != NULL, "req21");
1549 :
1550 8 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1551 8 : const struct smb2_lease_break *lb =
1552 : &lease_break_info.lease_break;
1553 8 : const struct smb2_lease *l = &lb->current_lease;
1554 8 : const struct smb2_lease_key *k = &l->lease_key;
1555 :
1556 8 : torture_wait_for_lease_break(tctx);
1557 8 : CHECK_VAL(break_info.count, 0);
1558 8 : CHECK_VAL(lease_break_info.count, 1);
1559 :
1560 8 : torture_assert(tctx,
1561 : lease_break_info.lease_transport == transport1,
1562 : "expect lease break on transport1\n");
1563 8 : CHECK_VAL(k->data[0], lease_key1);
1564 8 : CHECK_VAL(k->data[1], ~lease_key1);
1565 : /*
1566 : * With share none the handle lease
1567 : * is broken.
1568 : */
1569 8 : CHECK_VAL(lb->new_lease_state,
1570 : smb2_util_lease_state("RW"));
1571 8 : CHECK_VAL(lb->break_flags,
1572 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
1573 8 : CHECK_VAL(lb->new_epoch, lease_epoch1+1);
1574 8 : lease_epoch1 += 1;
1575 :
1576 8 : lb_ack1.in.lease.lease_key = lb->current_lease.lease_key;
1577 8 : lb_ack1.in.lease.lease_state = lb->new_lease_state;
1578 : } else {
1579 0 : torture_wait_for_oplock_break(tctx);
1580 0 : CHECK_VAL(break_info.count, 1);
1581 0 : CHECK_VAL(lease_break_info.count, 0);
1582 :
1583 0 : torture_assert(tctx,
1584 : break_info.received_transport == transport1,
1585 : "expect oplock break on transport1\n");
1586 0 : CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
1587 0 : CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
1588 0 : CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
1589 :
1590 0 : op_ack1.in = break_info.br.in;
1591 : }
1592 :
1593 8 : torture_reset_break_info(tctx, &break_info);
1594 8 : break_info.oplock_skip_ack = true;
1595 8 : torture_reset_lease_break_info(tctx, &lease_break_info);
1596 8 : lease_break_info.lease_skip_ack = true;
1597 :
1598 32 : WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
1599 :
1600 8 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1601 8 : torture_wait_for_lease_break(tctx);
1602 : } else {
1603 0 : torture_wait_for_oplock_break(tctx);
1604 : }
1605 8 : CHECK_VAL(break_info.count, 0);
1606 8 : CHECK_VAL(lease_break_info.count, 0);
1607 :
1608 8 : if (NT_STATUS_EQUAL(replay22_reject_status, NT_STATUS_SHARING_VIOLATION)) {
1609 : /*
1610 : * The server is broken and doesn't
1611 : * detect a replay, so we start an async
1612 : * request and send a lease break ack
1613 : * after 5 seconds in order to avoid
1614 : * the 35 second delay.
1615 : */
1616 4 : torture_comment(tctx, "Starting ASYNC Replay req22 expecting %s\n",
1617 : nt_errstr(replay22_reject_status));
1618 4 : smb2cli_session_start_replay(session2->smbXcli);
1619 4 : transport2->options.request_timeout = 15;
1620 4 : req22 = smb2_create_send(tree2, &io22);
1621 4 : torture_assert(tctx, req22 != NULL, "req22");
1622 4 : transport2->options.request_timeout = request_timeout2;
1623 4 : smb2cli_session_stop_replay(session2->smbXcli);
1624 :
1625 20 : WAIT_FOR_ASYNC_RESPONSE(tctx, req22);
1626 : } else {
1627 4 : torture_comment(tctx, "SYNC Replay io22 expecting %s\n",
1628 : nt_errstr(replay22_reject_status));
1629 4 : smb2cli_session_start_replay(session2->smbXcli);
1630 4 : transport2->options.request_timeout = 5;
1631 4 : status = smb2_create(tree2, tctx, &io22);
1632 4 : CHECK_STATUS(status, replay22_reject_status);
1633 4 : transport2->options.request_timeout = request_timeout2;
1634 4 : smb2cli_session_stop_replay(session2->smbXcli);
1635 : }
1636 :
1637 : /*
1638 : * We don't expect any action for 35 seconds
1639 : *
1640 : * But we sleep just 5 seconds before we
1641 : * ack the break.
1642 : */
1643 8 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1644 8 : torture_wait_for_lease_break(tctx);
1645 8 : torture_wait_for_lease_break(tctx);
1646 8 : torture_wait_for_lease_break(tctx);
1647 8 : torture_wait_for_lease_break(tctx);
1648 8 : torture_wait_for_lease_break(tctx);
1649 8 : CHECK_VAL(break_info.count, 0);
1650 8 : CHECK_VAL(lease_break_info.count, 0);
1651 :
1652 8 : if (release_op == SMB2_OP_CLOSE) {
1653 4 : torture_comment(tctx, "Closing h1\n");
1654 4 : smb2_util_close(tree1, _h1);
1655 4 : h1 = NULL;
1656 : } else {
1657 4 : torture_comment(tctx, "Acking lease_key1\n");
1658 4 : status = smb2_lease_break_ack(tree1, &lb_ack1);
1659 4 : CHECK_STATUS(status, NT_STATUS_OK);
1660 4 : CHECK_VAL(lb_ack1.out.lease.lease_flags, 0);
1661 4 : CHECK_VAL(lb_ack1.out.lease.lease_state, lb_ack1.in.lease.lease_state);
1662 4 : CHECK_VAL(lb_ack1.out.lease.lease_key.data[0], lease_key1);
1663 4 : CHECK_VAL(lb_ack1.out.lease.lease_key.data[1], ~lease_key1);
1664 4 : CHECK_VAL(lb_ack1.out.lease.lease_duration, 0);
1665 : }
1666 : } else {
1667 0 : torture_wait_for_oplock_break(tctx);
1668 0 : torture_wait_for_oplock_break(tctx);
1669 0 : torture_wait_for_oplock_break(tctx);
1670 0 : torture_wait_for_oplock_break(tctx);
1671 0 : torture_wait_for_oplock_break(tctx);
1672 0 : CHECK_VAL(break_info.count, 0);
1673 0 : CHECK_VAL(lease_break_info.count, 0);
1674 :
1675 0 : if (release_op == SMB2_OP_CLOSE) {
1676 0 : torture_comment(tctx, "Closing h1\n");
1677 0 : smb2_util_close(tree1, _h1);
1678 0 : h1 = NULL;
1679 : } else {
1680 0 : torture_comment(tctx, "Acking break h1\n");
1681 0 : status = smb2_break(tree1, &op_ack1);
1682 0 : CHECK_STATUS(status, NT_STATUS_OK);
1683 0 : CHECK_VAL(op_ack1.out.oplock_level, op_ack1.in.oplock_level);
1684 : }
1685 : }
1686 :
1687 8 : torture_comment(tctx, "Checking req21 expecting %s\n",
1688 : nt_errstr(orig21_reject_status));
1689 8 : status = smb2_create_recv(req21, tctx, &io21);
1690 8 : CHECK_STATUS(status, orig21_reject_status);
1691 8 : if (NT_STATUS_IS_OK(orig21_reject_status)) {
1692 4 : _h21 = io21.out.file.handle;
1693 4 : h21 = &_h21;
1694 4 : if (h2f == NULL) {
1695 4 : h2f = h21;
1696 : }
1697 4 : CHECK_VAL(h21->data[0], h2f->data[0]);
1698 4 : CHECK_VAL(h21->data[1], h2f->data[1]);
1699 4 : CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1700 4 : CHECK_VAL(io21.out.oplock_level, client2_level);
1701 4 : CHECK_VAL(io21.out.durable_open, false);
1702 4 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
1703 0 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[0], lease_key2);
1704 0 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[1], ~lease_key2);
1705 0 : CHECK_VAL(io21.out.lease_response_v2.lease_epoch, lease_epoch2);
1706 0 : CHECK_VAL(io21.out.lease_response_v2.lease_state,
1707 : smb2_util_lease_state("RHW"));
1708 0 : CHECK_VAL(io21.out.durable_open_v2, true);
1709 0 : CHECK_VAL(io21.out.timeout, 300*1000);
1710 4 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
1711 0 : CHECK_VAL(io21.out.durable_open_v2, true);
1712 0 : CHECK_VAL(io21.out.timeout, 300*1000);
1713 : } else {
1714 4 : CHECK_VAL(io21.out.durable_open_v2, false);
1715 : }
1716 : }
1717 :
1718 8 : if (NT_STATUS_EQUAL(replay22_reject_status, NT_STATUS_SHARING_VIOLATION)) {
1719 4 : torture_comment(tctx, "Checking req22 expecting %s\n",
1720 : nt_errstr(replay22_reject_status));
1721 4 : status = smb2_create_recv(req22, tctx, &io22);
1722 4 : CHECK_STATUS(status, replay22_reject_status);
1723 : }
1724 :
1725 4 : torture_comment(tctx, "SYNC Replay io23 expecting %s\n",
1726 : nt_errstr(replay23_reject_status));
1727 4 : smb2cli_session_start_replay(session2->smbXcli);
1728 4 : transport2->options.request_timeout = 5;
1729 4 : status = smb2_create(tree2, tctx, &io23);
1730 4 : transport2->options.request_timeout = request_timeout2;
1731 4 : CHECK_STATUS(status, replay23_reject_status);
1732 4 : smb2cli_session_stop_replay(session2->smbXcli);
1733 4 : if (NT_STATUS_IS_OK(replay23_reject_status)) {
1734 2 : _h23 = io23.out.file.handle;
1735 2 : h23 = &_h23;
1736 2 : if (h2f == NULL) {
1737 0 : h2f = h23;
1738 : }
1739 2 : CHECK_VAL(h23->data[0], h2f->data[0]);
1740 2 : CHECK_VAL(h23->data[1], h2f->data[1]);
1741 2 : CHECK_CREATED(&io23, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1742 2 : CHECK_VAL(io23.out.oplock_level, client2_level);
1743 2 : CHECK_VAL(io23.out.durable_open, false);
1744 2 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
1745 0 : CHECK_VAL(io23.out.lease_response_v2.lease_key.data[0], lease_key2);
1746 0 : CHECK_VAL(io23.out.lease_response_v2.lease_key.data[1], ~lease_key2);
1747 0 : CHECK_VAL(io23.out.lease_response_v2.lease_epoch, lease_epoch2);
1748 0 : CHECK_VAL(io23.out.lease_response_v2.lease_state,
1749 : smb2_util_lease_state("RHW"));
1750 0 : CHECK_VAL(io23.out.durable_open_v2, true);
1751 0 : CHECK_VAL(io23.out.timeout, 300*1000);
1752 2 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
1753 0 : CHECK_VAL(io23.out.durable_open_v2, true);
1754 0 : CHECK_VAL(io23.out.timeout, 300*1000);
1755 : } else {
1756 2 : CHECK_VAL(io23.out.durable_open_v2, false);
1757 : }
1758 : }
1759 :
1760 4 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1761 4 : torture_wait_for_lease_break(tctx);
1762 : } else {
1763 0 : torture_wait_for_oplock_break(tctx);
1764 : }
1765 4 : CHECK_VAL(break_info.count, 0);
1766 4 : CHECK_VAL(lease_break_info.count, 0);
1767 :
1768 4 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1769 4 : torture_wait_for_lease_break(tctx);
1770 : } else {
1771 0 : torture_wait_for_oplock_break(tctx);
1772 : }
1773 4 : CHECK_VAL(break_info.count, 0);
1774 4 : CHECK_VAL(lease_break_info.count, 0);
1775 :
1776 4 : if (h1 != NULL) {
1777 2 : torture_comment(tctx, "Closing h1\n");
1778 2 : smb2_util_close(tree1, _h1);
1779 2 : h1 = NULL;
1780 : }
1781 :
1782 4 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1783 4 : torture_wait_for_lease_break(tctx);
1784 : } else {
1785 0 : torture_wait_for_oplock_break(tctx);
1786 : }
1787 4 : CHECK_VAL(break_info.count, 0);
1788 4 : CHECK_VAL(lease_break_info.count, 0);
1789 :
1790 4 : torture_comment(tctx, "SYNC Replay io24 expecting %s\n",
1791 4 : nt_errstr(NT_STATUS_OK));
1792 4 : smb2cli_session_start_replay(session2->smbXcli);
1793 4 : transport2->options.request_timeout = 5;
1794 4 : status = smb2_create(tree2, tctx, &io24);
1795 4 : transport2->options.request_timeout = request_timeout2;
1796 4 : smb2cli_session_stop_replay(session2->smbXcli);
1797 4 : CHECK_STATUS(status, NT_STATUS_OK);
1798 4 : _h24 = io24.out.file.handle;
1799 4 : h24 = &_h24;
1800 4 : if (h2f == NULL) {
1801 2 : h2f = h24;
1802 : }
1803 4 : CHECK_VAL(h24->data[0], h2f->data[0]);
1804 4 : CHECK_VAL(h24->data[1], h2f->data[1]);
1805 4 : CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1806 4 : CHECK_VAL(io24.out.oplock_level, client2_level);
1807 4 : CHECK_VAL(io24.out.durable_open, false);
1808 4 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
1809 0 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
1810 0 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
1811 0 : CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
1812 0 : CHECK_VAL(io24.out.lease_response_v2.lease_state,
1813 : smb2_util_lease_state("RHW"));
1814 0 : CHECK_VAL(io24.out.durable_open_v2, true);
1815 0 : CHECK_VAL(io24.out.timeout, 300*1000);
1816 4 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
1817 0 : CHECK_VAL(io24.out.durable_open_v2, true);
1818 0 : CHECK_VAL(io24.out.timeout, 300*1000);
1819 : } else {
1820 4 : CHECK_VAL(io24.out.durable_open_v2, false);
1821 : }
1822 :
1823 4 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1824 4 : torture_wait_for_lease_break(tctx);
1825 : } else {
1826 0 : torture_wait_for_oplock_break(tctx);
1827 : }
1828 4 : CHECK_VAL(break_info.count, 0);
1829 4 : CHECK_VAL(lease_break_info.count, 0);
1830 4 : status = smb2_util_close(tree2, *h24);
1831 4 : CHECK_STATUS(status, NT_STATUS_OK);
1832 4 : h24 = NULL;
1833 :
1834 4 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1835 4 : torture_wait_for_lease_break(tctx);
1836 : } else {
1837 0 : torture_wait_for_oplock_break(tctx);
1838 : }
1839 4 : CHECK_VAL(break_info.count, 0);
1840 4 : CHECK_VAL(lease_break_info.count, 0);
1841 :
1842 4 : done:
1843 :
1844 8 : smbXcli_conn_disconnect(transport2->conn, NT_STATUS_LOCAL_DISCONNECT);
1845 :
1846 8 : if (h1 != NULL) {
1847 2 : smb2_util_close(tree1, *h1);
1848 : }
1849 :
1850 8 : smb2_deltree(tree1, BASEDIR);
1851 :
1852 8 : TALLOC_FREE(tree1);
1853 8 : talloc_free(mem_ctx);
1854 :
1855 8 : return ret;
1856 : }
1857 :
1858 : /*
1859 : * This tests replay with a pending open on a single
1860 : * channel. It tests the case where the client2 open
1861 : * is deferred because it conflicts with a HANDLE lease,
1862 : * which is broken because the operation should otherwise
1863 : * return NT_STATUS_SHARING_VIOLATION.
1864 : *
1865 : * With a durablev2 request containing a create_guid,
1866 : * but without asking for an oplock nor a lease.
1867 : *
1868 : * While another client holds an RWH lease,
1869 : * which is released by a close.
1870 : *
1871 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1872 : *
1873 : * This expects the sane reject status of
1874 : * NT_STATUS_FILE_NOT_AVAILABLE.
1875 : *
1876 : * It won't pass against Windows as it returns
1877 : * NT_STATUS_SHARING_VIOLATION to the replay (after
1878 : * 35 seconds), and this tests reports NT_STATUS_IO_TIMEOUT,
1879 : * as it expects a NT_STATUS_FILE_NOT_AVAILABLE within 5 seconds.
1880 : * see test_dhv2_pending1n_vs_violation_lease_close_windows().
1881 : */
1882 5 : static bool test_dhv2_pending1n_vs_violation_lease_close_sane(struct torture_context *tctx,
1883 : struct smb2_tree *tree1,
1884 : struct smb2_tree *tree2)
1885 : {
1886 10 : return _test_dhv2_pending1_vs_violation(tctx, __func__,
1887 : tree1,
1888 : SMB2_OPLOCK_LEVEL_LEASE,
1889 : SMB2_OP_CLOSE,
1890 : tree2,
1891 : SMB2_OPLOCK_LEVEL_NONE,
1892 5 : NT_STATUS_OK,
1893 5 : NT_STATUS_FILE_NOT_AVAILABLE,
1894 5 : NT_STATUS_OK);
1895 : }
1896 :
1897 : /*
1898 : * This tests replay with a pending open on a single
1899 : * channel. It tests the case where the client2 open
1900 : * is deferred because it conflicts with a HANDLE lease,
1901 : * which is broken because the operation should otherwise
1902 : * return NT_STATUS_SHARING_VIOLATION.
1903 : *
1904 : * With a durablev2 request containing a create_guid,
1905 : * but without asking for an oplock nor a lease.
1906 : *
1907 : * While another client holds an RWH lease,
1908 : * which is released by a close.
1909 : *
1910 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1911 : *
1912 : * This expects the strange behavior of ignoring the
1913 : * replay, which is returned done by Windows Servers.
1914 : *
1915 : * It won't pass against Samba as it returns
1916 : * NT_STATUS_FILE_NOT_AVAILABLE
1917 : * see test_dhv2_pending1n_vs_violation_lease_close_sane().
1918 : */
1919 5 : static bool test_dhv2_pending1n_vs_violation_lease_close_windows(struct torture_context *tctx,
1920 : struct smb2_tree *tree1,
1921 : struct smb2_tree *tree2)
1922 : {
1923 10 : return _test_dhv2_pending1_vs_violation(tctx, __func__,
1924 : tree1,
1925 : SMB2_OPLOCK_LEVEL_LEASE,
1926 : SMB2_OP_CLOSE,
1927 : tree2,
1928 : SMB2_OPLOCK_LEVEL_NONE,
1929 5 : NT_STATUS_OK,
1930 5 : NT_STATUS_SHARING_VIOLATION,
1931 5 : NT_STATUS_OK);
1932 : }
1933 :
1934 : /*
1935 : * This tests replay with a pending open on a single
1936 : * channel. It tests the case where the client2 open
1937 : * is deferred because it conflicts with a HANDLE lease,
1938 : * which is broken because the operation should otherwise
1939 : * return NT_STATUS_SHARING_VIOLATION.
1940 : *
1941 : * With a durablev2 request containing a create_guid,
1942 : * but without asking for an oplock nor a lease.
1943 : *
1944 : * While another client holds an RWH lease,
1945 : * which is released by a lease break ack.
1946 : *
1947 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1948 : *
1949 : * This expects the sane reject status of
1950 : * NT_STATUS_FILE_NOT_AVAILABLE.
1951 : *
1952 : * It won't pass against Windows as it returns
1953 : * NT_STATUS_SHARING_VIOLATION to the replay (after
1954 : * 35 seconds), and this tests reports NT_STATUS_IO_TIMEOUT,
1955 : * as it expects a NT_STATUS_FILE_NOT_AVAILABLE within 5 seconds.
1956 : * see test_dhv2_pending1n_vs_violation_lease_ack_windows().
1957 : */
1958 5 : static bool test_dhv2_pending1n_vs_violation_lease_ack_sane(struct torture_context *tctx,
1959 : struct smb2_tree *tree1,
1960 : struct smb2_tree *tree2)
1961 : {
1962 10 : return _test_dhv2_pending1_vs_violation(tctx, __func__,
1963 : tree1,
1964 : SMB2_OPLOCK_LEVEL_LEASE,
1965 : SMB2_OP_BREAK,
1966 : tree2,
1967 : SMB2_OPLOCK_LEVEL_NONE,
1968 5 : NT_STATUS_SHARING_VIOLATION,
1969 5 : NT_STATUS_FILE_NOT_AVAILABLE,
1970 5 : NT_STATUS_SHARING_VIOLATION);
1971 : }
1972 :
1973 : /*
1974 : * This tests replay with a pending open on a single
1975 : * channel. It tests the case where the client2 open
1976 : * is deferred because it conflicts with a HANDLE lease,
1977 : * which is broken because the operation should otherwise
1978 : * return NT_STATUS_SHARING_VIOLATION.
1979 : *
1980 : * With a durablev2 request containing a create_guid,
1981 : * but without asking for an oplock nor a lease.
1982 : *
1983 : * While another client holds an RWH lease,
1984 : * which is released by a close.
1985 : *
1986 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1987 : *
1988 : * This expects the strange behavior of ignoring the
1989 : * replay, which is returned done by Windows Servers.
1990 : *
1991 : * It won't pass against Samba as it returns
1992 : * NT_STATUS_FILE_NOT_AVAILABLE
1993 : * see test_dhv2_pending1n_vs_violation_lease_ack_sane().
1994 : */
1995 5 : static bool test_dhv2_pending1n_vs_violation_lease_ack_windows(struct torture_context *tctx,
1996 : struct smb2_tree *tree1,
1997 : struct smb2_tree *tree2)
1998 : {
1999 10 : return _test_dhv2_pending1_vs_violation(tctx, __func__,
2000 : tree1,
2001 : SMB2_OPLOCK_LEVEL_LEASE,
2002 : SMB2_OP_BREAK,
2003 : tree2,
2004 : SMB2_OPLOCK_LEVEL_NONE,
2005 5 : NT_STATUS_SHARING_VIOLATION,
2006 5 : NT_STATUS_SHARING_VIOLATION,
2007 5 : NT_STATUS_SHARING_VIOLATION);
2008 : }
2009 :
2010 : /**
2011 : * This tests replay with a pending open on a single
2012 : * channel.
2013 : *
2014 : * With a durablev2 request containing a create_guid and
2015 : * a share_access of READ/WRITE/DELETE:
2016 : * - client2_level = NONE:
2017 : * but without asking for an oplock nor a lease.
2018 : * - client2_level = BATCH:
2019 : * and asking for a batch oplock.
2020 : * - client2_level = LEASE
2021 : * and asking for an RWH lease.
2022 : *
2023 : * While another client holds a batch oplock or
2024 : * RWH lease. (client1_level => LEASE or BATCH).
2025 : * And allows share_access of READ/WRITE/DELETE.
2026 : *
2027 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2028 : */
2029 60 : static bool _test_dhv2_pending1_vs_hold(struct torture_context *tctx,
2030 : const char *testname,
2031 : uint8_t client1_level,
2032 : uint8_t client2_level,
2033 : NTSTATUS reject_status,
2034 : struct smb2_tree *tree1,
2035 : struct smb2_tree *tree2)
2036 : {
2037 0 : NTSTATUS status;
2038 60 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
2039 0 : struct smb2_handle _h1;
2040 60 : struct smb2_handle *h1 = NULL;
2041 0 : struct smb2_handle _h21;
2042 60 : struct smb2_handle *h21 = NULL;
2043 0 : struct smb2_handle _h24;
2044 60 : struct smb2_handle *h24 = NULL;
2045 0 : struct smb2_create io1, io21, io22, io23, io24;
2046 60 : struct GUID create_guid1 = GUID_random();
2047 60 : struct GUID create_guid2 = GUID_random();
2048 60 : struct smb2_request *req21 = NULL;
2049 60 : bool ret = true;
2050 0 : char fname[256];
2051 60 : struct smb2_transport *transport1 = tree1->session->transport;
2052 0 : uint32_t server_capabilities;
2053 0 : uint32_t share_capabilities;
2054 0 : struct smb2_lease ls1;
2055 0 : uint64_t lease_key1;
2056 60 : uint16_t lease_epoch1 = 0;
2057 0 : struct smb2_lease ls2;
2058 0 : uint64_t lease_key2;
2059 60 : uint16_t lease_epoch2 = 0;
2060 0 : bool share_is_so;
2061 60 : struct smb2_transport *transport2 = tree2->session->transport;
2062 60 : int request_timeout2 = transport2->options.request_timeout;
2063 60 : struct smb2_session *session2 = tree2->session;
2064 60 : const char *hold_name = NULL;
2065 :
2066 60 : switch (client1_level) {
2067 30 : case SMB2_OPLOCK_LEVEL_LEASE:
2068 30 : hold_name = "RWH Lease";
2069 30 : break;
2070 30 : case SMB2_OPLOCK_LEVEL_BATCH:
2071 30 : hold_name = "BATCH Oplock";
2072 30 : break;
2073 0 : default:
2074 0 : smb_panic(__location__);
2075 0 : break;
2076 : }
2077 :
2078 60 : if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
2079 12 : torture_skip(tctx, "SMB 3.X Dialect family required for "
2080 : "replay tests\n");
2081 : }
2082 :
2083 48 : server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
2084 48 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
2085 24 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
2086 0 : client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2087 16 : torture_skip(tctx, "leases are not supported");
2088 : }
2089 : }
2090 :
2091 32 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
2092 32 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
2093 32 : if (share_is_so) {
2094 0 : torture_skip(tctx, talloc_asprintf(tctx,
2095 : "%s not supported on SCALEOUT share",
2096 : hold_name));
2097 : }
2098 :
2099 : /* Add some random component to the file name. */
2100 32 : snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
2101 : BASEDIR, testname, generate_random_str(tctx, 8));
2102 :
2103 32 : torture_reset_break_info(tctx, &break_info);
2104 32 : break_info.oplock_skip_ack = true;
2105 32 : torture_reset_lease_break_info(tctx, &lease_break_info);
2106 32 : lease_break_info.lease_skip_ack = true;
2107 32 : transport1->oplock.handler = torture_oplock_ack_handler;
2108 32 : transport1->oplock.private_data = tree1;
2109 32 : transport1->lease.handler = torture_lease_handler;
2110 32 : transport1->lease.private_data = tree1;
2111 32 : smb2_keepalive(transport1);
2112 32 : transport2->oplock.handler = torture_oplock_ack_handler;
2113 32 : transport2->oplock.private_data = tree2;
2114 32 : transport2->lease.handler = torture_lease_handler;
2115 32 : transport2->lease.private_data = tree2;
2116 32 : smb2_keepalive(transport2);
2117 :
2118 32 : smb2_util_unlink(tree1, fname);
2119 32 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
2120 32 : CHECK_STATUS(status, NT_STATUS_OK);
2121 32 : smb2_util_close(tree1, _h1);
2122 32 : CHECK_VAL(break_info.count, 0);
2123 :
2124 32 : lease_key1 = random();
2125 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2126 12 : smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
2127 12 : lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
2128 : } else {
2129 20 : smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
2130 : }
2131 32 : io1.in.share_access = smb2_util_share_access("RWD");
2132 32 : io1.in.durable_open = false;
2133 32 : io1.in.durable_open_v2 = true;
2134 32 : io1.in.persistent_open = false;
2135 32 : io1.in.create_guid = create_guid1;
2136 32 : io1.in.timeout = UINT32_MAX;
2137 :
2138 32 : status = smb2_create(tree1, mem_ctx, &io1);
2139 32 : CHECK_STATUS(status, NT_STATUS_OK);
2140 32 : _h1 = io1.out.file.handle;
2141 32 : h1 = &_h1;
2142 32 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2143 32 : CHECK_VAL(io1.out.durable_open, false);
2144 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2145 12 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
2146 12 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
2147 12 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
2148 12 : CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
2149 12 : CHECK_VAL(io1.out.lease_response_v2.lease_state,
2150 : smb2_util_lease_state("RHW"));
2151 : } else {
2152 20 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2153 : }
2154 32 : CHECK_VAL(io1.out.durable_open_v2, true);
2155 32 : CHECK_VAL(io1.out.timeout, 300*1000);
2156 :
2157 32 : lease_key2 = random();
2158 32 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2159 8 : smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
2160 8 : lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
2161 : } else {
2162 24 : smb2_oplock_create(&io21, fname, client2_level);
2163 : }
2164 32 : io21.in.share_access = smb2_util_share_access("RWD");
2165 32 : io21.in.durable_open = false;
2166 32 : io21.in.durable_open_v2 = true;
2167 32 : io21.in.persistent_open = false;
2168 32 : io21.in.create_guid = create_guid2;
2169 32 : io21.in.timeout = UINT32_MAX;
2170 32 : io24 = io23 = io22 = io21;
2171 :
2172 32 : req21 = smb2_create_send(tree2, &io21);
2173 32 : torture_assert(tctx, req21 != NULL, "req21");
2174 :
2175 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2176 12 : const struct smb2_lease_break *lb =
2177 : &lease_break_info.lease_break;
2178 12 : const struct smb2_lease *l = &lb->current_lease;
2179 12 : const struct smb2_lease_key *k = &l->lease_key;
2180 :
2181 12 : torture_wait_for_lease_break(tctx);
2182 12 : CHECK_VAL(break_info.count, 0);
2183 12 : CHECK_VAL(lease_break_info.count, 1);
2184 :
2185 12 : torture_assert(tctx,
2186 : lease_break_info.lease_transport == transport1,
2187 : "expect lease break on transport1\n");
2188 12 : CHECK_VAL(k->data[0], lease_key1);
2189 12 : CHECK_VAL(k->data[1], ~lease_key1);
2190 12 : CHECK_VAL(lb->new_lease_state,
2191 : smb2_util_lease_state("RH"));
2192 12 : CHECK_VAL(lb->break_flags,
2193 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
2194 12 : CHECK_VAL(lb->new_epoch, lease_epoch1+1);
2195 12 : lease_epoch1 += 1;
2196 : } else {
2197 20 : torture_wait_for_oplock_break(tctx);
2198 20 : CHECK_VAL(break_info.count, 1);
2199 20 : CHECK_VAL(lease_break_info.count, 0);
2200 :
2201 20 : torture_assert(tctx,
2202 : break_info.received_transport == transport1,
2203 : "expect oplock break on transport1\n");
2204 20 : CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
2205 20 : CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
2206 20 : CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2207 : }
2208 :
2209 32 : torture_reset_break_info(tctx, &break_info);
2210 32 : break_info.oplock_skip_ack = true;
2211 32 : torture_reset_lease_break_info(tctx, &lease_break_info);
2212 32 : lease_break_info.lease_skip_ack = true;
2213 :
2214 128 : WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
2215 :
2216 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2217 12 : torture_wait_for_lease_break(tctx);
2218 : } else {
2219 20 : torture_wait_for_oplock_break(tctx);
2220 : }
2221 32 : CHECK_VAL(break_info.count, 0);
2222 32 : CHECK_VAL(lease_break_info.count, 0);
2223 :
2224 32 : smb2cli_session_start_replay(session2->smbXcli);
2225 32 : transport2->options.request_timeout = 5;
2226 32 : status = smb2_create(tree2, tctx, &io22);
2227 32 : transport2->options.request_timeout = request_timeout2;
2228 32 : CHECK_STATUS(status, reject_status);
2229 16 : smb2cli_session_stop_replay(session2->smbXcli);
2230 :
2231 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2232 6 : torture_wait_for_lease_break(tctx);
2233 : } else {
2234 10 : torture_wait_for_oplock_break(tctx);
2235 : }
2236 16 : CHECK_VAL(break_info.count, 0);
2237 16 : CHECK_VAL(lease_break_info.count, 0);
2238 :
2239 16 : smb2cli_session_start_replay(session2->smbXcli);
2240 16 : transport2->options.request_timeout = 5;
2241 16 : status = smb2_create(tree2, tctx, &io23);
2242 16 : transport2->options.request_timeout = request_timeout2;
2243 16 : CHECK_STATUS(status, reject_status);
2244 16 : smb2cli_session_stop_replay(session2->smbXcli);
2245 :
2246 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2247 6 : torture_wait_for_lease_break(tctx);
2248 : } else {
2249 10 : torture_wait_for_oplock_break(tctx);
2250 : }
2251 16 : CHECK_VAL(break_info.count, 0);
2252 16 : CHECK_VAL(lease_break_info.count, 0);
2253 :
2254 16 : smb2_util_close(tree1, _h1);
2255 16 : h1 = NULL;
2256 :
2257 16 : status = smb2_create_recv(req21, tctx, &io21);
2258 16 : CHECK_STATUS(status, NT_STATUS_OK);
2259 16 : _h21 = io21.out.file.handle;
2260 16 : h21 = &_h21;
2261 16 : CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2262 16 : CHECK_VAL(io21.out.oplock_level, client2_level);
2263 16 : CHECK_VAL(io21.out.durable_open, false);
2264 16 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2265 4 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[0], lease_key2);
2266 4 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[1], ~lease_key2);
2267 4 : CHECK_VAL(io21.out.lease_response_v2.lease_epoch, lease_epoch2);
2268 4 : CHECK_VAL(io21.out.lease_response_v2.lease_state,
2269 : smb2_util_lease_state("RHW"));
2270 4 : CHECK_VAL(io21.out.durable_open_v2, true);
2271 4 : CHECK_VAL(io21.out.timeout, 300*1000);
2272 12 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
2273 6 : CHECK_VAL(io21.out.durable_open_v2, true);
2274 6 : CHECK_VAL(io21.out.timeout, 300*1000);
2275 : } else {
2276 6 : CHECK_VAL(io21.out.durable_open_v2, false);
2277 : }
2278 :
2279 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2280 6 : torture_wait_for_lease_break(tctx);
2281 : } else {
2282 10 : torture_wait_for_oplock_break(tctx);
2283 : }
2284 16 : CHECK_VAL(break_info.count, 0);
2285 16 : CHECK_VAL(lease_break_info.count, 0);
2286 :
2287 16 : smb2cli_session_start_replay(session2->smbXcli);
2288 16 : status = smb2_create(tree2, tctx, &io24);
2289 16 : smb2cli_session_stop_replay(session2->smbXcli);
2290 16 : CHECK_STATUS(status, NT_STATUS_OK);
2291 16 : _h24 = io24.out.file.handle;
2292 16 : h24 = &_h24;
2293 16 : CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2294 16 : CHECK_VAL(h24->data[0], h21->data[0]);
2295 16 : CHECK_VAL(h24->data[1], h21->data[1]);
2296 16 : CHECK_VAL(io24.out.oplock_level, client2_level);
2297 16 : CHECK_VAL(io24.out.durable_open, false);
2298 16 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2299 4 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
2300 4 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
2301 4 : CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
2302 4 : CHECK_VAL(io24.out.lease_response_v2.lease_state,
2303 : smb2_util_lease_state("RHW"));
2304 4 : CHECK_VAL(io24.out.durable_open_v2, true);
2305 4 : CHECK_VAL(io24.out.timeout, 300*1000);
2306 12 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
2307 6 : CHECK_VAL(io24.out.durable_open_v2, true);
2308 6 : CHECK_VAL(io24.out.timeout, 300*1000);
2309 : } else {
2310 6 : CHECK_VAL(io24.out.durable_open_v2, false);
2311 : }
2312 :
2313 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2314 6 : torture_wait_for_lease_break(tctx);
2315 : } else {
2316 10 : torture_wait_for_oplock_break(tctx);
2317 : }
2318 16 : CHECK_VAL(break_info.count, 0);
2319 16 : CHECK_VAL(lease_break_info.count, 0);
2320 16 : status = smb2_util_close(tree2, *h24);
2321 16 : CHECK_STATUS(status, NT_STATUS_OK);
2322 16 : h24 = NULL;
2323 :
2324 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2325 6 : torture_wait_for_lease_break(tctx);
2326 : } else {
2327 10 : torture_wait_for_oplock_break(tctx);
2328 : }
2329 16 : CHECK_VAL(break_info.count, 0);
2330 16 : CHECK_VAL(lease_break_info.count, 0);
2331 :
2332 16 : done:
2333 :
2334 32 : smbXcli_conn_disconnect(transport2->conn, NT_STATUS_LOCAL_DISCONNECT);
2335 :
2336 32 : if (h1 != NULL) {
2337 16 : smb2_util_close(tree1, *h1);
2338 : }
2339 :
2340 32 : smb2_deltree(tree1, BASEDIR);
2341 :
2342 32 : TALLOC_FREE(tree1);
2343 32 : talloc_free(mem_ctx);
2344 :
2345 32 : return ret;
2346 : }
2347 :
2348 : /**
2349 : * This tests replay with a pending open on a single
2350 : * channel.
2351 : *
2352 : * With a durablev2 request containing a create_guid,
2353 : * a share_access of READ/WRITE/DELETE,
2354 : * but without asking for an oplock nor a lease.
2355 : *
2356 : * While another client holds a batch oplock.
2357 : * And allows share_access of READ/WRITE/DELETE.
2358 : *
2359 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2360 : *
2361 : * This expects the sane reject status of
2362 : * NT_STATUS_FILE_NOT_AVAILABLE.
2363 : *
2364 : * It won't pass against Windows as it returns
2365 : * NT_STATUS_ACCESS_DENIED see
2366 : * test_dhv2_pending1n_vs_oplock_windows().
2367 : */
2368 5 : static bool test_dhv2_pending1n_vs_oplock_sane(struct torture_context *tctx,
2369 : struct smb2_tree *tree1,
2370 : struct smb2_tree *tree2)
2371 : {
2372 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2373 : SMB2_OPLOCK_LEVEL_BATCH,
2374 : SMB2_OPLOCK_LEVEL_NONE,
2375 5 : NT_STATUS_FILE_NOT_AVAILABLE,
2376 : tree1, tree2);
2377 : }
2378 :
2379 : /**
2380 : * This tests replay with a pending open on a single
2381 : * channel.
2382 : *
2383 : * With a durablev2 request containing a create_guid,
2384 : * a share_access of READ/WRITE/DELETE,
2385 : * but without asking for an oplock nor a lease.
2386 : *
2387 : * While another client holds a batch oplock.
2388 : * And allows share_access of READ/WRITE/DELETE.
2389 : *
2390 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2391 : *
2392 : * This expects the strange reject status of
2393 : * NT_STATUS_ACCESS_DENIED, which is returned
2394 : * by Windows Servers.
2395 : *
2396 : * It won't pass against Samba as it returns
2397 : * NT_STATUS_FILE_NOT_AVAILABLE. see
2398 : * test_dhv2_pending1n_vs_oplock_sane.
2399 : */
2400 5 : static bool test_dhv2_pending1n_vs_oplock_windows(struct torture_context *tctx,
2401 : struct smb2_tree *tree1,
2402 : struct smb2_tree *tree2)
2403 : {
2404 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2405 : SMB2_OPLOCK_LEVEL_BATCH,
2406 : SMB2_OPLOCK_LEVEL_NONE,
2407 5 : NT_STATUS_ACCESS_DENIED,
2408 : tree1, tree2);
2409 : }
2410 :
2411 : /**
2412 : * This tests replay with a pending open on a single
2413 : * channel.
2414 : *
2415 : * With a durablev2 request containing a create_guid,
2416 : * a share_access of READ/WRITE/DELETE,
2417 : * but without asking for an oplock nor a lease.
2418 : *
2419 : * While another client holds an RWH lease.
2420 : * And allows share_access of READ/WRITE/DELETE.
2421 : *
2422 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2423 : *
2424 : * This expects the sane reject status of
2425 : * NT_STATUS_FILE_NOT_AVAILABLE.
2426 : *
2427 : * It won't pass against Windows as it returns
2428 : * NT_STATUS_ACCESS_DENIED see
2429 : * test_dhv2_pending1n_vs_lease_windows().
2430 : */
2431 5 : static bool test_dhv2_pending1n_vs_lease_sane(struct torture_context *tctx,
2432 : struct smb2_tree *tree1,
2433 : struct smb2_tree *tree2)
2434 : {
2435 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2436 : SMB2_OPLOCK_LEVEL_LEASE,
2437 : SMB2_OPLOCK_LEVEL_NONE,
2438 5 : NT_STATUS_FILE_NOT_AVAILABLE,
2439 : tree1, tree2);
2440 : }
2441 :
2442 : /**
2443 : * This tests replay with a pending open on a single
2444 : * channel.
2445 : *
2446 : * With a durablev2 request containing a create_guid,
2447 : * a share_access of READ/WRITE/DELETE,
2448 : * but without asking for an oplock nor a lease.
2449 : *
2450 : * While another client holds an RWH lease.
2451 : * And allows share_access of READ/WRITE/DELETE.
2452 : *
2453 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2454 : *
2455 : * This expects the strange reject status of
2456 : * NT_STATUS_ACCESS_DENIED, which is returned
2457 : * by Windows Servers.
2458 : *
2459 : * It won't pass against Samba as it returns
2460 : * NT_STATUS_FILE_NOT_AVAILABLE. see
2461 : * test_dhv2_pending1n_vs_lease_sane.
2462 : */
2463 5 : static bool test_dhv2_pending1n_vs_lease_windows(struct torture_context *tctx,
2464 : struct smb2_tree *tree1,
2465 : struct smb2_tree *tree2)
2466 : {
2467 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2468 : SMB2_OPLOCK_LEVEL_LEASE,
2469 : SMB2_OPLOCK_LEVEL_NONE,
2470 5 : NT_STATUS_ACCESS_DENIED,
2471 : tree1, tree2);
2472 : }
2473 :
2474 : /**
2475 : * This tests replay with a pending open on a single
2476 : * channel.
2477 : *
2478 : * With a durablev2 request containing a create_guid,
2479 : * a share_access of READ/WRITE/DELETE,
2480 : * and asking for a v2 lease.
2481 : *
2482 : * While another client holds a batch oplock.
2483 : * And allows share_access of READ/WRITE/DELETE.
2484 : *
2485 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2486 : *
2487 : * This expects the sane reject status of
2488 : * NT_STATUS_FILE_NOT_AVAILABLE.
2489 : *
2490 : * It won't pass against Windows as it returns
2491 : * NT_STATUS_ACCESS_DENIED see
2492 : * test_dhv2_pending1l_vs_oplock_windows().
2493 : */
2494 5 : static bool test_dhv2_pending1l_vs_oplock_sane(struct torture_context *tctx,
2495 : struct smb2_tree *tree1,
2496 : struct smb2_tree *tree2)
2497 : {
2498 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2499 : SMB2_OPLOCK_LEVEL_BATCH,
2500 : SMB2_OPLOCK_LEVEL_LEASE,
2501 5 : NT_STATUS_FILE_NOT_AVAILABLE,
2502 : tree1, tree2);
2503 : }
2504 :
2505 : /**
2506 : * This tests replay with a pending open on a single
2507 : * channel.
2508 : *
2509 : * With a durablev2 request containing a create_guid,
2510 : * a share_access of READ/WRITE/DELETE,
2511 : * and asking for a v2 lease.
2512 : *
2513 : * While another client holds a batch oplock.
2514 : * And allows share_access of READ/WRITE/DELETE.
2515 : *
2516 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2517 : *
2518 : * This expects the strange reject status of
2519 : * NT_STATUS_ACCESS_DENIED, which is returned
2520 : * by Windows Servers.
2521 : *
2522 : * It won't pass against Samba as it returns
2523 : * NT_STATUS_FILE_NOT_AVAILABLE. see
2524 : * test_dhv2_pending1l_vs_oplock_sane.
2525 : */
2526 5 : static bool test_dhv2_pending1l_vs_oplock_windows(struct torture_context *tctx,
2527 : struct smb2_tree *tree1,
2528 : struct smb2_tree *tree2)
2529 : {
2530 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2531 : SMB2_OPLOCK_LEVEL_BATCH,
2532 : SMB2_OPLOCK_LEVEL_LEASE,
2533 5 : NT_STATUS_ACCESS_DENIED,
2534 : tree1, tree2);
2535 : }
2536 :
2537 : /**
2538 : * This tests replay with a pending open on a single
2539 : * channel.
2540 : *
2541 : * With a durablev2 request containing a create_guid,
2542 : * a share_access of READ/WRITE/DELETE,
2543 : * and asking for a v2 lease.
2544 : *
2545 : * While another client holds an RWH lease.
2546 : * And allows share_access of READ/WRITE/DELETE.
2547 : *
2548 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2549 : *
2550 : * This expects the sane reject status of
2551 : * NT_STATUS_FILE_NOT_AVAILABLE.
2552 : *
2553 : * It won't pass against Windows as it returns
2554 : * NT_STATUS_ACCESS_DENIED see
2555 : * test_dhv2_pending1l_vs_lease_windows().
2556 : */
2557 5 : static bool test_dhv2_pending1l_vs_lease_sane(struct torture_context *tctx,
2558 : struct smb2_tree *tree1,
2559 : struct smb2_tree *tree2)
2560 : {
2561 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2562 : SMB2_OPLOCK_LEVEL_LEASE,
2563 : SMB2_OPLOCK_LEVEL_LEASE,
2564 5 : NT_STATUS_FILE_NOT_AVAILABLE,
2565 : tree1, tree2);
2566 : }
2567 :
2568 : /**
2569 : * This tests replay with a pending open on a single
2570 : * channel.
2571 : *
2572 : * With a durablev2 request containing a create_guid,
2573 : * a share_access of READ/WRITE/DELETE,
2574 : * and asking for a v2 lease.
2575 : *
2576 : * While another client holds an RWH lease.
2577 : * And allows share_access of READ/WRITE/DELETE.
2578 : *
2579 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2580 : *
2581 : * This expects the strange reject status of
2582 : * NT_STATUS_ACCESS_DENIED, which is returned
2583 : * by Windows Servers.
2584 : *
2585 : * It won't pass against Samba as it returns
2586 : * NT_STATUS_FILE_NOT_AVAILABLE. see
2587 : * test_dhv2_pending1l_vs_lease_sane.
2588 : */
2589 5 : static bool test_dhv2_pending1l_vs_lease_windows(struct torture_context *tctx,
2590 : struct smb2_tree *tree1,
2591 : struct smb2_tree *tree2)
2592 : {
2593 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2594 : SMB2_OPLOCK_LEVEL_LEASE,
2595 : SMB2_OPLOCK_LEVEL_LEASE,
2596 5 : NT_STATUS_ACCESS_DENIED,
2597 : tree1, tree2);
2598 : }
2599 :
2600 : /**
2601 : * This tests replay with a pending open on a single
2602 : * channel.
2603 : *
2604 : * With a durablev2 request containing a create_guid,
2605 : * a share_access of READ/WRITE/DELETE,
2606 : * and asking for a batch oplock.
2607 : *
2608 : * While another client holds a batch oplock.
2609 : * And allows share_access of READ/WRITE/DELETE.
2610 : *
2611 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2612 : *
2613 : * This expects the sane reject status of
2614 : * NT_STATUS_FILE_NOT_AVAILABLE.
2615 : *
2616 : * It won't pass against Windows as it returns
2617 : * NT_STATUS_ACCESS_DENIED see
2618 : * test_dhv2_pending1o_vs_oplock_windows().
2619 : */
2620 5 : static bool test_dhv2_pending1o_vs_oplock_sane(struct torture_context *tctx,
2621 : struct smb2_tree *tree1,
2622 : struct smb2_tree *tree2)
2623 : {
2624 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2625 : SMB2_OPLOCK_LEVEL_BATCH,
2626 : SMB2_OPLOCK_LEVEL_BATCH,
2627 5 : NT_STATUS_FILE_NOT_AVAILABLE,
2628 : tree1, tree2);
2629 : }
2630 :
2631 : /**
2632 : * This tests replay with a pending open on a single
2633 : * channel.
2634 : *
2635 : * With a durablev2 request containing a create_guid,
2636 : * a share_access of READ/WRITE/DELETE,
2637 : * and asking for a batch oplock.
2638 : *
2639 : * While another client holds a batch oplock.
2640 : * And allows share_access of READ/WRITE/DELETE.
2641 : *
2642 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2643 : *
2644 : * This expects the strange reject status of
2645 : * NT_STATUS_ACCESS_DENIED, which is returned
2646 : * by Windows Servers.
2647 : *
2648 : * It won't pass against Samba as it returns
2649 : * NT_STATUS_FILE_NOT_AVAILABLE. see
2650 : * test_dhv2_pending1o_vs_oplock_sane.
2651 : */
2652 5 : static bool test_dhv2_pending1o_vs_oplock_windows(struct torture_context *tctx,
2653 : struct smb2_tree *tree1,
2654 : struct smb2_tree *tree2)
2655 : {
2656 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2657 : SMB2_OPLOCK_LEVEL_BATCH,
2658 : SMB2_OPLOCK_LEVEL_BATCH,
2659 5 : NT_STATUS_ACCESS_DENIED,
2660 : tree1, tree2);
2661 : }
2662 :
2663 : /**
2664 : * This tests replay with a pending open on a single
2665 : * channel.
2666 : *
2667 : * With a durablev2 request containing a create_guid,
2668 : * a share_access of READ/WRITE/DELETE,
2669 : * and asking for a batch oplock.
2670 : *
2671 : * While another client holds an RWH lease.
2672 : * And allows share_access of READ/WRITE/DELETE.
2673 : *
2674 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2675 : *
2676 : * This expects the sane reject status of
2677 : * NT_STATUS_FILE_NOT_AVAILABLE.
2678 : *
2679 : * It won't pass against Windows as it returns
2680 : * NT_STATUS_ACCESS_DENIED see
2681 : * test_dhv2_pending1o_vs_lease_windows().
2682 : */
2683 5 : static bool test_dhv2_pending1o_vs_lease_sane(struct torture_context *tctx,
2684 : struct smb2_tree *tree1,
2685 : struct smb2_tree *tree2_1)
2686 : {
2687 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2688 : SMB2_OPLOCK_LEVEL_LEASE,
2689 : SMB2_OPLOCK_LEVEL_BATCH,
2690 5 : NT_STATUS_FILE_NOT_AVAILABLE,
2691 : tree1, tree2_1);
2692 : }
2693 :
2694 : /**
2695 : * This tests replay with a pending open on a single
2696 : * channel.
2697 : *
2698 : * With a durablev2 request containing a create_guid,
2699 : * a share_access of READ/WRITE/DELETE,
2700 : * and asking for a batch oplock.
2701 : *
2702 : * While another client holds an RWH lease.
2703 : * And allows share_access of READ/WRITE/DELETE.
2704 : *
2705 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2706 : *
2707 : * This expects the strange reject status of
2708 : * NT_STATUS_ACCESS_DENIED, which is returned
2709 : * by Windows Servers.
2710 : *
2711 : * It won't pass against Samba as it returns
2712 : * NT_STATUS_FILE_NOT_AVAILABLE. see
2713 : * test_dhv2_pending1o_vs_lease_sane.
2714 : */
2715 5 : static bool test_dhv2_pending1o_vs_lease_windows(struct torture_context *tctx,
2716 : struct smb2_tree *tree1,
2717 : struct smb2_tree *tree2)
2718 : {
2719 10 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2720 : SMB2_OPLOCK_LEVEL_LEASE,
2721 : SMB2_OPLOCK_LEVEL_BATCH,
2722 5 : NT_STATUS_ACCESS_DENIED,
2723 : tree1, tree2);
2724 : }
2725 :
2726 : /**
2727 : * This tests replay with a pending open with 4 channels
2728 : * and closed transports on the client and server side.
2729 : *
2730 : * With a durablev2 request containing a create_guid and
2731 : * a share_access of READ/WRITE/DELETE:
2732 : * - client2_level = NONE:
2733 : * but without asking for an oplock nor a lease.
2734 : * - client2_level = BATCH:
2735 : * and asking for a batch oplock.
2736 : * - client2_level = LEASE
2737 : * and asking for an RWH lease.
2738 : *
2739 : * While another client holds a batch oplock or
2740 : * RWH lease. (client1_level => LEASE or BATCH).
2741 : * And allows share_access of READ/WRITE/DELETE.
2742 : *
2743 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2744 : */
2745 60 : static bool _test_dhv2_pending2_vs_hold(struct torture_context *tctx,
2746 : const char *testname,
2747 : uint8_t client1_level,
2748 : uint8_t client2_level,
2749 : NTSTATUS reject_status,
2750 : struct smb2_tree *tree1,
2751 : struct smb2_tree *tree2_1)
2752 : {
2753 60 : const char *host = torture_setting_string(tctx, "host", NULL);
2754 60 : const char *share = torture_setting_string(tctx, "share", NULL);
2755 60 : struct cli_credentials *credentials = samba_cmdline_get_creds();
2756 0 : NTSTATUS status;
2757 60 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
2758 0 : struct smb2_handle _h1;
2759 60 : struct smb2_handle *h1 = NULL;
2760 0 : struct smb2_handle _h24;
2761 60 : struct smb2_handle *h24 = NULL;
2762 0 : struct smb2_create io1, io21, io22, io23, io24;
2763 60 : struct GUID create_guid1 = GUID_random();
2764 60 : struct GUID create_guid2 = GUID_random();
2765 60 : struct smb2_request *req21 = NULL;
2766 60 : bool ret = true;
2767 0 : char fname[256];
2768 60 : struct smb2_transport *transport1 = tree1->session->transport;
2769 0 : uint32_t server_capabilities;
2770 0 : uint32_t share_capabilities;
2771 0 : struct smb2_lease ls1;
2772 0 : uint64_t lease_key1;
2773 60 : uint16_t lease_epoch1 = 0;
2774 0 : struct smb2_lease ls2;
2775 0 : uint64_t lease_key2;
2776 60 : uint16_t lease_epoch2 = 0;
2777 0 : bool share_is_so;
2778 60 : struct smb2_transport *transport2_1 = tree2_1->session->transport;
2779 60 : int request_timeout2 = transport2_1->options.request_timeout;
2780 0 : struct smbcli_options options2x;
2781 60 : struct smb2_tree *tree2_2 = NULL;
2782 60 : struct smb2_tree *tree2_3 = NULL;
2783 60 : struct smb2_tree *tree2_4 = NULL;
2784 60 : struct smb2_transport *transport2_2 = NULL;
2785 60 : struct smb2_transport *transport2_3 = NULL;
2786 60 : struct smb2_transport *transport2_4 = NULL;
2787 60 : struct smb2_session *session2_1 = tree2_1->session;
2788 60 : struct smb2_session *session2_2 = NULL;
2789 60 : struct smb2_session *session2_3 = NULL;
2790 60 : struct smb2_session *session2_4 = NULL;
2791 60 : uint16_t csn2 = 1;
2792 60 : const char *hold_name = NULL;
2793 :
2794 60 : switch (client1_level) {
2795 30 : case SMB2_OPLOCK_LEVEL_LEASE:
2796 30 : hold_name = "RWH Lease";
2797 30 : break;
2798 30 : case SMB2_OPLOCK_LEVEL_BATCH:
2799 30 : hold_name = "BATCH Oplock";
2800 30 : break;
2801 0 : default:
2802 0 : smb_panic(__location__);
2803 0 : break;
2804 : }
2805 :
2806 60 : if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
2807 12 : torture_skip(tctx, "SMB 3.X Dialect family required for "
2808 : "replay tests\n");
2809 : }
2810 :
2811 48 : server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
2812 48 : if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
2813 0 : torture_skip(tctx, "MULTI_CHANNEL are not supported");
2814 : }
2815 48 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
2816 24 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
2817 0 : client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2818 16 : torture_skip(tctx, "leases are not supported");
2819 : }
2820 : }
2821 :
2822 32 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
2823 32 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
2824 32 : if (share_is_so) {
2825 0 : torture_skip(tctx, talloc_asprintf(tctx,
2826 : "%s not supported on SCALEOUT share",
2827 : hold_name));
2828 : }
2829 :
2830 : /* Add some random component to the file name. */
2831 32 : snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
2832 : BASEDIR, testname, generate_random_str(tctx, 8));
2833 :
2834 32 : options2x = transport2_1->options;
2835 32 : options2x.only_negprot = true;
2836 :
2837 32 : status = smb2_connect(tctx,
2838 : host,
2839 : lpcfg_smb_ports(tctx->lp_ctx),
2840 : share,
2841 : lpcfg_resolve_context(tctx->lp_ctx),
2842 : credentials,
2843 : &tree2_2,
2844 : tctx->ev,
2845 : &options2x,
2846 : lpcfg_socket_options(tctx->lp_ctx),
2847 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
2848 : );
2849 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2850 : "smb2_connect failed");
2851 32 : transport2_2 = tree2_2->session->transport;
2852 :
2853 32 : session2_2 = smb2_session_channel(transport2_2,
2854 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
2855 : tctx,
2856 : session2_1);
2857 32 : torture_assert(tctx, session2_2 != NULL, "smb2_session_channel failed");
2858 :
2859 32 : status = smb2_session_setup_spnego(session2_2,
2860 : credentials,
2861 : 0 /* previous_session_id */);
2862 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2863 : "smb2_session_setup_spnego failed");
2864 32 : tree2_2->smbXcli = tree2_1->smbXcli;
2865 32 : tree2_2->session = session2_2;
2866 :
2867 32 : status = smb2_connect(tctx,
2868 : host,
2869 : lpcfg_smb_ports(tctx->lp_ctx),
2870 : share,
2871 : lpcfg_resolve_context(tctx->lp_ctx),
2872 : credentials,
2873 : &tree2_3,
2874 : tctx->ev,
2875 : &options2x,
2876 : lpcfg_socket_options(tctx->lp_ctx),
2877 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
2878 : );
2879 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2880 : "smb2_connect failed");
2881 32 : transport2_3 = tree2_3->session->transport;
2882 :
2883 32 : session2_3 = smb2_session_channel(transport2_3,
2884 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
2885 : tctx,
2886 : session2_1);
2887 32 : torture_assert(tctx, session2_3 != NULL, "smb2_session_channel failed");
2888 :
2889 32 : status = smb2_session_setup_spnego(session2_3,
2890 : credentials,
2891 : 0 /* previous_session_id */);
2892 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2893 : "smb2_session_setup_spnego failed");
2894 32 : tree2_3->smbXcli = tree2_1->smbXcli;
2895 32 : tree2_3->session = session2_3;
2896 :
2897 32 : status = smb2_connect(tctx,
2898 : host,
2899 : lpcfg_smb_ports(tctx->lp_ctx),
2900 : share,
2901 : lpcfg_resolve_context(tctx->lp_ctx),
2902 : credentials,
2903 : &tree2_4,
2904 : tctx->ev,
2905 : &options2x,
2906 : lpcfg_socket_options(tctx->lp_ctx),
2907 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
2908 : );
2909 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2910 : "smb2_connect failed");
2911 32 : transport2_4 = tree2_4->session->transport;
2912 :
2913 32 : session2_4 = smb2_session_channel(transport2_4,
2914 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
2915 : tctx,
2916 : session2_1);
2917 32 : torture_assert(tctx, session2_4 != NULL, "smb2_session_channel failed");
2918 :
2919 32 : status = smb2_session_setup_spnego(session2_4,
2920 : credentials,
2921 : 0 /* previous_session_id */);
2922 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2923 : "smb2_session_setup_spnego failed");
2924 32 : tree2_4->smbXcli = tree2_1->smbXcli;
2925 32 : tree2_4->session = session2_4;
2926 :
2927 32 : smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
2928 :
2929 32 : torture_reset_break_info(tctx, &break_info);
2930 32 : break_info.oplock_skip_ack = true;
2931 32 : torture_reset_lease_break_info(tctx, &lease_break_info);
2932 32 : lease_break_info.lease_skip_ack = true;
2933 32 : transport1->oplock.handler = torture_oplock_ack_handler;
2934 32 : transport1->oplock.private_data = tree1;
2935 32 : transport1->lease.handler = torture_lease_handler;
2936 32 : transport1->lease.private_data = tree1;
2937 32 : smb2_keepalive(transport1);
2938 32 : transport2_1->oplock.handler = torture_oplock_ack_handler;
2939 32 : transport2_1->oplock.private_data = tree2_1;
2940 32 : transport2_1->lease.handler = torture_lease_handler;
2941 32 : transport2_1->lease.private_data = tree2_1;
2942 32 : smb2_keepalive(transport2_1);
2943 32 : transport2_2->oplock.handler = torture_oplock_ack_handler;
2944 32 : transport2_2->oplock.private_data = tree2_2;
2945 32 : transport2_2->lease.handler = torture_lease_handler;
2946 32 : transport2_2->lease.private_data = tree2_2;
2947 32 : smb2_keepalive(transport2_2);
2948 32 : transport2_3->oplock.handler = torture_oplock_ack_handler;
2949 32 : transport2_3->oplock.private_data = tree2_3;
2950 32 : transport2_3->lease.handler = torture_lease_handler;
2951 32 : transport2_3->lease.private_data = tree2_3;
2952 32 : smb2_keepalive(transport2_3);
2953 32 : transport2_4->oplock.handler = torture_oplock_ack_handler;
2954 32 : transport2_4->oplock.private_data = tree2_4;
2955 32 : transport2_4->lease.handler = torture_lease_handler;
2956 32 : transport2_4->lease.private_data = tree2_4;
2957 32 : smb2_keepalive(transport2_4);
2958 :
2959 32 : smb2_util_unlink(tree1, fname);
2960 32 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
2961 32 : CHECK_STATUS(status, NT_STATUS_OK);
2962 32 : smb2_util_close(tree1, _h1);
2963 32 : CHECK_VAL(break_info.count, 0);
2964 :
2965 32 : lease_key1 = random();
2966 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2967 12 : smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
2968 12 : lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
2969 : } else {
2970 20 : smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
2971 : }
2972 32 : io1.in.durable_open = false;
2973 32 : io1.in.durable_open_v2 = true;
2974 32 : io1.in.persistent_open = false;
2975 32 : io1.in.create_guid = create_guid1;
2976 32 : io1.in.timeout = UINT32_MAX;
2977 :
2978 32 : status = smb2_create(tree1, mem_ctx, &io1);
2979 32 : CHECK_STATUS(status, NT_STATUS_OK);
2980 32 : _h1 = io1.out.file.handle;
2981 32 : h1 = &_h1;
2982 32 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2983 32 : CHECK_VAL(io1.out.durable_open, false);
2984 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2985 12 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
2986 12 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
2987 12 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
2988 12 : CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
2989 12 : CHECK_VAL(io1.out.lease_response_v2.lease_state,
2990 : smb2_util_lease_state("RHW"));
2991 : } else {
2992 20 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2993 : }
2994 32 : CHECK_VAL(io1.out.durable_open_v2, true);
2995 32 : CHECK_VAL(io1.out.timeout, 300*1000);
2996 :
2997 32 : lease_key2 = random();
2998 32 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2999 8 : smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
3000 8 : lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
3001 : } else {
3002 24 : smb2_oplock_create(&io21, fname, client2_level);
3003 : }
3004 32 : io21.in.durable_open = false;
3005 32 : io21.in.durable_open_v2 = true;
3006 32 : io21.in.persistent_open = false;
3007 32 : io21.in.create_guid = create_guid2;
3008 32 : io21.in.timeout = UINT32_MAX;
3009 32 : io24 = io23 = io22 = io21;
3010 :
3011 32 : req21 = smb2_create_send(tree2_1, &io21);
3012 32 : torture_assert(tctx, req21 != NULL, "req21");
3013 :
3014 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3015 12 : const struct smb2_lease_break *lb =
3016 : &lease_break_info.lease_break;
3017 12 : const struct smb2_lease *l = &lb->current_lease;
3018 12 : const struct smb2_lease_key *k = &l->lease_key;
3019 :
3020 12 : torture_wait_for_lease_break(tctx);
3021 12 : CHECK_VAL(break_info.count, 0);
3022 12 : CHECK_VAL(lease_break_info.count, 1);
3023 :
3024 12 : torture_assert(tctx,
3025 : lease_break_info.lease_transport == transport1,
3026 : "expect lease break on transport1\n");
3027 12 : CHECK_VAL(k->data[0], lease_key1);
3028 12 : CHECK_VAL(k->data[1], ~lease_key1);
3029 12 : CHECK_VAL(lb->new_lease_state,
3030 : smb2_util_lease_state("RH"));
3031 12 : CHECK_VAL(lb->break_flags,
3032 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
3033 12 : CHECK_VAL(lb->new_epoch, lease_epoch1+1);
3034 12 : lease_epoch1 += 1;
3035 : } else {
3036 20 : torture_wait_for_oplock_break(tctx);
3037 20 : CHECK_VAL(break_info.count, 1);
3038 20 : CHECK_VAL(lease_break_info.count, 0);
3039 :
3040 20 : torture_assert(tctx,
3041 : break_info.received_transport == transport1,
3042 : "expect oplock break on transport1\n");
3043 20 : CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
3044 20 : CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
3045 20 : CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3046 : }
3047 :
3048 32 : torture_reset_break_info(tctx, &break_info);
3049 32 : break_info.oplock_skip_ack = true;
3050 32 : torture_reset_lease_break_info(tctx, &lease_break_info);
3051 32 : lease_break_info.lease_skip_ack = true;
3052 :
3053 128 : WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
3054 :
3055 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3056 12 : torture_wait_for_lease_break(tctx);
3057 : } else {
3058 20 : torture_wait_for_oplock_break(tctx);
3059 : }
3060 32 : CHECK_VAL(break_info.count, 0);
3061 32 : CHECK_VAL(lease_break_info.count, 0);
3062 :
3063 32 : smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
3064 32 : smb2cli_session_reset_channel_sequence(session2_1->smbXcli, csn2++);
3065 :
3066 32 : smb2cli_session_start_replay(session2_2->smbXcli);
3067 32 : transport2_2->options.request_timeout = 5;
3068 32 : status = smb2_create(tree2_2, tctx, &io22);
3069 32 : transport2_2->options.request_timeout = request_timeout2;
3070 32 : CHECK_STATUS(status, reject_status);
3071 16 : smb2cli_session_stop_replay(session2_2->smbXcli);
3072 :
3073 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3074 6 : torture_wait_for_lease_break(tctx);
3075 : } else {
3076 10 : torture_wait_for_oplock_break(tctx);
3077 : }
3078 16 : CHECK_VAL(break_info.count, 0);
3079 16 : CHECK_VAL(lease_break_info.count, 0);
3080 :
3081 16 : smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
3082 16 : smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
3083 :
3084 16 : smb2cli_session_start_replay(session2_3->smbXcli);
3085 16 : transport2_3->options.request_timeout = 5;
3086 16 : status = smb2_create(tree2_3, tctx, &io23);
3087 16 : transport2_3->options.request_timeout = request_timeout2;
3088 16 : CHECK_STATUS(status, reject_status);
3089 16 : smb2cli_session_stop_replay(session2_3->smbXcli);
3090 :
3091 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3092 6 : torture_wait_for_lease_break(tctx);
3093 : } else {
3094 10 : torture_wait_for_oplock_break(tctx);
3095 : }
3096 16 : CHECK_VAL(break_info.count, 0);
3097 16 : CHECK_VAL(lease_break_info.count, 0);
3098 :
3099 16 : smb2_util_close(tree1, _h1);
3100 16 : h1 = NULL;
3101 :
3102 16 : status = smb2_create_recv(req21, tctx, &io21);
3103 16 : CHECK_STATUS(status, NT_STATUS_LOCAL_DISCONNECT);
3104 :
3105 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3106 6 : torture_wait_for_lease_break(tctx);
3107 : } else {
3108 10 : torture_wait_for_oplock_break(tctx);
3109 : }
3110 16 : CHECK_VAL(break_info.count, 0);
3111 16 : CHECK_VAL(lease_break_info.count, 0);
3112 :
3113 16 : smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
3114 16 : smb2cli_session_reset_channel_sequence(session2_3->smbXcli, csn2++);
3115 :
3116 16 : smb2cli_session_start_replay(session2_4->smbXcli);
3117 16 : status = smb2_create(tree2_4, tctx, &io24);
3118 16 : smb2cli_session_stop_replay(session2_4->smbXcli);
3119 16 : CHECK_STATUS(status, NT_STATUS_OK);
3120 16 : _h24 = io24.out.file.handle;
3121 16 : h24 = &_h24;
3122 16 : CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3123 16 : CHECK_VAL(io24.out.oplock_level, client2_level);
3124 16 : CHECK_VAL(io24.out.durable_open, false);
3125 16 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3126 4 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
3127 4 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
3128 4 : CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
3129 4 : CHECK_VAL(io24.out.lease_response_v2.lease_state,
3130 : smb2_util_lease_state("RHW"));
3131 4 : CHECK_VAL(io24.out.durable_open_v2, true);
3132 4 : CHECK_VAL(io24.out.timeout, 300*1000);
3133 12 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
3134 6 : CHECK_VAL(io24.out.durable_open_v2, true);
3135 6 : CHECK_VAL(io24.out.timeout, 300*1000);
3136 : } else {
3137 6 : CHECK_VAL(io24.out.durable_open_v2, false);
3138 : }
3139 :
3140 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3141 6 : torture_wait_for_lease_break(tctx);
3142 : } else {
3143 10 : torture_wait_for_oplock_break(tctx);
3144 : }
3145 16 : CHECK_VAL(break_info.count, 0);
3146 16 : CHECK_VAL(lease_break_info.count, 0);
3147 16 : status = smb2_util_close(tree2_4, *h24);
3148 16 : CHECK_STATUS(status, NT_STATUS_OK);
3149 16 : h24 = NULL;
3150 :
3151 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3152 6 : torture_wait_for_lease_break(tctx);
3153 : } else {
3154 10 : torture_wait_for_oplock_break(tctx);
3155 : }
3156 16 : CHECK_VAL(break_info.count, 0);
3157 16 : CHECK_VAL(lease_break_info.count, 0);
3158 :
3159 16 : done:
3160 :
3161 32 : smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
3162 32 : smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
3163 32 : smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
3164 32 : smbXcli_conn_disconnect(transport2_4->conn, NT_STATUS_LOCAL_DISCONNECT);
3165 :
3166 32 : if (h1 != NULL) {
3167 16 : smb2_util_close(tree1, *h1);
3168 : }
3169 :
3170 32 : smb2_deltree(tree1, BASEDIR);
3171 :
3172 32 : TALLOC_FREE(tree1);
3173 32 : talloc_free(mem_ctx);
3174 :
3175 32 : return ret;
3176 : }
3177 :
3178 : /**
3179 : * This tests replay with a pending open with 4 channels
3180 : * and closed transports on the client and server side.
3181 : *
3182 : * With a durablev2 request containing a create_guid,
3183 : * a share_access of READ/WRITE/DELETE,
3184 : * but without asking for an oplock nor a lease.
3185 : *
3186 : * While another client holds an RWH lease.
3187 : * And allows share_access of READ/WRITE/DELETE.
3188 : *
3189 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3190 : *
3191 : * This expects the sane reject status of
3192 : * NT_STATUS_FILE_NOT_AVAILABLE.
3193 : *
3194 : * It won't pass against Windows as it returns
3195 : * NT_STATUS_ACCESS_DENIED see
3196 : * test_dhv2_pending2n_vs_lease_windows().
3197 : */
3198 5 : static bool test_dhv2_pending2n_vs_lease_sane(struct torture_context *tctx,
3199 : struct smb2_tree *tree1,
3200 : struct smb2_tree *tree2_1)
3201 : {
3202 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3203 : SMB2_OPLOCK_LEVEL_LEASE,
3204 : SMB2_OPLOCK_LEVEL_NONE,
3205 5 : NT_STATUS_FILE_NOT_AVAILABLE,
3206 : tree1, tree2_1);
3207 : }
3208 :
3209 : /**
3210 : * This tests replay with a pending open with 4 channels
3211 : * and closed transports on the client and server side.
3212 : *
3213 : * With a durablev2 request containing a create_guid,
3214 : * a share_access of READ/WRITE/DELETE,
3215 : * but without asking for an oplock nor a lease.
3216 : *
3217 : * While another client holds an RWH lease.
3218 : * And allows share_access of READ/WRITE/DELETE.
3219 : *
3220 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3221 : *
3222 : * This expects the strange reject status of
3223 : * NT_STATUS_ACCESS_DENIED, which is returned
3224 : * by Windows Servers.
3225 : *
3226 : * It won't pass against Samba as it returns
3227 : * NT_STATUS_FILE_NOT_AVAILABLE. see
3228 : * test_dhv2_pending2n_vs_lease_sane().
3229 : */
3230 5 : static bool test_dhv2_pending2n_vs_lease_windows(struct torture_context *tctx,
3231 : struct smb2_tree *tree1,
3232 : struct smb2_tree *tree2_1)
3233 : {
3234 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3235 : SMB2_OPLOCK_LEVEL_LEASE,
3236 : SMB2_OPLOCK_LEVEL_NONE,
3237 5 : NT_STATUS_ACCESS_DENIED,
3238 : tree1, tree2_1);
3239 : }
3240 :
3241 : /**
3242 : * This tests replay with a pending open with 4 channels
3243 : * and closed transports on the client and server side.
3244 : *
3245 : * With a durablev2 request containing a create_guid,
3246 : * a share_access of READ/WRITE/DELETE,
3247 : * but without asking for an oplock nor a lease.
3248 : *
3249 : * While another client holds a batch oplock.
3250 : * And allows share_access of READ/WRITE/DELETE.
3251 : *
3252 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3253 : *
3254 : * This expects the sane reject status of
3255 : * NT_STATUS_FILE_NOT_AVAILABLE.
3256 : *
3257 : * It won't pass against Windows as it returns
3258 : * NT_STATUS_ACCESS_DENIED see
3259 : * test_dhv2_pending2n_vs_oplock_windows().
3260 : */
3261 5 : static bool test_dhv2_pending2n_vs_oplock_sane(struct torture_context *tctx,
3262 : struct smb2_tree *tree1,
3263 : struct smb2_tree *tree2_1)
3264 : {
3265 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3266 : SMB2_OPLOCK_LEVEL_BATCH,
3267 : SMB2_OPLOCK_LEVEL_NONE,
3268 5 : NT_STATUS_FILE_NOT_AVAILABLE,
3269 : tree1, tree2_1);
3270 : }
3271 :
3272 : /**
3273 : * This tests replay with a pending open with 4 channels
3274 : * and closed transports on the client and server side.
3275 : *
3276 : * With a durablev2 request containing a create_guid,
3277 : * a share_access of READ/WRITE/DELETE,
3278 : * but without asking for an oplock nor a lease.
3279 : *
3280 : * While another client holds a batch oplock.
3281 : * And allows share_access of READ/WRITE/DELETE.
3282 : *
3283 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3284 : *
3285 : * This expects the strange reject status of
3286 : * NT_STATUS_ACCESS_DENIED, which is returned
3287 : * by Windows Servers.
3288 : *
3289 : * It won't pass against Samba as it returns
3290 : * NT_STATUS_FILE_NOT_AVAILABLE. see
3291 : * test_dhv2_pending2n_vs_oplock_sane().
3292 : */
3293 5 : static bool test_dhv2_pending2n_vs_oplock_windows(struct torture_context *tctx,
3294 : struct smb2_tree *tree1,
3295 : struct smb2_tree *tree2_1)
3296 : {
3297 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3298 : SMB2_OPLOCK_LEVEL_BATCH,
3299 : SMB2_OPLOCK_LEVEL_NONE,
3300 5 : NT_STATUS_ACCESS_DENIED,
3301 : tree1, tree2_1);
3302 : }
3303 :
3304 : /**
3305 : * This tests replay with a pending open with 4 channels
3306 : * and closed transports on the client and server side.
3307 : *
3308 : * With a durablev2 request containing a create_guid,
3309 : * a share_access of READ/WRITE/DELETE,
3310 : * and asking for a v2 lease.
3311 : *
3312 : * While another client holds a batch oplock.
3313 : * And allows share_access of READ/WRITE/DELETE.
3314 : *
3315 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3316 : *
3317 : * This expects the sane reject status of
3318 : * NT_STATUS_FILE_NOT_AVAILABLE.
3319 : *
3320 : * It won't pass against Windows as it returns
3321 : * NT_STATUS_ACCESS_DENIED see
3322 : * test_dhv2_pending2l_vs_oplock_windows().
3323 : */
3324 5 : static bool test_dhv2_pending2l_vs_oplock_sane(struct torture_context *tctx,
3325 : struct smb2_tree *tree1,
3326 : struct smb2_tree *tree2_1)
3327 : {
3328 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3329 : SMB2_OPLOCK_LEVEL_BATCH,
3330 : SMB2_OPLOCK_LEVEL_LEASE,
3331 5 : NT_STATUS_FILE_NOT_AVAILABLE,
3332 : tree1, tree2_1);
3333 : }
3334 :
3335 : /**
3336 : * This tests replay with a pending open with 4 channels
3337 : * and closed transports on the client and server side.
3338 : *
3339 : * With a durablev2 request containing a create_guid,
3340 : * a share_access of READ/WRITE/DELETE,
3341 : * and asking for a v2 lease.
3342 : *
3343 : * While another client holds a batch oplock.
3344 : * And allows share_access of READ/WRITE/DELETE.
3345 : *
3346 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3347 : *
3348 : * This expects the strange reject status of
3349 : * NT_STATUS_ACCESS_DENIED, which is returned
3350 : * by Windows Servers.
3351 : *
3352 : * It won't pass against Samba as it returns
3353 : * NT_STATUS_FILE_NOT_AVAILABLE. see
3354 : * test_dhv2_pending2l_vs_oplock_sane().
3355 : */
3356 5 : static bool test_dhv2_pending2l_vs_oplock_windows(struct torture_context *tctx,
3357 : struct smb2_tree *tree1,
3358 : struct smb2_tree *tree2_1)
3359 : {
3360 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3361 : SMB2_OPLOCK_LEVEL_BATCH,
3362 : SMB2_OPLOCK_LEVEL_LEASE,
3363 5 : NT_STATUS_ACCESS_DENIED,
3364 : tree1, tree2_1);
3365 : }
3366 :
3367 : /**
3368 : * This tests replay with a pending open with 4 channels
3369 : * and closed transports on the client and server side.
3370 : *
3371 : * With a durablev2 request containing a create_guid,
3372 : * a share_access of READ/WRITE/DELETE,
3373 : * and asking for a v2 lease.
3374 : *
3375 : * While another client holds an RWH lease.
3376 : * And allows share_access of READ/WRITE/DELETE.
3377 : *
3378 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3379 : *
3380 : * This expects the sane reject status of
3381 : * NT_STATUS_FILE_NOT_AVAILABLE.
3382 : *
3383 : * It won't pass against Windows as it returns
3384 : * NT_STATUS_ACCESS_DENIED see
3385 : * test_dhv2_pending2l_vs_oplock_windows().
3386 : */
3387 5 : static bool test_dhv2_pending2l_vs_lease_sane(struct torture_context *tctx,
3388 : struct smb2_tree *tree1,
3389 : struct smb2_tree *tree2_1)
3390 : {
3391 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3392 : SMB2_OPLOCK_LEVEL_LEASE,
3393 : SMB2_OPLOCK_LEVEL_LEASE,
3394 5 : NT_STATUS_FILE_NOT_AVAILABLE,
3395 : tree1, tree2_1);
3396 : }
3397 :
3398 : /**
3399 : * This tests replay with a pending open with 4 channels
3400 : * and closed transports on the client and server side.
3401 : *
3402 : * With a durablev2 request containing a create_guid,
3403 : * a share_access of READ/WRITE/DELETE,
3404 : * and asking for a v2 lease.
3405 : *
3406 : * While another client holds an RWH lease.
3407 : * And allows share_access of READ/WRITE/DELETE.
3408 : *
3409 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3410 : *
3411 : * This expects the strange reject status of
3412 : * NT_STATUS_ACCESS_DENIED, which is returned
3413 : * by Windows Servers.
3414 : *
3415 : * It won't pass against Samba as it returns
3416 : * NT_STATUS_FILE_NOT_AVAILABLE. see
3417 : * test_dhv2_pending2l_vs_oplock_sane().
3418 : */
3419 5 : static bool test_dhv2_pending2l_vs_lease_windows(struct torture_context *tctx,
3420 : struct smb2_tree *tree1,
3421 : struct smb2_tree *tree2_1)
3422 : {
3423 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3424 : SMB2_OPLOCK_LEVEL_LEASE,
3425 : SMB2_OPLOCK_LEVEL_LEASE,
3426 5 : NT_STATUS_ACCESS_DENIED,
3427 : tree1, tree2_1);
3428 : }
3429 :
3430 : /**
3431 : * This tests replay with a pending open with 4 channels
3432 : * and closed transports on the client and server side.
3433 : *
3434 : * With a durablev2 request containing a create_guid,
3435 : * a share_access of READ/WRITE/DELETE,
3436 : * and asking for a batch oplock
3437 : *
3438 : * While another client holds a batch oplock.
3439 : * And allows share_access of READ/WRITE/DELETE.
3440 : *
3441 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3442 : *
3443 : * This expects the sane reject status of
3444 : * NT_STATUS_FILE_NOT_AVAILABLE.
3445 : *
3446 : * It won't pass against Windows as it returns
3447 : * NT_STATUS_ACCESS_DENIED see
3448 : * test_dhv2_pending2o_vs_oplock_windows().
3449 : */
3450 5 : static bool test_dhv2_pending2o_vs_oplock_sane(struct torture_context *tctx,
3451 : struct smb2_tree *tree1,
3452 : struct smb2_tree *tree2_1)
3453 : {
3454 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3455 : SMB2_OPLOCK_LEVEL_BATCH,
3456 : SMB2_OPLOCK_LEVEL_BATCH,
3457 5 : NT_STATUS_FILE_NOT_AVAILABLE,
3458 : tree1, tree2_1);
3459 : }
3460 :
3461 : /**
3462 : * This tests replay with a pending open with 4 channels
3463 : * and closed transports on the client and server side.
3464 : *
3465 : * With a durablev2 request containing a create_guid,
3466 : * a share_access of READ/WRITE/DELETE,
3467 : * and asking for a batch oplock.
3468 : *
3469 : * While another client holds a batch oplock.
3470 : * And allows share_access of READ/WRITE/DELETE.
3471 : *
3472 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3473 : *
3474 : * This expects the strange reject status of
3475 : * NT_STATUS_ACCESS_DENIED, which is returned
3476 : * by Windows Servers.
3477 : *
3478 : * It won't pass against Samba as it returns
3479 : * NT_STATUS_FILE_NOT_AVAILABLE. see
3480 : * test_dhv2_pending2o_vs_oplock_sane().
3481 : */
3482 5 : static bool test_dhv2_pending2o_vs_oplock_windows(struct torture_context *tctx,
3483 : struct smb2_tree *tree1,
3484 : struct smb2_tree *tree2_1)
3485 : {
3486 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3487 : SMB2_OPLOCK_LEVEL_BATCH,
3488 : SMB2_OPLOCK_LEVEL_BATCH,
3489 5 : NT_STATUS_ACCESS_DENIED,
3490 : tree1, tree2_1);
3491 : }
3492 :
3493 : /**
3494 : * This tests replay with a pending open with 4 channels
3495 : * and closed transports on the client and server side.
3496 : *
3497 : * With a durablev2 request containing a create_guid,
3498 : * a share_access of READ/WRITE/DELETE,
3499 : * and asking for a batch oplock
3500 : *
3501 : * While another client holds an RWH lease.
3502 : * And allows share_access of READ/WRITE/DELETE.
3503 : *
3504 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3505 : *
3506 : * This expects the sane reject status of
3507 : * NT_STATUS_FILE_NOT_AVAILABLE.
3508 : *
3509 : * It won't pass against Windows as it returns
3510 : * NT_STATUS_ACCESS_DENIED see
3511 : * test_dhv2_pending2o_vs_lease_windows().
3512 : */
3513 5 : static bool test_dhv2_pending2o_vs_lease_sane(struct torture_context *tctx,
3514 : struct smb2_tree *tree1,
3515 : struct smb2_tree *tree2_1)
3516 : {
3517 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3518 : SMB2_OPLOCK_LEVEL_LEASE,
3519 : SMB2_OPLOCK_LEVEL_BATCH,
3520 5 : NT_STATUS_FILE_NOT_AVAILABLE,
3521 : tree1, tree2_1);
3522 : }
3523 :
3524 : /**
3525 : * This tests replay with a pending open with 4 channels
3526 : * and closed transports on the client and server side.
3527 : *
3528 : * With a durablev2 request containing a create_guid,
3529 : * a share_access of READ/WRITE/DELETE,
3530 : * and asking for a batch oplock.
3531 : *
3532 : * While another client holds an RWH lease.
3533 : * And allows share_access of READ/WRITE/DELETE.
3534 : *
3535 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3536 : *
3537 : * This expects the strange reject status of
3538 : * NT_STATUS_ACCESS_DENIED, which is returned
3539 : * by Windows Servers.
3540 : *
3541 : * It won't pass against Samba as it returns
3542 : * NT_STATUS_FILE_NOT_AVAILABLE. see
3543 : * test_dhv2_pending2o_vs_lease_sane().
3544 : */
3545 5 : static bool test_dhv2_pending2o_vs_lease_windows(struct torture_context *tctx,
3546 : struct smb2_tree *tree1,
3547 : struct smb2_tree *tree2_1)
3548 : {
3549 10 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3550 : SMB2_OPLOCK_LEVEL_LEASE,
3551 : SMB2_OPLOCK_LEVEL_BATCH,
3552 5 : NT_STATUS_ACCESS_DENIED,
3553 : tree1, tree2_1);
3554 : }
3555 :
3556 : /**
3557 : * This tests replay with a pending open with 4 channels
3558 : * and blocked transports on the client side.
3559 : *
3560 : * With a durablev2 request containing a create_guid and
3561 : * a share_access of READ/WRITE/DELETE:
3562 : * - client2_level = NONE:
3563 : * but without asking for an oplock nor a lease.
3564 : * - client2_level = BATCH:
3565 : * and asking for a batch oplock.
3566 : * - client2_level = LEASE
3567 : * and asking for an RWH lease.
3568 : *
3569 : * While another client holds a batch oplock or
3570 : * RWH lease. (client1_level => LEASE or BATCH).
3571 : * And allows share_access of READ/WRITE/DELETE.
3572 : *
3573 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3574 : */
3575 60 : static bool _test_dhv2_pending3_vs_hold(struct torture_context *tctx,
3576 : const char *testname,
3577 : uint8_t client1_level,
3578 : uint8_t client2_level,
3579 : NTSTATUS reject_status,
3580 : struct smb2_tree *tree1,
3581 : struct smb2_tree *tree2_1)
3582 : {
3583 60 : const char *host = torture_setting_string(tctx, "host", NULL);
3584 60 : const char *share = torture_setting_string(tctx, "share", NULL);
3585 60 : struct cli_credentials *credentials = samba_cmdline_get_creds();
3586 0 : NTSTATUS status;
3587 60 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
3588 0 : struct smb2_handle _h1;
3589 60 : struct smb2_handle *h1 = NULL;
3590 0 : struct smb2_handle _h21;
3591 60 : struct smb2_handle *h21 = NULL;
3592 0 : struct smb2_handle _h24;
3593 60 : struct smb2_handle *h24 = NULL;
3594 0 : struct smb2_create io1, io21, io22, io23, io24;
3595 60 : struct GUID create_guid1 = GUID_random();
3596 60 : struct GUID create_guid2 = GUID_random();
3597 60 : struct smb2_request *req21 = NULL;
3598 60 : bool ret = true;
3599 0 : char fname[256];
3600 60 : struct smb2_transport *transport1 = tree1->session->transport;
3601 0 : uint32_t server_capabilities;
3602 0 : uint32_t share_capabilities;
3603 0 : struct smb2_lease ls1;
3604 0 : uint64_t lease_key1;
3605 60 : uint16_t lease_epoch1 = 0;
3606 0 : struct smb2_lease ls2;
3607 0 : uint64_t lease_key2;
3608 60 : uint16_t lease_epoch2 = 0;
3609 0 : bool share_is_so;
3610 60 : struct smb2_transport *transport2_1 = tree2_1->session->transport;
3611 60 : int request_timeout2 = transport2_1->options.request_timeout;
3612 0 : struct smbcli_options options2x;
3613 60 : struct smb2_tree *tree2_2 = NULL;
3614 60 : struct smb2_tree *tree2_3 = NULL;
3615 60 : struct smb2_tree *tree2_4 = NULL;
3616 60 : struct smb2_transport *transport2_2 = NULL;
3617 60 : struct smb2_transport *transport2_3 = NULL;
3618 60 : struct smb2_transport *transport2_4 = NULL;
3619 60 : struct smb2_session *session2_1 = tree2_1->session;
3620 60 : struct smb2_session *session2_2 = NULL;
3621 60 : struct smb2_session *session2_3 = NULL;
3622 60 : struct smb2_session *session2_4 = NULL;
3623 60 : bool block_setup = false;
3624 60 : bool blocked2_1 = false;
3625 60 : bool blocked2_2 = false;
3626 60 : bool blocked2_3 = false;
3627 60 : uint16_t csn2 = 1;
3628 60 : const char *hold_name = NULL;
3629 :
3630 60 : switch (client1_level) {
3631 30 : case SMB2_OPLOCK_LEVEL_LEASE:
3632 30 : hold_name = "RWH Lease";
3633 30 : break;
3634 30 : case SMB2_OPLOCK_LEVEL_BATCH:
3635 30 : hold_name = "BATCH Oplock";
3636 30 : break;
3637 0 : default:
3638 0 : smb_panic(__location__);
3639 0 : break;
3640 : }
3641 :
3642 60 : if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
3643 12 : torture_skip(tctx, "SMB 3.X Dialect family required for "
3644 : "replay tests\n");
3645 : }
3646 :
3647 48 : server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
3648 48 : if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
3649 0 : torture_skip(tctx, "MULTI_CHANNEL are not supported");
3650 : }
3651 48 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
3652 24 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
3653 0 : client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3654 16 : torture_skip(tctx, "leases are not supported");
3655 : }
3656 : }
3657 :
3658 32 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
3659 32 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
3660 32 : if (share_is_so) {
3661 0 : torture_skip(tctx, talloc_asprintf(tctx,
3662 : "%s not supported on SCALEOUT share",
3663 : hold_name));
3664 : }
3665 :
3666 : /* Add some random component to the file name. */
3667 32 : snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
3668 : BASEDIR, testname, generate_random_str(tctx, 8));
3669 :
3670 32 : options2x = transport2_1->options;
3671 32 : options2x.only_negprot = true;
3672 :
3673 32 : status = smb2_connect(tctx,
3674 : host,
3675 : lpcfg_smb_ports(tctx->lp_ctx),
3676 : share,
3677 : lpcfg_resolve_context(tctx->lp_ctx),
3678 : credentials,
3679 : &tree2_2,
3680 : tctx->ev,
3681 : &options2x,
3682 : lpcfg_socket_options(tctx->lp_ctx),
3683 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
3684 : );
3685 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3686 : "smb2_connect failed");
3687 32 : transport2_2 = tree2_2->session->transport;
3688 :
3689 32 : session2_2 = smb2_session_channel(transport2_2,
3690 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
3691 : tctx,
3692 : session2_1);
3693 32 : torture_assert(tctx, session2_2 != NULL, "smb2_session_channel failed");
3694 :
3695 32 : status = smb2_session_setup_spnego(session2_2,
3696 : credentials,
3697 : 0 /* previous_session_id */);
3698 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3699 : "smb2_session_setup_spnego failed");
3700 32 : tree2_2->smbXcli = tree2_1->smbXcli;
3701 32 : tree2_2->session = session2_2;
3702 :
3703 32 : status = smb2_connect(tctx,
3704 : host,
3705 : lpcfg_smb_ports(tctx->lp_ctx),
3706 : share,
3707 : lpcfg_resolve_context(tctx->lp_ctx),
3708 : credentials,
3709 : &tree2_3,
3710 : tctx->ev,
3711 : &options2x,
3712 : lpcfg_socket_options(tctx->lp_ctx),
3713 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
3714 : );
3715 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3716 : "smb2_connect failed");
3717 32 : transport2_3 = tree2_3->session->transport;
3718 :
3719 32 : session2_3 = smb2_session_channel(transport2_3,
3720 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
3721 : tctx,
3722 : session2_1);
3723 32 : torture_assert(tctx, session2_3 != NULL, "smb2_session_channel failed");
3724 :
3725 32 : status = smb2_session_setup_spnego(session2_3,
3726 : credentials,
3727 : 0 /* previous_session_id */);
3728 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3729 : "smb2_session_setup_spnego failed");
3730 32 : tree2_3->smbXcli = tree2_1->smbXcli;
3731 32 : tree2_3->session = session2_3;
3732 :
3733 32 : status = smb2_connect(tctx,
3734 : host,
3735 : lpcfg_smb_ports(tctx->lp_ctx),
3736 : share,
3737 : lpcfg_resolve_context(tctx->lp_ctx),
3738 : credentials,
3739 : &tree2_4,
3740 : tctx->ev,
3741 : &options2x,
3742 : lpcfg_socket_options(tctx->lp_ctx),
3743 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
3744 : );
3745 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3746 : "smb2_connect failed");
3747 32 : transport2_4 = tree2_4->session->transport;
3748 :
3749 32 : session2_4 = smb2_session_channel(transport2_4,
3750 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
3751 : tctx,
3752 : session2_1);
3753 32 : torture_assert(tctx, session2_4 != NULL, "smb2_session_channel failed");
3754 :
3755 32 : status = smb2_session_setup_spnego(session2_4,
3756 : credentials,
3757 : 0 /* previous_session_id */);
3758 32 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3759 : "smb2_session_setup_spnego failed");
3760 32 : tree2_4->smbXcli = tree2_1->smbXcli;
3761 32 : tree2_4->session = session2_4;
3762 :
3763 32 : smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
3764 :
3765 32 : torture_reset_break_info(tctx, &break_info);
3766 32 : break_info.oplock_skip_ack = true;
3767 32 : torture_reset_lease_break_info(tctx, &lease_break_info);
3768 32 : lease_break_info.lease_skip_ack = true;
3769 32 : transport1->oplock.handler = torture_oplock_ack_handler;
3770 32 : transport1->oplock.private_data = tree1;
3771 32 : transport1->lease.handler = torture_lease_handler;
3772 32 : transport1->lease.private_data = tree1;
3773 32 : smb2_keepalive(transport1);
3774 32 : transport2_1->oplock.handler = torture_oplock_ack_handler;
3775 32 : transport2_1->oplock.private_data = tree2_1;
3776 32 : transport2_1->lease.handler = torture_lease_handler;
3777 32 : transport2_1->lease.private_data = tree2_1;
3778 32 : smb2_keepalive(transport2_1);
3779 32 : transport2_2->oplock.handler = torture_oplock_ack_handler;
3780 32 : transport2_2->oplock.private_data = tree2_2;
3781 32 : transport2_2->lease.handler = torture_lease_handler;
3782 32 : transport2_2->lease.private_data = tree2_2;
3783 32 : smb2_keepalive(transport2_2);
3784 32 : transport2_3->oplock.handler = torture_oplock_ack_handler;
3785 32 : transport2_3->oplock.private_data = tree2_3;
3786 32 : transport2_3->lease.handler = torture_lease_handler;
3787 32 : transport2_3->lease.private_data = tree2_3;
3788 32 : smb2_keepalive(transport2_3);
3789 32 : transport2_4->oplock.handler = torture_oplock_ack_handler;
3790 32 : transport2_4->oplock.private_data = tree2_4;
3791 32 : transport2_4->lease.handler = torture_lease_handler;
3792 32 : transport2_4->lease.private_data = tree2_4;
3793 32 : smb2_keepalive(transport2_4);
3794 :
3795 32 : smb2_util_unlink(tree1, fname);
3796 32 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
3797 32 : CHECK_STATUS(status, NT_STATUS_OK);
3798 32 : smb2_util_close(tree1, _h1);
3799 32 : CHECK_VAL(break_info.count, 0);
3800 :
3801 32 : lease_key1 = random();
3802 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3803 12 : smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
3804 12 : lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
3805 : } else {
3806 20 : smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
3807 : }
3808 32 : io1.in.durable_open = false;
3809 32 : io1.in.durable_open_v2 = true;
3810 32 : io1.in.persistent_open = false;
3811 32 : io1.in.create_guid = create_guid1;
3812 32 : io1.in.timeout = UINT32_MAX;
3813 :
3814 32 : status = smb2_create(tree1, mem_ctx, &io1);
3815 32 : CHECK_STATUS(status, NT_STATUS_OK);
3816 32 : _h1 = io1.out.file.handle;
3817 32 : h1 = &_h1;
3818 32 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3819 32 : CHECK_VAL(io1.out.durable_open, false);
3820 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3821 12 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
3822 12 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
3823 12 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
3824 12 : CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
3825 12 : CHECK_VAL(io1.out.lease_response_v2.lease_state,
3826 : smb2_util_lease_state("RHW"));
3827 : } else {
3828 20 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3829 : }
3830 32 : CHECK_VAL(io1.out.durable_open_v2, true);
3831 32 : CHECK_VAL(io1.out.timeout, 300*1000);
3832 :
3833 32 : lease_key2 = random();
3834 32 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3835 8 : smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
3836 8 : lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
3837 : } else {
3838 24 : smb2_oplock_create(&io21, fname, client2_level);
3839 : }
3840 32 : io21.in.durable_open = false;
3841 32 : io21.in.durable_open_v2 = true;
3842 32 : io21.in.persistent_open = false;
3843 32 : io21.in.create_guid = create_guid2;
3844 32 : io21.in.timeout = UINT32_MAX;
3845 32 : io24 = io23 = io22 = io21;
3846 :
3847 32 : req21 = smb2_create_send(tree2_1, &io21);
3848 32 : torture_assert(tctx, req21 != NULL, "req21");
3849 :
3850 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3851 12 : const struct smb2_lease_break *lb =
3852 : &lease_break_info.lease_break;
3853 12 : const struct smb2_lease *l = &lb->current_lease;
3854 12 : const struct smb2_lease_key *k = &l->lease_key;
3855 :
3856 12 : torture_wait_for_lease_break(tctx);
3857 12 : CHECK_VAL(break_info.count, 0);
3858 12 : CHECK_VAL(lease_break_info.count, 1);
3859 :
3860 12 : torture_assert(tctx,
3861 : lease_break_info.lease_transport == transport1,
3862 : "expect lease break on transport1\n");
3863 12 : CHECK_VAL(k->data[0], lease_key1);
3864 12 : CHECK_VAL(k->data[1], ~lease_key1);
3865 12 : CHECK_VAL(lb->new_lease_state,
3866 : smb2_util_lease_state("RH"));
3867 12 : CHECK_VAL(lb->break_flags,
3868 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
3869 12 : CHECK_VAL(lb->new_epoch, lease_epoch1+1);
3870 12 : lease_epoch1 += 1;
3871 : } else {
3872 20 : torture_wait_for_oplock_break(tctx);
3873 20 : CHECK_VAL(break_info.count, 1);
3874 20 : CHECK_VAL(lease_break_info.count, 0);
3875 :
3876 20 : torture_assert(tctx,
3877 : break_info.received_transport == transport1,
3878 : "expect oplock break on transport1\n");
3879 20 : CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
3880 20 : CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
3881 20 : CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3882 : }
3883 :
3884 32 : torture_reset_break_info(tctx, &break_info);
3885 32 : break_info.oplock_skip_ack = true;
3886 32 : torture_reset_lease_break_info(tctx, &lease_break_info);
3887 32 : lease_break_info.lease_skip_ack = true;
3888 :
3889 125 : WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
3890 :
3891 32 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3892 12 : torture_wait_for_lease_break(tctx);
3893 : } else {
3894 20 : torture_wait_for_oplock_break(tctx);
3895 : }
3896 32 : CHECK_VAL(break_info.count, 0);
3897 32 : CHECK_VAL(lease_break_info.count, 0);
3898 :
3899 32 : block_setup = test_setup_blocked_transports(tctx);
3900 32 : torture_assert(tctx, block_setup, "test_setup_blocked_transports");
3901 :
3902 32 : blocked2_1 = _test_block_smb2_transport(tctx, transport2_1, "transport2_1");
3903 32 : torture_assert_goto(tctx, blocked2_1, ret, done, "we could not block tcp transport");
3904 32 : smb2cli_session_reset_channel_sequence(session2_1->smbXcli, csn2++);
3905 :
3906 32 : smb2cli_session_start_replay(session2_2->smbXcli);
3907 32 : transport2_2->options.request_timeout = 5;
3908 32 : status = smb2_create(tree2_2, tctx, &io22);
3909 32 : transport2_2->options.request_timeout = request_timeout2;
3910 32 : CHECK_STATUS(status, reject_status);
3911 16 : smb2cli_session_stop_replay(session2_2->smbXcli);
3912 :
3913 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3914 6 : torture_wait_for_lease_break(tctx);
3915 : } else {
3916 10 : torture_wait_for_oplock_break(tctx);
3917 : }
3918 16 : CHECK_VAL(break_info.count, 0);
3919 16 : CHECK_VAL(lease_break_info.count, 0);
3920 :
3921 16 : blocked2_2 = _test_block_smb2_transport(tctx, transport2_2, "transport2_2");
3922 16 : torture_assert_goto(tctx, blocked2_2, ret, done, "we could not block tcp transport");
3923 16 : smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
3924 :
3925 16 : smb2cli_session_start_replay(session2_3->smbXcli);
3926 16 : transport2_3->options.request_timeout = 5;
3927 16 : status = smb2_create(tree2_3, tctx, &io23);
3928 16 : transport2_3->options.request_timeout = request_timeout2;
3929 16 : CHECK_STATUS(status, reject_status);
3930 16 : smb2cli_session_stop_replay(session2_3->smbXcli);
3931 :
3932 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3933 6 : torture_wait_for_lease_break(tctx);
3934 : } else {
3935 10 : torture_wait_for_oplock_break(tctx);
3936 : }
3937 16 : CHECK_VAL(break_info.count, 0);
3938 16 : CHECK_VAL(lease_break_info.count, 0);
3939 :
3940 16 : smb2_util_close(tree1, _h1);
3941 16 : h1 = NULL;
3942 :
3943 16 : status = smb2_create_recv(req21, tctx, &io21);
3944 16 : CHECK_STATUS(status, NT_STATUS_OK);
3945 16 : _h21 = io21.out.file.handle;
3946 16 : h21 = &_h21;
3947 16 : CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3948 16 : CHECK_VAL(io21.out.oplock_level, client2_level);
3949 16 : CHECK_VAL(io21.out.durable_open, false);
3950 16 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3951 4 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[0], lease_key2);
3952 4 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[1], ~lease_key2);
3953 4 : CHECK_VAL(io21.out.lease_response_v2.lease_epoch, lease_epoch2);
3954 4 : CHECK_VAL(io21.out.lease_response_v2.lease_state,
3955 : smb2_util_lease_state("RHW"));
3956 4 : CHECK_VAL(io21.out.durable_open_v2, true);
3957 4 : CHECK_VAL(io21.out.timeout, 300*1000);
3958 12 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
3959 6 : CHECK_VAL(io21.out.durable_open_v2, true);
3960 6 : CHECK_VAL(io21.out.timeout, 300*1000);
3961 : } else {
3962 6 : CHECK_VAL(io21.out.durable_open_v2, false);
3963 : }
3964 :
3965 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3966 6 : torture_wait_for_lease_break(tctx);
3967 : } else {
3968 10 : torture_wait_for_oplock_break(tctx);
3969 : }
3970 16 : CHECK_VAL(break_info.count, 0);
3971 16 : CHECK_VAL(lease_break_info.count, 0);
3972 :
3973 16 : blocked2_3 = _test_block_smb2_transport(tctx, transport2_3, "transport2_3");
3974 16 : torture_assert_goto(tctx, blocked2_3, ret, done, "we could not block tcp transport");
3975 16 : smb2cli_session_reset_channel_sequence(session2_3->smbXcli, csn2++);
3976 :
3977 16 : smb2cli_session_start_replay(session2_4->smbXcli);
3978 16 : status = smb2_create(tree2_4, tctx, &io24);
3979 16 : smb2cli_session_stop_replay(session2_4->smbXcli);
3980 16 : CHECK_STATUS(status, NT_STATUS_OK);
3981 16 : _h24 = io24.out.file.handle;
3982 16 : h24 = &_h24;
3983 16 : CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3984 16 : CHECK_VAL(h24->data[0], h21->data[0]);
3985 16 : CHECK_VAL(h24->data[1], h21->data[1]);
3986 16 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3987 4 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
3988 4 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
3989 4 : CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
3990 4 : CHECK_VAL(io24.out.lease_response_v2.lease_state,
3991 : smb2_util_lease_state("RHW"));
3992 4 : CHECK_VAL(io24.out.durable_open_v2, true);
3993 4 : CHECK_VAL(io24.out.timeout, 300*1000);
3994 12 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
3995 6 : CHECK_VAL(io24.out.durable_open_v2, true);
3996 6 : CHECK_VAL(io24.out.timeout, 300*1000);
3997 : } else {
3998 6 : CHECK_VAL(io24.out.durable_open_v2, false);
3999 : }
4000 :
4001 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
4002 6 : torture_wait_for_lease_break(tctx);
4003 : } else {
4004 10 : torture_wait_for_oplock_break(tctx);
4005 : }
4006 16 : CHECK_VAL(break_info.count, 0);
4007 16 : CHECK_VAL(lease_break_info.count, 0);
4008 16 : status = smb2_util_close(tree2_4, *h24);
4009 16 : CHECK_STATUS(status, NT_STATUS_OK);
4010 16 : h24 = NULL;
4011 :
4012 16 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
4013 6 : torture_wait_for_lease_break(tctx);
4014 : } else {
4015 10 : torture_wait_for_oplock_break(tctx);
4016 : }
4017 16 : CHECK_VAL(break_info.count, 0);
4018 16 : CHECK_VAL(lease_break_info.count, 0);
4019 :
4020 16 : done:
4021 :
4022 32 : if (blocked2_3) {
4023 16 : _test_unblock_smb2_transport(tctx, transport2_3, "transport2_3");
4024 : }
4025 32 : if (blocked2_2) {
4026 16 : _test_unblock_smb2_transport(tctx, transport2_2, "transport2_2");
4027 : }
4028 32 : if (blocked2_1) {
4029 32 : _test_unblock_smb2_transport(tctx, transport2_1, "transport2_1");
4030 : }
4031 32 : if (block_setup) {
4032 32 : test_cleanup_blocked_transports(tctx);
4033 : }
4034 :
4035 32 : smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
4036 32 : smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
4037 32 : smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
4038 32 : smbXcli_conn_disconnect(transport2_4->conn, NT_STATUS_LOCAL_DISCONNECT);
4039 :
4040 32 : if (h1 != NULL) {
4041 16 : smb2_util_close(tree1, *h1);
4042 : }
4043 :
4044 32 : smb2_deltree(tree1, BASEDIR);
4045 :
4046 32 : TALLOC_FREE(tree1);
4047 32 : talloc_free(mem_ctx);
4048 :
4049 32 : return ret;
4050 : }
4051 :
4052 : /**
4053 : * This tests replay with a pending open with 4 channels
4054 : * and blocked transports on the client side.
4055 : *
4056 : * With a durablev2 request containing a create_guid,
4057 : * a share_access of READ/WRITE/DELETE,
4058 : * but without asking for an oplock nor a lease.
4059 : *
4060 : * While another client holds an RWH lease.
4061 : * And allows share_access of READ/WRITE/DELETE.
4062 : *
4063 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4064 : *
4065 : * This expects the sane reject status of
4066 : * NT_STATUS_FILE_NOT_AVAILABLE.
4067 : *
4068 : * It won't pass against Windows as it returns
4069 : * NT_STATUS_ACCESS_DENIED see
4070 : * test_dhv2_pending3n_vs_lease_windows().
4071 : */
4072 5 : static bool test_dhv2_pending3n_vs_lease_sane(struct torture_context *tctx,
4073 : struct smb2_tree *tree1,
4074 : struct smb2_tree *tree2_1)
4075 : {
4076 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4077 : SMB2_OPLOCK_LEVEL_LEASE,
4078 : SMB2_OPLOCK_LEVEL_NONE,
4079 5 : NT_STATUS_FILE_NOT_AVAILABLE,
4080 : tree1, tree2_1);
4081 : }
4082 :
4083 : /**
4084 : * This tests replay with a pending open with 4 channels
4085 : * and blocked transports on the client side.
4086 : *
4087 : * With a durablev2 request containing a create_guid,
4088 : * a share_access of READ/WRITE/DELETE,
4089 : * but without asking for an oplock nor a lease.
4090 : *
4091 : * While another client holds an RWH lease.
4092 : * And allows share_access of READ/WRITE/DELETE.
4093 : *
4094 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4095 : *
4096 : * This expects the strange reject status of
4097 : * NT_STATUS_ACCESS_DENIED, which is returned
4098 : * by Windows Servers.
4099 : *
4100 : * It won't pass against Samba as it returns
4101 : * NT_STATUS_FILE_NOT_AVAILABLE. see
4102 : * test_dhv2_pending3n_vs_lease_sane.
4103 : */
4104 5 : static bool test_dhv2_pending3n_vs_lease_windows(struct torture_context *tctx,
4105 : struct smb2_tree *tree1,
4106 : struct smb2_tree *tree2_1)
4107 : {
4108 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4109 : SMB2_OPLOCK_LEVEL_LEASE,
4110 : SMB2_OPLOCK_LEVEL_NONE,
4111 5 : NT_STATUS_ACCESS_DENIED,
4112 : tree1, tree2_1);
4113 : }
4114 :
4115 : /**
4116 : * This tests replay with a pending open with 4 channels
4117 : * and blocked transports on the client side.
4118 : *
4119 : * With a durablev2 request containing a create_guid,
4120 : * a share_access of READ/WRITE/DELETE,
4121 : * but without asking for an oplock nor a lease.
4122 : *
4123 : * While another client holds a batch oplock.
4124 : * And allows share_access of READ/WRITE/DELETE.
4125 : *
4126 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4127 : *
4128 : * This expects the sane reject status of
4129 : * NT_STATUS_FILE_NOT_AVAILABLE.
4130 : *
4131 : * It won't pass against Windows as it returns
4132 : * NT_STATUS_ACCESS_DENIED see
4133 : * test_dhv2_pending3n_vs_oplock_windows().
4134 : */
4135 5 : static bool test_dhv2_pending3n_vs_oplock_sane(struct torture_context *tctx,
4136 : struct smb2_tree *tree1,
4137 : struct smb2_tree *tree2_1)
4138 : {
4139 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4140 : SMB2_OPLOCK_LEVEL_BATCH,
4141 : SMB2_OPLOCK_LEVEL_NONE,
4142 5 : NT_STATUS_FILE_NOT_AVAILABLE,
4143 : tree1, tree2_1);
4144 : }
4145 :
4146 : /**
4147 : * This tests replay with a pending open with 4 channels
4148 : * and blocked transports on the client side.
4149 : *
4150 : * With a durablev2 request containing a create_guid,
4151 : * a share_access of READ/WRITE/DELETE,
4152 : * but without asking for an oplock nor a lease.
4153 : *
4154 : * While another client holds a batch oplock.
4155 : * And allows share_access of READ/WRITE/DELETE.
4156 : *
4157 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4158 : *
4159 : * This expects the strange reject status of
4160 : * NT_STATUS_ACCESS_DENIED, which is returned
4161 : * by Windows Servers.
4162 : *
4163 : * It won't pass against Samba as it returns
4164 : * NT_STATUS_FILE_NOT_AVAILABLE. see
4165 : * test_dhv2_pending3n_vs_oplock_sane.
4166 : */
4167 5 : static bool test_dhv2_pending3n_vs_oplock_windows(struct torture_context *tctx,
4168 : struct smb2_tree *tree1,
4169 : struct smb2_tree *tree2_1)
4170 : {
4171 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4172 : SMB2_OPLOCK_LEVEL_BATCH,
4173 : SMB2_OPLOCK_LEVEL_NONE,
4174 5 : NT_STATUS_ACCESS_DENIED,
4175 : tree1, tree2_1);
4176 : }
4177 :
4178 : /**
4179 : * This tests replay with a pending open with 4 channels
4180 : * and blocked transports on the client side.
4181 : *
4182 : * With a durablev2 request containing a create_guid,
4183 : * a share_access of READ/WRITE/DELETE,
4184 : * and asking for a v2 lease.
4185 : *
4186 : * While another client holds a batch oplock.
4187 : * And allows share_access of READ/WRITE/DELETE.
4188 : *
4189 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4190 : *
4191 : * This expects the sane reject status of
4192 : * NT_STATUS_FILE_NOT_AVAILABLE.
4193 : *
4194 : * It won't pass against Windows as it returns
4195 : * NT_STATUS_ACCESS_DENIED see
4196 : * test_dhv2_pending3l_vs_oplock_windows().
4197 : */
4198 5 : static bool test_dhv2_pending3l_vs_oplock_sane(struct torture_context *tctx,
4199 : struct smb2_tree *tree1,
4200 : struct smb2_tree *tree2_1)
4201 : {
4202 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4203 : SMB2_OPLOCK_LEVEL_BATCH,
4204 : SMB2_OPLOCK_LEVEL_LEASE,
4205 5 : NT_STATUS_FILE_NOT_AVAILABLE,
4206 : tree1, tree2_1);
4207 : }
4208 :
4209 : /**
4210 : * This tests replay with a pending open with 4 channels
4211 : * and blocked transports on the client side.
4212 : *
4213 : * With a durablev2 request containing a create_guid,
4214 : * a share_access of READ/WRITE/DELETE,
4215 : * and asking for a v2 lease.
4216 : *
4217 : * While another client holds a batch oplock.
4218 : * And allows share_access of READ/WRITE/DELETE.
4219 : *
4220 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4221 : *
4222 : * This expects the strange reject status of
4223 : * NT_STATUS_ACCESS_DENIED, which is returned
4224 : * by Windows Servers.
4225 : *
4226 : * It won't pass against Samba as it returns
4227 : * NT_STATUS_FILE_NOT_AVAILABLE. see
4228 : * test_dhv2_pending3l_vs_oplock_sane.
4229 : */
4230 5 : static bool test_dhv2_pending3l_vs_oplock_windows(struct torture_context *tctx,
4231 : struct smb2_tree *tree1,
4232 : struct smb2_tree *tree2_1)
4233 : {
4234 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4235 : SMB2_OPLOCK_LEVEL_BATCH,
4236 : SMB2_OPLOCK_LEVEL_LEASE,
4237 5 : NT_STATUS_ACCESS_DENIED,
4238 : tree1, tree2_1);
4239 : }
4240 :
4241 : /**
4242 : * This tests replay with a pending open with 4 channels
4243 : * and blocked transports on the client side.
4244 : *
4245 : * With a durablev2 request containing a create_guid,
4246 : * a share_access of READ/WRITE/DELETE,
4247 : * and asking for a v2 lease.
4248 : *
4249 : * While another client holds an RWH lease.
4250 : * And allows share_access of READ/WRITE/DELETE.
4251 : *
4252 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4253 : *
4254 : * This expects the sane reject status of
4255 : * NT_STATUS_FILE_NOT_AVAILABLE.
4256 : *
4257 : * It won't pass against Windows as it returns
4258 : * NT_STATUS_ACCESS_DENIED see
4259 : * test_dhv2_pending3l_vs_lease_windows().
4260 : */
4261 5 : static bool test_dhv2_pending3l_vs_lease_sane(struct torture_context *tctx,
4262 : struct smb2_tree *tree1,
4263 : struct smb2_tree *tree2_1)
4264 : {
4265 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4266 : SMB2_OPLOCK_LEVEL_LEASE,
4267 : SMB2_OPLOCK_LEVEL_LEASE,
4268 5 : NT_STATUS_FILE_NOT_AVAILABLE,
4269 : tree1, tree2_1);
4270 : }
4271 :
4272 : /**
4273 : * This tests replay with a pending open with 4 channels
4274 : * and blocked transports on the client side.
4275 : *
4276 : * With a durablev2 request containing a create_guid,
4277 : * a share_access of READ/WRITE/DELETE,
4278 : * and asking for a v2 lease.
4279 : *
4280 : * While another client holds an RWH lease.
4281 : * And allows share_access of READ/WRITE/DELETE.
4282 : *
4283 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4284 : *
4285 : * This expects the strange reject status of
4286 : * NT_STATUS_ACCESS_DENIED, which is returned
4287 : * by Windows Servers.
4288 : *
4289 : * It won't pass against Samba as it returns
4290 : * NT_STATUS_FILE_NOT_AVAILABLE. see
4291 : * test_dhv2_pending3l_vs_lease_sane().
4292 : */
4293 5 : static bool test_dhv2_pending3l_vs_lease_windows(struct torture_context *tctx,
4294 : struct smb2_tree *tree1,
4295 : struct smb2_tree *tree2_1)
4296 : {
4297 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4298 : SMB2_OPLOCK_LEVEL_LEASE,
4299 : SMB2_OPLOCK_LEVEL_LEASE,
4300 5 : NT_STATUS_ACCESS_DENIED,
4301 : tree1, tree2_1);
4302 : }
4303 :
4304 : /**
4305 : * This tests replay with a pending open with 4 channels
4306 : * and blocked transports on the client side.
4307 : *
4308 : * With a durablev2 request containing a create_guid,
4309 : * a share_access of READ/WRITE/DELETE,
4310 : * and asking for a batch oplock.
4311 : *
4312 : * While another client holds a batch oplock.
4313 : * And allows share_access of READ/WRITE/DELETE.
4314 : *
4315 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4316 : *
4317 : * This expects the sane reject status of
4318 : * NT_STATUS_FILE_NOT_AVAILABLE.
4319 : *
4320 : * It won't pass against Windows as it returns
4321 : * NT_STATUS_ACCESS_DENIED see
4322 : * test_dhv2_pending3o_vs_oplock_windows().
4323 : */
4324 5 : static bool test_dhv2_pending3o_vs_oplock_sane(struct torture_context *tctx,
4325 : struct smb2_tree *tree1,
4326 : struct smb2_tree *tree2_1)
4327 : {
4328 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4329 : SMB2_OPLOCK_LEVEL_BATCH,
4330 : SMB2_OPLOCK_LEVEL_BATCH,
4331 5 : NT_STATUS_FILE_NOT_AVAILABLE,
4332 : tree1, tree2_1);
4333 : }
4334 :
4335 : /**
4336 : * This tests replay with a pending open with 4 channels
4337 : * and blocked transports on the client side.
4338 : *
4339 : * With a durablev2 request containing a create_guid,
4340 : * a share_access of READ/WRITE/DELETE,
4341 : * and asking for a batch oplock.
4342 : *
4343 : * While another client holds a batch oplock.
4344 : * And allows share_access of READ/WRITE/DELETE.
4345 : *
4346 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4347 : *
4348 : * This expects the strange reject status of
4349 : * NT_STATUS_ACCESS_DENIED, which is returned
4350 : * by Windows Servers.
4351 : *
4352 : * It won't pass against Samba as it returns
4353 : * NT_STATUS_FILE_NOT_AVAILABLE. see
4354 : * test_dhv2_pending3o_vs_oplock_sane().
4355 : */
4356 5 : static bool test_dhv2_pending3o_vs_oplock_windows(struct torture_context *tctx,
4357 : struct smb2_tree *tree1,
4358 : struct smb2_tree *tree2_1)
4359 : {
4360 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4361 : SMB2_OPLOCK_LEVEL_BATCH,
4362 : SMB2_OPLOCK_LEVEL_BATCH,
4363 5 : NT_STATUS_ACCESS_DENIED,
4364 : tree1, tree2_1);
4365 : }
4366 :
4367 : /**
4368 : * This tests replay with a pending open with 4 channels
4369 : * and blocked transports on the client side.
4370 : *
4371 : * With a durablev2 request containing a create_guid,
4372 : * a share_access of READ/WRITE/DELETE,
4373 : * and asking for a batch oplock.
4374 : *
4375 : * While another client holds an RWH lease.
4376 : * And allows share_access of READ/WRITE/DELETE.
4377 : *
4378 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4379 : *
4380 : * This expects the sane reject status of
4381 : * NT_STATUS_FILE_NOT_AVAILABLE.
4382 : *
4383 : * It won't pass against Windows as it returns
4384 : * NT_STATUS_ACCESS_DENIED see
4385 : * test_dhv2_pending3o_vs_lease_windows().
4386 : */
4387 5 : static bool test_dhv2_pending3o_vs_lease_sane(struct torture_context *tctx,
4388 : struct smb2_tree *tree1,
4389 : struct smb2_tree *tree2_1)
4390 : {
4391 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4392 : SMB2_OPLOCK_LEVEL_LEASE,
4393 : SMB2_OPLOCK_LEVEL_BATCH,
4394 5 : NT_STATUS_FILE_NOT_AVAILABLE,
4395 : tree1, tree2_1);
4396 : }
4397 :
4398 : /**
4399 : * This tests replay with a pending open with 4 channels
4400 : * and blocked transports on the client side.
4401 : *
4402 : * With a durablev2 request containing a create_guid,
4403 : * a share_access of READ/WRITE/DELETE,
4404 : * and asking for a batch oplock.
4405 : *
4406 : * While another client holds an RWH lease.
4407 : * And allows share_access of READ/WRITE/DELETE.
4408 : *
4409 : * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4410 : *
4411 : * This expects the strange reject status of
4412 : * NT_STATUS_ACCESS_DENIED, which is returned
4413 : * by Windows Servers.
4414 : *
4415 : * It won't pass against Samba as it returns
4416 : * NT_STATUS_FILE_NOT_AVAILABLE. see
4417 : * test_dhv2_pending3o_vs_lease_sane().
4418 : */
4419 5 : static bool test_dhv2_pending3o_vs_lease_windows(struct torture_context *tctx,
4420 : struct smb2_tree *tree1,
4421 : struct smb2_tree *tree2_1)
4422 : {
4423 10 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4424 : SMB2_OPLOCK_LEVEL_LEASE,
4425 : SMB2_OPLOCK_LEVEL_BATCH,
4426 5 : NT_STATUS_ACCESS_DENIED,
4427 : tree1, tree2_1);
4428 : }
4429 :
4430 24 : static bool test_channel_sequence_table(struct torture_context *tctx,
4431 : struct smb2_tree *tree,
4432 : bool do_replay,
4433 : uint16_t opcode)
4434 : {
4435 24 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
4436 24 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
4437 0 : struct smb2_handle handle;
4438 24 : struct smb2_handle *phandle = NULL;
4439 0 : struct smb2_create io;
4440 24 : struct GUID create_guid = GUID_random();
4441 24 : bool ret = true;
4442 24 : const char *fname = BASEDIR "\\channel_sequence.dat";
4443 24 : uint16_t csn = 0;
4444 24 : uint16_t limit = UINT16_MAX - 0x7fff;
4445 0 : int i;
4446 0 : struct {
4447 : uint16_t csn;
4448 : bool csn_rand_low;
4449 : bool csn_rand_high;
4450 : NTSTATUS expected_status;
4451 24 : } tests[] = {
4452 : {
4453 : .csn = 0,
4454 : .expected_status = NT_STATUS_OK,
4455 : },{
4456 : .csn = 0x7fff + 1,
4457 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4458 : },{
4459 : .csn = 0x7fff + 2,
4460 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4461 : },{
4462 : .csn = -1,
4463 : .csn_rand_high = true,
4464 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4465 : },{
4466 : .csn = 0xffff,
4467 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4468 : },{
4469 : .csn = 0x7fff,
4470 : .expected_status = NT_STATUS_OK,
4471 : },{
4472 : .csn = 0x7ffe,
4473 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4474 : },{
4475 : .csn = 0,
4476 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4477 : },{
4478 : .csn = -1,
4479 : .csn_rand_low = true,
4480 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4481 : },{
4482 : .csn = 0x7fff + 1,
4483 : .expected_status = NT_STATUS_OK,
4484 : },{
4485 : .csn = 0xffff,
4486 : .expected_status = NT_STATUS_OK,
4487 : },{
4488 : .csn = 0,
4489 : .expected_status = NT_STATUS_OK,
4490 : },{
4491 : .csn = 1,
4492 : .expected_status = NT_STATUS_OK,
4493 : },{
4494 : .csn = 0,
4495 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4496 : },{
4497 : .csn = 1,
4498 : .expected_status = NT_STATUS_OK,
4499 : },{
4500 : .csn = 0xffff,
4501 : .expected_status = NT_STATUS_FILE_NOT_AVAILABLE,
4502 : }
4503 : };
4504 :
4505 24 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
4506 :
4507 24 : csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli);
4508 24 : torture_comment(tctx, "Testing create with channel sequence number: 0x%04x\n", csn);
4509 :
4510 24 : smb2_oplock_create_share(&io, fname,
4511 : smb2_util_share_access("RWD"),
4512 24 : smb2_util_oplock_level("b"));
4513 24 : io.in.durable_open = false;
4514 24 : io.in.durable_open_v2 = true;
4515 24 : io.in.create_guid = create_guid;
4516 24 : io.in.timeout = UINT32_MAX;
4517 :
4518 24 : torture_assert_ntstatus_ok_goto(tctx,
4519 : smb2_create(tree, mem_ctx, &io),
4520 : ret, done, "failed to call smb2_create");
4521 :
4522 24 : handle = io.out.file.handle;
4523 24 : phandle = &handle;
4524 :
4525 408 : for (i=0; i <ARRAY_SIZE(tests); i++) {
4526 :
4527 384 : const char *opstr = "";
4528 0 : union smb_fileinfo qfinfo;
4529 :
4530 384 : csn = tests[i].csn;
4531 :
4532 384 : if (tests[i].csn_rand_low) {
4533 24 : csn = rand() % limit;
4534 360 : } else if (tests[i].csn_rand_high) {
4535 24 : csn = rand() % limit + 0x7fff;
4536 : }
4537 :
4538 384 : switch (opcode) {
4539 128 : case SMB2_OP_WRITE:
4540 128 : opstr = "write";
4541 128 : break;
4542 128 : case SMB2_OP_IOCTL:
4543 128 : opstr = "ioctl";
4544 128 : break;
4545 128 : case SMB2_OP_SETINFO:
4546 128 : opstr = "setinfo";
4547 128 : break;
4548 0 : default:
4549 0 : break;
4550 : }
4551 :
4552 384 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, csn);
4553 384 : csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli);
4554 :
4555 384 : torture_comment(tctx, "Testing %s (replay: %s) with CSN 0x%04x, expecting: %s\n",
4556 : opstr, do_replay ? "true" : "false", csn,
4557 : nt_errstr(tests[i].expected_status));
4558 :
4559 384 : if (do_replay) {
4560 192 : smb2cli_session_start_replay(tree->session->smbXcli);
4561 : }
4562 :
4563 384 : switch (opcode) {
4564 128 : case SMB2_OP_WRITE: {
4565 128 : DATA_BLOB blob = data_blob_talloc(tctx, NULL, 255);
4566 :
4567 128 : generate_random_buffer(blob.data, blob.length);
4568 :
4569 128 : status = smb2_util_write(tree, handle, blob.data, 0, blob.length);
4570 128 : if (NT_STATUS_IS_OK(status)) {
4571 0 : struct smb2_read rd;
4572 :
4573 56 : rd = (struct smb2_read) {
4574 : .in.file.handle = handle,
4575 56 : .in.length = blob.length,
4576 : .in.offset = 0
4577 : };
4578 :
4579 56 : torture_assert_ntstatus_ok_goto(tctx,
4580 : smb2_read(tree, tree, &rd),
4581 : ret, done, "failed to read after write");
4582 :
4583 56 : torture_assert_data_blob_equal(tctx,
4584 : rd.out.data, blob,
4585 : "read/write mismatch");
4586 : }
4587 128 : break;
4588 : }
4589 128 : case SMB2_OP_IOCTL: {
4590 0 : union smb_ioctl ioctl;
4591 128 : ioctl = (union smb_ioctl) {
4592 : .smb2.level = RAW_IOCTL_SMB2,
4593 : .smb2.in.file.handle = handle,
4594 : .smb2.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID,
4595 : .smb2.in.max_output_response = 64,
4596 : .smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL
4597 : };
4598 128 : status = smb2_ioctl(tree, mem_ctx, &ioctl.smb2);
4599 128 : break;
4600 : }
4601 128 : case SMB2_OP_SETINFO: {
4602 0 : union smb_setfileinfo sfinfo;
4603 128 : ZERO_STRUCT(sfinfo);
4604 128 : sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
4605 128 : sfinfo.generic.in.file.handle = handle;
4606 128 : sfinfo.position_information.in.position = 0x1000;
4607 128 : status = smb2_setinfo_file(tree, &sfinfo);
4608 128 : break;
4609 : }
4610 0 : default:
4611 0 : break;
4612 : }
4613 :
4614 384 : qfinfo = (union smb_fileinfo) {
4615 : .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
4616 : .generic.in.file.handle = handle
4617 : };
4618 :
4619 384 : torture_assert_ntstatus_ok_goto(tctx,
4620 : smb2_getinfo_file(tree, mem_ctx, &qfinfo),
4621 : ret, done, "failed to read after write");
4622 :
4623 384 : if (do_replay) {
4624 192 : smb2cli_session_stop_replay(tree->session->smbXcli);
4625 : }
4626 :
4627 384 : torture_assert_ntstatus_equal_goto(tctx,
4628 : status, tests[i].expected_status,
4629 : ret, done, "got unexpected failure code");
4630 :
4631 : }
4632 24 : done:
4633 24 : if (phandle != NULL) {
4634 24 : smb2_util_close(tree, *phandle);
4635 : }
4636 :
4637 24 : smb2_util_unlink(tree, fname);
4638 :
4639 24 : return ret;
4640 : }
4641 :
4642 5 : static bool test_channel_sequence(struct torture_context *tctx,
4643 : struct smb2_tree *tree)
4644 : {
4645 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
4646 5 : bool ret = true;
4647 5 : const char *fname = BASEDIR "\\channel_sequence.dat";
4648 5 : struct smb2_transport *transport1 = tree->session->transport;
4649 0 : struct smb2_handle handle;
4650 5 : uint16_t opcodes[] = { SMB2_OP_WRITE, SMB2_OP_IOCTL, SMB2_OP_SETINFO };
4651 0 : int i;
4652 :
4653 5 : if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
4654 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
4655 : "Replay tests\n");
4656 : }
4657 :
4658 4 : torture_comment(tctx, "Testing channel sequence numbers\n");
4659 :
4660 4 : smbXcli_conn_set_force_channel_sequence(transport1->conn, true);
4661 :
4662 4 : torture_assert_ntstatus_ok_goto(tctx,
4663 : torture_smb2_testdir(tree, BASEDIR, &handle),
4664 : ret, done, "failed to setup test directory");
4665 :
4666 4 : smb2_util_close(tree, handle);
4667 4 : smb2_util_unlink(tree, fname);
4668 :
4669 16 : for (i=0; i <ARRAY_SIZE(opcodes); i++) {
4670 12 : torture_assert(tctx,
4671 : test_channel_sequence_table(tctx, tree, false, opcodes[i]),
4672 : "failed to test CSN without replay flag");
4673 12 : torture_assert(tctx,
4674 : test_channel_sequence_table(tctx, tree, true, opcodes[i]),
4675 : "failed to test CSN with replay flag");
4676 : }
4677 :
4678 4 : done:
4679 :
4680 4 : smb2_util_unlink(tree, fname);
4681 4 : smb2_deltree(tree, BASEDIR);
4682 :
4683 4 : talloc_free(tree);
4684 4 : talloc_free(mem_ctx);
4685 :
4686 4 : return ret;
4687 : }
4688 :
4689 : /**
4690 : * Test Durability V2 Create Replay Detection on Multi Channel
4691 : */
4692 5 : static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1)
4693 : {
4694 5 : const char *host = torture_setting_string(tctx, "host", NULL);
4695 5 : const char *share = torture_setting_string(tctx, "share", NULL);
4696 0 : NTSTATUS status;
4697 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
4698 0 : struct smb2_handle _h;
4699 5 : struct smb2_handle *h = NULL;
4700 0 : struct smb2_create io;
4701 5 : struct GUID create_guid = GUID_random();
4702 5 : bool ret = true;
4703 5 : const char *fname = BASEDIR "\\replay3.dat";
4704 5 : struct smb2_tree *tree2 = NULL;
4705 5 : struct smb2_transport *transport1 = tree1->session->transport;
4706 5 : struct smb2_transport *transport2 = NULL;
4707 5 : struct smb2_session *session1_1 = tree1->session;
4708 5 : struct smb2_session *session1_2 = NULL;
4709 0 : uint32_t share_capabilities;
4710 0 : bool share_is_so;
4711 0 : uint32_t server_capabilities;
4712 :
4713 5 : if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
4714 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
4715 : "Replay tests\n");
4716 : }
4717 :
4718 4 : server_capabilities = smb2cli_conn_server_capabilities(
4719 4 : tree1->session->transport->conn);
4720 4 : if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
4721 0 : torture_skip(tctx,
4722 : "Server does not support multi-channel.");
4723 : }
4724 :
4725 4 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
4726 4 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
4727 :
4728 4 : torture_reset_break_info(tctx, &break_info);
4729 4 : transport1->oplock.handler = torture_oplock_ack_handler;
4730 4 : transport1->oplock.private_data = tree1;
4731 :
4732 4 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Multi "
4733 : "Channel\n");
4734 4 : status = torture_smb2_testdir(tree1, BASEDIR, &_h);
4735 4 : CHECK_STATUS(status, NT_STATUS_OK);
4736 4 : smb2_util_close(tree1, _h);
4737 4 : smb2_util_unlink(tree1, fname);
4738 4 : CHECK_VAL(break_info.count, 0);
4739 :
4740 : /*
4741 : * use the 1st channel, 1st session
4742 : */
4743 4 : smb2_oplock_create_share(&io, fname,
4744 : smb2_util_share_access(""),
4745 4 : smb2_util_oplock_level("b"));
4746 4 : io.in.durable_open = false;
4747 4 : io.in.durable_open_v2 = true;
4748 4 : io.in.persistent_open = false;
4749 4 : io.in.create_guid = create_guid;
4750 4 : io.in.timeout = UINT32_MAX;
4751 :
4752 4 : tree1->session = session1_1;
4753 4 : status = smb2_create(tree1, mem_ctx, &io);
4754 4 : CHECK_STATUS(status, NT_STATUS_OK);
4755 4 : _h = io.out.file.handle;
4756 4 : h = &_h;
4757 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
4758 4 : if (share_is_so) {
4759 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
4760 0 : CHECK_VAL(io.out.durable_open_v2, false);
4761 0 : CHECK_VAL(io.out.timeout, 0);
4762 : } else {
4763 4 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
4764 4 : CHECK_VAL(io.out.durable_open_v2, true);
4765 4 : CHECK_VAL(io.out.timeout, 300*1000);
4766 : }
4767 4 : CHECK_VAL(io.out.durable_open, false);
4768 4 : CHECK_VAL(break_info.count, 0);
4769 :
4770 8 : status = smb2_connect(tctx,
4771 : host,
4772 : lpcfg_smb_ports(tctx->lp_ctx),
4773 : share,
4774 : lpcfg_resolve_context(tctx->lp_ctx),
4775 : samba_cmdline_get_creds(),
4776 : &tree2,
4777 : tctx->ev,
4778 4 : &transport1->options,
4779 : lpcfg_socket_options(tctx->lp_ctx),
4780 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
4781 : );
4782 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4783 : "smb2_connect failed");
4784 4 : transport2 = tree2->session->transport;
4785 :
4786 4 : transport2->oplock.handler = torture_oplock_ack_handler;
4787 4 : transport2->oplock.private_data = tree2;
4788 :
4789 : /*
4790 : * Now bind the 1st session to 2nd transport channel
4791 : */
4792 4 : session1_2 = smb2_session_channel(transport2,
4793 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
4794 : tree2, session1_1);
4795 4 : torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
4796 :
4797 4 : status = smb2_session_setup_spnego(session1_2,
4798 : samba_cmdline_get_creds(),
4799 : 0 /* previous_session_id */);
4800 4 : CHECK_STATUS(status, NT_STATUS_OK);
4801 :
4802 : /*
4803 : * use the 2nd channel, 1st session
4804 : */
4805 4 : tree1->session = session1_2;
4806 4 : smb2cli_session_start_replay(tree1->session->smbXcli);
4807 4 : status = smb2_create(tree1, mem_ctx, &io);
4808 4 : smb2cli_session_stop_replay(tree1->session->smbXcli);
4809 4 : CHECK_STATUS(status, NT_STATUS_OK);
4810 4 : _h = io.out.file.handle;
4811 4 : h = &_h;
4812 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
4813 4 : if (share_is_so) {
4814 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
4815 0 : CHECK_VAL(io.out.durable_open_v2, false);
4816 0 : CHECK_VAL(io.out.timeout, 0);
4817 : } else {
4818 4 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
4819 4 : CHECK_VAL(io.out.durable_open_v2, true);
4820 4 : CHECK_VAL(io.out.timeout, 300*1000);
4821 : }
4822 4 : CHECK_VAL(io.out.durable_open, false);
4823 4 : CHECK_VAL(break_info.count, 0);
4824 :
4825 4 : tree1->session = session1_1;
4826 4 : smb2_util_close(tree1, *h);
4827 4 : h = NULL;
4828 :
4829 4 : done:
4830 4 : talloc_free(tree2);
4831 4 : tree1->session = session1_1;
4832 :
4833 4 : if (h != NULL) {
4834 0 : smb2_util_close(tree1, *h);
4835 : }
4836 :
4837 4 : smb2_util_unlink(tree1, fname);
4838 4 : smb2_deltree(tree1, BASEDIR);
4839 :
4840 4 : talloc_free(tree1);
4841 4 : talloc_free(mem_ctx);
4842 :
4843 4 : return ret;
4844 : }
4845 :
4846 : /**
4847 : * Test Multichannel IO Ordering using ChannelSequence/Channel Epoch number
4848 : */
4849 5 : static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1)
4850 : {
4851 5 : const char *host = torture_setting_string(tctx, "host", NULL);
4852 5 : const char *share = torture_setting_string(tctx, "share", NULL);
4853 0 : NTSTATUS status;
4854 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
4855 0 : struct smb2_handle _h1;
4856 5 : struct smb2_handle *h1 = NULL;
4857 0 : struct smb2_create io;
4858 5 : struct GUID create_guid = GUID_random();
4859 0 : uint8_t buf[64];
4860 0 : struct smb2_read rd;
4861 0 : union smb_setfileinfo sfinfo;
4862 5 : bool ret = true;
4863 5 : const char *fname = BASEDIR "\\replay4.dat";
4864 5 : struct smb2_tree *tree2 = NULL;
4865 5 : struct smb2_transport *transport1 = tree1->session->transport;
4866 5 : struct smb2_transport *transport2 = NULL;
4867 5 : struct smb2_session *session1_1 = tree1->session;
4868 5 : struct smb2_session *session1_2 = NULL;
4869 0 : uint16_t curr_cs;
4870 0 : uint32_t share_capabilities;
4871 0 : bool share_is_so;
4872 0 : uint32_t server_capabilities;
4873 :
4874 5 : if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
4875 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
4876 : "Replay tests\n");
4877 : }
4878 :
4879 4 : server_capabilities = smb2cli_conn_server_capabilities(
4880 4 : tree1->session->transport->conn);
4881 4 : if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
4882 0 : torture_skip(tctx,
4883 : "Server does not support multi-channel.");
4884 : }
4885 :
4886 4 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
4887 4 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
4888 :
4889 4 : torture_reset_break_info(tctx, &break_info);
4890 4 : transport1->oplock.handler = torture_oplock_ack_handler;
4891 4 : transport1->oplock.private_data = tree1;
4892 :
4893 4 : torture_comment(tctx, "IO Ordering for Multi Channel\n");
4894 4 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
4895 4 : CHECK_STATUS(status, NT_STATUS_OK);
4896 4 : smb2_util_close(tree1, _h1);
4897 4 : smb2_util_unlink(tree1, fname);
4898 4 : CHECK_VAL(break_info.count, 0);
4899 :
4900 : /*
4901 : * use the 1st channel, 1st session
4902 : */
4903 :
4904 4 : smb2_oplock_create_share(&io, fname,
4905 : smb2_util_share_access(""),
4906 4 : smb2_util_oplock_level("b"));
4907 4 : io.in.durable_open = false;
4908 4 : io.in.durable_open_v2 = true;
4909 4 : io.in.persistent_open = false;
4910 4 : io.in.create_guid = create_guid;
4911 4 : io.in.timeout = UINT32_MAX;
4912 :
4913 4 : tree1->session = session1_1;
4914 4 : status = smb2_create(tree1, mem_ctx, &io);
4915 4 : CHECK_STATUS(status, NT_STATUS_OK);
4916 4 : _h1 = io.out.file.handle;
4917 4 : h1 = &_h1;
4918 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
4919 4 : if (share_is_so) {
4920 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
4921 0 : CHECK_VAL(io.out.durable_open_v2, false);
4922 0 : CHECK_VAL(io.out.timeout, 0);
4923 : } else {
4924 4 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
4925 4 : CHECK_VAL(io.out.durable_open_v2, true);
4926 4 : CHECK_VAL(io.out.timeout, 300*1000);
4927 : }
4928 4 : CHECK_VAL(io.out.durable_open, false);
4929 4 : CHECK_VAL(break_info.count, 0);
4930 :
4931 4 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
4932 4 : CHECK_STATUS(status, NT_STATUS_OK);
4933 :
4934 : /*
4935 : * Increment ChannelSequence so that server thinks that there's a
4936 : * Channel Failure
4937 : */
4938 4 : smb2cli_session_increment_channel_sequence(tree1->session->smbXcli);
4939 :
4940 : /*
4941 : * Perform a Read with incremented ChannelSequence
4942 : */
4943 4 : rd = (struct smb2_read) {
4944 4 : .in.file.handle = *h1,
4945 : .in.length = sizeof(buf),
4946 : .in.offset = 0
4947 : };
4948 4 : status = smb2_read(tree1, tree1, &rd);
4949 4 : CHECK_STATUS(status, NT_STATUS_OK);
4950 :
4951 : /*
4952 : * Performing a Write with Stale ChannelSequence is not allowed by
4953 : * server
4954 : */
4955 4 : curr_cs = smb2cli_session_reset_channel_sequence(
4956 4 : tree1->session->smbXcli, 0);
4957 4 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
4958 4 : CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
4959 :
4960 : /*
4961 : * Performing a Write Replay with Stale ChannelSequence is not allowed
4962 : * by server
4963 : */
4964 4 : smb2cli_session_start_replay(tree1->session->smbXcli);
4965 4 : smb2cli_session_reset_channel_sequence(tree1->session->smbXcli, 0);
4966 4 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
4967 4 : smb2cli_session_stop_replay(tree1->session->smbXcli);
4968 4 : CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
4969 :
4970 : /*
4971 : * Performing a SetInfo with stale ChannelSequence is not allowed by
4972 : * server
4973 : */
4974 4 : ZERO_STRUCT(sfinfo);
4975 4 : sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
4976 4 : sfinfo.generic.in.file.handle = *h1;
4977 4 : sfinfo.position_information.in.position = 0x1000;
4978 4 : status = smb2_setinfo_file(tree1, &sfinfo);
4979 4 : CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
4980 :
4981 : /*
4982 : * Performing a Read with stale ChannelSequence is allowed
4983 : */
4984 4 : rd = (struct smb2_read) {
4985 4 : .in.file.handle = *h1,
4986 : .in.length = ARRAY_SIZE(buf),
4987 : .in.offset = 0
4988 : };
4989 4 : status = smb2_read(tree1, tree1, &rd);
4990 4 : CHECK_STATUS(status, NT_STATUS_OK);
4991 :
4992 8 : status = smb2_connect(tctx,
4993 : host,
4994 : lpcfg_smb_ports(tctx->lp_ctx),
4995 : share,
4996 : lpcfg_resolve_context(tctx->lp_ctx),
4997 : samba_cmdline_get_creds(),
4998 : &tree2,
4999 : tctx->ev,
5000 4 : &transport1->options,
5001 : lpcfg_socket_options(tctx->lp_ctx),
5002 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
5003 : );
5004 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5005 : "smb2_connect failed");
5006 4 : transport2 = tree2->session->transport;
5007 :
5008 4 : transport2->oplock.handler = torture_oplock_ack_handler;
5009 4 : transport2->oplock.private_data = tree2;
5010 :
5011 : /*
5012 : * Now bind the 1st session to 2nd transport channel
5013 : */
5014 4 : session1_2 = smb2_session_channel(transport2,
5015 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
5016 : tree2, session1_1);
5017 4 : torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
5018 :
5019 4 : status = smb2_session_setup_spnego(session1_2,
5020 : samba_cmdline_get_creds(),
5021 : 0 /* previous_session_id */);
5022 4 : CHECK_STATUS(status, NT_STATUS_OK);
5023 :
5024 : /*
5025 : * use the 2nd channel, 1st session
5026 : */
5027 4 : tree1->session = session1_2;
5028 :
5029 : /*
5030 : * Write Replay with Correct ChannelSequence is allowed by the server
5031 : */
5032 4 : smb2cli_session_start_replay(tree1->session->smbXcli);
5033 4 : smb2cli_session_reset_channel_sequence(tree1->session->smbXcli,
5034 : curr_cs);
5035 4 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
5036 4 : CHECK_STATUS(status, NT_STATUS_OK);
5037 4 : smb2cli_session_stop_replay(tree1->session->smbXcli);
5038 :
5039 : /*
5040 : * See what happens if we change the Buffer and perform a Write Replay.
5041 : * This is to show that Write Replay does not really care about the data
5042 : */
5043 4 : memset(buf, 'r', ARRAY_SIZE(buf));
5044 4 : smb2cli_session_start_replay(tree1->session->smbXcli);
5045 4 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
5046 4 : CHECK_STATUS(status, NT_STATUS_OK);
5047 4 : smb2cli_session_stop_replay(tree1->session->smbXcli);
5048 :
5049 : /*
5050 : * Read back from File to verify what was written
5051 : */
5052 4 : rd = (struct smb2_read) {
5053 4 : .in.file.handle = *h1,
5054 : .in.length = ARRAY_SIZE(buf),
5055 : .in.offset = 0
5056 : };
5057 4 : status = smb2_read(tree1, tree1, &rd);
5058 4 : CHECK_STATUS(status, NT_STATUS_OK);
5059 :
5060 4 : if ((rd.out.data.length != ARRAY_SIZE(buf)) ||
5061 4 : memcmp(rd.out.data.data, buf, ARRAY_SIZE(buf))) {
5062 0 : torture_comment(tctx, "Write Replay Data Mismatch\n");
5063 : }
5064 :
5065 4 : tree1->session = session1_1;
5066 4 : smb2_util_close(tree1, *h1);
5067 4 : h1 = NULL;
5068 :
5069 4 : if (share_is_so) {
5070 0 : CHECK_VAL(break_info.count, 1);
5071 : } else {
5072 4 : CHECK_VAL(break_info.count, 0);
5073 : }
5074 4 : done:
5075 4 : talloc_free(tree2);
5076 4 : tree1->session = session1_1;
5077 :
5078 4 : if (h1 != NULL) {
5079 0 : smb2_util_close(tree1, *h1);
5080 : }
5081 :
5082 4 : smb2_util_unlink(tree1, fname);
5083 4 : smb2_deltree(tree1, BASEDIR);
5084 :
5085 4 : talloc_free(tree1);
5086 4 : talloc_free(mem_ctx);
5087 :
5088 4 : return ret;
5089 : }
5090 :
5091 : /**
5092 : * Test Durability V2 Persistent Create Replay on a Single Channel
5093 : */
5094 5 : static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree)
5095 : {
5096 0 : NTSTATUS status;
5097 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
5098 0 : struct smb2_handle _h;
5099 5 : struct smb2_handle *h = NULL;
5100 0 : struct smb2_create io;
5101 5 : struct GUID create_guid = GUID_random();
5102 5 : bool ret = true;
5103 0 : uint32_t share_capabilities;
5104 0 : bool share_is_ca;
5105 0 : bool share_is_so;
5106 0 : uint32_t server_capabilities;
5107 5 : const char *fname = BASEDIR "\\replay5.dat";
5108 5 : struct smb2_transport *transport = tree->session->transport;
5109 5 : struct smbcli_options options = tree->session->transport->options;
5110 5 : uint8_t expect_oplock = smb2_util_oplock_level("b");
5111 5 : NTSTATUS expect_status = NT_STATUS_DUPLICATE_OBJECTID;
5112 :
5113 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
5114 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
5115 : "Replay tests\n");
5116 : }
5117 :
5118 4 : server_capabilities = smb2cli_conn_server_capabilities(
5119 4 : tree->session->transport->conn);
5120 4 : if (!(server_capabilities & SMB2_CAP_PERSISTENT_HANDLES)) {
5121 4 : torture_skip(tctx,
5122 : "Server does not support persistent handles.");
5123 : }
5124 :
5125 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
5126 :
5127 0 : share_is_ca = share_capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
5128 0 : if (!share_is_ca) {
5129 0 : torture_skip(tctx, "Share is not continuously available.");
5130 : }
5131 :
5132 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
5133 0 : if (share_is_so) {
5134 0 : expect_oplock = smb2_util_oplock_level("s");
5135 0 : expect_status = NT_STATUS_FILE_NOT_AVAILABLE;
5136 : }
5137 :
5138 0 : torture_reset_break_info(tctx, &break_info);
5139 0 : transport->oplock.handler = torture_oplock_ack_handler;
5140 0 : transport->oplock.private_data = tree;
5141 :
5142 0 : torture_comment(tctx, "Replay of Persistent DurableHandleReqV2 on Single "
5143 : "Channel\n");
5144 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
5145 0 : CHECK_STATUS(status, NT_STATUS_OK);
5146 0 : smb2_util_close(tree, _h);
5147 0 : smb2_util_unlink(tree, fname);
5148 0 : CHECK_VAL(break_info.count, 0);
5149 :
5150 0 : smb2_oplock_create_share(&io, fname,
5151 : smb2_util_share_access("RWD"),
5152 0 : smb2_util_oplock_level("b"));
5153 0 : io.in.durable_open = false;
5154 0 : io.in.durable_open_v2 = true;
5155 0 : io.in.persistent_open = true;
5156 0 : io.in.create_guid = create_guid;
5157 0 : io.in.timeout = UINT32_MAX;
5158 :
5159 0 : status = smb2_create(tree, mem_ctx, &io);
5160 0 : CHECK_STATUS(status, NT_STATUS_OK);
5161 0 : _h = io.out.file.handle;
5162 0 : h = &_h;
5163 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
5164 0 : CHECK_VAL(io.out.oplock_level, expect_oplock);
5165 0 : CHECK_VAL(io.out.durable_open, false);
5166 0 : CHECK_VAL(io.out.durable_open_v2, true);
5167 0 : CHECK_VAL(io.out.persistent_open, true);
5168 0 : CHECK_VAL(io.out.timeout, 300*1000);
5169 0 : CHECK_VAL(break_info.count, 0);
5170 :
5171 : /* disconnect, leaving the durable open */
5172 0 : TALLOC_FREE(tree);
5173 :
5174 0 : if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) {
5175 0 : torture_warning(tctx, "couldn't reconnect, bailing\n");
5176 0 : ret = false;
5177 0 : goto done;
5178 : }
5179 :
5180 : /* a re-open of a persistent handle causes an error */
5181 0 : status = smb2_create(tree, mem_ctx, &io);
5182 0 : CHECK_STATUS(status, expect_status);
5183 :
5184 : /* SMB2_FLAGS_REPLAY_OPERATION must be set to open the Persistent Handle */
5185 0 : smb2cli_session_start_replay(tree->session->smbXcli);
5186 0 : smb2cli_session_increment_channel_sequence(tree->session->smbXcli);
5187 0 : status = smb2_create(tree, mem_ctx, &io);
5188 0 : CHECK_STATUS(status, NT_STATUS_OK);
5189 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
5190 0 : CHECK_VAL(io.out.durable_open, false);
5191 0 : CHECK_VAL(io.out.persistent_open, true);
5192 0 : CHECK_VAL(io.out.oplock_level, expect_oplock);
5193 0 : _h = io.out.file.handle;
5194 0 : h = &_h;
5195 :
5196 0 : smb2_util_close(tree, *h);
5197 0 : h = NULL;
5198 0 : done:
5199 0 : if (h != NULL) {
5200 0 : smb2_util_close(tree, *h);
5201 : }
5202 :
5203 0 : smb2_util_unlink(tree, fname);
5204 0 : smb2_deltree(tree, BASEDIR);
5205 :
5206 0 : talloc_free(tree);
5207 0 : talloc_free(mem_ctx);
5208 :
5209 0 : return ret;
5210 : }
5211 :
5212 :
5213 : /**
5214 : * Test Error Codes when a DurableHandleReqV2 with matching CreateGuid is
5215 : * re-sent with or without SMB2_FLAGS_REPLAY_OPERATION
5216 : */
5217 5 : static bool test_replay6(struct torture_context *tctx, struct smb2_tree *tree)
5218 : {
5219 0 : NTSTATUS status;
5220 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
5221 0 : struct smb2_handle _h;
5222 5 : struct smb2_handle *h = NULL;
5223 0 : struct smb2_create io, ref1;
5224 0 : union smb_fileinfo qfinfo;
5225 5 : struct GUID create_guid = GUID_random();
5226 5 : bool ret = true;
5227 5 : const char *fname = BASEDIR "\\replay6.dat";
5228 5 : struct smb2_transport *transport = tree->session->transport;
5229 :
5230 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
5231 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
5232 : "replay tests\n");
5233 : }
5234 :
5235 4 : torture_reset_break_info(tctx, &break_info);
5236 4 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
5237 4 : tree->session->transport->oplock.private_data = tree;
5238 :
5239 4 : torture_comment(tctx, "Error Codes for DurableHandleReqV2 Replay\n");
5240 4 : smb2_util_unlink(tree, fname);
5241 4 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
5242 4 : CHECK_STATUS(status, NT_STATUS_OK);
5243 4 : smb2_util_close(tree, _h);
5244 4 : torture_wait_for_oplock_break(tctx);
5245 4 : CHECK_VAL(break_info.count, 0);
5246 4 : torture_reset_break_info(tctx, &break_info);
5247 :
5248 4 : smb2_oplock_create_share(&io, fname,
5249 : smb2_util_share_access("RWD"),
5250 4 : smb2_util_oplock_level("b"));
5251 4 : io.in.durable_open = false;
5252 4 : io.in.durable_open_v2 = true;
5253 4 : io.in.persistent_open = false;
5254 4 : io.in.create_guid = create_guid;
5255 4 : io.in.timeout = UINT32_MAX;
5256 :
5257 4 : status = smb2_create(tree, mem_ctx, &io);
5258 4 : CHECK_STATUS(status, NT_STATUS_OK);
5259 4 : ref1 = io;
5260 4 : _h = io.out.file.handle;
5261 4 : h = &_h;
5262 4 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
5263 4 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
5264 4 : CHECK_VAL(io.out.durable_open, false);
5265 4 : CHECK_VAL(io.out.durable_open_v2, true);
5266 :
5267 4 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
5268 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
5269 4 : smb2cli_session_start_replay(tree->session->smbXcli);
5270 4 : status = smb2_create(tree, mem_ctx, &io);
5271 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
5272 4 : CHECK_STATUS(status, NT_STATUS_OK);
5273 4 : CHECK_CREATE_OUT(&io, &ref1);
5274 4 : torture_wait_for_oplock_break(tctx);
5275 4 : CHECK_VAL(break_info.count, 0);
5276 4 : torture_reset_break_info(tctx, &break_info);
5277 :
5278 4 : qfinfo = (union smb_fileinfo) {
5279 : .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
5280 4 : .generic.in.file.handle = *h
5281 : };
5282 4 : torture_comment(tctx, "Trying getinfo\n");
5283 4 : status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
5284 4 : CHECK_STATUS(status, NT_STATUS_OK);
5285 4 : CHECK_VAL(qfinfo.position_information.out.position, 0);
5286 :
5287 4 : smb2cli_session_start_replay(tree->session->smbXcli);
5288 4 : status = smb2_create(tree, mem_ctx, &io);
5289 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
5290 4 : CHECK_STATUS(status, NT_STATUS_OK);
5291 4 : torture_assert_u64_not_equal_goto(tctx,
5292 : io.out.file.handle.data[0],
5293 : ref1.out.file.handle.data[0],
5294 : ret, done, "data 0");
5295 4 : torture_assert_u64_not_equal_goto(tctx,
5296 : io.out.file.handle.data[1],
5297 : ref1.out.file.handle.data[1],
5298 : ret, done, "data 1");
5299 4 : torture_wait_for_oplock_break(tctx);
5300 4 : CHECK_VAL(break_info.count, 1);
5301 4 : CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
5302 4 : torture_reset_break_info(tctx, &break_info);
5303 :
5304 : /*
5305 : * Resend the matching Durable V2 Create without
5306 : * SMB2_FLAGS_REPLAY_OPERATION. This triggers an oplock break and still
5307 : * gets NT_STATUS_DUPLICATE_OBJECTID
5308 : */
5309 4 : status = smb2_create(tree, mem_ctx, &io);
5310 4 : CHECK_STATUS(status, NT_STATUS_DUPLICATE_OBJECTID);
5311 4 : torture_wait_for_oplock_break(tctx);
5312 4 : CHECK_VAL(break_info.count, 0);
5313 4 : torture_reset_break_info(tctx, &break_info);
5314 :
5315 : /*
5316 : * According to MS-SMB2 3.3.5.9.10 if Durable V2 Create is replayed and
5317 : * FileAttributes or CreateDisposition do not match the earlier Create
5318 : * request the Server fails request with
5319 : * NT_STATUS_INVALID_PARAMETER. But through this test we see that server
5320 : * does not really care about changed FileAttributes or
5321 : * CreateDisposition.
5322 : */
5323 4 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
5324 4 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
5325 4 : smb2cli_session_start_replay(tree->session->smbXcli);
5326 4 : status = smb2_create(tree, mem_ctx, &io);
5327 4 : smb2cli_session_stop_replay(tree->session->smbXcli);
5328 4 : CHECK_STATUS(status, NT_STATUS_OK);
5329 4 : torture_assert_u64_not_equal_goto(tctx,
5330 : io.out.file.handle.data[0],
5331 : ref1.out.file.handle.data[0],
5332 : ret, done, "data 0");
5333 4 : torture_assert_u64_not_equal_goto(tctx,
5334 : io.out.file.handle.data[1],
5335 : ref1.out.file.handle.data[1],
5336 : ret, done, "data 1");
5337 4 : torture_wait_for_oplock_break(tctx);
5338 4 : CHECK_VAL(break_info.count, 0);
5339 :
5340 4 : done:
5341 4 : if (h != NULL) {
5342 4 : smb2_util_close(tree, *h);
5343 : }
5344 :
5345 4 : smb2_util_unlink(tree, fname);
5346 4 : smb2_deltree(tree, BASEDIR);
5347 :
5348 4 : talloc_free(tree);
5349 4 : talloc_free(mem_ctx);
5350 :
5351 4 : return ret;
5352 : }
5353 :
5354 5 : static bool test_replay7(struct torture_context *tctx, struct smb2_tree *tree)
5355 : {
5356 5 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
5357 5 : struct smb2_transport *transport = tree->session->transport;
5358 0 : NTSTATUS status;
5359 0 : struct smb2_handle _dh;
5360 5 : struct smb2_handle *dh = NULL;
5361 0 : struct smb2_notify notify;
5362 0 : struct smb2_request *req;
5363 0 : union smb_fileinfo qfinfo;
5364 5 : bool ret = false;
5365 :
5366 5 : if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
5367 1 : torture_skip(tctx, "SMB 3.X Dialect family required for "
5368 : "replay tests\n");
5369 : }
5370 :
5371 4 : torture_comment(tctx, "Notify across increment/decrement of csn\n");
5372 :
5373 4 : smbXcli_conn_set_force_channel_sequence(transport->conn, true);
5374 :
5375 4 : status = torture_smb2_testdir(tree, BASEDIR, &_dh);
5376 4 : CHECK_STATUS(status, NT_STATUS_OK);
5377 4 : dh = &_dh;
5378 :
5379 4 : notify.in.recursive = 0x0000;
5380 4 : notify.in.buffer_size = 0xffff;
5381 4 : notify.in.file.handle = _dh;
5382 4 : notify.in.completion_filter = FILE_NOTIFY_CHANGE_FILE_NAME;
5383 4 : notify.in.unknown = 0x00000000;
5384 :
5385 : /*
5386 : * This posts a long-running request with csn==0 to "dh". Now
5387 : * op->request_count==1 in smb2_server.c.
5388 : */
5389 4 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
5390 4 : req = smb2_notify_send(tree, ¬ify);
5391 :
5392 4 : qfinfo = (union smb_fileinfo) {
5393 : .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
5394 : .generic.in.file.handle = _dh
5395 : };
5396 :
5397 : /*
5398 : * This sequence of 2 dummy requests moves
5399 : * op->request_count==1 to op->pre_request_count. The numbers
5400 : * used avoid int16 overflow.
5401 : */
5402 :
5403 4 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 30000);
5404 4 : status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
5405 4 : CHECK_STATUS(status, NT_STATUS_OK);
5406 :
5407 4 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 60000);
5408 4 : status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
5409 4 : CHECK_STATUS(status, NT_STATUS_OK);
5410 :
5411 : /*
5412 : * This final request turns the op->global->channel_sequence
5413 : * to the same as we had when sending the notify above. The
5414 : * notify's request count has in the meantime moved to
5415 : * op->pre_request_count.
5416 : */
5417 :
5418 4 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
5419 4 : status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
5420 4 : CHECK_STATUS(status, NT_STATUS_OK);
5421 :
5422 : /*
5423 : * At this point op->request_count==0.
5424 : *
5425 : * The next cancel makes us reply to the notify. Because the
5426 : * csn we currently use is the same as we used when sending
5427 : * the notify, smbd thinks it must decrement op->request_count
5428 : * and not op->pre_request_count.
5429 : */
5430 :
5431 4 : status = smb2_cancel(req);
5432 4 : CHECK_STATUS(status, NT_STATUS_OK);
5433 :
5434 4 : status = smb2_notify_recv(req, mem_ctx, ¬ify);
5435 4 : CHECK_STATUS(status, NT_STATUS_CANCELLED);
5436 :
5437 4 : ret = true;
5438 :
5439 4 : done:
5440 4 : if (dh != NULL) {
5441 4 : smb2_util_close(tree, _dh);
5442 : }
5443 4 : smb2_deltree(tree, BASEDIR);
5444 4 : talloc_free(tree);
5445 4 : talloc_free(mem_ctx);
5446 :
5447 4 : return ret;
5448 : }
5449 :
5450 2354 : struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx)
5451 : {
5452 125 : struct torture_suite *suite =
5453 2354 : torture_suite_create(ctx, "replay");
5454 :
5455 2354 : torture_suite_add_1smb2_test(suite, "replay-commands", test_replay_commands);
5456 2354 : torture_suite_add_1smb2_test(suite, "replay-regular", test_replay_regular);
5457 2354 : torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock1", test_replay_dhv2_oplock1);
5458 2354 : torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2);
5459 2354 : torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3);
5460 2354 : torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock-lease", test_replay_dhv2_oplock_lease);
5461 2354 : torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1", test_replay_dhv2_lease1);
5462 2354 : torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2", test_replay_dhv2_lease2);
5463 2354 : torture_suite_add_1smb2_test(suite, "replay-dhv2-lease3", test_replay_dhv2_lease3);
5464 2354 : torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock", test_replay_dhv2_lease_oplock);
5465 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-close-sane", test_dhv2_pending1n_vs_violation_lease_close_sane);
5466 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-ack-sane", test_dhv2_pending1n_vs_violation_lease_ack_sane);
5467 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-close-windows", test_dhv2_pending1n_vs_violation_lease_close_windows);
5468 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-ack-windows", test_dhv2_pending1n_vs_violation_lease_ack_windows);
5469 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-oplock-sane", test_dhv2_pending1n_vs_oplock_sane);
5470 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-oplock-windows", test_dhv2_pending1n_vs_oplock_windows);
5471 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-lease-sane", test_dhv2_pending1n_vs_lease_sane);
5472 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-lease-windows", test_dhv2_pending1n_vs_lease_windows);
5473 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-oplock-sane", test_dhv2_pending1l_vs_oplock_sane);
5474 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-oplock-windows", test_dhv2_pending1l_vs_oplock_windows);
5475 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-lease-sane", test_dhv2_pending1l_vs_lease_sane);
5476 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-lease-windows", test_dhv2_pending1l_vs_lease_windows);
5477 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-oplock-sane", test_dhv2_pending1o_vs_oplock_sane);
5478 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-oplock-windows", test_dhv2_pending1o_vs_oplock_windows);
5479 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-lease-sane", test_dhv2_pending1o_vs_lease_sane);
5480 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-lease-windows", test_dhv2_pending1o_vs_lease_windows);
5481 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-oplock-sane", test_dhv2_pending2n_vs_oplock_sane);
5482 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-oplock-windows", test_dhv2_pending2n_vs_oplock_windows);
5483 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-lease-sane", test_dhv2_pending2n_vs_lease_sane);
5484 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-lease-windows", test_dhv2_pending2n_vs_lease_windows);
5485 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-oplock-sane", test_dhv2_pending2l_vs_oplock_sane);
5486 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-oplock-windows", test_dhv2_pending2l_vs_oplock_windows);
5487 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-lease-sane", test_dhv2_pending2l_vs_lease_sane);
5488 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-lease-windows", test_dhv2_pending2l_vs_lease_windows);
5489 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-oplock-sane", test_dhv2_pending2o_vs_oplock_sane);
5490 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-oplock-windows", test_dhv2_pending2o_vs_oplock_windows);
5491 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-lease-sane", test_dhv2_pending2o_vs_lease_sane);
5492 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-lease-windows", test_dhv2_pending2o_vs_lease_windows);
5493 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-oplock-sane", test_dhv2_pending3n_vs_oplock_sane);
5494 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-oplock-windows", test_dhv2_pending3n_vs_oplock_windows);
5495 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-lease-sane", test_dhv2_pending3n_vs_lease_sane);
5496 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-lease-windows", test_dhv2_pending3n_vs_lease_windows);
5497 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-oplock-sane", test_dhv2_pending3l_vs_oplock_sane);
5498 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-oplock-windows", test_dhv2_pending3l_vs_oplock_windows);
5499 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-lease-sane", test_dhv2_pending3l_vs_lease_sane);
5500 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-lease-windows", test_dhv2_pending3l_vs_lease_windows);
5501 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-oplock-sane", test_dhv2_pending3o_vs_oplock_sane);
5502 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-oplock-windows", test_dhv2_pending3o_vs_oplock_windows);
5503 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-lease-sane", test_dhv2_pending3o_vs_lease_sane);
5504 2354 : torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-lease-windows", test_dhv2_pending3o_vs_lease_windows);
5505 2354 : torture_suite_add_1smb2_test(suite, "channel-sequence", test_channel_sequence);
5506 2354 : torture_suite_add_1smb2_test(suite, "replay3", test_replay3);
5507 2354 : torture_suite_add_1smb2_test(suite, "replay4", test_replay4);
5508 2354 : torture_suite_add_1smb2_test(suite, "replay5", test_replay5);
5509 2354 : torture_suite_add_1smb2_test(suite, "replay6", test_replay6);
5510 2354 : torture_suite_add_1smb2_test(suite, "replay7", test_replay7);
5511 :
5512 2354 : suite->description = talloc_strdup(suite, "SMB2 REPLAY tests");
5513 :
5514 2354 : return suite;
5515 : }
|