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 1 : static bool test_replay_commands(struct torture_context *tctx, struct smb2_tree *tree)
112 : {
113 1 : bool ret = true;
114 : NTSTATUS status;
115 : struct smb2_handle h;
116 : uint8_t buf[200];
117 : struct smb2_read rd;
118 : union smb_setfileinfo sfinfo;
119 : union smb_fileinfo qfinfo;
120 : union smb_ioctl ioctl;
121 : struct smb2_lock lck;
122 : struct smb2_lock_element el[2];
123 : struct smb2_flush f;
124 1 : TALLOC_CTX *tmp_ctx = talloc_new(tree);
125 1 : const char *fname = BASEDIR "\\replay_commands.dat";
126 1 : struct smb2_transport *transport = tree->session->transport;
127 :
128 1 : 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 0 : torture_reset_break_info(tctx, &break_info);
134 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
135 0 : tree->session->transport->oplock.private_data = tree;
136 :
137 0 : status = torture_smb2_testdir(tree, BASEDIR, &h);
138 0 : CHECK_STATUS(status, NT_STATUS_OK);
139 0 : smb2_util_close(tree, h);
140 :
141 0 : smb2cli_session_start_replay(tree->session->smbXcli);
142 :
143 0 : torture_comment(tctx, "Try Commands with Replay Flags Enabled\n");
144 :
145 0 : torture_comment(tctx, "Trying create\n");
146 0 : status = torture_smb2_testfile(tree, fname, &h);
147 0 : CHECK_STATUS(status, NT_STATUS_OK);
148 0 : 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 0 : torture_comment(tctx, "Trying write\n");
155 0 : status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
156 0 : CHECK_STATUS(status, NT_STATUS_OK);
157 :
158 0 : f = (struct smb2_flush) {
159 : .in.file.handle = h
160 : };
161 0 : torture_comment(tctx, "Trying flush\n");
162 0 : status = smb2_flush(tree, &f);
163 0 : CHECK_STATUS(status, NT_STATUS_OK);
164 :
165 0 : rd = (struct smb2_read) {
166 : .in.file.handle = h,
167 : .in.length = 10,
168 : .in.offset = 0,
169 : .in.min_count = 1
170 : };
171 0 : torture_comment(tctx, "Trying read\n");
172 0 : status = smb2_read(tree, tmp_ctx, &rd);
173 0 : CHECK_STATUS(status, NT_STATUS_OK);
174 0 : CHECK_VAL(rd.out.data.length, 10);
175 :
176 0 : sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
177 0 : sfinfo.position_information.in.file.handle = h;
178 0 : sfinfo.position_information.in.position = 0x1000;
179 0 : torture_comment(tctx, "Trying setinfo\n");
180 0 : status = smb2_setinfo_file(tree, &sfinfo);
181 0 : CHECK_STATUS(status, NT_STATUS_OK);
182 :
183 0 : qfinfo = (union smb_fileinfo) {
184 : .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
185 : .generic.in.file.handle = h
186 : };
187 0 : torture_comment(tctx, "Trying getinfo\n");
188 0 : status = smb2_getinfo_file(tree, tmp_ctx, &qfinfo);
189 0 : CHECK_STATUS(status, NT_STATUS_OK);
190 0 : CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
191 :
192 0 : 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 0 : torture_comment(tctx, "Trying ioctl\n");
200 0 : status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
201 0 : CHECK_STATUS(status, NT_STATUS_OK);
202 :
203 0 : 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 0 : el[0].reserved = 0x00000000;
210 0 : el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
211 : SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
212 :
213 0 : torture_comment(tctx, "Trying lock\n");
214 0 : el[0].offset = 0x0000000000000000;
215 0 : el[0].length = 0x0000000000000100;
216 0 : status = smb2_lock(tree, &lck);
217 0 : CHECK_STATUS(status, NT_STATUS_OK);
218 :
219 0 : lck.in.file.handle = h;
220 0 : el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
221 0 : status = smb2_lock(tree, &lck);
222 0 : CHECK_STATUS(status, NT_STATUS_OK);
223 :
224 0 : CHECK_VAL(break_info.count, 0);
225 0 : done:
226 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
227 0 : smb2_util_close(tree, h);
228 0 : smb2_deltree(tree, BASEDIR);
229 :
230 0 : talloc_free(tmp_ctx);
231 :
232 0 : 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 1 : static bool test_replay_regular(struct torture_context *tctx,
241 : struct smb2_tree *tree)
242 : {
243 : NTSTATUS status;
244 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
245 : struct smb2_handle _h;
246 1 : struct smb2_handle *h = NULL;
247 : struct smb2_create io;
248 1 : uint32_t perms = 0;
249 1 : bool ret = true;
250 1 : const char *fname = BASEDIR "\\replay_regular.dat";
251 1 : struct smb2_transport *transport = tree->session->transport;
252 :
253 1 : 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 0 : torture_reset_break_info(tctx, &break_info);
259 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
260 0 : tree->session->transport->oplock.private_data = tree;
261 :
262 0 : smb2_util_unlink(tree, fname);
263 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
264 0 : CHECK_STATUS(status, NT_STATUS_OK);
265 0 : smb2_util_close(tree, _h);
266 0 : CHECK_VAL(break_info.count, 0);
267 :
268 0 : torture_comment(tctx, "No replay detection for regular create\n");
269 :
270 0 : 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 0 : 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 0 : status = smb2_create(tree, tctx, &io);
285 0 : CHECK_STATUS(status, NT_STATUS_OK);
286 0 : CHECK_VAL(break_info.count, 0);
287 0 : _h = io.out.file.handle;
288 0 : h = &_h;
289 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
290 :
291 0 : smb2cli_session_start_replay(tree->session->smbXcli);
292 0 : status = smb2_create(tree, tctx, &io);
293 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
294 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
295 0 : CHECK_VAL(break_info.count, 0);
296 :
297 0 : smb2_util_close(tree, *h);
298 0 : h = NULL;
299 0 : smb2_util_unlink(tree, fname);
300 :
301 : /*
302 : * Same experiment with different create disposition.
303 : */
304 0 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
305 0 : status = smb2_create(tree, tctx, &io);
306 0 : CHECK_STATUS(status, NT_STATUS_OK);
307 0 : CHECK_VAL(break_info.count, 0);
308 0 : _h = io.out.file.handle;
309 0 : h = &_h;
310 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
311 :
312 0 : smb2cli_session_start_replay(tree->session->smbXcli);
313 0 : status = smb2_create(tree, tctx, &io);
314 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
315 0 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
316 0 : CHECK_VAL(break_info.count, 0);
317 :
318 0 : smb2_util_close(tree, *h);
319 0 : h = NULL;
320 0 : smb2_util_unlink(tree, fname);
321 :
322 : /*
323 : * Now with more generous share mode.
324 : */
325 0 : io.in.share_access = smb2_util_share_access("RWD");
326 0 : status = smb2_create(tree, tctx, &io);
327 0 : CHECK_STATUS(status, NT_STATUS_OK);
328 0 : CHECK_VAL(break_info.count, 0);
329 0 : _h = io.out.file.handle;
330 0 : h = &_h;
331 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
332 :
333 0 : smb2cli_session_start_replay(tree->session->smbXcli);
334 0 : status = smb2_create(tree, tctx, &io);
335 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
336 0 : CHECK_STATUS(status, NT_STATUS_OK);
337 0 : CHECK_VAL(break_info.count, 0);
338 :
339 0 : done:
340 0 : if (h != NULL) {
341 0 : smb2_util_close(tree, *h);
342 : }
343 0 : smb2_deltree(tree, BASEDIR);
344 :
345 0 : talloc_free(tree);
346 0 : talloc_free(mem_ctx);
347 :
348 0 : return ret;
349 : }
350 :
351 : /**
352 : * Test Durability V2 Create Replay Detection on Single Channel.
353 : */
354 1 : static bool test_replay_dhv2_oplock1(struct torture_context *tctx,
355 : struct smb2_tree *tree)
356 : {
357 : NTSTATUS status;
358 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
359 : struct smb2_handle _h;
360 1 : struct smb2_handle *h = NULL;
361 : struct smb2_create io, ref1;
362 1 : struct GUID create_guid = GUID_random();
363 1 : bool ret = true;
364 1 : const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat";
365 1 : struct smb2_transport *transport = tree->session->transport;
366 : uint32_t share_capabilities;
367 : bool share_is_so;
368 :
369 1 : 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 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
375 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
376 :
377 0 : torture_reset_break_info(tctx, &break_info);
378 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
379 0 : tree->session->transport->oplock.private_data = tree;
380 :
381 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
382 : "Channel\n");
383 0 : smb2_util_unlink(tree, fname);
384 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
385 0 : CHECK_STATUS(status, NT_STATUS_OK);
386 0 : smb2_util_close(tree, _h);
387 0 : CHECK_VAL(break_info.count, 0);
388 :
389 0 : smb2_oplock_create_share(&io, fname,
390 : smb2_util_share_access(""),
391 0 : smb2_util_oplock_level("b"));
392 0 : io.in.durable_open = false;
393 0 : io.in.durable_open_v2 = true;
394 0 : io.in.persistent_open = false;
395 0 : io.in.create_guid = create_guid;
396 0 : io.in.timeout = UINT32_MAX;
397 :
398 0 : status = smb2_create(tree, mem_ctx, &io);
399 0 : CHECK_STATUS(status, NT_STATUS_OK);
400 0 : ref1 = io;
401 0 : _h = io.out.file.handle;
402 0 : h = &_h;
403 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
404 0 : CHECK_VAL(io.out.durable_open, false);
405 0 : 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 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
411 0 : CHECK_VAL(io.out.durable_open_v2, true);
412 0 : CHECK_VAL(io.out.timeout, 300*1000);
413 : }
414 :
415 : /*
416 : * Replay Durable V2 Create on single channel
417 : */
418 0 : smb2cli_session_start_replay(tree->session->smbXcli);
419 0 : status = smb2_create(tree, mem_ctx, &io);
420 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
421 0 : CHECK_STATUS(status, NT_STATUS_OK);
422 0 : CHECK_CREATE_OUT(&io, &ref1);
423 0 : CHECK_VAL(break_info.count, 0);
424 :
425 0 : done:
426 0 : if (h != NULL) {
427 0 : smb2_util_close(tree, *h);
428 : }
429 0 : smb2_deltree(tree, BASEDIR);
430 :
431 0 : talloc_free(tree);
432 0 : talloc_free(mem_ctx);
433 :
434 0 : 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 1 : static bool test_replay_dhv2_oplock2(struct torture_context *tctx,
445 : struct smb2_tree *tree)
446 : {
447 : NTSTATUS status;
448 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
449 : struct smb2_handle _h;
450 1 : struct smb2_handle *h = NULL;
451 : struct smb2_create io, ref1, ref2;
452 1 : struct GUID create_guid = GUID_random();
453 1 : bool ret = true;
454 1 : const char *fname = BASEDIR "\\replay_dhv2_oplock2.dat";
455 1 : struct smb2_transport *transport = tree->session->transport;
456 : uint32_t share_capabilities;
457 : bool share_is_so;
458 :
459 1 : 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 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
465 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
466 :
467 0 : torture_reset_break_info(tctx, &break_info);
468 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
469 0 : tree->session->transport->oplock.private_data = tree;
470 :
471 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
472 : "Channel\n");
473 0 : smb2_util_unlink(tree, fname);
474 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
475 0 : CHECK_STATUS(status, NT_STATUS_OK);
476 0 : smb2_util_close(tree, _h);
477 0 : CHECK_VAL(break_info.count, 0);
478 :
479 0 : smb2_oplock_create_share(&io, fname,
480 : smb2_util_share_access(""),
481 0 : smb2_util_oplock_level("b"));
482 0 : io.in.durable_open = false;
483 0 : io.in.durable_open_v2 = true;
484 0 : io.in.persistent_open = false;
485 0 : io.in.create_guid = create_guid;
486 0 : io.in.timeout = UINT32_MAX;
487 :
488 0 : status = smb2_create(tree, mem_ctx, &io);
489 0 : CHECK_STATUS(status, NT_STATUS_OK);
490 0 : ref1 = io;
491 0 : _h = io.out.file.handle;
492 0 : h = &_h;
493 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
494 0 : CHECK_VAL(io.out.durable_open, false);
495 0 : 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 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
501 0 : CHECK_VAL(io.out.durable_open_v2, true);
502 0 : 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 0 : smb2_oplock_create_share(&io, fname,
515 : smb2_util_share_access(""),
516 0 : smb2_util_oplock_level(""));
517 0 : io.in.durable_open = false;
518 0 : io.in.durable_open_v2 = true;
519 0 : io.in.persistent_open = false;
520 0 : io.in.create_guid = create_guid;
521 0 : io.in.timeout = UINT32_MAX;
522 :
523 : /*
524 : * Adapt the response to the exepected values
525 : */
526 0 : ref2 = ref1;
527 0 : ref2.out.oplock_level = smb2_util_oplock_level("");
528 0 : ref2.out.durable_open_v2 = false;
529 0 : ref2.out.timeout = 0;
530 0 : ref2.out.blobs.num_blobs = 0;
531 :
532 0 : smb2cli_session_start_replay(tree->session->smbXcli);
533 0 : status = smb2_create(tree, mem_ctx, &io);
534 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
535 0 : CHECK_STATUS(status, NT_STATUS_OK);
536 0 : CHECK_CREATE_OUT(&io, &ref2);
537 0 : 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 0 : smb2_oplock_create_share(&io, fname,
544 : smb2_util_share_access(""),
545 0 : smb2_util_oplock_level("b"));
546 0 : io.in.durable_open = false;
547 0 : io.in.durable_open_v2 = true;
548 0 : io.in.persistent_open = false;
549 0 : io.in.create_guid = GUID_random();
550 0 : io.in.timeout = UINT32_MAX;
551 0 : status = smb2_create(tree, mem_ctx, &io);
552 0 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
553 :
554 0 : if (!share_is_so) {
555 0 : CHECK_VAL(break_info.count, 1);
556 0 : CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle);
557 0 : CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
558 0 : torture_reset_break_info(tctx, &break_info);
559 : }
560 :
561 0 : done:
562 0 : if (h != NULL) {
563 0 : smb2_util_close(tree, *h);
564 : }
565 0 : smb2_deltree(tree, BASEDIR);
566 :
567 0 : talloc_free(tree);
568 0 : talloc_free(mem_ctx);
569 :
570 0 : 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 1 : static bool test_replay_dhv2_oplock3(struct torture_context *tctx,
579 : struct smb2_tree *tree)
580 : {
581 : NTSTATUS status;
582 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
583 : struct smb2_handle _h;
584 1 : struct smb2_handle *h = NULL;
585 : struct smb2_create io, ref1;
586 1 : struct GUID create_guid = GUID_random();
587 1 : bool ret = true;
588 1 : const char *fname = BASEDIR "\\replay_dhv2_oplock3.dat";
589 1 : struct smb2_transport *transport = tree->session->transport;
590 : uint32_t share_capabilities;
591 : bool share_is_so;
592 :
593 1 : 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 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
599 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
600 :
601 0 : torture_reset_break_info(tctx, &break_info);
602 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
603 0 : tree->session->transport->oplock.private_data = tree;
604 :
605 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
606 : "Channel\n");
607 0 : smb2_util_unlink(tree, fname);
608 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
609 0 : CHECK_STATUS(status, NT_STATUS_OK);
610 0 : smb2_util_close(tree, _h);
611 0 : CHECK_VAL(break_info.count, 0);
612 :
613 0 : smb2_oplock_create_share(&io, fname,
614 : smb2_util_share_access(""),
615 0 : smb2_util_oplock_level("b"));
616 0 : io.in.durable_open = false;
617 0 : io.in.durable_open_v2 = true;
618 0 : io.in.persistent_open = false;
619 0 : io.in.create_guid = create_guid;
620 0 : io.in.timeout = UINT32_MAX;
621 :
622 0 : status = smb2_create(tree, mem_ctx, &io);
623 0 : CHECK_STATUS(status, NT_STATUS_OK);
624 0 : ref1 = io;
625 0 : _h = io.out.file.handle;
626 0 : h = &_h;
627 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
628 0 : CHECK_VAL(io.out.durable_open, false);
629 0 : 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 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
635 0 : CHECK_VAL(io.out.durable_open_v2, true);
636 0 : 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 0 : smb2_oplock_create_share(&io, fname,
648 : smb2_util_share_access("RWD"),
649 0 : smb2_util_oplock_level("b"));
650 0 : io.in.durable_open = false;
651 0 : io.in.durable_open_v2 = true;
652 0 : io.in.persistent_open = false;
653 0 : io.in.create_guid = create_guid;
654 0 : io.in.timeout = UINT32_MAX;
655 :
656 0 : smb2cli_session_start_replay(tree->session->smbXcli);
657 0 : status = smb2_create(tree, mem_ctx, &io);
658 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
659 0 : CHECK_STATUS(status, NT_STATUS_OK);
660 0 : CHECK_CREATE_OUT(&io, &ref1);
661 0 : 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 0 : smb2_oplock_create_share(&io, fname,
669 : smb2_util_share_access(""),
670 0 : smb2_util_oplock_level("b"));
671 0 : io.in.durable_open = false;
672 0 : io.in.durable_open_v2 = true;
673 0 : io.in.persistent_open = false;
674 0 : io.in.create_guid = GUID_random();
675 0 : io.in.timeout = UINT32_MAX;
676 0 : status = smb2_create(tree, mem_ctx, &io);
677 0 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
678 :
679 0 : if (!share_is_so) {
680 0 : CHECK_VAL(break_info.count, 1);
681 0 : CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle);
682 0 : CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
683 0 : torture_reset_break_info(tctx, &break_info);
684 : }
685 :
686 0 : done:
687 0 : if (h != NULL) {
688 0 : smb2_util_close(tree, *h);
689 : }
690 0 : smb2_deltree(tree, BASEDIR);
691 :
692 0 : talloc_free(tree);
693 0 : talloc_free(mem_ctx);
694 :
695 0 : 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 1 : static bool test_replay_dhv2_oplock_lease(struct torture_context *tctx,
703 : struct smb2_tree *tree)
704 : {
705 : NTSTATUS status;
706 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
707 : struct smb2_handle _h;
708 1 : struct smb2_handle *h = NULL;
709 : struct smb2_create io;
710 1 : struct GUID create_guid = GUID_random();
711 1 : bool ret = true;
712 1 : const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat";
713 1 : struct smb2_transport *transport = tree->session->transport;
714 : uint32_t share_capabilities;
715 : bool share_is_so;
716 : uint32_t server_capabilities;
717 : struct smb2_lease ls;
718 : uint64_t lease_key;
719 :
720 1 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
726 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
727 0 : torture_skip(tctx, "leases are not supported");
728 : }
729 :
730 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
731 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
732 :
733 0 : torture_reset_break_info(tctx, &break_info);
734 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
735 0 : tree->session->transport->oplock.private_data = tree;
736 :
737 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
738 : "Channel\n");
739 0 : smb2_util_unlink(tree, fname);
740 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
741 0 : CHECK_STATUS(status, NT_STATUS_OK);
742 0 : smb2_util_close(tree, _h);
743 0 : CHECK_VAL(break_info.count, 0);
744 :
745 0 : smb2_oplock_create_share(&io, fname,
746 : smb2_util_share_access(""),
747 0 : smb2_util_oplock_level("b"));
748 0 : io.in.durable_open = false;
749 0 : io.in.durable_open_v2 = true;
750 0 : io.in.persistent_open = false;
751 0 : io.in.create_guid = create_guid;
752 0 : io.in.timeout = UINT32_MAX;
753 :
754 0 : status = smb2_create(tree, mem_ctx, &io);
755 0 : CHECK_STATUS(status, NT_STATUS_OK);
756 0 : _h = io.out.file.handle;
757 0 : h = &_h;
758 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
759 0 : CHECK_VAL(io.out.durable_open, false);
760 0 : 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 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
766 0 : CHECK_VAL(io.out.durable_open_v2, true);
767 0 : 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 0 : lease_key = random();
775 0 : smb2_lease_create(&io, &ls, false /* dir */, fname,
776 : lease_key, smb2_util_lease_state("RH"));
777 0 : io.in.durable_open = false;
778 0 : io.in.durable_open_v2 = true;
779 0 : io.in.persistent_open = false;
780 0 : io.in.create_guid = create_guid;
781 0 : io.in.timeout = UINT32_MAX;
782 :
783 0 : smb2cli_session_start_replay(tree->session->smbXcli);
784 0 : status = smb2_create(tree, mem_ctx, &io);
785 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
786 0 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
787 :
788 0 : done:
789 0 : if (h != NULL) {
790 0 : smb2_util_close(tree, *h);
791 : }
792 0 : smb2_deltree(tree, BASEDIR);
793 :
794 0 : talloc_free(tree);
795 0 : talloc_free(mem_ctx);
796 :
797 0 : 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 1 : static bool test_replay_dhv2_lease1(struct torture_context *tctx,
810 : struct smb2_tree *tree)
811 : {
812 : NTSTATUS status;
813 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
814 : struct smb2_handle _h1;
815 1 : struct smb2_handle *h1 = NULL;
816 : struct smb2_handle _h2;
817 1 : struct smb2_handle *h2 = NULL;
818 : struct smb2_create io1, io2, ref1;
819 1 : struct GUID create_guid = GUID_random();
820 1 : bool ret = true;
821 1 : const char *fname = BASEDIR "\\replay2_lease1.dat";
822 1 : struct smb2_transport *transport = tree->session->transport;
823 : uint32_t share_capabilities;
824 : bool share_is_so;
825 : uint32_t server_capabilities;
826 : struct smb2_lease ls1, ls2;
827 : uint64_t lease_key;
828 :
829 1 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
835 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
836 0 : torture_skip(tctx, "leases are not supported");
837 : }
838 :
839 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
840 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
841 :
842 0 : torture_reset_break_info(tctx, &break_info);
843 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
844 0 : tree->session->transport->oplock.private_data = tree;
845 :
846 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
847 : "on Single Channel\n");
848 0 : smb2_util_unlink(tree, fname);
849 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h1);
850 0 : CHECK_STATUS(status, NT_STATUS_OK);
851 0 : smb2_util_close(tree, _h1);
852 0 : CHECK_VAL(break_info.count, 0);
853 :
854 0 : lease_key = random();
855 :
856 0 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
857 : lease_key, smb2_util_lease_state("RH"));
858 0 : io1.in.durable_open = false;
859 0 : io1.in.durable_open_v2 = true;
860 0 : io1.in.persistent_open = false;
861 0 : io1.in.create_guid = create_guid;
862 0 : io1.in.timeout = UINT32_MAX;
863 :
864 0 : status = smb2_create(tree, mem_ctx, &io1);
865 0 : CHECK_STATUS(status, NT_STATUS_OK);
866 0 : ref1 = io1;
867 0 : _h1 = io1.out.file.handle;
868 0 : h1 = &_h1;
869 0 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
870 0 : CHECK_VAL(io1.out.durable_open, false);
871 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
872 0 : CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
873 0 : CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
874 0 : 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 0 : CHECK_VAL(io1.out.lease_response.lease_state,
881 : smb2_util_lease_state("RH"));
882 0 : CHECK_VAL(io1.out.durable_open_v2, true);
883 0 : CHECK_VAL(io1.out.timeout, 300*1000);
884 : }
885 :
886 : /*
887 : * Upgrade the lease to RWH
888 : */
889 0 : smb2_lease_create(&io2, &ls2, false /* dir */, fname,
890 : lease_key, smb2_util_lease_state("RHW"));
891 0 : io2.in.durable_open = false;
892 0 : io2.in.durable_open_v2 = true;
893 0 : io2.in.persistent_open = false;
894 0 : io2.in.create_guid = GUID_random(); /* new guid... */
895 0 : io2.in.timeout = UINT32_MAX;
896 :
897 0 : status = smb2_create(tree, mem_ctx, &io2);
898 0 : CHECK_STATUS(status, NT_STATUS_OK);
899 0 : _h2 = io2.out.file.handle;
900 0 : 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 0 : if (!share_is_so) {
910 0 : ref1.out.lease_response.lease_state =
911 0 : smb2_util_lease_state("RHW");
912 : }
913 :
914 0 : smb2cli_session_start_replay(tree->session->smbXcli);
915 0 : status = smb2_create(tree, mem_ctx, &io1);
916 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
917 0 : CHECK_STATUS(status, NT_STATUS_OK);
918 0 : CHECK_CREATE_OUT(&io1, &ref1);
919 0 : CHECK_VAL(break_info.count, 0);
920 :
921 0 : done:
922 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
923 :
924 0 : if (h1 != NULL) {
925 0 : smb2_util_close(tree, *h1);
926 : }
927 0 : if (h2 != NULL) {
928 0 : smb2_util_close(tree, *h2);
929 : }
930 0 : smb2_deltree(tree, BASEDIR);
931 :
932 0 : talloc_free(tree);
933 0 : talloc_free(mem_ctx);
934 :
935 0 : 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 1 : static bool test_replay_dhv2_lease2(struct torture_context *tctx,
950 : struct smb2_tree *tree)
951 : {
952 : NTSTATUS status;
953 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
954 : struct smb2_handle _h1;
955 1 : struct smb2_handle *h1 = NULL;
956 : struct smb2_handle _h2;
957 1 : struct smb2_handle *h2 = NULL;
958 : struct smb2_create io1, io2, ref1;
959 1 : struct GUID create_guid = GUID_random();
960 1 : bool ret = true;
961 1 : const char *fname = BASEDIR "\\replay2_lease2.dat";
962 1 : struct smb2_transport *transport = tree->session->transport;
963 : uint32_t share_capabilities;
964 : bool share_is_so;
965 : uint32_t server_capabilities;
966 : struct smb2_lease ls1, ls2;
967 : uint64_t lease_key;
968 :
969 1 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
975 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
976 0 : torture_skip(tctx, "leases are not supported");
977 : }
978 :
979 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
980 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
981 :
982 0 : torture_reset_break_info(tctx, &break_info);
983 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
984 0 : tree->session->transport->oplock.private_data = tree;
985 :
986 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
987 : "on Single Channel\n");
988 0 : smb2_util_unlink(tree, fname);
989 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h1);
990 0 : CHECK_STATUS(status, NT_STATUS_OK);
991 0 : smb2_util_close(tree, _h1);
992 0 : CHECK_VAL(break_info.count, 0);
993 :
994 0 : lease_key = random();
995 :
996 0 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
997 : lease_key, smb2_util_lease_state("RH"));
998 0 : io1.in.durable_open = false;
999 0 : io1.in.durable_open_v2 = true;
1000 0 : io1.in.persistent_open = false;
1001 0 : io1.in.create_guid = create_guid;
1002 0 : io1.in.timeout = UINT32_MAX;
1003 :
1004 0 : status = smb2_create(tree, mem_ctx, &io1);
1005 0 : CHECK_STATUS(status, NT_STATUS_OK);
1006 0 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1007 0 : CHECK_VAL(io1.out.durable_open, false);
1008 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1009 0 : CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1010 0 : CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1011 0 : 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 0 : CHECK_VAL(io1.out.lease_response.lease_state,
1018 : smb2_util_lease_state("RH"));
1019 0 : CHECK_VAL(io1.out.durable_open_v2, true);
1020 0 : CHECK_VAL(io1.out.timeout, 300*1000);
1021 : }
1022 0 : ref1 = io1;
1023 0 : _h1 = io1.out.file.handle;
1024 0 : h1 = &_h1;
1025 :
1026 : /*
1027 : * Upgrade the lease to RWH
1028 : */
1029 0 : smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1030 : lease_key, smb2_util_lease_state("RHW"));
1031 0 : io2.in.durable_open = false;
1032 0 : io2.in.durable_open_v2 = true;
1033 0 : io2.in.persistent_open = false;
1034 0 : io2.in.create_guid = GUID_random(); /* new guid... */
1035 0 : io2.in.timeout = UINT32_MAX;
1036 :
1037 0 : status = smb2_create(tree, mem_ctx, &io2);
1038 0 : CHECK_STATUS(status, NT_STATUS_OK);
1039 0 : _h2 = io2.out.file.handle;
1040 0 : 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 0 : if (!share_is_so) {
1052 0 : ref1.out.lease_response.lease_state =
1053 0 : smb2_util_lease_state("RHW");
1054 : }
1055 :
1056 0 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1057 : lease_key, smb2_util_lease_state("R"));
1058 0 : io1.in.durable_open = false;
1059 0 : io1.in.durable_open_v2 = true;
1060 0 : io1.in.persistent_open = false;
1061 0 : io1.in.create_guid = create_guid;
1062 0 : io1.in.timeout = UINT32_MAX;
1063 :
1064 0 : smb2cli_session_start_replay(tree->session->smbXcli);
1065 0 : status = smb2_create(tree, mem_ctx, &io1);
1066 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
1067 0 : CHECK_STATUS(status, NT_STATUS_OK);
1068 0 : CHECK_CREATE_OUT(&io1, &ref1);
1069 0 : CHECK_VAL(break_info.count, 0);
1070 :
1071 0 : done:
1072 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
1073 :
1074 0 : if (h1 != NULL) {
1075 0 : smb2_util_close(tree, *h1);
1076 : }
1077 0 : if (h2 != NULL) {
1078 0 : smb2_util_close(tree, *h2);
1079 : }
1080 0 : smb2_deltree(tree, BASEDIR);
1081 :
1082 0 : talloc_free(tree);
1083 0 : talloc_free(mem_ctx);
1084 :
1085 0 : 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 1 : static bool test_replay_dhv2_lease3(struct torture_context *tctx,
1093 : struct smb2_tree *tree)
1094 : {
1095 : NTSTATUS status;
1096 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1097 : struct smb2_handle _h1;
1098 1 : struct smb2_handle *h1 = NULL;
1099 : struct smb2_handle _h2;
1100 1 : struct smb2_handle *h2 = NULL;
1101 : struct smb2_create io1, io2;
1102 1 : struct GUID create_guid = GUID_random();
1103 1 : bool ret = true;
1104 1 : const char *fname = BASEDIR "\\replay2_lease2.dat";
1105 1 : struct smb2_transport *transport = tree->session->transport;
1106 : uint32_t share_capabilities;
1107 : bool share_is_so;
1108 : uint32_t server_capabilities;
1109 : struct smb2_lease ls1, ls2;
1110 : uint64_t lease_key;
1111 :
1112 1 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
1118 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
1119 0 : torture_skip(tctx, "leases are not supported");
1120 : }
1121 :
1122 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
1123 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1124 :
1125 0 : torture_reset_break_info(tctx, &break_info);
1126 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
1127 0 : tree->session->transport->oplock.private_data = tree;
1128 :
1129 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
1130 : "on Single Channel\n");
1131 0 : smb2_util_unlink(tree, fname);
1132 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h1);
1133 0 : CHECK_STATUS(status, NT_STATUS_OK);
1134 0 : smb2_util_close(tree, _h1);
1135 0 : CHECK_VAL(break_info.count, 0);
1136 :
1137 0 : lease_key = random();
1138 :
1139 0 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1140 : lease_key, smb2_util_lease_state("RH"));
1141 0 : io1.in.durable_open = false;
1142 0 : io1.in.durable_open_v2 = true;
1143 0 : io1.in.persistent_open = false;
1144 0 : io1.in.create_guid = create_guid;
1145 0 : io1.in.timeout = UINT32_MAX;
1146 :
1147 0 : status = smb2_create(tree, mem_ctx, &io1);
1148 0 : CHECK_STATUS(status, NT_STATUS_OK);
1149 0 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1150 0 : CHECK_VAL(io1.out.durable_open, false);
1151 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1152 0 : CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1153 0 : CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1154 0 : 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 0 : CHECK_VAL(io1.out.lease_response.lease_state,
1161 : smb2_util_lease_state("RH"));
1162 0 : CHECK_VAL(io1.out.durable_open_v2, true);
1163 0 : CHECK_VAL(io1.out.timeout, 300*1000);
1164 : }
1165 0 : _h1 = io1.out.file.handle;
1166 0 : h1 = &_h1;
1167 :
1168 : /*
1169 : * Upgrade the lease to RWH
1170 : */
1171 0 : smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1172 : lease_key, smb2_util_lease_state("RHW"));
1173 0 : io2.in.durable_open = false;
1174 0 : io2.in.durable_open_v2 = true;
1175 0 : io2.in.persistent_open = false;
1176 0 : io2.in.create_guid = GUID_random(); /* new guid... */
1177 0 : io2.in.timeout = UINT32_MAX;
1178 :
1179 0 : status = smb2_create(tree, mem_ctx, &io2);
1180 0 : CHECK_STATUS(status, NT_STATUS_OK);
1181 0 : _h2 = io2.out.file.handle;
1182 0 : h2 = &_h2;
1183 :
1184 : /*
1185 : * Replay Durable V2 Create on single channel.
1186 : * use a different lease key.
1187 : */
1188 :
1189 0 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1190 0 : random() /* lease key */,
1191 : smb2_util_lease_state("RH"));
1192 0 : io1.in.durable_open = false;
1193 0 : io1.in.durable_open_v2 = true;
1194 0 : io1.in.persistent_open = false;
1195 0 : io1.in.create_guid = create_guid;
1196 0 : io1.in.timeout = UINT32_MAX;
1197 :
1198 0 : smb2cli_session_start_replay(tree->session->smbXcli);
1199 0 : status = smb2_create(tree, mem_ctx, &io1);
1200 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
1201 0 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1202 :
1203 0 : done:
1204 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
1205 :
1206 0 : if (h1 != NULL) {
1207 0 : smb2_util_close(tree, *h1);
1208 : }
1209 0 : if (h2 != NULL) {
1210 0 : smb2_util_close(tree, *h2);
1211 : }
1212 0 : smb2_deltree(tree, BASEDIR);
1213 :
1214 0 : talloc_free(tree);
1215 0 : talloc_free(mem_ctx);
1216 :
1217 0 : 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 1 : static bool test_replay_dhv2_lease_oplock(struct torture_context *tctx,
1226 : struct smb2_tree *tree)
1227 : {
1228 : NTSTATUS status;
1229 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1230 : struct smb2_handle _h1;
1231 1 : struct smb2_handle *h1 = NULL;
1232 : struct smb2_handle _h2;
1233 1 : struct smb2_handle *h2 = NULL;
1234 : struct smb2_create io1, io2, ref1;
1235 1 : struct GUID create_guid = GUID_random();
1236 1 : bool ret = true;
1237 1 : const char *fname = BASEDIR "\\replay2_lease1.dat";
1238 1 : struct smb2_transport *transport = tree->session->transport;
1239 : uint32_t share_capabilities;
1240 : bool share_is_so;
1241 : uint32_t server_capabilities;
1242 : struct smb2_lease ls1, ls2;
1243 : uint64_t lease_key;
1244 :
1245 1 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
1251 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
1252 0 : torture_skip(tctx, "leases are not supported");
1253 : }
1254 :
1255 0 : share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
1256 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1257 :
1258 0 : torture_reset_break_info(tctx, &break_info);
1259 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
1260 0 : tree->session->transport->oplock.private_data = tree;
1261 :
1262 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
1263 : "on Single Channel\n");
1264 0 : smb2_util_unlink(tree, fname);
1265 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h1);
1266 0 : CHECK_STATUS(status, NT_STATUS_OK);
1267 0 : smb2_util_close(tree, _h1);
1268 0 : CHECK_VAL(break_info.count, 0);
1269 :
1270 0 : lease_key = random();
1271 :
1272 0 : smb2_lease_create(&io1, &ls1, false /* dir */, fname,
1273 : lease_key, smb2_util_lease_state("RH"));
1274 0 : io1.in.durable_open = false;
1275 0 : io1.in.durable_open_v2 = true;
1276 0 : io1.in.persistent_open = false;
1277 0 : io1.in.create_guid = create_guid;
1278 0 : io1.in.timeout = UINT32_MAX;
1279 :
1280 0 : status = smb2_create(tree, mem_ctx, &io1);
1281 0 : CHECK_STATUS(status, NT_STATUS_OK);
1282 0 : ref1 = io1;
1283 0 : _h1 = io1.out.file.handle;
1284 0 : h1 = &_h1;
1285 0 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1286 0 : CHECK_VAL(io1.out.durable_open, false);
1287 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1288 0 : CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
1289 0 : CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
1290 0 : 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 0 : CHECK_VAL(io1.out.lease_response.lease_state,
1297 : smb2_util_lease_state("RH"));
1298 0 : CHECK_VAL(io1.out.durable_open_v2, true);
1299 0 : CHECK_VAL(io1.out.timeout, 300*1000);
1300 : }
1301 :
1302 : /*
1303 : * Upgrade the lease to RWH
1304 : */
1305 0 : smb2_lease_create(&io2, &ls2, false /* dir */, fname,
1306 : lease_key, smb2_util_lease_state("RHW"));
1307 0 : io2.in.durable_open = false;
1308 0 : io2.in.durable_open_v2 = true;
1309 0 : io2.in.persistent_open = false;
1310 0 : io2.in.create_guid = GUID_random(); /* new guid... */
1311 0 : io2.in.timeout = UINT32_MAX;
1312 :
1313 0 : status = smb2_create(tree, mem_ctx, &io2);
1314 0 : CHECK_STATUS(status, NT_STATUS_OK);
1315 0 : _h2 = io2.out.file.handle;
1316 0 : 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 0 : smb2_oplock_create_share(&io2, fname,
1325 : smb2_util_share_access(""),
1326 0 : smb2_util_oplock_level("b"));
1327 0 : io2.in.durable_open = false;
1328 0 : io2.in.durable_open_v2 = true;
1329 0 : io2.in.persistent_open = false;
1330 0 : io2.in.create_guid = create_guid;
1331 0 : io2.in.timeout = UINT32_MAX;
1332 :
1333 : /* adapt expected lease in response */
1334 0 : if (!share_is_so) {
1335 0 : ref1.out.lease_response.lease_state =
1336 0 : smb2_util_lease_state("RHW");
1337 : }
1338 :
1339 0 : smb2cli_session_start_replay(tree->session->smbXcli);
1340 0 : status = smb2_create(tree, mem_ctx, &io1);
1341 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
1342 0 : CHECK_STATUS(status, NT_STATUS_OK);
1343 0 : CHECK_CREATE_OUT(&io1, &ref1);
1344 0 : CHECK_VAL(break_info.count, 0);
1345 :
1346 0 : done:
1347 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
1348 :
1349 0 : if (h1 != NULL) {
1350 0 : smb2_util_close(tree, *h1);
1351 : }
1352 0 : if (h2 != NULL) {
1353 0 : smb2_util_close(tree, *h2);
1354 : }
1355 0 : smb2_deltree(tree, BASEDIR);
1356 :
1357 0 : talloc_free(tree);
1358 0 : talloc_free(mem_ctx);
1359 :
1360 0 : 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 4 : 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 : NTSTATUS status;
1402 4 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1403 : struct smb2_handle _h1;
1404 4 : struct smb2_handle *h1 = NULL;
1405 4 : struct smb2_handle *h2f = NULL;
1406 : struct smb2_handle _h21;
1407 4 : struct smb2_handle *h21 = NULL;
1408 : struct smb2_handle _h23;
1409 4 : struct smb2_handle *h23 = NULL;
1410 : struct smb2_handle _h24;
1411 4 : struct smb2_handle *h24 = NULL;
1412 : struct smb2_create io1, io21, io22, io23, io24;
1413 4 : struct GUID create_guid1 = GUID_random();
1414 4 : struct GUID create_guid2 = GUID_random();
1415 4 : struct smb2_request *req21 = NULL;
1416 4 : struct smb2_request *req22 = NULL;
1417 4 : bool ret = true;
1418 : char fname[256];
1419 4 : struct smb2_transport *transport1 = tree1->session->transport;
1420 : uint32_t server_capabilities;
1421 : uint32_t share_capabilities;
1422 : struct smb2_lease ls1;
1423 : uint64_t lease_key1;
1424 4 : uint16_t lease_epoch1 = 0;
1425 : struct smb2_break op_ack1;
1426 : struct smb2_lease_break_ack lb_ack1;
1427 : struct smb2_lease ls2;
1428 : uint64_t lease_key2;
1429 4 : uint16_t lease_epoch2 = 0;
1430 : bool share_is_so;
1431 4 : struct smb2_transport *transport2 = tree2->session->transport;
1432 4 : int request_timeout2 = transport2->options.request_timeout;
1433 4 : struct smb2_session *session2 = tree2->session;
1434 4 : const char *hold_name = NULL;
1435 :
1436 4 : switch (client1_level) {
1437 4 : case SMB2_OPLOCK_LEVEL_LEASE:
1438 4 : hold_name = "RWH Lease";
1439 4 : 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 : break;
1446 : }
1447 :
1448 4 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
1454 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
1455 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
1456 : client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
1457 0 : torture_skip(tctx, "leases are not supported");
1458 : }
1459 : }
1460 :
1461 0 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
1462 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
1463 0 : 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 0 : snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
1471 : BASEDIR, testname, generate_random_str(tctx, 8));
1472 :
1473 0 : torture_reset_break_info(tctx, &break_info);
1474 0 : break_info.oplock_skip_ack = true;
1475 0 : ZERO_STRUCT(op_ack1);
1476 0 : torture_reset_lease_break_info(tctx, &lease_break_info);
1477 0 : lease_break_info.lease_skip_ack = true;
1478 0 : ZERO_STRUCT(lb_ack1);
1479 0 : transport1->oplock.handler = torture_oplock_ack_handler;
1480 0 : transport1->oplock.private_data = tree1;
1481 0 : transport1->lease.handler = torture_lease_handler;
1482 0 : transport1->lease.private_data = tree1;
1483 0 : smb2_keepalive(transport1);
1484 0 : transport2->oplock.handler = torture_oplock_ack_handler;
1485 0 : transport2->oplock.private_data = tree2;
1486 0 : transport2->lease.handler = torture_lease_handler;
1487 0 : transport2->lease.private_data = tree2;
1488 0 : smb2_keepalive(transport2);
1489 :
1490 0 : smb2_util_unlink(tree1, fname);
1491 0 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
1492 0 : CHECK_STATUS(status, NT_STATUS_OK);
1493 0 : smb2_util_close(tree1, _h1);
1494 0 : CHECK_VAL(break_info.count, 0);
1495 :
1496 0 : lease_key1 = random();
1497 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1498 0 : smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
1499 0 : 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 0 : io1.in.share_access = 0;
1504 0 : io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
1505 0 : io1.in.durable_open = false;
1506 0 : io1.in.durable_open_v2 = true;
1507 0 : io1.in.persistent_open = false;
1508 0 : io1.in.create_guid = create_guid1;
1509 0 : io1.in.timeout = UINT32_MAX;
1510 :
1511 0 : status = smb2_create(tree1, mem_ctx, &io1);
1512 0 : CHECK_STATUS(status, NT_STATUS_OK);
1513 0 : _h1 = io1.out.file.handle;
1514 0 : h1 = &_h1;
1515 0 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1516 0 : CHECK_VAL(io1.out.durable_open, false);
1517 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1518 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
1519 0 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
1520 0 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
1521 0 : CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
1522 0 : 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 0 : CHECK_VAL(io1.out.durable_open_v2, true);
1528 0 : CHECK_VAL(io1.out.timeout, 300*1000);
1529 :
1530 0 : lease_key2 = random();
1531 0 : 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 0 : smb2_oplock_create(&io21, fname, client2_level);
1536 : }
1537 0 : io21.in.share_access = 0;
1538 0 : io21.in.desired_access = SEC_RIGHTS_FILE_ALL;
1539 0 : io21.in.desired_access = SEC_RIGHTS_FILE_READ;
1540 0 : io21.in.durable_open = false;
1541 0 : io21.in.durable_open_v2 = true;
1542 0 : io21.in.persistent_open = false;
1543 0 : io21.in.create_guid = create_guid2;
1544 0 : io21.in.timeout = UINT32_MAX;
1545 0 : io24 = io23 = io22 = io21;
1546 :
1547 0 : req21 = smb2_create_send(tree2, &io21);
1548 0 : torture_assert(tctx, req21 != NULL, "req21");
1549 :
1550 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1551 0 : const struct smb2_lease_break *lb =
1552 : &lease_break_info.lease_break;
1553 0 : const struct smb2_lease *l = &lb->current_lease;
1554 0 : const struct smb2_lease_key *k = &l->lease_key;
1555 :
1556 0 : torture_wait_for_lease_break(tctx);
1557 0 : CHECK_VAL(break_info.count, 0);
1558 0 : CHECK_VAL(lease_break_info.count, 1);
1559 :
1560 0 : torture_assert(tctx,
1561 : lease_break_info.lease_transport == transport1,
1562 : "expect lease break on transport1\n");
1563 0 : CHECK_VAL(k->data[0], lease_key1);
1564 0 : CHECK_VAL(k->data[1], ~lease_key1);
1565 : /*
1566 : * With share none the handle lease
1567 : * is broken.
1568 : */
1569 0 : CHECK_VAL(lb->new_lease_state,
1570 : smb2_util_lease_state("RW"));
1571 0 : CHECK_VAL(lb->break_flags,
1572 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
1573 0 : CHECK_VAL(lb->new_epoch, lease_epoch1+1);
1574 0 : lease_epoch1 += 1;
1575 :
1576 0 : lb_ack1.in.lease.lease_key = lb->current_lease.lease_key;
1577 0 : 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 0 : torture_reset_break_info(tctx, &break_info);
1594 0 : break_info.oplock_skip_ack = true;
1595 0 : torture_reset_lease_break_info(tctx, &lease_break_info);
1596 0 : lease_break_info.lease_skip_ack = true;
1597 :
1598 0 : WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
1599 :
1600 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1601 0 : torture_wait_for_lease_break(tctx);
1602 : } else {
1603 0 : torture_wait_for_oplock_break(tctx);
1604 : }
1605 0 : CHECK_VAL(break_info.count, 0);
1606 0 : CHECK_VAL(lease_break_info.count, 0);
1607 :
1608 0 : 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 0 : torture_comment(tctx, "Starting ASYNC Replay req22 expecting %s\n",
1617 : nt_errstr(replay22_reject_status));
1618 0 : smb2cli_session_start_replay(session2->smbXcli);
1619 0 : transport2->options.request_timeout = 15;
1620 0 : req22 = smb2_create_send(tree2, &io22);
1621 0 : torture_assert(tctx, req22 != NULL, "req22");
1622 0 : transport2->options.request_timeout = request_timeout2;
1623 0 : smb2cli_session_stop_replay(session2->smbXcli);
1624 :
1625 0 : WAIT_FOR_ASYNC_RESPONSE(tctx, req22);
1626 : } else {
1627 0 : torture_comment(tctx, "SYNC Replay io22 expecting %s\n",
1628 : nt_errstr(replay22_reject_status));
1629 0 : smb2cli_session_start_replay(session2->smbXcli);
1630 0 : transport2->options.request_timeout = 5;
1631 0 : status = smb2_create(tree2, tctx, &io22);
1632 0 : CHECK_STATUS(status, replay22_reject_status);
1633 0 : transport2->options.request_timeout = request_timeout2;
1634 0 : 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 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1644 0 : torture_wait_for_lease_break(tctx);
1645 0 : torture_wait_for_lease_break(tctx);
1646 0 : torture_wait_for_lease_break(tctx);
1647 0 : torture_wait_for_lease_break(tctx);
1648 0 : torture_wait_for_lease_break(tctx);
1649 0 : CHECK_VAL(break_info.count, 0);
1650 0 : CHECK_VAL(lease_break_info.count, 0);
1651 :
1652 0 : if (release_op == SMB2_OP_CLOSE) {
1653 0 : torture_comment(tctx, "Closing h1\n");
1654 0 : smb2_util_close(tree1, _h1);
1655 0 : h1 = NULL;
1656 : } else {
1657 0 : torture_comment(tctx, "Acking lease_key1\n");
1658 0 : status = smb2_lease_break_ack(tree1, &lb_ack1);
1659 0 : CHECK_STATUS(status, NT_STATUS_OK);
1660 0 : CHECK_VAL(lb_ack1.out.lease.lease_flags, 0);
1661 0 : CHECK_VAL(lb_ack1.out.lease.lease_state, lb_ack1.in.lease.lease_state);
1662 0 : CHECK_VAL(lb_ack1.out.lease.lease_key.data[0], lease_key1);
1663 0 : CHECK_VAL(lb_ack1.out.lease.lease_key.data[1], ~lease_key1);
1664 0 : 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 0 : torture_comment(tctx, "Checking req21 expecting %s\n",
1688 : nt_errstr(orig21_reject_status));
1689 0 : status = smb2_create_recv(req21, tctx, &io21);
1690 0 : CHECK_STATUS(status, orig21_reject_status);
1691 0 : if (NT_STATUS_IS_OK(orig21_reject_status)) {
1692 0 : _h21 = io21.out.file.handle;
1693 0 : h21 = &_h21;
1694 0 : if (h2f == NULL) {
1695 0 : h2f = h21;
1696 : }
1697 0 : CHECK_VAL(h21->data[0], h2f->data[0]);
1698 0 : CHECK_VAL(h21->data[1], h2f->data[1]);
1699 0 : CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1700 0 : CHECK_VAL(io21.out.oplock_level, client2_level);
1701 0 : CHECK_VAL(io21.out.durable_open, false);
1702 0 : 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 0 : } 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 0 : CHECK_VAL(io21.out.durable_open_v2, false);
1715 : }
1716 : }
1717 :
1718 0 : if (NT_STATUS_EQUAL(replay22_reject_status, NT_STATUS_SHARING_VIOLATION)) {
1719 0 : torture_comment(tctx, "Checking req22 expecting %s\n",
1720 : nt_errstr(replay22_reject_status));
1721 0 : status = smb2_create_recv(req22, tctx, &io22);
1722 0 : CHECK_STATUS(status, replay22_reject_status);
1723 : }
1724 :
1725 0 : torture_comment(tctx, "SYNC Replay io23 expecting %s\n",
1726 : nt_errstr(replay23_reject_status));
1727 0 : smb2cli_session_start_replay(session2->smbXcli);
1728 0 : transport2->options.request_timeout = 5;
1729 0 : status = smb2_create(tree2, tctx, &io23);
1730 0 : transport2->options.request_timeout = request_timeout2;
1731 0 : CHECK_STATUS(status, replay23_reject_status);
1732 0 : smb2cli_session_stop_replay(session2->smbXcli);
1733 0 : if (NT_STATUS_IS_OK(replay23_reject_status)) {
1734 0 : _h23 = io23.out.file.handle;
1735 0 : h23 = &_h23;
1736 0 : if (h2f == NULL) {
1737 0 : h2f = h23;
1738 : }
1739 0 : CHECK_VAL(h23->data[0], h2f->data[0]);
1740 0 : CHECK_VAL(h23->data[1], h2f->data[1]);
1741 0 : CHECK_CREATED(&io23, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1742 0 : CHECK_VAL(io23.out.oplock_level, client2_level);
1743 0 : CHECK_VAL(io23.out.durable_open, false);
1744 0 : 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 0 : } 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 0 : CHECK_VAL(io23.out.durable_open_v2, false);
1757 : }
1758 : }
1759 :
1760 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1761 0 : torture_wait_for_lease_break(tctx);
1762 : } else {
1763 0 : torture_wait_for_oplock_break(tctx);
1764 : }
1765 0 : CHECK_VAL(break_info.count, 0);
1766 0 : CHECK_VAL(lease_break_info.count, 0);
1767 :
1768 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1769 0 : torture_wait_for_lease_break(tctx);
1770 : } else {
1771 0 : torture_wait_for_oplock_break(tctx);
1772 : }
1773 0 : CHECK_VAL(break_info.count, 0);
1774 0 : CHECK_VAL(lease_break_info.count, 0);
1775 :
1776 0 : if (h1 != NULL) {
1777 0 : torture_comment(tctx, "Closing h1\n");
1778 0 : smb2_util_close(tree1, _h1);
1779 0 : h1 = NULL;
1780 : }
1781 :
1782 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1783 0 : torture_wait_for_lease_break(tctx);
1784 : } else {
1785 0 : torture_wait_for_oplock_break(tctx);
1786 : }
1787 0 : CHECK_VAL(break_info.count, 0);
1788 0 : CHECK_VAL(lease_break_info.count, 0);
1789 :
1790 0 : torture_comment(tctx, "SYNC Replay io24 expecting %s\n",
1791 0 : nt_errstr(NT_STATUS_OK));
1792 0 : smb2cli_session_start_replay(session2->smbXcli);
1793 0 : transport2->options.request_timeout = 5;
1794 0 : status = smb2_create(tree2, tctx, &io24);
1795 0 : transport2->options.request_timeout = request_timeout2;
1796 0 : smb2cli_session_stop_replay(session2->smbXcli);
1797 0 : CHECK_STATUS(status, NT_STATUS_OK);
1798 0 : _h24 = io24.out.file.handle;
1799 0 : h24 = &_h24;
1800 0 : if (h2f == NULL) {
1801 0 : h2f = h24;
1802 : }
1803 0 : CHECK_VAL(h24->data[0], h2f->data[0]);
1804 0 : CHECK_VAL(h24->data[1], h2f->data[1]);
1805 0 : CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1806 0 : CHECK_VAL(io24.out.oplock_level, client2_level);
1807 0 : CHECK_VAL(io24.out.durable_open, false);
1808 0 : 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 0 : } 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 0 : CHECK_VAL(io24.out.durable_open_v2, false);
1821 : }
1822 :
1823 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1824 0 : torture_wait_for_lease_break(tctx);
1825 : } else {
1826 0 : torture_wait_for_oplock_break(tctx);
1827 : }
1828 0 : CHECK_VAL(break_info.count, 0);
1829 0 : CHECK_VAL(lease_break_info.count, 0);
1830 0 : status = smb2_util_close(tree2, *h24);
1831 0 : CHECK_STATUS(status, NT_STATUS_OK);
1832 0 : h24 = NULL;
1833 :
1834 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
1835 0 : torture_wait_for_lease_break(tctx);
1836 : } else {
1837 0 : torture_wait_for_oplock_break(tctx);
1838 : }
1839 0 : CHECK_VAL(break_info.count, 0);
1840 0 : CHECK_VAL(lease_break_info.count, 0);
1841 :
1842 0 : done:
1843 :
1844 0 : smbXcli_conn_disconnect(transport2->conn, NT_STATUS_LOCAL_DISCONNECT);
1845 :
1846 0 : if (h1 != NULL) {
1847 0 : smb2_util_close(tree1, *h1);
1848 : }
1849 :
1850 0 : smb2_deltree(tree1, BASEDIR);
1851 :
1852 0 : TALLOC_FREE(tree1);
1853 0 : talloc_free(mem_ctx);
1854 :
1855 0 : 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 expectes a NT_STATUS_FILE_NOT_AVAILABLE within 5 seconds.
1880 : * see test_dhv2_pending1n_vs_violation_lease_close_windows().
1881 : */
1882 1 : 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 1 : 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 1 : NT_STATUS_OK,
1893 1 : NT_STATUS_FILE_NOT_AVAILABLE,
1894 1 : 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 1 : 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 1 : 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 1 : NT_STATUS_OK,
1930 1 : NT_STATUS_SHARING_VIOLATION,
1931 1 : 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 expectes a NT_STATUS_FILE_NOT_AVAILABLE within 5 seconds.
1956 : * see test_dhv2_pending1n_vs_violation_lease_ack_windows().
1957 : */
1958 1 : 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 1 : 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 1 : NT_STATUS_SHARING_VIOLATION,
1969 1 : NT_STATUS_FILE_NOT_AVAILABLE,
1970 1 : 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 1 : 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 1 : 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 1 : NT_STATUS_SHARING_VIOLATION,
2006 1 : NT_STATUS_SHARING_VIOLATION,
2007 1 : 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 12 : 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 : NTSTATUS status;
2038 12 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
2039 : struct smb2_handle _h1;
2040 12 : struct smb2_handle *h1 = NULL;
2041 : struct smb2_handle _h21;
2042 12 : struct smb2_handle *h21 = NULL;
2043 : struct smb2_handle _h24;
2044 12 : struct smb2_handle *h24 = NULL;
2045 : struct smb2_create io1, io21, io22, io23, io24;
2046 12 : struct GUID create_guid1 = GUID_random();
2047 12 : struct GUID create_guid2 = GUID_random();
2048 12 : struct smb2_request *req21 = NULL;
2049 12 : bool ret = true;
2050 : char fname[256];
2051 12 : struct smb2_transport *transport1 = tree1->session->transport;
2052 : uint32_t server_capabilities;
2053 : uint32_t share_capabilities;
2054 : struct smb2_lease ls1;
2055 : uint64_t lease_key1;
2056 12 : uint16_t lease_epoch1 = 0;
2057 : struct smb2_lease ls2;
2058 : uint64_t lease_key2;
2059 12 : uint16_t lease_epoch2 = 0;
2060 : bool share_is_so;
2061 12 : struct smb2_transport *transport2 = tree2->session->transport;
2062 12 : int request_timeout2 = transport2->options.request_timeout;
2063 12 : struct smb2_session *session2 = tree2->session;
2064 12 : const char *hold_name = NULL;
2065 :
2066 12 : switch (client1_level) {
2067 6 : case SMB2_OPLOCK_LEVEL_LEASE:
2068 6 : hold_name = "RWH Lease";
2069 6 : break;
2070 6 : case SMB2_OPLOCK_LEVEL_BATCH:
2071 6 : hold_name = "BATCH Oplock";
2072 6 : break;
2073 0 : default:
2074 0 : smb_panic(__location__);
2075 : break;
2076 : }
2077 :
2078 12 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
2084 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
2085 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
2086 : client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2087 0 : torture_skip(tctx, "leases are not supported");
2088 : }
2089 : }
2090 :
2091 0 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
2092 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
2093 0 : 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 0 : snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
2101 : BASEDIR, testname, generate_random_str(tctx, 8));
2102 :
2103 0 : torture_reset_break_info(tctx, &break_info);
2104 0 : break_info.oplock_skip_ack = true;
2105 0 : torture_reset_lease_break_info(tctx, &lease_break_info);
2106 0 : lease_break_info.lease_skip_ack = true;
2107 0 : transport1->oplock.handler = torture_oplock_ack_handler;
2108 0 : transport1->oplock.private_data = tree1;
2109 0 : transport1->lease.handler = torture_lease_handler;
2110 0 : transport1->lease.private_data = tree1;
2111 0 : smb2_keepalive(transport1);
2112 0 : transport2->oplock.handler = torture_oplock_ack_handler;
2113 0 : transport2->oplock.private_data = tree2;
2114 0 : transport2->lease.handler = torture_lease_handler;
2115 0 : transport2->lease.private_data = tree2;
2116 0 : smb2_keepalive(transport2);
2117 :
2118 0 : smb2_util_unlink(tree1, fname);
2119 0 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
2120 0 : CHECK_STATUS(status, NT_STATUS_OK);
2121 0 : smb2_util_close(tree1, _h1);
2122 0 : CHECK_VAL(break_info.count, 0);
2123 :
2124 0 : lease_key1 = random();
2125 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2126 0 : smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
2127 0 : lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
2128 : } else {
2129 0 : smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
2130 : }
2131 0 : io1.in.share_access = smb2_util_share_access("RWD");
2132 0 : io1.in.durable_open = false;
2133 0 : io1.in.durable_open_v2 = true;
2134 0 : io1.in.persistent_open = false;
2135 0 : io1.in.create_guid = create_guid1;
2136 0 : io1.in.timeout = UINT32_MAX;
2137 :
2138 0 : status = smb2_create(tree1, mem_ctx, &io1);
2139 0 : CHECK_STATUS(status, NT_STATUS_OK);
2140 0 : _h1 = io1.out.file.handle;
2141 0 : h1 = &_h1;
2142 0 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2143 0 : CHECK_VAL(io1.out.durable_open, false);
2144 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2145 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
2146 0 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
2147 0 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
2148 0 : CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
2149 0 : CHECK_VAL(io1.out.lease_response_v2.lease_state,
2150 : smb2_util_lease_state("RHW"));
2151 : } else {
2152 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2153 : }
2154 0 : CHECK_VAL(io1.out.durable_open_v2, true);
2155 0 : CHECK_VAL(io1.out.timeout, 300*1000);
2156 :
2157 0 : lease_key2 = random();
2158 0 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2159 0 : smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
2160 0 : lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
2161 : } else {
2162 0 : smb2_oplock_create(&io21, fname, client2_level);
2163 : }
2164 0 : io21.in.share_access = smb2_util_share_access("RWD");
2165 0 : io21.in.durable_open = false;
2166 0 : io21.in.durable_open_v2 = true;
2167 0 : io21.in.persistent_open = false;
2168 0 : io21.in.create_guid = create_guid2;
2169 0 : io21.in.timeout = UINT32_MAX;
2170 0 : io24 = io23 = io22 = io21;
2171 :
2172 0 : req21 = smb2_create_send(tree2, &io21);
2173 0 : torture_assert(tctx, req21 != NULL, "req21");
2174 :
2175 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2176 0 : const struct smb2_lease_break *lb =
2177 : &lease_break_info.lease_break;
2178 0 : const struct smb2_lease *l = &lb->current_lease;
2179 0 : const struct smb2_lease_key *k = &l->lease_key;
2180 :
2181 0 : torture_wait_for_lease_break(tctx);
2182 0 : CHECK_VAL(break_info.count, 0);
2183 0 : CHECK_VAL(lease_break_info.count, 1);
2184 :
2185 0 : torture_assert(tctx,
2186 : lease_break_info.lease_transport == transport1,
2187 : "expect lease break on transport1\n");
2188 0 : CHECK_VAL(k->data[0], lease_key1);
2189 0 : CHECK_VAL(k->data[1], ~lease_key1);
2190 0 : CHECK_VAL(lb->new_lease_state,
2191 : smb2_util_lease_state("RH"));
2192 0 : CHECK_VAL(lb->break_flags,
2193 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
2194 0 : CHECK_VAL(lb->new_epoch, lease_epoch1+1);
2195 0 : lease_epoch1 += 1;
2196 : } else {
2197 0 : torture_wait_for_oplock_break(tctx);
2198 0 : CHECK_VAL(break_info.count, 1);
2199 0 : CHECK_VAL(lease_break_info.count, 0);
2200 :
2201 0 : torture_assert(tctx,
2202 : break_info.received_transport == transport1,
2203 : "expect oplock break on transport1\n");
2204 0 : CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
2205 0 : CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
2206 0 : CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
2207 : }
2208 :
2209 0 : torture_reset_break_info(tctx, &break_info);
2210 0 : break_info.oplock_skip_ack = true;
2211 0 : torture_reset_lease_break_info(tctx, &lease_break_info);
2212 0 : lease_break_info.lease_skip_ack = true;
2213 :
2214 0 : WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
2215 :
2216 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2217 0 : torture_wait_for_lease_break(tctx);
2218 : } else {
2219 0 : torture_wait_for_oplock_break(tctx);
2220 : }
2221 0 : CHECK_VAL(break_info.count, 0);
2222 0 : CHECK_VAL(lease_break_info.count, 0);
2223 :
2224 0 : smb2cli_session_start_replay(session2->smbXcli);
2225 0 : transport2->options.request_timeout = 5;
2226 0 : status = smb2_create(tree2, tctx, &io22);
2227 0 : transport2->options.request_timeout = request_timeout2;
2228 0 : CHECK_STATUS(status, reject_status);
2229 0 : smb2cli_session_stop_replay(session2->smbXcli);
2230 :
2231 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2232 0 : torture_wait_for_lease_break(tctx);
2233 : } else {
2234 0 : torture_wait_for_oplock_break(tctx);
2235 : }
2236 0 : CHECK_VAL(break_info.count, 0);
2237 0 : CHECK_VAL(lease_break_info.count, 0);
2238 :
2239 0 : smb2cli_session_start_replay(session2->smbXcli);
2240 0 : transport2->options.request_timeout = 5;
2241 0 : status = smb2_create(tree2, tctx, &io23);
2242 0 : transport2->options.request_timeout = request_timeout2;
2243 0 : CHECK_STATUS(status, reject_status);
2244 0 : smb2cli_session_stop_replay(session2->smbXcli);
2245 :
2246 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2247 0 : torture_wait_for_lease_break(tctx);
2248 : } else {
2249 0 : torture_wait_for_oplock_break(tctx);
2250 : }
2251 0 : CHECK_VAL(break_info.count, 0);
2252 0 : CHECK_VAL(lease_break_info.count, 0);
2253 :
2254 0 : smb2_util_close(tree1, _h1);
2255 0 : h1 = NULL;
2256 :
2257 0 : status = smb2_create_recv(req21, tctx, &io21);
2258 0 : CHECK_STATUS(status, NT_STATUS_OK);
2259 0 : _h21 = io21.out.file.handle;
2260 0 : h21 = &_h21;
2261 0 : CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2262 0 : CHECK_VAL(io21.out.oplock_level, client2_level);
2263 0 : CHECK_VAL(io21.out.durable_open, false);
2264 0 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2265 0 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[0], lease_key2);
2266 0 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[1], ~lease_key2);
2267 0 : CHECK_VAL(io21.out.lease_response_v2.lease_epoch, lease_epoch2);
2268 0 : CHECK_VAL(io21.out.lease_response_v2.lease_state,
2269 : smb2_util_lease_state("RHW"));
2270 0 : CHECK_VAL(io21.out.durable_open_v2, true);
2271 0 : CHECK_VAL(io21.out.timeout, 300*1000);
2272 0 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
2273 0 : CHECK_VAL(io21.out.durable_open_v2, true);
2274 0 : CHECK_VAL(io21.out.timeout, 300*1000);
2275 : } else {
2276 0 : CHECK_VAL(io21.out.durable_open_v2, false);
2277 : }
2278 :
2279 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2280 0 : torture_wait_for_lease_break(tctx);
2281 : } else {
2282 0 : torture_wait_for_oplock_break(tctx);
2283 : }
2284 0 : CHECK_VAL(break_info.count, 0);
2285 0 : CHECK_VAL(lease_break_info.count, 0);
2286 :
2287 0 : smb2cli_session_start_replay(session2->smbXcli);
2288 0 : status = smb2_create(tree2, tctx, &io24);
2289 0 : smb2cli_session_stop_replay(session2->smbXcli);
2290 0 : CHECK_STATUS(status, NT_STATUS_OK);
2291 0 : _h24 = io24.out.file.handle;
2292 0 : h24 = &_h24;
2293 0 : CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2294 0 : CHECK_VAL(h24->data[0], h21->data[0]);
2295 0 : CHECK_VAL(h24->data[1], h21->data[1]);
2296 0 : CHECK_VAL(io24.out.oplock_level, client2_level);
2297 0 : CHECK_VAL(io24.out.durable_open, false);
2298 0 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2299 0 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
2300 0 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
2301 0 : CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
2302 0 : CHECK_VAL(io24.out.lease_response_v2.lease_state,
2303 : smb2_util_lease_state("RHW"));
2304 0 : CHECK_VAL(io24.out.durable_open_v2, true);
2305 0 : CHECK_VAL(io24.out.timeout, 300*1000);
2306 0 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
2307 0 : CHECK_VAL(io24.out.durable_open_v2, true);
2308 0 : CHECK_VAL(io24.out.timeout, 300*1000);
2309 : } else {
2310 0 : CHECK_VAL(io24.out.durable_open_v2, false);
2311 : }
2312 :
2313 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2314 0 : torture_wait_for_lease_break(tctx);
2315 : } else {
2316 0 : torture_wait_for_oplock_break(tctx);
2317 : }
2318 0 : CHECK_VAL(break_info.count, 0);
2319 0 : CHECK_VAL(lease_break_info.count, 0);
2320 0 : status = smb2_util_close(tree2, *h24);
2321 0 : CHECK_STATUS(status, NT_STATUS_OK);
2322 0 : h24 = NULL;
2323 :
2324 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2325 0 : torture_wait_for_lease_break(tctx);
2326 : } else {
2327 0 : torture_wait_for_oplock_break(tctx);
2328 : }
2329 0 : CHECK_VAL(break_info.count, 0);
2330 0 : CHECK_VAL(lease_break_info.count, 0);
2331 :
2332 0 : done:
2333 :
2334 0 : smbXcli_conn_disconnect(transport2->conn, NT_STATUS_LOCAL_DISCONNECT);
2335 :
2336 0 : if (h1 != NULL) {
2337 0 : smb2_util_close(tree1, *h1);
2338 : }
2339 :
2340 0 : smb2_deltree(tree1, BASEDIR);
2341 :
2342 0 : TALLOC_FREE(tree1);
2343 0 : talloc_free(mem_ctx);
2344 :
2345 0 : 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 1 : static bool test_dhv2_pending1n_vs_oplock_sane(struct torture_context *tctx,
2369 : struct smb2_tree *tree1,
2370 : struct smb2_tree *tree2)
2371 : {
2372 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2373 : SMB2_OPLOCK_LEVEL_BATCH,
2374 : SMB2_OPLOCK_LEVEL_NONE,
2375 1 : 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 1 : static bool test_dhv2_pending1n_vs_oplock_windows(struct torture_context *tctx,
2401 : struct smb2_tree *tree1,
2402 : struct smb2_tree *tree2)
2403 : {
2404 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2405 : SMB2_OPLOCK_LEVEL_BATCH,
2406 : SMB2_OPLOCK_LEVEL_NONE,
2407 1 : 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 1 : static bool test_dhv2_pending1n_vs_lease_sane(struct torture_context *tctx,
2432 : struct smb2_tree *tree1,
2433 : struct smb2_tree *tree2)
2434 : {
2435 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2436 : SMB2_OPLOCK_LEVEL_LEASE,
2437 : SMB2_OPLOCK_LEVEL_NONE,
2438 1 : 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 1 : static bool test_dhv2_pending1n_vs_lease_windows(struct torture_context *tctx,
2464 : struct smb2_tree *tree1,
2465 : struct smb2_tree *tree2)
2466 : {
2467 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2468 : SMB2_OPLOCK_LEVEL_LEASE,
2469 : SMB2_OPLOCK_LEVEL_NONE,
2470 1 : 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 1 : static bool test_dhv2_pending1l_vs_oplock_sane(struct torture_context *tctx,
2495 : struct smb2_tree *tree1,
2496 : struct smb2_tree *tree2)
2497 : {
2498 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2499 : SMB2_OPLOCK_LEVEL_BATCH,
2500 : SMB2_OPLOCK_LEVEL_LEASE,
2501 1 : 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 1 : static bool test_dhv2_pending1l_vs_oplock_windows(struct torture_context *tctx,
2527 : struct smb2_tree *tree1,
2528 : struct smb2_tree *tree2)
2529 : {
2530 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2531 : SMB2_OPLOCK_LEVEL_BATCH,
2532 : SMB2_OPLOCK_LEVEL_LEASE,
2533 1 : 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 1 : static bool test_dhv2_pending1l_vs_lease_sane(struct torture_context *tctx,
2558 : struct smb2_tree *tree1,
2559 : struct smb2_tree *tree2)
2560 : {
2561 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2562 : SMB2_OPLOCK_LEVEL_LEASE,
2563 : SMB2_OPLOCK_LEVEL_LEASE,
2564 1 : 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 1 : static bool test_dhv2_pending1l_vs_lease_windows(struct torture_context *tctx,
2590 : struct smb2_tree *tree1,
2591 : struct smb2_tree *tree2)
2592 : {
2593 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2594 : SMB2_OPLOCK_LEVEL_LEASE,
2595 : SMB2_OPLOCK_LEVEL_LEASE,
2596 1 : 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 1 : static bool test_dhv2_pending1o_vs_oplock_sane(struct torture_context *tctx,
2621 : struct smb2_tree *tree1,
2622 : struct smb2_tree *tree2)
2623 : {
2624 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2625 : SMB2_OPLOCK_LEVEL_BATCH,
2626 : SMB2_OPLOCK_LEVEL_BATCH,
2627 1 : 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 1 : static bool test_dhv2_pending1o_vs_oplock_windows(struct torture_context *tctx,
2653 : struct smb2_tree *tree1,
2654 : struct smb2_tree *tree2)
2655 : {
2656 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2657 : SMB2_OPLOCK_LEVEL_BATCH,
2658 : SMB2_OPLOCK_LEVEL_BATCH,
2659 1 : 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 1 : 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 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2688 : SMB2_OPLOCK_LEVEL_LEASE,
2689 : SMB2_OPLOCK_LEVEL_BATCH,
2690 1 : 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 1 : static bool test_dhv2_pending1o_vs_lease_windows(struct torture_context *tctx,
2716 : struct smb2_tree *tree1,
2717 : struct smb2_tree *tree2)
2718 : {
2719 1 : return _test_dhv2_pending1_vs_hold(tctx, __func__,
2720 : SMB2_OPLOCK_LEVEL_LEASE,
2721 : SMB2_OPLOCK_LEVEL_BATCH,
2722 1 : 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 12 : 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 12 : const char *host = torture_setting_string(tctx, "host", NULL);
2754 12 : const char *share = torture_setting_string(tctx, "share", NULL);
2755 12 : struct cli_credentials *credentials = samba_cmdline_get_creds();
2756 : NTSTATUS status;
2757 12 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
2758 : struct smb2_handle _h1;
2759 12 : struct smb2_handle *h1 = NULL;
2760 : struct smb2_handle _h24;
2761 12 : struct smb2_handle *h24 = NULL;
2762 : struct smb2_create io1, io21, io22, io23, io24;
2763 12 : struct GUID create_guid1 = GUID_random();
2764 12 : struct GUID create_guid2 = GUID_random();
2765 12 : struct smb2_request *req21 = NULL;
2766 12 : bool ret = true;
2767 : char fname[256];
2768 12 : struct smb2_transport *transport1 = tree1->session->transport;
2769 : uint32_t server_capabilities;
2770 : uint32_t share_capabilities;
2771 : struct smb2_lease ls1;
2772 : uint64_t lease_key1;
2773 12 : uint16_t lease_epoch1 = 0;
2774 : struct smb2_lease ls2;
2775 : uint64_t lease_key2;
2776 12 : uint16_t lease_epoch2 = 0;
2777 : bool share_is_so;
2778 12 : struct smb2_transport *transport2_1 = tree2_1->session->transport;
2779 12 : int request_timeout2 = transport2_1->options.request_timeout;
2780 : struct smbcli_options options2x;
2781 12 : struct smb2_tree *tree2_2 = NULL;
2782 12 : struct smb2_tree *tree2_3 = NULL;
2783 12 : struct smb2_tree *tree2_4 = NULL;
2784 12 : struct smb2_transport *transport2_2 = NULL;
2785 12 : struct smb2_transport *transport2_3 = NULL;
2786 12 : struct smb2_transport *transport2_4 = NULL;
2787 12 : struct smb2_session *session2_1 = tree2_1->session;
2788 12 : struct smb2_session *session2_2 = NULL;
2789 12 : struct smb2_session *session2_3 = NULL;
2790 12 : struct smb2_session *session2_4 = NULL;
2791 12 : uint16_t csn2 = 1;
2792 12 : const char *hold_name = NULL;
2793 :
2794 12 : switch (client1_level) {
2795 6 : case SMB2_OPLOCK_LEVEL_LEASE:
2796 6 : hold_name = "RWH Lease";
2797 6 : break;
2798 6 : case SMB2_OPLOCK_LEVEL_BATCH:
2799 6 : hold_name = "BATCH Oplock";
2800 6 : break;
2801 0 : default:
2802 0 : smb_panic(__location__);
2803 : break;
2804 : }
2805 :
2806 12 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
2812 0 : if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
2813 0 : torture_skip(tctx, "MULTI_CHANNEL are not supported");
2814 : }
2815 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
2816 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
2817 : client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2818 0 : torture_skip(tctx, "leases are not supported");
2819 : }
2820 : }
2821 :
2822 0 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
2823 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
2824 0 : 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 0 : snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
2832 : BASEDIR, testname, generate_random_str(tctx, 8));
2833 :
2834 0 : options2x = transport2_1->options;
2835 0 : options2x.only_negprot = true;
2836 :
2837 0 : 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 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2850 : "smb2_connect failed");
2851 0 : transport2_2 = tree2_2->session->transport;
2852 :
2853 0 : session2_2 = smb2_session_channel(transport2_2,
2854 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
2855 : tctx,
2856 : session2_1);
2857 0 : torture_assert(tctx, session2_2 != NULL, "smb2_session_channel failed");
2858 :
2859 0 : status = smb2_session_setup_spnego(session2_2,
2860 : credentials,
2861 : 0 /* previous_session_id */);
2862 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2863 : "smb2_session_setup_spnego failed");
2864 0 : tree2_2->smbXcli = tree2_1->smbXcli;
2865 0 : tree2_2->session = session2_2;
2866 :
2867 0 : 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 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2880 : "smb2_connect failed");
2881 0 : transport2_3 = tree2_3->session->transport;
2882 :
2883 0 : session2_3 = smb2_session_channel(transport2_3,
2884 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
2885 : tctx,
2886 : session2_1);
2887 0 : torture_assert(tctx, session2_3 != NULL, "smb2_session_channel failed");
2888 :
2889 0 : status = smb2_session_setup_spnego(session2_3,
2890 : credentials,
2891 : 0 /* previous_session_id */);
2892 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2893 : "smb2_session_setup_spnego failed");
2894 0 : tree2_3->smbXcli = tree2_1->smbXcli;
2895 0 : tree2_3->session = session2_3;
2896 :
2897 0 : 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 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2910 : "smb2_connect failed");
2911 0 : transport2_4 = tree2_4->session->transport;
2912 :
2913 0 : session2_4 = smb2_session_channel(transport2_4,
2914 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
2915 : tctx,
2916 : session2_1);
2917 0 : torture_assert(tctx, session2_4 != NULL, "smb2_session_channel failed");
2918 :
2919 0 : status = smb2_session_setup_spnego(session2_4,
2920 : credentials,
2921 : 0 /* previous_session_id */);
2922 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2923 : "smb2_session_setup_spnego failed");
2924 0 : tree2_4->smbXcli = tree2_1->smbXcli;
2925 0 : tree2_4->session = session2_4;
2926 :
2927 0 : smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
2928 :
2929 0 : torture_reset_break_info(tctx, &break_info);
2930 0 : break_info.oplock_skip_ack = true;
2931 0 : torture_reset_lease_break_info(tctx, &lease_break_info);
2932 0 : lease_break_info.lease_skip_ack = true;
2933 0 : transport1->oplock.handler = torture_oplock_ack_handler;
2934 0 : transport1->oplock.private_data = tree1;
2935 0 : transport1->lease.handler = torture_lease_handler;
2936 0 : transport1->lease.private_data = tree1;
2937 0 : smb2_keepalive(transport1);
2938 0 : transport2_1->oplock.handler = torture_oplock_ack_handler;
2939 0 : transport2_1->oplock.private_data = tree2_1;
2940 0 : transport2_1->lease.handler = torture_lease_handler;
2941 0 : transport2_1->lease.private_data = tree2_1;
2942 0 : smb2_keepalive(transport2_1);
2943 0 : transport2_2->oplock.handler = torture_oplock_ack_handler;
2944 0 : transport2_2->oplock.private_data = tree2_2;
2945 0 : transport2_2->lease.handler = torture_lease_handler;
2946 0 : transport2_2->lease.private_data = tree2_2;
2947 0 : smb2_keepalive(transport2_2);
2948 0 : transport2_3->oplock.handler = torture_oplock_ack_handler;
2949 0 : transport2_3->oplock.private_data = tree2_3;
2950 0 : transport2_3->lease.handler = torture_lease_handler;
2951 0 : transport2_3->lease.private_data = tree2_3;
2952 0 : smb2_keepalive(transport2_3);
2953 0 : transport2_4->oplock.handler = torture_oplock_ack_handler;
2954 0 : transport2_4->oplock.private_data = tree2_4;
2955 0 : transport2_4->lease.handler = torture_lease_handler;
2956 0 : transport2_4->lease.private_data = tree2_4;
2957 0 : smb2_keepalive(transport2_4);
2958 :
2959 0 : smb2_util_unlink(tree1, fname);
2960 0 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
2961 0 : CHECK_STATUS(status, NT_STATUS_OK);
2962 0 : smb2_util_close(tree1, _h1);
2963 0 : CHECK_VAL(break_info.count, 0);
2964 :
2965 0 : lease_key1 = random();
2966 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2967 0 : smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
2968 0 : lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
2969 : } else {
2970 0 : smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
2971 : }
2972 0 : io1.in.durable_open = false;
2973 0 : io1.in.durable_open_v2 = true;
2974 0 : io1.in.persistent_open = false;
2975 0 : io1.in.create_guid = create_guid1;
2976 0 : io1.in.timeout = UINT32_MAX;
2977 :
2978 0 : status = smb2_create(tree1, mem_ctx, &io1);
2979 0 : CHECK_STATUS(status, NT_STATUS_OK);
2980 0 : _h1 = io1.out.file.handle;
2981 0 : h1 = &_h1;
2982 0 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2983 0 : CHECK_VAL(io1.out.durable_open, false);
2984 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
2985 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
2986 0 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
2987 0 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
2988 0 : CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
2989 0 : CHECK_VAL(io1.out.lease_response_v2.lease_state,
2990 : smb2_util_lease_state("RHW"));
2991 : } else {
2992 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
2993 : }
2994 0 : CHECK_VAL(io1.out.durable_open_v2, true);
2995 0 : CHECK_VAL(io1.out.timeout, 300*1000);
2996 :
2997 0 : lease_key2 = random();
2998 0 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
2999 0 : smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
3000 0 : lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
3001 : } else {
3002 0 : smb2_oplock_create(&io21, fname, client2_level);
3003 : }
3004 0 : io21.in.durable_open = false;
3005 0 : io21.in.durable_open_v2 = true;
3006 0 : io21.in.persistent_open = false;
3007 0 : io21.in.create_guid = create_guid2;
3008 0 : io21.in.timeout = UINT32_MAX;
3009 0 : io24 = io23 = io22 = io21;
3010 :
3011 0 : req21 = smb2_create_send(tree2_1, &io21);
3012 0 : torture_assert(tctx, req21 != NULL, "req21");
3013 :
3014 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3015 0 : const struct smb2_lease_break *lb =
3016 : &lease_break_info.lease_break;
3017 0 : const struct smb2_lease *l = &lb->current_lease;
3018 0 : const struct smb2_lease_key *k = &l->lease_key;
3019 :
3020 0 : torture_wait_for_lease_break(tctx);
3021 0 : CHECK_VAL(break_info.count, 0);
3022 0 : CHECK_VAL(lease_break_info.count, 1);
3023 :
3024 0 : torture_assert(tctx,
3025 : lease_break_info.lease_transport == transport1,
3026 : "expect lease break on transport1\n");
3027 0 : CHECK_VAL(k->data[0], lease_key1);
3028 0 : CHECK_VAL(k->data[1], ~lease_key1);
3029 0 : CHECK_VAL(lb->new_lease_state,
3030 : smb2_util_lease_state("RH"));
3031 0 : CHECK_VAL(lb->break_flags,
3032 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
3033 0 : CHECK_VAL(lb->new_epoch, lease_epoch1+1);
3034 0 : lease_epoch1 += 1;
3035 : } else {
3036 0 : torture_wait_for_oplock_break(tctx);
3037 0 : CHECK_VAL(break_info.count, 1);
3038 0 : CHECK_VAL(lease_break_info.count, 0);
3039 :
3040 0 : torture_assert(tctx,
3041 : break_info.received_transport == transport1,
3042 : "expect oplock break on transport1\n");
3043 0 : CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
3044 0 : CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
3045 0 : CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3046 : }
3047 :
3048 0 : torture_reset_break_info(tctx, &break_info);
3049 0 : break_info.oplock_skip_ack = true;
3050 0 : torture_reset_lease_break_info(tctx, &lease_break_info);
3051 0 : lease_break_info.lease_skip_ack = true;
3052 :
3053 0 : WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
3054 :
3055 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3056 0 : torture_wait_for_lease_break(tctx);
3057 : } else {
3058 0 : torture_wait_for_oplock_break(tctx);
3059 : }
3060 0 : CHECK_VAL(break_info.count, 0);
3061 0 : CHECK_VAL(lease_break_info.count, 0);
3062 :
3063 0 : smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
3064 0 : smb2cli_session_reset_channel_sequence(session2_1->smbXcli, csn2++);
3065 :
3066 0 : smb2cli_session_start_replay(session2_2->smbXcli);
3067 0 : transport2_2->options.request_timeout = 5;
3068 0 : status = smb2_create(tree2_2, tctx, &io22);
3069 0 : transport2_2->options.request_timeout = request_timeout2;
3070 0 : CHECK_STATUS(status, reject_status);
3071 0 : smb2cli_session_stop_replay(session2_2->smbXcli);
3072 :
3073 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3074 0 : torture_wait_for_lease_break(tctx);
3075 : } else {
3076 0 : torture_wait_for_oplock_break(tctx);
3077 : }
3078 0 : CHECK_VAL(break_info.count, 0);
3079 0 : CHECK_VAL(lease_break_info.count, 0);
3080 :
3081 0 : smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
3082 0 : smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
3083 :
3084 0 : smb2cli_session_start_replay(session2_3->smbXcli);
3085 0 : transport2_3->options.request_timeout = 5;
3086 0 : status = smb2_create(tree2_3, tctx, &io23);
3087 0 : transport2_3->options.request_timeout = request_timeout2;
3088 0 : CHECK_STATUS(status, reject_status);
3089 0 : smb2cli_session_stop_replay(session2_3->smbXcli);
3090 :
3091 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3092 0 : torture_wait_for_lease_break(tctx);
3093 : } else {
3094 0 : torture_wait_for_oplock_break(tctx);
3095 : }
3096 0 : CHECK_VAL(break_info.count, 0);
3097 0 : CHECK_VAL(lease_break_info.count, 0);
3098 :
3099 0 : smb2_util_close(tree1, _h1);
3100 0 : h1 = NULL;
3101 :
3102 0 : status = smb2_create_recv(req21, tctx, &io21);
3103 0 : CHECK_STATUS(status, NT_STATUS_LOCAL_DISCONNECT);
3104 :
3105 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3106 0 : torture_wait_for_lease_break(tctx);
3107 : } else {
3108 0 : torture_wait_for_oplock_break(tctx);
3109 : }
3110 0 : CHECK_VAL(break_info.count, 0);
3111 0 : CHECK_VAL(lease_break_info.count, 0);
3112 :
3113 0 : smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
3114 0 : smb2cli_session_reset_channel_sequence(session2_3->smbXcli, csn2++);
3115 :
3116 0 : smb2cli_session_start_replay(session2_4->smbXcli);
3117 0 : status = smb2_create(tree2_4, tctx, &io24);
3118 0 : smb2cli_session_stop_replay(session2_4->smbXcli);
3119 0 : CHECK_STATUS(status, NT_STATUS_OK);
3120 0 : _h24 = io24.out.file.handle;
3121 0 : h24 = &_h24;
3122 0 : CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3123 0 : CHECK_VAL(io24.out.oplock_level, client2_level);
3124 0 : CHECK_VAL(io24.out.durable_open, false);
3125 0 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3126 0 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
3127 0 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
3128 0 : CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
3129 0 : CHECK_VAL(io24.out.lease_response_v2.lease_state,
3130 : smb2_util_lease_state("RHW"));
3131 0 : CHECK_VAL(io24.out.durable_open_v2, true);
3132 0 : CHECK_VAL(io24.out.timeout, 300*1000);
3133 0 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
3134 0 : CHECK_VAL(io24.out.durable_open_v2, true);
3135 0 : CHECK_VAL(io24.out.timeout, 300*1000);
3136 : } else {
3137 0 : CHECK_VAL(io24.out.durable_open_v2, false);
3138 : }
3139 :
3140 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3141 0 : torture_wait_for_lease_break(tctx);
3142 : } else {
3143 0 : torture_wait_for_oplock_break(tctx);
3144 : }
3145 0 : CHECK_VAL(break_info.count, 0);
3146 0 : CHECK_VAL(lease_break_info.count, 0);
3147 0 : status = smb2_util_close(tree2_4, *h24);
3148 0 : CHECK_STATUS(status, NT_STATUS_OK);
3149 0 : h24 = NULL;
3150 :
3151 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3152 0 : torture_wait_for_lease_break(tctx);
3153 : } else {
3154 0 : torture_wait_for_oplock_break(tctx);
3155 : }
3156 0 : CHECK_VAL(break_info.count, 0);
3157 0 : CHECK_VAL(lease_break_info.count, 0);
3158 :
3159 0 : done:
3160 :
3161 0 : smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
3162 0 : smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
3163 0 : smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
3164 0 : smbXcli_conn_disconnect(transport2_4->conn, NT_STATUS_LOCAL_DISCONNECT);
3165 :
3166 0 : if (h1 != NULL) {
3167 0 : smb2_util_close(tree1, *h1);
3168 : }
3169 :
3170 0 : smb2_deltree(tree1, BASEDIR);
3171 :
3172 0 : TALLOC_FREE(tree1);
3173 0 : talloc_free(mem_ctx);
3174 :
3175 0 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3203 : SMB2_OPLOCK_LEVEL_LEASE,
3204 : SMB2_OPLOCK_LEVEL_NONE,
3205 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3235 : SMB2_OPLOCK_LEVEL_LEASE,
3236 : SMB2_OPLOCK_LEVEL_NONE,
3237 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3266 : SMB2_OPLOCK_LEVEL_BATCH,
3267 : SMB2_OPLOCK_LEVEL_NONE,
3268 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3298 : SMB2_OPLOCK_LEVEL_BATCH,
3299 : SMB2_OPLOCK_LEVEL_NONE,
3300 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3329 : SMB2_OPLOCK_LEVEL_BATCH,
3330 : SMB2_OPLOCK_LEVEL_LEASE,
3331 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3361 : SMB2_OPLOCK_LEVEL_BATCH,
3362 : SMB2_OPLOCK_LEVEL_LEASE,
3363 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3392 : SMB2_OPLOCK_LEVEL_LEASE,
3393 : SMB2_OPLOCK_LEVEL_LEASE,
3394 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3424 : SMB2_OPLOCK_LEVEL_LEASE,
3425 : SMB2_OPLOCK_LEVEL_LEASE,
3426 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3455 : SMB2_OPLOCK_LEVEL_BATCH,
3456 : SMB2_OPLOCK_LEVEL_BATCH,
3457 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3487 : SMB2_OPLOCK_LEVEL_BATCH,
3488 : SMB2_OPLOCK_LEVEL_BATCH,
3489 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3518 : SMB2_OPLOCK_LEVEL_LEASE,
3519 : SMB2_OPLOCK_LEVEL_BATCH,
3520 1 : 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 1 : 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 1 : return _test_dhv2_pending2_vs_hold(tctx, __func__,
3550 : SMB2_OPLOCK_LEVEL_LEASE,
3551 : SMB2_OPLOCK_LEVEL_BATCH,
3552 1 : 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 12 : 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 12 : const char *host = torture_setting_string(tctx, "host", NULL);
3584 12 : const char *share = torture_setting_string(tctx, "share", NULL);
3585 12 : struct cli_credentials *credentials = samba_cmdline_get_creds();
3586 : NTSTATUS status;
3587 12 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
3588 : struct smb2_handle _h1;
3589 12 : struct smb2_handle *h1 = NULL;
3590 : struct smb2_handle _h21;
3591 12 : struct smb2_handle *h21 = NULL;
3592 : struct smb2_handle _h24;
3593 12 : struct smb2_handle *h24 = NULL;
3594 : struct smb2_create io1, io21, io22, io23, io24;
3595 12 : struct GUID create_guid1 = GUID_random();
3596 12 : struct GUID create_guid2 = GUID_random();
3597 12 : struct smb2_request *req21 = NULL;
3598 12 : bool ret = true;
3599 : char fname[256];
3600 12 : struct smb2_transport *transport1 = tree1->session->transport;
3601 : uint32_t server_capabilities;
3602 : uint32_t share_capabilities;
3603 : struct smb2_lease ls1;
3604 : uint64_t lease_key1;
3605 12 : uint16_t lease_epoch1 = 0;
3606 : struct smb2_lease ls2;
3607 : uint64_t lease_key2;
3608 12 : uint16_t lease_epoch2 = 0;
3609 : bool share_is_so;
3610 12 : struct smb2_transport *transport2_1 = tree2_1->session->transport;
3611 12 : int request_timeout2 = transport2_1->options.request_timeout;
3612 : struct smbcli_options options2x;
3613 12 : struct smb2_tree *tree2_2 = NULL;
3614 12 : struct smb2_tree *tree2_3 = NULL;
3615 12 : struct smb2_tree *tree2_4 = NULL;
3616 12 : struct smb2_transport *transport2_2 = NULL;
3617 12 : struct smb2_transport *transport2_3 = NULL;
3618 12 : struct smb2_transport *transport2_4 = NULL;
3619 12 : struct smb2_session *session2_1 = tree2_1->session;
3620 12 : struct smb2_session *session2_2 = NULL;
3621 12 : struct smb2_session *session2_3 = NULL;
3622 12 : struct smb2_session *session2_4 = NULL;
3623 12 : bool block_setup = false;
3624 12 : bool blocked2_1 = false;
3625 12 : bool blocked2_2 = false;
3626 12 : bool blocked2_3 = false;
3627 12 : uint16_t csn2 = 1;
3628 12 : const char *hold_name = NULL;
3629 :
3630 12 : switch (client1_level) {
3631 6 : case SMB2_OPLOCK_LEVEL_LEASE:
3632 6 : hold_name = "RWH Lease";
3633 6 : break;
3634 6 : case SMB2_OPLOCK_LEVEL_BATCH:
3635 6 : hold_name = "BATCH Oplock";
3636 6 : break;
3637 0 : default:
3638 0 : smb_panic(__location__);
3639 : break;
3640 : }
3641 :
3642 12 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
3648 0 : if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
3649 0 : torture_skip(tctx, "MULTI_CHANNEL are not supported");
3650 : }
3651 0 : if (!(server_capabilities & SMB2_CAP_LEASING)) {
3652 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
3653 : client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3654 0 : torture_skip(tctx, "leases are not supported");
3655 : }
3656 : }
3657 :
3658 0 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
3659 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
3660 0 : 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 0 : snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
3668 : BASEDIR, testname, generate_random_str(tctx, 8));
3669 :
3670 0 : options2x = transport2_1->options;
3671 0 : options2x.only_negprot = true;
3672 :
3673 0 : 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 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3686 : "smb2_connect failed");
3687 0 : transport2_2 = tree2_2->session->transport;
3688 :
3689 0 : session2_2 = smb2_session_channel(transport2_2,
3690 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
3691 : tctx,
3692 : session2_1);
3693 0 : torture_assert(tctx, session2_2 != NULL, "smb2_session_channel failed");
3694 :
3695 0 : status = smb2_session_setup_spnego(session2_2,
3696 : credentials,
3697 : 0 /* previous_session_id */);
3698 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3699 : "smb2_session_setup_spnego failed");
3700 0 : tree2_2->smbXcli = tree2_1->smbXcli;
3701 0 : tree2_2->session = session2_2;
3702 :
3703 0 : 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 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3716 : "smb2_connect failed");
3717 0 : transport2_3 = tree2_3->session->transport;
3718 :
3719 0 : session2_3 = smb2_session_channel(transport2_3,
3720 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
3721 : tctx,
3722 : session2_1);
3723 0 : torture_assert(tctx, session2_3 != NULL, "smb2_session_channel failed");
3724 :
3725 0 : status = smb2_session_setup_spnego(session2_3,
3726 : credentials,
3727 : 0 /* previous_session_id */);
3728 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3729 : "smb2_session_setup_spnego failed");
3730 0 : tree2_3->smbXcli = tree2_1->smbXcli;
3731 0 : tree2_3->session = session2_3;
3732 :
3733 0 : 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 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3746 : "smb2_connect failed");
3747 0 : transport2_4 = tree2_4->session->transport;
3748 :
3749 0 : session2_4 = smb2_session_channel(transport2_4,
3750 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
3751 : tctx,
3752 : session2_1);
3753 0 : torture_assert(tctx, session2_4 != NULL, "smb2_session_channel failed");
3754 :
3755 0 : status = smb2_session_setup_spnego(session2_4,
3756 : credentials,
3757 : 0 /* previous_session_id */);
3758 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3759 : "smb2_session_setup_spnego failed");
3760 0 : tree2_4->smbXcli = tree2_1->smbXcli;
3761 0 : tree2_4->session = session2_4;
3762 :
3763 0 : smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
3764 :
3765 0 : torture_reset_break_info(tctx, &break_info);
3766 0 : break_info.oplock_skip_ack = true;
3767 0 : torture_reset_lease_break_info(tctx, &lease_break_info);
3768 0 : lease_break_info.lease_skip_ack = true;
3769 0 : transport1->oplock.handler = torture_oplock_ack_handler;
3770 0 : transport1->oplock.private_data = tree1;
3771 0 : transport1->lease.handler = torture_lease_handler;
3772 0 : transport1->lease.private_data = tree1;
3773 0 : smb2_keepalive(transport1);
3774 0 : transport2_1->oplock.handler = torture_oplock_ack_handler;
3775 0 : transport2_1->oplock.private_data = tree2_1;
3776 0 : transport2_1->lease.handler = torture_lease_handler;
3777 0 : transport2_1->lease.private_data = tree2_1;
3778 0 : smb2_keepalive(transport2_1);
3779 0 : transport2_2->oplock.handler = torture_oplock_ack_handler;
3780 0 : transport2_2->oplock.private_data = tree2_2;
3781 0 : transport2_2->lease.handler = torture_lease_handler;
3782 0 : transport2_2->lease.private_data = tree2_2;
3783 0 : smb2_keepalive(transport2_2);
3784 0 : transport2_3->oplock.handler = torture_oplock_ack_handler;
3785 0 : transport2_3->oplock.private_data = tree2_3;
3786 0 : transport2_3->lease.handler = torture_lease_handler;
3787 0 : transport2_3->lease.private_data = tree2_3;
3788 0 : smb2_keepalive(transport2_3);
3789 0 : transport2_4->oplock.handler = torture_oplock_ack_handler;
3790 0 : transport2_4->oplock.private_data = tree2_4;
3791 0 : transport2_4->lease.handler = torture_lease_handler;
3792 0 : transport2_4->lease.private_data = tree2_4;
3793 0 : smb2_keepalive(transport2_4);
3794 :
3795 0 : smb2_util_unlink(tree1, fname);
3796 0 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
3797 0 : CHECK_STATUS(status, NT_STATUS_OK);
3798 0 : smb2_util_close(tree1, _h1);
3799 0 : CHECK_VAL(break_info.count, 0);
3800 :
3801 0 : lease_key1 = random();
3802 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3803 0 : smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
3804 0 : lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
3805 : } else {
3806 0 : smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
3807 : }
3808 0 : io1.in.durable_open = false;
3809 0 : io1.in.durable_open_v2 = true;
3810 0 : io1.in.persistent_open = false;
3811 0 : io1.in.create_guid = create_guid1;
3812 0 : io1.in.timeout = UINT32_MAX;
3813 :
3814 0 : status = smb2_create(tree1, mem_ctx, &io1);
3815 0 : CHECK_STATUS(status, NT_STATUS_OK);
3816 0 : _h1 = io1.out.file.handle;
3817 0 : h1 = &_h1;
3818 0 : CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3819 0 : CHECK_VAL(io1.out.durable_open, false);
3820 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3821 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
3822 0 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
3823 0 : CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
3824 0 : CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
3825 0 : CHECK_VAL(io1.out.lease_response_v2.lease_state,
3826 : smb2_util_lease_state("RHW"));
3827 : } else {
3828 0 : CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
3829 : }
3830 0 : CHECK_VAL(io1.out.durable_open_v2, true);
3831 0 : CHECK_VAL(io1.out.timeout, 300*1000);
3832 :
3833 0 : lease_key2 = random();
3834 0 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3835 0 : smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
3836 0 : lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
3837 : } else {
3838 0 : smb2_oplock_create(&io21, fname, client2_level);
3839 : }
3840 0 : io21.in.durable_open = false;
3841 0 : io21.in.durable_open_v2 = true;
3842 0 : io21.in.persistent_open = false;
3843 0 : io21.in.create_guid = create_guid2;
3844 0 : io21.in.timeout = UINT32_MAX;
3845 0 : io24 = io23 = io22 = io21;
3846 :
3847 0 : req21 = smb2_create_send(tree2_1, &io21);
3848 0 : torture_assert(tctx, req21 != NULL, "req21");
3849 :
3850 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3851 0 : const struct smb2_lease_break *lb =
3852 : &lease_break_info.lease_break;
3853 0 : const struct smb2_lease *l = &lb->current_lease;
3854 0 : const struct smb2_lease_key *k = &l->lease_key;
3855 :
3856 0 : torture_wait_for_lease_break(tctx);
3857 0 : CHECK_VAL(break_info.count, 0);
3858 0 : CHECK_VAL(lease_break_info.count, 1);
3859 :
3860 0 : torture_assert(tctx,
3861 : lease_break_info.lease_transport == transport1,
3862 : "expect lease break on transport1\n");
3863 0 : CHECK_VAL(k->data[0], lease_key1);
3864 0 : CHECK_VAL(k->data[1], ~lease_key1);
3865 0 : CHECK_VAL(lb->new_lease_state,
3866 : smb2_util_lease_state("RH"));
3867 0 : CHECK_VAL(lb->break_flags,
3868 : SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
3869 0 : CHECK_VAL(lb->new_epoch, lease_epoch1+1);
3870 0 : lease_epoch1 += 1;
3871 : } else {
3872 0 : torture_wait_for_oplock_break(tctx);
3873 0 : CHECK_VAL(break_info.count, 1);
3874 0 : CHECK_VAL(lease_break_info.count, 0);
3875 :
3876 0 : torture_assert(tctx,
3877 : break_info.received_transport == transport1,
3878 : "expect oplock break on transport1\n");
3879 0 : CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
3880 0 : CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
3881 0 : CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
3882 : }
3883 :
3884 0 : torture_reset_break_info(tctx, &break_info);
3885 0 : break_info.oplock_skip_ack = true;
3886 0 : torture_reset_lease_break_info(tctx, &lease_break_info);
3887 0 : lease_break_info.lease_skip_ack = true;
3888 :
3889 0 : WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
3890 :
3891 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3892 0 : torture_wait_for_lease_break(tctx);
3893 : } else {
3894 0 : torture_wait_for_oplock_break(tctx);
3895 : }
3896 0 : CHECK_VAL(break_info.count, 0);
3897 0 : CHECK_VAL(lease_break_info.count, 0);
3898 :
3899 0 : block_setup = test_setup_blocked_transports(tctx);
3900 0 : torture_assert(tctx, block_setup, "test_setup_blocked_transports");
3901 :
3902 0 : blocked2_1 = _test_block_smb2_transport(tctx, transport2_1, "transport2_1");
3903 0 : torture_assert_goto(tctx, blocked2_1, ret, done, "we could not block tcp transport");
3904 0 : smb2cli_session_reset_channel_sequence(session2_1->smbXcli, csn2++);
3905 :
3906 0 : smb2cli_session_start_replay(session2_2->smbXcli);
3907 0 : transport2_2->options.request_timeout = 5;
3908 0 : status = smb2_create(tree2_2, tctx, &io22);
3909 0 : transport2_2->options.request_timeout = request_timeout2;
3910 0 : CHECK_STATUS(status, reject_status);
3911 0 : smb2cli_session_stop_replay(session2_2->smbXcli);
3912 :
3913 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3914 0 : torture_wait_for_lease_break(tctx);
3915 : } else {
3916 0 : torture_wait_for_oplock_break(tctx);
3917 : }
3918 0 : CHECK_VAL(break_info.count, 0);
3919 0 : CHECK_VAL(lease_break_info.count, 0);
3920 :
3921 0 : blocked2_2 = _test_block_smb2_transport(tctx, transport2_2, "transport2_2");
3922 0 : torture_assert_goto(tctx, blocked2_2, ret, done, "we could not block tcp transport");
3923 0 : smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
3924 :
3925 0 : smb2cli_session_start_replay(session2_3->smbXcli);
3926 0 : transport2_3->options.request_timeout = 5;
3927 0 : status = smb2_create(tree2_3, tctx, &io23);
3928 0 : transport2_3->options.request_timeout = request_timeout2;
3929 0 : CHECK_STATUS(status, reject_status);
3930 0 : smb2cli_session_stop_replay(session2_3->smbXcli);
3931 :
3932 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3933 0 : torture_wait_for_lease_break(tctx);
3934 : } else {
3935 0 : torture_wait_for_oplock_break(tctx);
3936 : }
3937 0 : CHECK_VAL(break_info.count, 0);
3938 0 : CHECK_VAL(lease_break_info.count, 0);
3939 :
3940 0 : smb2_util_close(tree1, _h1);
3941 0 : h1 = NULL;
3942 :
3943 0 : status = smb2_create_recv(req21, tctx, &io21);
3944 0 : CHECK_STATUS(status, NT_STATUS_OK);
3945 0 : _h21 = io21.out.file.handle;
3946 0 : h21 = &_h21;
3947 0 : CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3948 0 : CHECK_VAL(io21.out.oplock_level, client2_level);
3949 0 : CHECK_VAL(io21.out.durable_open, false);
3950 0 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3951 0 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[0], lease_key2);
3952 0 : CHECK_VAL(io21.out.lease_response_v2.lease_key.data[1], ~lease_key2);
3953 0 : CHECK_VAL(io21.out.lease_response_v2.lease_epoch, lease_epoch2);
3954 0 : CHECK_VAL(io21.out.lease_response_v2.lease_state,
3955 : smb2_util_lease_state("RHW"));
3956 0 : CHECK_VAL(io21.out.durable_open_v2, true);
3957 0 : CHECK_VAL(io21.out.timeout, 300*1000);
3958 0 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
3959 0 : CHECK_VAL(io21.out.durable_open_v2, true);
3960 0 : CHECK_VAL(io21.out.timeout, 300*1000);
3961 : } else {
3962 0 : CHECK_VAL(io21.out.durable_open_v2, false);
3963 : }
3964 :
3965 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
3966 0 : torture_wait_for_lease_break(tctx);
3967 : } else {
3968 0 : torture_wait_for_oplock_break(tctx);
3969 : }
3970 0 : CHECK_VAL(break_info.count, 0);
3971 0 : CHECK_VAL(lease_break_info.count, 0);
3972 :
3973 0 : blocked2_3 = _test_block_smb2_transport(tctx, transport2_3, "transport2_3");
3974 0 : torture_assert_goto(tctx, blocked2_3, ret, done, "we could not block tcp transport");
3975 0 : smb2cli_session_reset_channel_sequence(session2_3->smbXcli, csn2++);
3976 :
3977 0 : smb2cli_session_start_replay(session2_4->smbXcli);
3978 0 : status = smb2_create(tree2_4, tctx, &io24);
3979 0 : smb2cli_session_stop_replay(session2_4->smbXcli);
3980 0 : CHECK_STATUS(status, NT_STATUS_OK);
3981 0 : _h24 = io24.out.file.handle;
3982 0 : h24 = &_h24;
3983 0 : CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3984 0 : CHECK_VAL(h24->data[0], h21->data[0]);
3985 0 : CHECK_VAL(h24->data[1], h21->data[1]);
3986 0 : if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
3987 0 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
3988 0 : CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
3989 0 : CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
3990 0 : CHECK_VAL(io24.out.lease_response_v2.lease_state,
3991 : smb2_util_lease_state("RHW"));
3992 0 : CHECK_VAL(io24.out.durable_open_v2, true);
3993 0 : CHECK_VAL(io24.out.timeout, 300*1000);
3994 0 : } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
3995 0 : CHECK_VAL(io24.out.durable_open_v2, true);
3996 0 : CHECK_VAL(io24.out.timeout, 300*1000);
3997 : } else {
3998 0 : CHECK_VAL(io24.out.durable_open_v2, false);
3999 : }
4000 :
4001 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
4002 0 : torture_wait_for_lease_break(tctx);
4003 : } else {
4004 0 : torture_wait_for_oplock_break(tctx);
4005 : }
4006 0 : CHECK_VAL(break_info.count, 0);
4007 0 : CHECK_VAL(lease_break_info.count, 0);
4008 0 : status = smb2_util_close(tree2_4, *h24);
4009 0 : CHECK_STATUS(status, NT_STATUS_OK);
4010 0 : h24 = NULL;
4011 :
4012 0 : if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
4013 0 : torture_wait_for_lease_break(tctx);
4014 : } else {
4015 0 : torture_wait_for_oplock_break(tctx);
4016 : }
4017 0 : CHECK_VAL(break_info.count, 0);
4018 0 : CHECK_VAL(lease_break_info.count, 0);
4019 :
4020 0 : done:
4021 :
4022 0 : if (blocked2_3) {
4023 0 : _test_unblock_smb2_transport(tctx, transport2_3, "transport2_3");
4024 : }
4025 0 : if (blocked2_2) {
4026 0 : _test_unblock_smb2_transport(tctx, transport2_2, "transport2_2");
4027 : }
4028 0 : if (blocked2_1) {
4029 0 : _test_unblock_smb2_transport(tctx, transport2_1, "transport2_1");
4030 : }
4031 0 : if (block_setup) {
4032 0 : test_cleanup_blocked_transports(tctx);
4033 : }
4034 :
4035 0 : smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
4036 0 : smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
4037 0 : smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
4038 0 : smbXcli_conn_disconnect(transport2_4->conn, NT_STATUS_LOCAL_DISCONNECT);
4039 :
4040 0 : if (h1 != NULL) {
4041 0 : smb2_util_close(tree1, *h1);
4042 : }
4043 :
4044 0 : smb2_deltree(tree1, BASEDIR);
4045 :
4046 0 : TALLOC_FREE(tree1);
4047 0 : talloc_free(mem_ctx);
4048 :
4049 0 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4077 : SMB2_OPLOCK_LEVEL_LEASE,
4078 : SMB2_OPLOCK_LEVEL_NONE,
4079 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4109 : SMB2_OPLOCK_LEVEL_LEASE,
4110 : SMB2_OPLOCK_LEVEL_NONE,
4111 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4140 : SMB2_OPLOCK_LEVEL_BATCH,
4141 : SMB2_OPLOCK_LEVEL_NONE,
4142 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4172 : SMB2_OPLOCK_LEVEL_BATCH,
4173 : SMB2_OPLOCK_LEVEL_NONE,
4174 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4203 : SMB2_OPLOCK_LEVEL_BATCH,
4204 : SMB2_OPLOCK_LEVEL_LEASE,
4205 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4235 : SMB2_OPLOCK_LEVEL_BATCH,
4236 : SMB2_OPLOCK_LEVEL_LEASE,
4237 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4266 : SMB2_OPLOCK_LEVEL_LEASE,
4267 : SMB2_OPLOCK_LEVEL_LEASE,
4268 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4298 : SMB2_OPLOCK_LEVEL_LEASE,
4299 : SMB2_OPLOCK_LEVEL_LEASE,
4300 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4329 : SMB2_OPLOCK_LEVEL_BATCH,
4330 : SMB2_OPLOCK_LEVEL_BATCH,
4331 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4361 : SMB2_OPLOCK_LEVEL_BATCH,
4362 : SMB2_OPLOCK_LEVEL_BATCH,
4363 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4392 : SMB2_OPLOCK_LEVEL_LEASE,
4393 : SMB2_OPLOCK_LEVEL_BATCH,
4394 1 : 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 1 : 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 1 : return _test_dhv2_pending3_vs_hold(tctx, __func__,
4424 : SMB2_OPLOCK_LEVEL_LEASE,
4425 : SMB2_OPLOCK_LEVEL_BATCH,
4426 1 : NT_STATUS_ACCESS_DENIED,
4427 : tree1, tree2_1);
4428 : }
4429 :
4430 0 : 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 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
4436 0 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
4437 : struct smb2_handle handle;
4438 0 : struct smb2_handle *phandle = NULL;
4439 : struct smb2_create io;
4440 0 : struct GUID create_guid = GUID_random();
4441 0 : bool ret = true;
4442 0 : const char *fname = BASEDIR "\\channel_sequence.dat";
4443 0 : uint16_t csn = 0;
4444 0 : uint16_t limit = UINT16_MAX - 0x7fff;
4445 : int i;
4446 : struct {
4447 : uint16_t csn;
4448 : bool csn_rand_low;
4449 : bool csn_rand_high;
4450 : NTSTATUS expected_status;
4451 0 : } 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 0 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
4506 :
4507 0 : csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli);
4508 0 : torture_comment(tctx, "Testing create with channel sequence number: 0x%04x\n", csn);
4509 :
4510 0 : smb2_oplock_create_share(&io, fname,
4511 : smb2_util_share_access("RWD"),
4512 0 : smb2_util_oplock_level("b"));
4513 0 : io.in.durable_open = false;
4514 0 : io.in.durable_open_v2 = true;
4515 0 : io.in.create_guid = create_guid;
4516 0 : io.in.timeout = UINT32_MAX;
4517 :
4518 0 : torture_assert_ntstatus_ok_goto(tctx,
4519 : smb2_create(tree, mem_ctx, &io),
4520 : ret, done, "failed to call smb2_create");
4521 :
4522 0 : handle = io.out.file.handle;
4523 0 : phandle = &handle;
4524 :
4525 0 : for (i=0; i <ARRAY_SIZE(tests); i++) {
4526 :
4527 0 : const char *opstr = "";
4528 : union smb_fileinfo qfinfo;
4529 :
4530 0 : csn = tests[i].csn;
4531 :
4532 0 : if (tests[i].csn_rand_low) {
4533 0 : csn = rand() % limit;
4534 0 : } else if (tests[i].csn_rand_high) {
4535 0 : csn = rand() % limit + 0x7fff;
4536 : }
4537 :
4538 0 : switch (opcode) {
4539 0 : case SMB2_OP_WRITE:
4540 0 : opstr = "write";
4541 0 : break;
4542 0 : case SMB2_OP_IOCTL:
4543 0 : opstr = "ioctl";
4544 0 : break;
4545 0 : case SMB2_OP_SETINFO:
4546 0 : opstr = "setinfo";
4547 0 : break;
4548 0 : default:
4549 0 : break;
4550 : }
4551 :
4552 0 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, csn);
4553 0 : csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli);
4554 :
4555 0 : 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 0 : if (do_replay) {
4560 0 : smb2cli_session_start_replay(tree->session->smbXcli);
4561 : }
4562 :
4563 0 : switch (opcode) {
4564 0 : case SMB2_OP_WRITE: {
4565 0 : DATA_BLOB blob = data_blob_talloc(tctx, NULL, 255);
4566 :
4567 0 : generate_random_buffer(blob.data, blob.length);
4568 :
4569 0 : status = smb2_util_write(tree, handle, blob.data, 0, blob.length);
4570 0 : if (NT_STATUS_IS_OK(status)) {
4571 : struct smb2_read rd;
4572 :
4573 0 : rd = (struct smb2_read) {
4574 : .in.file.handle = handle,
4575 0 : .in.length = blob.length,
4576 : .in.offset = 0
4577 : };
4578 :
4579 0 : torture_assert_ntstatus_ok_goto(tctx,
4580 : smb2_read(tree, tree, &rd),
4581 : ret, done, "failed to read after write");
4582 :
4583 0 : torture_assert_data_blob_equal(tctx,
4584 : rd.out.data, blob,
4585 : "read/write mismatch");
4586 : }
4587 0 : break;
4588 : }
4589 0 : case SMB2_OP_IOCTL: {
4590 : union smb_ioctl ioctl;
4591 0 : 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 0 : status = smb2_ioctl(tree, mem_ctx, &ioctl.smb2);
4599 0 : break;
4600 : }
4601 0 : case SMB2_OP_SETINFO: {
4602 : union smb_setfileinfo sfinfo;
4603 0 : ZERO_STRUCT(sfinfo);
4604 0 : sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
4605 0 : sfinfo.generic.in.file.handle = handle;
4606 0 : sfinfo.position_information.in.position = 0x1000;
4607 0 : status = smb2_setinfo_file(tree, &sfinfo);
4608 0 : break;
4609 : }
4610 0 : default:
4611 0 : break;
4612 : }
4613 :
4614 0 : qfinfo = (union smb_fileinfo) {
4615 : .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
4616 : .generic.in.file.handle = handle
4617 : };
4618 :
4619 0 : torture_assert_ntstatus_ok_goto(tctx,
4620 : smb2_getinfo_file(tree, mem_ctx, &qfinfo),
4621 : ret, done, "failed to read after write");
4622 :
4623 0 : if (do_replay) {
4624 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
4625 : }
4626 :
4627 0 : torture_assert_ntstatus_equal_goto(tctx,
4628 : status, tests[i].expected_status,
4629 : ret, done, "got unexpected failure code");
4630 :
4631 : }
4632 0 : done:
4633 0 : if (phandle != NULL) {
4634 0 : smb2_util_close(tree, *phandle);
4635 : }
4636 :
4637 0 : smb2_util_unlink(tree, fname);
4638 :
4639 0 : return ret;
4640 : }
4641 :
4642 1 : static bool test_channel_sequence(struct torture_context *tctx,
4643 : struct smb2_tree *tree)
4644 : {
4645 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
4646 1 : bool ret = true;
4647 1 : const char *fname = BASEDIR "\\channel_sequence.dat";
4648 1 : struct smb2_transport *transport1 = tree->session->transport;
4649 : struct smb2_handle handle;
4650 1 : uint16_t opcodes[] = { SMB2_OP_WRITE, SMB2_OP_IOCTL, SMB2_OP_SETINFO };
4651 : int i;
4652 :
4653 1 : 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 0 : torture_comment(tctx, "Testing channel sequence numbers\n");
4659 :
4660 0 : smbXcli_conn_set_force_channel_sequence(transport1->conn, true);
4661 :
4662 0 : torture_assert_ntstatus_ok_goto(tctx,
4663 : torture_smb2_testdir(tree, BASEDIR, &handle),
4664 : ret, done, "failed to setup test directory");
4665 :
4666 0 : smb2_util_close(tree, handle);
4667 0 : smb2_util_unlink(tree, fname);
4668 :
4669 0 : for (i=0; i <ARRAY_SIZE(opcodes); i++) {
4670 0 : torture_assert(tctx,
4671 : test_channel_sequence_table(tctx, tree, false, opcodes[i]),
4672 : "failed to test CSN without replay flag");
4673 0 : torture_assert(tctx,
4674 : test_channel_sequence_table(tctx, tree, true, opcodes[i]),
4675 : "failed to test CSN with replay flag");
4676 : }
4677 :
4678 0 : done:
4679 :
4680 0 : smb2_util_unlink(tree, fname);
4681 0 : smb2_deltree(tree, BASEDIR);
4682 :
4683 0 : talloc_free(tree);
4684 0 : talloc_free(mem_ctx);
4685 :
4686 0 : return ret;
4687 : }
4688 :
4689 : /**
4690 : * Test Durability V2 Create Replay Detection on Multi Channel
4691 : */
4692 1 : static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1)
4693 : {
4694 1 : const char *host = torture_setting_string(tctx, "host", NULL);
4695 1 : const char *share = torture_setting_string(tctx, "share", NULL);
4696 : NTSTATUS status;
4697 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
4698 : struct smb2_handle _h;
4699 1 : struct smb2_handle *h = NULL;
4700 : struct smb2_create io;
4701 1 : struct GUID create_guid = GUID_random();
4702 1 : bool ret = true;
4703 1 : const char *fname = BASEDIR "\\replay3.dat";
4704 1 : struct smb2_tree *tree2 = NULL;
4705 1 : struct smb2_transport *transport1 = tree1->session->transport;
4706 1 : struct smb2_transport *transport2 = NULL;
4707 1 : struct smb2_session *session1_1 = tree1->session;
4708 1 : struct smb2_session *session1_2 = NULL;
4709 : uint32_t share_capabilities;
4710 : bool share_is_so;
4711 : uint32_t server_capabilities;
4712 :
4713 1 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(
4719 0 : tree1->session->transport->conn);
4720 0 : if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
4721 0 : torture_skip(tctx,
4722 : "Server does not support multi-channel.");
4723 : }
4724 :
4725 0 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
4726 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
4727 :
4728 0 : torture_reset_break_info(tctx, &break_info);
4729 0 : transport1->oplock.handler = torture_oplock_ack_handler;
4730 0 : transport1->oplock.private_data = tree1;
4731 :
4732 0 : torture_comment(tctx, "Replay of DurableHandleReqV2 on Multi "
4733 : "Channel\n");
4734 0 : status = torture_smb2_testdir(tree1, BASEDIR, &_h);
4735 0 : CHECK_STATUS(status, NT_STATUS_OK);
4736 0 : smb2_util_close(tree1, _h);
4737 0 : smb2_util_unlink(tree1, fname);
4738 0 : CHECK_VAL(break_info.count, 0);
4739 :
4740 : /*
4741 : * use the 1st channel, 1st session
4742 : */
4743 0 : smb2_oplock_create_share(&io, fname,
4744 : smb2_util_share_access(""),
4745 0 : smb2_util_oplock_level("b"));
4746 0 : io.in.durable_open = false;
4747 0 : io.in.durable_open_v2 = true;
4748 0 : io.in.persistent_open = false;
4749 0 : io.in.create_guid = create_guid;
4750 0 : io.in.timeout = UINT32_MAX;
4751 :
4752 0 : tree1->session = session1_1;
4753 0 : status = smb2_create(tree1, mem_ctx, &io);
4754 0 : CHECK_STATUS(status, NT_STATUS_OK);
4755 0 : _h = io.out.file.handle;
4756 0 : h = &_h;
4757 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
4758 0 : 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 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
4764 0 : CHECK_VAL(io.out.durable_open_v2, true);
4765 0 : CHECK_VAL(io.out.timeout, 300*1000);
4766 : }
4767 0 : CHECK_VAL(io.out.durable_open, false);
4768 0 : CHECK_VAL(break_info.count, 0);
4769 :
4770 0 : 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 0 : &transport1->options,
4779 : lpcfg_socket_options(tctx->lp_ctx),
4780 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
4781 : );
4782 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4783 : "smb2_connect failed");
4784 0 : transport2 = tree2->session->transport;
4785 :
4786 0 : transport2->oplock.handler = torture_oplock_ack_handler;
4787 0 : transport2->oplock.private_data = tree2;
4788 :
4789 : /*
4790 : * Now bind the 1st session to 2nd transport channel
4791 : */
4792 0 : session1_2 = smb2_session_channel(transport2,
4793 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
4794 : tree2, session1_1);
4795 0 : torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
4796 :
4797 0 : status = smb2_session_setup_spnego(session1_2,
4798 : samba_cmdline_get_creds(),
4799 : 0 /* previous_session_id */);
4800 0 : CHECK_STATUS(status, NT_STATUS_OK);
4801 :
4802 : /*
4803 : * use the 2nd channel, 1st session
4804 : */
4805 0 : tree1->session = session1_2;
4806 0 : smb2cli_session_start_replay(tree1->session->smbXcli);
4807 0 : status = smb2_create(tree1, mem_ctx, &io);
4808 0 : smb2cli_session_stop_replay(tree1->session->smbXcli);
4809 0 : CHECK_STATUS(status, NT_STATUS_OK);
4810 0 : _h = io.out.file.handle;
4811 0 : h = &_h;
4812 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
4813 0 : 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 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
4819 0 : CHECK_VAL(io.out.durable_open_v2, true);
4820 0 : CHECK_VAL(io.out.timeout, 300*1000);
4821 : }
4822 0 : CHECK_VAL(io.out.durable_open, false);
4823 0 : CHECK_VAL(break_info.count, 0);
4824 :
4825 0 : tree1->session = session1_1;
4826 0 : smb2_util_close(tree1, *h);
4827 0 : h = NULL;
4828 :
4829 0 : done:
4830 0 : talloc_free(tree2);
4831 0 : tree1->session = session1_1;
4832 :
4833 0 : if (h != NULL) {
4834 0 : smb2_util_close(tree1, *h);
4835 : }
4836 :
4837 0 : smb2_util_unlink(tree1, fname);
4838 0 : smb2_deltree(tree1, BASEDIR);
4839 :
4840 0 : talloc_free(tree1);
4841 0 : talloc_free(mem_ctx);
4842 :
4843 0 : return ret;
4844 : }
4845 :
4846 : /**
4847 : * Test Multichannel IO Ordering using ChannelSequence/Channel Epoch number
4848 : */
4849 1 : static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1)
4850 : {
4851 1 : const char *host = torture_setting_string(tctx, "host", NULL);
4852 1 : const char *share = torture_setting_string(tctx, "share", NULL);
4853 : NTSTATUS status;
4854 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
4855 : struct smb2_handle _h1;
4856 1 : struct smb2_handle *h1 = NULL;
4857 : struct smb2_create io;
4858 1 : struct GUID create_guid = GUID_random();
4859 : uint8_t buf[64];
4860 : struct smb2_read rd;
4861 : union smb_setfileinfo sfinfo;
4862 1 : bool ret = true;
4863 1 : const char *fname = BASEDIR "\\replay4.dat";
4864 1 : struct smb2_tree *tree2 = NULL;
4865 1 : struct smb2_transport *transport1 = tree1->session->transport;
4866 1 : struct smb2_transport *transport2 = NULL;
4867 1 : struct smb2_session *session1_1 = tree1->session;
4868 1 : struct smb2_session *session1_2 = NULL;
4869 : uint16_t curr_cs;
4870 : uint32_t share_capabilities;
4871 : bool share_is_so;
4872 : uint32_t server_capabilities;
4873 :
4874 1 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(
4880 0 : tree1->session->transport->conn);
4881 0 : if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
4882 0 : torture_skip(tctx,
4883 : "Server does not support multi-channel.");
4884 : }
4885 :
4886 0 : share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
4887 0 : share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
4888 :
4889 0 : torture_reset_break_info(tctx, &break_info);
4890 0 : transport1->oplock.handler = torture_oplock_ack_handler;
4891 0 : transport1->oplock.private_data = tree1;
4892 :
4893 0 : torture_comment(tctx, "IO Ordering for Multi Channel\n");
4894 0 : status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
4895 0 : CHECK_STATUS(status, NT_STATUS_OK);
4896 0 : smb2_util_close(tree1, _h1);
4897 0 : smb2_util_unlink(tree1, fname);
4898 0 : CHECK_VAL(break_info.count, 0);
4899 :
4900 : /*
4901 : * use the 1st channel, 1st session
4902 : */
4903 :
4904 0 : smb2_oplock_create_share(&io, fname,
4905 : smb2_util_share_access(""),
4906 0 : smb2_util_oplock_level("b"));
4907 0 : io.in.durable_open = false;
4908 0 : io.in.durable_open_v2 = true;
4909 0 : io.in.persistent_open = false;
4910 0 : io.in.create_guid = create_guid;
4911 0 : io.in.timeout = UINT32_MAX;
4912 :
4913 0 : tree1->session = session1_1;
4914 0 : status = smb2_create(tree1, mem_ctx, &io);
4915 0 : CHECK_STATUS(status, NT_STATUS_OK);
4916 0 : _h1 = io.out.file.handle;
4917 0 : h1 = &_h1;
4918 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
4919 0 : 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 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
4925 0 : CHECK_VAL(io.out.durable_open_v2, true);
4926 0 : CHECK_VAL(io.out.timeout, 300*1000);
4927 : }
4928 0 : CHECK_VAL(io.out.durable_open, false);
4929 0 : CHECK_VAL(break_info.count, 0);
4930 :
4931 0 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
4932 0 : CHECK_STATUS(status, NT_STATUS_OK);
4933 :
4934 : /*
4935 : * Increment ChannelSequence so that server thinks that there's a
4936 : * Channel Failure
4937 : */
4938 0 : smb2cli_session_increment_channel_sequence(tree1->session->smbXcli);
4939 :
4940 : /*
4941 : * Perform a Read with incremented ChannelSequence
4942 : */
4943 0 : rd = (struct smb2_read) {
4944 0 : .in.file.handle = *h1,
4945 : .in.length = sizeof(buf),
4946 : .in.offset = 0
4947 : };
4948 0 : status = smb2_read(tree1, tree1, &rd);
4949 0 : CHECK_STATUS(status, NT_STATUS_OK);
4950 :
4951 : /*
4952 : * Performing a Write with Stale ChannelSequence is not allowed by
4953 : * server
4954 : */
4955 0 : curr_cs = smb2cli_session_reset_channel_sequence(
4956 0 : tree1->session->smbXcli, 0);
4957 0 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
4958 0 : 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 0 : smb2cli_session_start_replay(tree1->session->smbXcli);
4965 0 : smb2cli_session_reset_channel_sequence(tree1->session->smbXcli, 0);
4966 0 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
4967 0 : smb2cli_session_stop_replay(tree1->session->smbXcli);
4968 0 : 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 0 : ZERO_STRUCT(sfinfo);
4975 0 : sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
4976 0 : sfinfo.generic.in.file.handle = *h1;
4977 0 : sfinfo.position_information.in.position = 0x1000;
4978 0 : status = smb2_setinfo_file(tree1, &sfinfo);
4979 0 : CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
4980 :
4981 : /*
4982 : * Performing a Read with stale ChannelSequence is allowed
4983 : */
4984 0 : rd = (struct smb2_read) {
4985 0 : .in.file.handle = *h1,
4986 : .in.length = ARRAY_SIZE(buf),
4987 : .in.offset = 0
4988 : };
4989 0 : status = smb2_read(tree1, tree1, &rd);
4990 0 : CHECK_STATUS(status, NT_STATUS_OK);
4991 :
4992 0 : 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 0 : &transport1->options,
5001 : lpcfg_socket_options(tctx->lp_ctx),
5002 : lpcfg_gensec_settings(tctx, tctx->lp_ctx)
5003 : );
5004 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5005 : "smb2_connect failed");
5006 0 : transport2 = tree2->session->transport;
5007 :
5008 0 : transport2->oplock.handler = torture_oplock_ack_handler;
5009 0 : transport2->oplock.private_data = tree2;
5010 :
5011 : /*
5012 : * Now bind the 1st session to 2nd transport channel
5013 : */
5014 0 : session1_2 = smb2_session_channel(transport2,
5015 : lpcfg_gensec_settings(tctx, tctx->lp_ctx),
5016 : tree2, session1_1);
5017 0 : torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
5018 :
5019 0 : status = smb2_session_setup_spnego(session1_2,
5020 : samba_cmdline_get_creds(),
5021 : 0 /* previous_session_id */);
5022 0 : CHECK_STATUS(status, NT_STATUS_OK);
5023 :
5024 : /*
5025 : * use the 2nd channel, 1st session
5026 : */
5027 0 : tree1->session = session1_2;
5028 :
5029 : /*
5030 : * Write Replay with Correct ChannelSequence is allowed by the server
5031 : */
5032 0 : smb2cli_session_start_replay(tree1->session->smbXcli);
5033 0 : smb2cli_session_reset_channel_sequence(tree1->session->smbXcli,
5034 : curr_cs);
5035 0 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
5036 0 : CHECK_STATUS(status, NT_STATUS_OK);
5037 0 : 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 0 : memset(buf, 'r', ARRAY_SIZE(buf));
5044 0 : smb2cli_session_start_replay(tree1->session->smbXcli);
5045 0 : status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
5046 0 : CHECK_STATUS(status, NT_STATUS_OK);
5047 0 : smb2cli_session_stop_replay(tree1->session->smbXcli);
5048 :
5049 : /*
5050 : * Read back from File to verify what was written
5051 : */
5052 0 : rd = (struct smb2_read) {
5053 0 : .in.file.handle = *h1,
5054 : .in.length = ARRAY_SIZE(buf),
5055 : .in.offset = 0
5056 : };
5057 0 : status = smb2_read(tree1, tree1, &rd);
5058 0 : CHECK_STATUS(status, NT_STATUS_OK);
5059 :
5060 0 : if ((rd.out.data.length != ARRAY_SIZE(buf)) ||
5061 0 : memcmp(rd.out.data.data, buf, ARRAY_SIZE(buf))) {
5062 0 : torture_comment(tctx, "Write Replay Data Mismatch\n");
5063 : }
5064 :
5065 0 : tree1->session = session1_1;
5066 0 : smb2_util_close(tree1, *h1);
5067 0 : h1 = NULL;
5068 :
5069 0 : if (share_is_so) {
5070 0 : CHECK_VAL(break_info.count, 1);
5071 : } else {
5072 0 : CHECK_VAL(break_info.count, 0);
5073 : }
5074 0 : done:
5075 0 : talloc_free(tree2);
5076 0 : tree1->session = session1_1;
5077 :
5078 0 : if (h1 != NULL) {
5079 0 : smb2_util_close(tree1, *h1);
5080 : }
5081 :
5082 0 : smb2_util_unlink(tree1, fname);
5083 0 : smb2_deltree(tree1, BASEDIR);
5084 :
5085 0 : talloc_free(tree1);
5086 0 : talloc_free(mem_ctx);
5087 :
5088 0 : return ret;
5089 : }
5090 :
5091 : /**
5092 : * Test Durability V2 Persistent Create Replay on a Single Channel
5093 : */
5094 1 : static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree)
5095 : {
5096 : NTSTATUS status;
5097 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
5098 : struct smb2_handle _h;
5099 1 : struct smb2_handle *h = NULL;
5100 : struct smb2_create io;
5101 1 : struct GUID create_guid = GUID_random();
5102 1 : bool ret = true;
5103 : uint32_t share_capabilities;
5104 : bool share_is_ca;
5105 : bool share_is_so;
5106 : uint32_t server_capabilities;
5107 1 : const char *fname = BASEDIR "\\replay5.dat";
5108 1 : struct smb2_transport *transport = tree->session->transport;
5109 1 : struct smbcli_options options = tree->session->transport->options;
5110 1 : uint8_t expect_oplock = smb2_util_oplock_level("b");
5111 1 : NTSTATUS expect_status = NT_STATUS_DUPLICATE_OBJECTID;
5112 :
5113 1 : 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 0 : server_capabilities = smb2cli_conn_server_capabilities(
5119 0 : tree->session->transport->conn);
5120 0 : if (!(server_capabilities & SMB2_CAP_PERSISTENT_HANDLES)) {
5121 0 : 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 1 : static bool test_replay6(struct torture_context *tctx, struct smb2_tree *tree)
5218 : {
5219 : NTSTATUS status;
5220 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
5221 : struct smb2_handle _h;
5222 1 : struct smb2_handle *h = NULL;
5223 : struct smb2_create io, ref1;
5224 : union smb_fileinfo qfinfo;
5225 1 : struct GUID create_guid = GUID_random();
5226 1 : bool ret = true;
5227 1 : const char *fname = BASEDIR "\\replay6.dat";
5228 1 : struct smb2_transport *transport = tree->session->transport;
5229 :
5230 1 : 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 0 : torture_reset_break_info(tctx, &break_info);
5236 0 : tree->session->transport->oplock.handler = torture_oplock_ack_handler;
5237 0 : tree->session->transport->oplock.private_data = tree;
5238 :
5239 0 : torture_comment(tctx, "Error Codes for DurableHandleReqV2 Replay\n");
5240 0 : smb2_util_unlink(tree, fname);
5241 0 : status = torture_smb2_testdir(tree, BASEDIR, &_h);
5242 0 : CHECK_STATUS(status, NT_STATUS_OK);
5243 0 : smb2_util_close(tree, _h);
5244 0 : torture_wait_for_oplock_break(tctx);
5245 0 : CHECK_VAL(break_info.count, 0);
5246 0 : torture_reset_break_info(tctx, &break_info);
5247 :
5248 0 : smb2_oplock_create_share(&io, fname,
5249 : smb2_util_share_access("RWD"),
5250 0 : smb2_util_oplock_level("b"));
5251 0 : io.in.durable_open = false;
5252 0 : io.in.durable_open_v2 = true;
5253 0 : io.in.persistent_open = false;
5254 0 : io.in.create_guid = create_guid;
5255 0 : io.in.timeout = UINT32_MAX;
5256 :
5257 0 : status = smb2_create(tree, mem_ctx, &io);
5258 0 : CHECK_STATUS(status, NT_STATUS_OK);
5259 0 : ref1 = io;
5260 0 : _h = io.out.file.handle;
5261 0 : h = &_h;
5262 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
5263 0 : CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
5264 0 : CHECK_VAL(io.out.durable_open, false);
5265 0 : CHECK_VAL(io.out.durable_open_v2, true);
5266 :
5267 0 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
5268 0 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
5269 0 : smb2cli_session_start_replay(tree->session->smbXcli);
5270 0 : status = smb2_create(tree, mem_ctx, &io);
5271 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
5272 0 : CHECK_STATUS(status, NT_STATUS_OK);
5273 0 : CHECK_CREATE_OUT(&io, &ref1);
5274 0 : torture_wait_for_oplock_break(tctx);
5275 0 : CHECK_VAL(break_info.count, 0);
5276 0 : torture_reset_break_info(tctx, &break_info);
5277 :
5278 0 : qfinfo = (union smb_fileinfo) {
5279 : .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
5280 0 : .generic.in.file.handle = *h
5281 : };
5282 0 : torture_comment(tctx, "Trying getinfo\n");
5283 0 : status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
5284 0 : CHECK_STATUS(status, NT_STATUS_OK);
5285 0 : CHECK_VAL(qfinfo.position_information.out.position, 0);
5286 :
5287 0 : smb2cli_session_start_replay(tree->session->smbXcli);
5288 0 : status = smb2_create(tree, mem_ctx, &io);
5289 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
5290 0 : CHECK_STATUS(status, NT_STATUS_OK);
5291 0 : 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 0 : 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 0 : torture_wait_for_oplock_break(tctx);
5300 0 : CHECK_VAL(break_info.count, 1);
5301 0 : CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
5302 0 : 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 0 : status = smb2_create(tree, mem_ctx, &io);
5310 0 : CHECK_STATUS(status, NT_STATUS_DUPLICATE_OBJECTID);
5311 0 : torture_wait_for_oplock_break(tctx);
5312 0 : CHECK_VAL(break_info.count, 0);
5313 0 : 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 0 : io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
5324 0 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
5325 0 : smb2cli_session_start_replay(tree->session->smbXcli);
5326 0 : status = smb2_create(tree, mem_ctx, &io);
5327 0 : smb2cli_session_stop_replay(tree->session->smbXcli);
5328 0 : CHECK_STATUS(status, NT_STATUS_OK);
5329 0 : 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 0 : 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 0 : torture_wait_for_oplock_break(tctx);
5338 0 : CHECK_VAL(break_info.count, 0);
5339 :
5340 0 : done:
5341 0 : if (h != NULL) {
5342 0 : smb2_util_close(tree, *h);
5343 : }
5344 :
5345 0 : smb2_util_unlink(tree, fname);
5346 0 : smb2_deltree(tree, BASEDIR);
5347 :
5348 0 : talloc_free(tree);
5349 0 : talloc_free(mem_ctx);
5350 :
5351 0 : return ret;
5352 : }
5353 :
5354 1 : static bool test_replay7(struct torture_context *tctx, struct smb2_tree *tree)
5355 : {
5356 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
5357 1 : struct smb2_transport *transport = tree->session->transport;
5358 : NTSTATUS status;
5359 : struct smb2_handle _dh;
5360 1 : struct smb2_handle *dh = NULL;
5361 : struct smb2_notify notify;
5362 : struct smb2_request *req;
5363 : union smb_fileinfo qfinfo;
5364 1 : bool ret = false;
5365 :
5366 1 : 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 0 : torture_comment(tctx, "Notify across increment/decrement of csn\n");
5372 :
5373 0 : smbXcli_conn_set_force_channel_sequence(transport->conn, true);
5374 :
5375 0 : status = torture_smb2_testdir(tree, BASEDIR, &_dh);
5376 0 : CHECK_STATUS(status, NT_STATUS_OK);
5377 0 : dh = &_dh;
5378 :
5379 0 : notify.in.recursive = 0x0000;
5380 0 : notify.in.buffer_size = 0xffff;
5381 0 : notify.in.file.handle = _dh;
5382 0 : notify.in.completion_filter = FILE_NOTIFY_CHANGE_FILE_NAME;
5383 0 : 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 0 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
5390 0 : req = smb2_notify_send(tree, ¬ify);
5391 :
5392 0 : 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 0 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 30000);
5404 0 : status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
5405 0 : CHECK_STATUS(status, NT_STATUS_OK);
5406 :
5407 0 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 60000);
5408 0 : status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
5409 0 : 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 0 : smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
5419 0 : status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
5420 0 : 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 0 : status = smb2_cancel(req);
5432 0 : CHECK_STATUS(status, NT_STATUS_OK);
5433 :
5434 0 : status = smb2_notify_recv(req, mem_ctx, ¬ify);
5435 0 : CHECK_STATUS(status, NT_STATUS_CANCELLED);
5436 :
5437 0 : ret = true;
5438 :
5439 0 : done:
5440 0 : if (dh != NULL) {
5441 0 : smb2_util_close(tree, _dh);
5442 : }
5443 0 : smb2_deltree(tree, BASEDIR);
5444 0 : talloc_free(tree);
5445 0 : talloc_free(mem_ctx);
5446 :
5447 0 : return ret;
5448 : }
5449 :
5450 964 : struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx)
5451 : {
5452 738 : struct torture_suite *suite =
5453 226 : torture_suite_create(ctx, "replay");
5454 :
5455 964 : torture_suite_add_1smb2_test(suite, "replay-commands", test_replay_commands);
5456 964 : torture_suite_add_1smb2_test(suite, "replay-regular", test_replay_regular);
5457 964 : torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock1", test_replay_dhv2_oplock1);
5458 964 : torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2);
5459 964 : torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3);
5460 964 : torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock-lease", test_replay_dhv2_oplock_lease);
5461 964 : torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1", test_replay_dhv2_lease1);
5462 964 : torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2", test_replay_dhv2_lease2);
5463 964 : torture_suite_add_1smb2_test(suite, "replay-dhv2-lease3", test_replay_dhv2_lease3);
5464 964 : torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock", test_replay_dhv2_lease_oplock);
5465 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-close-sane", test_dhv2_pending1n_vs_violation_lease_close_sane);
5466 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-ack-sane", test_dhv2_pending1n_vs_violation_lease_ack_sane);
5467 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-close-windows", test_dhv2_pending1n_vs_violation_lease_close_windows);
5468 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-ack-windows", test_dhv2_pending1n_vs_violation_lease_ack_windows);
5469 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-oplock-sane", test_dhv2_pending1n_vs_oplock_sane);
5470 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-oplock-windows", test_dhv2_pending1n_vs_oplock_windows);
5471 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-lease-sane", test_dhv2_pending1n_vs_lease_sane);
5472 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-lease-windows", test_dhv2_pending1n_vs_lease_windows);
5473 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-oplock-sane", test_dhv2_pending1l_vs_oplock_sane);
5474 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-oplock-windows", test_dhv2_pending1l_vs_oplock_windows);
5475 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-lease-sane", test_dhv2_pending1l_vs_lease_sane);
5476 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-lease-windows", test_dhv2_pending1l_vs_lease_windows);
5477 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-oplock-sane", test_dhv2_pending1o_vs_oplock_sane);
5478 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-oplock-windows", test_dhv2_pending1o_vs_oplock_windows);
5479 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-lease-sane", test_dhv2_pending1o_vs_lease_sane);
5480 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-lease-windows", test_dhv2_pending1o_vs_lease_windows);
5481 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-oplock-sane", test_dhv2_pending2n_vs_oplock_sane);
5482 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-oplock-windows", test_dhv2_pending2n_vs_oplock_windows);
5483 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-lease-sane", test_dhv2_pending2n_vs_lease_sane);
5484 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-lease-windows", test_dhv2_pending2n_vs_lease_windows);
5485 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-oplock-sane", test_dhv2_pending2l_vs_oplock_sane);
5486 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-oplock-windows", test_dhv2_pending2l_vs_oplock_windows);
5487 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-lease-sane", test_dhv2_pending2l_vs_lease_sane);
5488 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-lease-windows", test_dhv2_pending2l_vs_lease_windows);
5489 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-oplock-sane", test_dhv2_pending2o_vs_oplock_sane);
5490 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-oplock-windows", test_dhv2_pending2o_vs_oplock_windows);
5491 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-lease-sane", test_dhv2_pending2o_vs_lease_sane);
5492 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-lease-windows", test_dhv2_pending2o_vs_lease_windows);
5493 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-oplock-sane", test_dhv2_pending3n_vs_oplock_sane);
5494 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-oplock-windows", test_dhv2_pending3n_vs_oplock_windows);
5495 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-lease-sane", test_dhv2_pending3n_vs_lease_sane);
5496 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-lease-windows", test_dhv2_pending3n_vs_lease_windows);
5497 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-oplock-sane", test_dhv2_pending3l_vs_oplock_sane);
5498 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-oplock-windows", test_dhv2_pending3l_vs_oplock_windows);
5499 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-lease-sane", test_dhv2_pending3l_vs_lease_sane);
5500 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-lease-windows", test_dhv2_pending3l_vs_lease_windows);
5501 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-oplock-sane", test_dhv2_pending3o_vs_oplock_sane);
5502 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-oplock-windows", test_dhv2_pending3o_vs_oplock_windows);
5503 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-lease-sane", test_dhv2_pending3o_vs_lease_sane);
5504 964 : torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-lease-windows", test_dhv2_pending3o_vs_lease_windows);
5505 964 : torture_suite_add_1smb2_test(suite, "channel-sequence", test_channel_sequence);
5506 964 : torture_suite_add_1smb2_test(suite, "replay3", test_replay3);
5507 964 : torture_suite_add_1smb2_test(suite, "replay4", test_replay4);
5508 964 : torture_suite_add_1smb2_test(suite, "replay5", test_replay5);
5509 964 : torture_suite_add_1smb2_test(suite, "replay6", test_replay6);
5510 964 : torture_suite_add_1smb2_test(suite, "replay7", test_replay7);
5511 :
5512 964 : suite->description = talloc_strdup(suite, "SMB2 REPLAY tests");
5513 :
5514 964 : return suite;
5515 : }
|