2 Unix SMB/CIFS implementation.
4 test suite for SMB2 replay
6 Copyright (C) Anubhav Rakshit 2014
7 Copyright (C) Stefan Metzmacher 2014
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.
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.
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/>.
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"
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); \
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)); \
54 #define CHECK_CREATED(__io, __created, __attribute) \
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); \
62 #define CHECK_HANDLE(__h1, __h2) \
64 CHECK_VAL((__h1)->data[0], (__h2)->data[0]); \
65 CHECK_VAL((__h1)->data[1], (__h2)->data[1]); \
68 #define __IO_OUT_VAL(__io1, __io2, __m) \
69 CHECK_VAL((__io1)->out.__m, (__io2)->out.__m)
71 #define CHECK_CREATE_OUT(__io1, __io2) \
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]);\
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) { \
105 #define BASEDIR "replaytestdir"
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.
111 static bool test_replay_commands(struct torture_context
*tctx
, struct smb2_tree
*tree
)
115 struct smb2_handle h
;
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];
124 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
125 const char *fname
= BASEDIR
"\\replay_commands.dat";
126 struct smb2_transport
*transport
= tree
->session
->transport
;
128 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
129 torture_skip(tctx
, "SMB 3.X Dialect family required for "
133 torture_reset_break_info(tctx
, &break_info
);
134 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
135 tree
->session
->transport
->oplock
.private_data
= tree
;
137 status
= torture_smb2_testdir(tree
, BASEDIR
, &h
);
138 CHECK_STATUS(status
, NT_STATUS_OK
);
139 smb2_util_close(tree
, h
);
141 smb2cli_session_start_replay(tree
->session
->smbXcli
);
143 torture_comment(tctx
, "Try Commands with Replay Flags Enabled\n");
145 torture_comment(tctx
, "Trying create\n");
146 status
= torture_smb2_testfile(tree
, fname
, &h
);
147 CHECK_STATUS(status
, NT_STATUS_OK
);
148 CHECK_VAL(break_info
.count
, 0);
150 * Wireshark shows that the response has SMB2_FLAGS_REPLAY_OPERATION
151 * flags set. The server should ignore this flag.
154 torture_comment(tctx
, "Trying write\n");
155 status
= smb2_util_write(tree
, h
, buf
, 0, ARRAY_SIZE(buf
));
156 CHECK_STATUS(status
, NT_STATUS_OK
);
158 f
= (struct smb2_flush
) {
161 torture_comment(tctx
, "Trying flush\n");
162 status
= smb2_flush(tree
, &f
);
163 CHECK_STATUS(status
, NT_STATUS_OK
);
165 rd
= (struct smb2_read
) {
171 torture_comment(tctx
, "Trying read\n");
172 status
= smb2_read(tree
, tmp_ctx
, &rd
);
173 CHECK_STATUS(status
, NT_STATUS_OK
);
174 CHECK_VAL(rd
.out
.data
.length
, 10);
176 sfinfo
.generic
.level
= RAW_SFILEINFO_POSITION_INFORMATION
;
177 sfinfo
.position_information
.in
.file
.handle
= h
;
178 sfinfo
.position_information
.in
.position
= 0x1000;
179 torture_comment(tctx
, "Trying setinfo\n");
180 status
= smb2_setinfo_file(tree
, &sfinfo
);
181 CHECK_STATUS(status
, NT_STATUS_OK
);
183 qfinfo
= (union smb_fileinfo
) {
184 .generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
,
185 .generic
.in
.file
.handle
= h
187 torture_comment(tctx
, "Trying getinfo\n");
188 status
= smb2_getinfo_file(tree
, tmp_ctx
, &qfinfo
);
189 CHECK_STATUS(status
, NT_STATUS_OK
);
190 CHECK_VAL(qfinfo
.position_information
.out
.position
, 0x1000);
192 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
199 torture_comment(tctx
, "Trying ioctl\n");
200 status
= smb2_ioctl(tree
, tmp_ctx
, &ioctl
.smb2
);
201 CHECK_STATUS(status
, NT_STATUS_OK
);
203 lck
= (struct smb2_lock
) {
205 .in
.lock_count
= 0x0001,
206 .in
.lock_sequence
= 0x00000000,
209 el
[0].reserved
= 0x00000000;
210 el
[0].flags
= SMB2_LOCK_FLAG_EXCLUSIVE
|
211 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY
;
213 torture_comment(tctx
, "Trying lock\n");
214 el
[0].offset
= 0x0000000000000000;
215 el
[0].length
= 0x0000000000000100;
216 status
= smb2_lock(tree
, &lck
);
217 CHECK_STATUS(status
, NT_STATUS_OK
);
219 lck
.in
.file
.handle
= h
;
220 el
[0].flags
= SMB2_LOCK_FLAG_UNLOCK
;
221 status
= smb2_lock(tree
, &lck
);
222 CHECK_STATUS(status
, NT_STATUS_OK
);
224 CHECK_VAL(break_info
.count
, 0);
226 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
227 smb2_util_close(tree
, h
);
228 smb2_deltree(tree
, BASEDIR
);
230 talloc_free(tmp_ctx
);
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.
240 static bool test_replay_regular(struct torture_context
*tctx
,
241 struct smb2_tree
*tree
)
244 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
245 struct smb2_handle _h
;
246 struct smb2_handle
*h
= NULL
;
247 struct smb2_create io
;
250 const char *fname
= BASEDIR
"\\replay_regular.dat";
251 struct smb2_transport
*transport
= tree
->session
->transport
;
253 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
254 torture_skip(tctx
, "SMB 3.X Dialect family required for "
258 torture_reset_break_info(tctx
, &break_info
);
259 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
260 tree
->session
->transport
->oplock
.private_data
= tree
;
262 smb2_util_unlink(tree
, fname
);
263 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h
);
264 CHECK_STATUS(status
, NT_STATUS_OK
);
265 smb2_util_close(tree
, _h
);
266 CHECK_VAL(break_info
.count
, 0);
268 torture_comment(tctx
, "No replay detection for regular create\n");
270 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
|
275 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,
284 status
= smb2_create(tree
, tctx
, &io
);
285 CHECK_STATUS(status
, NT_STATUS_OK
);
286 CHECK_VAL(break_info
.count
, 0);
287 _h
= io
.out
.file
.handle
;
289 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
291 smb2cli_session_start_replay(tree
->session
->smbXcli
);
292 status
= smb2_create(tree
, tctx
, &io
);
293 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
294 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
295 CHECK_VAL(break_info
.count
, 0);
297 smb2_util_close(tree
, *h
);
299 smb2_util_unlink(tree
, fname
);
302 * Same experiment with different create disposition.
304 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
305 status
= smb2_create(tree
, tctx
, &io
);
306 CHECK_STATUS(status
, NT_STATUS_OK
);
307 CHECK_VAL(break_info
.count
, 0);
308 _h
= io
.out
.file
.handle
;
310 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
312 smb2cli_session_start_replay(tree
->session
->smbXcli
);
313 status
= smb2_create(tree
, tctx
, &io
);
314 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
315 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
316 CHECK_VAL(break_info
.count
, 0);
318 smb2_util_close(tree
, *h
);
320 smb2_util_unlink(tree
, fname
);
323 * Now with more generous share mode.
325 io
.in
.share_access
= smb2_util_share_access("RWD");
326 status
= smb2_create(tree
, tctx
, &io
);
327 CHECK_STATUS(status
, NT_STATUS_OK
);
328 CHECK_VAL(break_info
.count
, 0);
329 _h
= io
.out
.file
.handle
;
331 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
333 smb2cli_session_start_replay(tree
->session
->smbXcli
);
334 status
= smb2_create(tree
, tctx
, &io
);
335 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
336 CHECK_STATUS(status
, NT_STATUS_OK
);
337 CHECK_VAL(break_info
.count
, 0);
341 smb2_util_close(tree
, *h
);
343 smb2_deltree(tree
, BASEDIR
);
346 talloc_free(mem_ctx
);
352 * Test Durability V2 Create Replay Detection on Single Channel.
354 static bool test_replay_dhv2_oplock1(struct torture_context
*tctx
,
355 struct smb2_tree
*tree
)
358 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
359 struct smb2_handle _h
;
360 struct smb2_handle
*h
= NULL
;
361 struct smb2_create io
, ref1
;
362 struct GUID create_guid
= GUID_random();
364 const char *fname
= BASEDIR
"\\replay_dhv2_oplock1.dat";
365 struct smb2_transport
*transport
= tree
->session
->transport
;
366 uint32_t share_capabilities
;
369 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
370 torture_skip(tctx
, "SMB 3.X Dialect family required for "
374 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
375 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
377 torture_reset_break_info(tctx
, &break_info
);
378 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
379 tree
->session
->transport
->oplock
.private_data
= tree
;
381 torture_comment(tctx
, "Replay of DurableHandleReqV2 on Single "
383 smb2_util_unlink(tree
, fname
);
384 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h
);
385 CHECK_STATUS(status
, NT_STATUS_OK
);
386 smb2_util_close(tree
, _h
);
387 CHECK_VAL(break_info
.count
, 0);
389 smb2_oplock_create_share(&io
, fname
,
390 smb2_util_share_access(""),
391 smb2_util_oplock_level("b"));
392 io
.in
.durable_open
= false;
393 io
.in
.durable_open_v2
= true;
394 io
.in
.persistent_open
= false;
395 io
.in
.create_guid
= create_guid
;
396 io
.in
.timeout
= UINT32_MAX
;
398 status
= smb2_create(tree
, mem_ctx
, &io
);
399 CHECK_STATUS(status
, NT_STATUS_OK
);
401 _h
= io
.out
.file
.handle
;
403 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
404 CHECK_VAL(io
.out
.durable_open
, false);
406 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("s"));
407 CHECK_VAL(io
.out
.durable_open_v2
, false);
408 CHECK_VAL(io
.out
.timeout
, 0);
410 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("b"));
411 CHECK_VAL(io
.out
.durable_open_v2
, true);
412 CHECK_VAL(io
.out
.timeout
, 300*1000);
416 * Replay Durable V2 Create on single channel
418 smb2cli_session_start_replay(tree
->session
->smbXcli
);
419 status
= smb2_create(tree
, mem_ctx
, &io
);
420 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
421 CHECK_STATUS(status
, NT_STATUS_OK
);
422 CHECK_CREATE_OUT(&io
, &ref1
);
423 CHECK_VAL(break_info
.count
, 0);
427 smb2_util_close(tree
, *h
);
429 smb2_deltree(tree
, BASEDIR
);
432 talloc_free(mem_ctx
);
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.
444 static bool test_replay_dhv2_oplock2(struct torture_context
*tctx
,
445 struct smb2_tree
*tree
)
448 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
449 struct smb2_handle _h
;
450 struct smb2_handle
*h
= NULL
;
451 struct smb2_create io
, ref1
, ref2
;
452 struct GUID create_guid
= GUID_random();
454 const char *fname
= BASEDIR
"\\replay_dhv2_oplock2.dat";
455 struct smb2_transport
*transport
= tree
->session
->transport
;
456 uint32_t share_capabilities
;
459 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
460 torture_skip(tctx
, "SMB 3.X Dialect family required for "
464 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
465 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
467 torture_reset_break_info(tctx
, &break_info
);
468 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
469 tree
->session
->transport
->oplock
.private_data
= tree
;
471 torture_comment(tctx
, "Replay of DurableHandleReqV2 on Single "
473 smb2_util_unlink(tree
, fname
);
474 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h
);
475 CHECK_STATUS(status
, NT_STATUS_OK
);
476 smb2_util_close(tree
, _h
);
477 CHECK_VAL(break_info
.count
, 0);
479 smb2_oplock_create_share(&io
, fname
,
480 smb2_util_share_access(""),
481 smb2_util_oplock_level("b"));
482 io
.in
.durable_open
= false;
483 io
.in
.durable_open_v2
= true;
484 io
.in
.persistent_open
= false;
485 io
.in
.create_guid
= create_guid
;
486 io
.in
.timeout
= UINT32_MAX
;
488 status
= smb2_create(tree
, mem_ctx
, &io
);
489 CHECK_STATUS(status
, NT_STATUS_OK
);
491 _h
= io
.out
.file
.handle
;
493 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
494 CHECK_VAL(io
.out
.durable_open
, false);
496 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("s"));
497 CHECK_VAL(io
.out
.durable_open_v2
, false);
498 CHECK_VAL(io
.out
.timeout
, 0);
500 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("b"));
501 CHECK_VAL(io
.out
.durable_open_v2
, true);
502 CHECK_VAL(io
.out
.timeout
, 300*1000);
506 * Replay durable v2 create on single channel:
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.
514 smb2_oplock_create_share(&io
, fname
,
515 smb2_util_share_access(""),
516 smb2_util_oplock_level(""));
517 io
.in
.durable_open
= false;
518 io
.in
.durable_open_v2
= true;
519 io
.in
.persistent_open
= false;
520 io
.in
.create_guid
= create_guid
;
521 io
.in
.timeout
= UINT32_MAX
;
524 * Adapt the response to the expected values
527 ref2
.out
.oplock_level
= smb2_util_oplock_level("");
528 ref2
.out
.durable_open_v2
= false;
529 ref2
.out
.timeout
= 0;
530 ref2
.out
.blobs
.num_blobs
= 0;
532 smb2cli_session_start_replay(tree
->session
->smbXcli
);
533 status
= smb2_create(tree
, mem_ctx
, &io
);
534 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
535 CHECK_STATUS(status
, NT_STATUS_OK
);
536 CHECK_CREATE_OUT(&io
, &ref2
);
537 CHECK_VAL(break_info
.count
, 0);
540 * Prove that the open file still has a batch oplock
541 * by breaking it with another open.
543 smb2_oplock_create_share(&io
, fname
,
544 smb2_util_share_access(""),
545 smb2_util_oplock_level("b"));
546 io
.in
.durable_open
= false;
547 io
.in
.durable_open_v2
= true;
548 io
.in
.persistent_open
= false;
549 io
.in
.create_guid
= GUID_random();
550 io
.in
.timeout
= UINT32_MAX
;
551 status
= smb2_create(tree
, mem_ctx
, &io
);
552 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
555 CHECK_VAL(break_info
.count
, 1);
556 CHECK_HANDLE(&break_info
.handle
, &ref1
.out
.file
.handle
);
557 CHECK_VAL(break_info
.level
, smb2_util_oplock_level("s"));
558 torture_reset_break_info(tctx
, &break_info
);
563 smb2_util_close(tree
, *h
);
565 smb2_deltree(tree
, BASEDIR
);
568 talloc_free(mem_ctx
);
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.
578 static bool test_replay_dhv2_oplock3(struct torture_context
*tctx
,
579 struct smb2_tree
*tree
)
582 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
583 struct smb2_handle _h
;
584 struct smb2_handle
*h
= NULL
;
585 struct smb2_create io
, ref1
;
586 struct GUID create_guid
= GUID_random();
588 const char *fname
= BASEDIR
"\\replay_dhv2_oplock3.dat";
589 struct smb2_transport
*transport
= tree
->session
->transport
;
590 uint32_t share_capabilities
;
593 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
594 torture_skip(tctx
, "SMB 3.X Dialect family required for "
598 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
599 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
601 torture_reset_break_info(tctx
, &break_info
);
602 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
603 tree
->session
->transport
->oplock
.private_data
= tree
;
605 torture_comment(tctx
, "Replay of DurableHandleReqV2 on Single "
607 smb2_util_unlink(tree
, fname
);
608 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h
);
609 CHECK_STATUS(status
, NT_STATUS_OK
);
610 smb2_util_close(tree
, _h
);
611 CHECK_VAL(break_info
.count
, 0);
613 smb2_oplock_create_share(&io
, fname
,
614 smb2_util_share_access(""),
615 smb2_util_oplock_level("b"));
616 io
.in
.durable_open
= false;
617 io
.in
.durable_open_v2
= true;
618 io
.in
.persistent_open
= false;
619 io
.in
.create_guid
= create_guid
;
620 io
.in
.timeout
= UINT32_MAX
;
622 status
= smb2_create(tree
, mem_ctx
, &io
);
623 CHECK_STATUS(status
, NT_STATUS_OK
);
625 _h
= io
.out
.file
.handle
;
627 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
628 CHECK_VAL(io
.out
.durable_open
, false);
630 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("s"));
631 CHECK_VAL(io
.out
.durable_open_v2
, false);
632 CHECK_VAL(io
.out
.timeout
, 0);
634 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("b"));
635 CHECK_VAL(io
.out
.durable_open_v2
, true);
636 CHECK_VAL(io
.out
.timeout
, 300*1000);
640 * Replay durable v2 create on single channel:
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
647 smb2_oplock_create_share(&io
, fname
,
648 smb2_util_share_access("RWD"),
649 smb2_util_oplock_level("b"));
650 io
.in
.durable_open
= false;
651 io
.in
.durable_open_v2
= true;
652 io
.in
.persistent_open
= false;
653 io
.in
.create_guid
= create_guid
;
654 io
.in
.timeout
= UINT32_MAX
;
656 smb2cli_session_start_replay(tree
->session
->smbXcli
);
657 status
= smb2_create(tree
, mem_ctx
, &io
);
658 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
659 CHECK_STATUS(status
, NT_STATUS_OK
);
660 CHECK_CREATE_OUT(&io
, &ref1
);
661 CHECK_VAL(break_info
.count
, 0);
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.
668 smb2_oplock_create_share(&io
, fname
,
669 smb2_util_share_access(""),
670 smb2_util_oplock_level("b"));
671 io
.in
.durable_open
= false;
672 io
.in
.durable_open_v2
= true;
673 io
.in
.persistent_open
= false;
674 io
.in
.create_guid
= GUID_random();
675 io
.in
.timeout
= UINT32_MAX
;
676 status
= smb2_create(tree
, mem_ctx
, &io
);
677 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
680 CHECK_VAL(break_info
.count
, 1);
681 CHECK_HANDLE(&break_info
.handle
, &ref1
.out
.file
.handle
);
682 CHECK_VAL(break_info
.level
, smb2_util_oplock_level("s"));
683 torture_reset_break_info(tctx
, &break_info
);
688 smb2_util_close(tree
, *h
);
690 smb2_deltree(tree
, BASEDIR
);
693 talloc_free(mem_ctx
);
699 * Test Durability V2 Create Replay Detection on Single Channel.
700 * Create with an oplock, and replay with a lease.
702 static bool test_replay_dhv2_oplock_lease(struct torture_context
*tctx
,
703 struct smb2_tree
*tree
)
706 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
707 struct smb2_handle _h
;
708 struct smb2_handle
*h
= NULL
;
709 struct smb2_create io
;
710 struct GUID create_guid
= GUID_random();
712 const char *fname
= BASEDIR
"\\replay_dhv2_oplock1.dat";
713 struct smb2_transport
*transport
= tree
->session
->transport
;
714 uint32_t share_capabilities
;
716 uint32_t server_capabilities
;
717 struct smb2_lease ls
;
720 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
721 torture_skip(tctx
, "SMB 3.X Dialect family required for "
725 server_capabilities
= smb2cli_conn_server_capabilities(transport
->conn
);
726 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
727 torture_skip(tctx
, "leases are not supported");
730 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
731 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
733 torture_reset_break_info(tctx
, &break_info
);
734 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
735 tree
->session
->transport
->oplock
.private_data
= tree
;
737 torture_comment(tctx
, "Replay of DurableHandleReqV2 on Single "
739 smb2_util_unlink(tree
, fname
);
740 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h
);
741 CHECK_STATUS(status
, NT_STATUS_OK
);
742 smb2_util_close(tree
, _h
);
743 CHECK_VAL(break_info
.count
, 0);
745 smb2_oplock_create_share(&io
, fname
,
746 smb2_util_share_access(""),
747 smb2_util_oplock_level("b"));
748 io
.in
.durable_open
= false;
749 io
.in
.durable_open_v2
= true;
750 io
.in
.persistent_open
= false;
751 io
.in
.create_guid
= create_guid
;
752 io
.in
.timeout
= UINT32_MAX
;
754 status
= smb2_create(tree
, mem_ctx
, &io
);
755 CHECK_STATUS(status
, NT_STATUS_OK
);
756 _h
= io
.out
.file
.handle
;
758 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
759 CHECK_VAL(io
.out
.durable_open
, false);
761 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("s"));
762 CHECK_VAL(io
.out
.durable_open_v2
, false);
763 CHECK_VAL(io
.out
.timeout
, 0);
765 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("b"));
766 CHECK_VAL(io
.out
.durable_open_v2
, true);
767 CHECK_VAL(io
.out
.timeout
, 300*1000);
771 * Replay Durable V2 Create on single channel
772 * but replay it with a lease instead of an oplock.
774 lease_key
= random();
775 smb2_lease_create(&io
, &ls
, false /* dir */, fname
,
776 lease_key
, smb2_util_lease_state("RH"));
777 io
.in
.durable_open
= false;
778 io
.in
.durable_open_v2
= true;
779 io
.in
.persistent_open
= false;
780 io
.in
.create_guid
= create_guid
;
781 io
.in
.timeout
= UINT32_MAX
;
783 smb2cli_session_start_replay(tree
->session
->smbXcli
);
784 status
= smb2_create(tree
, mem_ctx
, &io
);
785 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
786 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
790 smb2_util_close(tree
, *h
);
792 smb2_deltree(tree
, BASEDIR
);
795 talloc_free(mem_ctx
);
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
809 static bool test_replay_dhv2_lease1(struct torture_context
*tctx
,
810 struct smb2_tree
*tree
)
813 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
814 struct smb2_handle _h1
;
815 struct smb2_handle
*h1
= NULL
;
816 struct smb2_handle _h2
;
817 struct smb2_handle
*h2
= NULL
;
818 struct smb2_create io1
, io2
, ref1
;
819 struct GUID create_guid
= GUID_random();
821 const char *fname
= BASEDIR
"\\replay2_lease1.dat";
822 struct smb2_transport
*transport
= tree
->session
->transport
;
823 uint32_t share_capabilities
;
825 uint32_t server_capabilities
;
826 struct smb2_lease ls1
, ls2
;
829 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
830 torture_skip(tctx
, "SMB 3.X Dialect family required for "
834 server_capabilities
= smb2cli_conn_server_capabilities(transport
->conn
);
835 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
836 torture_skip(tctx
, "leases are not supported");
839 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
840 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
842 torture_reset_break_info(tctx
, &break_info
);
843 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
844 tree
->session
->transport
->oplock
.private_data
= tree
;
846 torture_comment(tctx
, "Replay of DurableHandleReqV2 with Lease "
847 "on Single Channel\n");
848 smb2_util_unlink(tree
, fname
);
849 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h1
);
850 CHECK_STATUS(status
, NT_STATUS_OK
);
851 smb2_util_close(tree
, _h1
);
852 CHECK_VAL(break_info
.count
, 0);
854 lease_key
= random();
856 smb2_lease_create(&io1
, &ls1
, false /* dir */, fname
,
857 lease_key
, smb2_util_lease_state("RH"));
858 io1
.in
.durable_open
= false;
859 io1
.in
.durable_open_v2
= true;
860 io1
.in
.persistent_open
= false;
861 io1
.in
.create_guid
= create_guid
;
862 io1
.in
.timeout
= UINT32_MAX
;
864 status
= smb2_create(tree
, mem_ctx
, &io1
);
865 CHECK_STATUS(status
, NT_STATUS_OK
);
867 _h1
= io1
.out
.file
.handle
;
869 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
870 CHECK_VAL(io1
.out
.durable_open
, false);
871 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_LEASE
);
872 CHECK_VAL(io1
.out
.lease_response
.lease_key
.data
[0], lease_key
);
873 CHECK_VAL(io1
.out
.lease_response
.lease_key
.data
[1], ~lease_key
);
875 CHECK_VAL(io1
.out
.lease_response
.lease_state
,
876 smb2_util_lease_state("R"));
877 CHECK_VAL(io1
.out
.durable_open_v2
, false);
878 CHECK_VAL(io1
.out
.timeout
, 0);
880 CHECK_VAL(io1
.out
.lease_response
.lease_state
,
881 smb2_util_lease_state("RH"));
882 CHECK_VAL(io1
.out
.durable_open_v2
, true);
883 CHECK_VAL(io1
.out
.timeout
, 300*1000);
887 * Upgrade the lease to RWH
889 smb2_lease_create(&io2
, &ls2
, false /* dir */, fname
,
890 lease_key
, smb2_util_lease_state("RHW"));
891 io2
.in
.durable_open
= false;
892 io2
.in
.durable_open_v2
= true;
893 io2
.in
.persistent_open
= false;
894 io2
.in
.create_guid
= GUID_random(); /* new guid... */
895 io2
.in
.timeout
= UINT32_MAX
;
897 status
= smb2_create(tree
, mem_ctx
, &io2
);
898 CHECK_STATUS(status
, NT_STATUS_OK
);
899 _h2
= io2
.out
.file
.handle
;
903 * Replay Durable V2 Create on single channel.
904 * We get the io from open #1 but with the
908 /* adapt expected lease in response */
910 ref1
.out
.lease_response
.lease_state
=
911 smb2_util_lease_state("RHW");
914 smb2cli_session_start_replay(tree
->session
->smbXcli
);
915 status
= smb2_create(tree
, mem_ctx
, &io1
);
916 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
917 CHECK_STATUS(status
, NT_STATUS_OK
);
918 CHECK_CREATE_OUT(&io1
, &ref1
);
919 CHECK_VAL(break_info
.count
, 0);
922 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
925 smb2_util_close(tree
, *h1
);
928 smb2_util_close(tree
, *h2
);
930 smb2_deltree(tree
, BASEDIR
);
933 talloc_free(mem_ctx
);
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
949 static bool test_replay_dhv2_lease2(struct torture_context
*tctx
,
950 struct smb2_tree
*tree
)
953 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
954 struct smb2_handle _h1
;
955 struct smb2_handle
*h1
= NULL
;
956 struct smb2_handle _h2
;
957 struct smb2_handle
*h2
= NULL
;
958 struct smb2_create io1
, io2
, ref1
;
959 struct GUID create_guid
= GUID_random();
961 const char *fname
= BASEDIR
"\\replay2_lease2.dat";
962 struct smb2_transport
*transport
= tree
->session
->transport
;
963 uint32_t share_capabilities
;
965 uint32_t server_capabilities
;
966 struct smb2_lease ls1
, ls2
;
969 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
970 torture_skip(tctx
, "SMB 3.X Dialect family required for "
974 server_capabilities
= smb2cli_conn_server_capabilities(transport
->conn
);
975 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
976 torture_skip(tctx
, "leases are not supported");
979 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
980 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
982 torture_reset_break_info(tctx
, &break_info
);
983 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
984 tree
->session
->transport
->oplock
.private_data
= tree
;
986 torture_comment(tctx
, "Replay of DurableHandleReqV2 with Lease "
987 "on Single Channel\n");
988 smb2_util_unlink(tree
, fname
);
989 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h1
);
990 CHECK_STATUS(status
, NT_STATUS_OK
);
991 smb2_util_close(tree
, _h1
);
992 CHECK_VAL(break_info
.count
, 0);
994 lease_key
= random();
996 smb2_lease_create(&io1
, &ls1
, false /* dir */, fname
,
997 lease_key
, smb2_util_lease_state("RH"));
998 io1
.in
.durable_open
= false;
999 io1
.in
.durable_open_v2
= true;
1000 io1
.in
.persistent_open
= false;
1001 io1
.in
.create_guid
= create_guid
;
1002 io1
.in
.timeout
= UINT32_MAX
;
1004 status
= smb2_create(tree
, mem_ctx
, &io1
);
1005 CHECK_STATUS(status
, NT_STATUS_OK
);
1006 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
1007 CHECK_VAL(io1
.out
.durable_open
, false);
1008 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_LEASE
);
1009 CHECK_VAL(io1
.out
.lease_response
.lease_key
.data
[0], lease_key
);
1010 CHECK_VAL(io1
.out
.lease_response
.lease_key
.data
[1], ~lease_key
);
1012 CHECK_VAL(io1
.out
.lease_response
.lease_state
,
1013 smb2_util_lease_state("R"));
1014 CHECK_VAL(io1
.out
.durable_open_v2
, false);
1015 CHECK_VAL(io1
.out
.timeout
, 0);
1017 CHECK_VAL(io1
.out
.lease_response
.lease_state
,
1018 smb2_util_lease_state("RH"));
1019 CHECK_VAL(io1
.out
.durable_open_v2
, true);
1020 CHECK_VAL(io1
.out
.timeout
, 300*1000);
1023 _h1
= io1
.out
.file
.handle
;
1027 * Upgrade the lease to RWH
1029 smb2_lease_create(&io2
, &ls2
, false /* dir */, fname
,
1030 lease_key
, smb2_util_lease_state("RHW"));
1031 io2
.in
.durable_open
= false;
1032 io2
.in
.durable_open_v2
= true;
1033 io2
.in
.persistent_open
= false;
1034 io2
.in
.create_guid
= GUID_random(); /* new guid... */
1035 io2
.in
.timeout
= UINT32_MAX
;
1037 status
= smb2_create(tree
, mem_ctx
, &io2
);
1038 CHECK_STATUS(status
, NT_STATUS_OK
);
1039 _h2
= io2
.out
.file
.handle
;
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
1050 /* adapt the expected response */
1052 ref1
.out
.lease_response
.lease_state
=
1053 smb2_util_lease_state("RHW");
1056 smb2_lease_create(&io1
, &ls1
, false /* dir */, fname
,
1057 lease_key
, smb2_util_lease_state("R"));
1058 io1
.in
.durable_open
= false;
1059 io1
.in
.durable_open_v2
= true;
1060 io1
.in
.persistent_open
= false;
1061 io1
.in
.create_guid
= create_guid
;
1062 io1
.in
.timeout
= UINT32_MAX
;
1064 smb2cli_session_start_replay(tree
->session
->smbXcli
);
1065 status
= smb2_create(tree
, mem_ctx
, &io1
);
1066 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
1067 CHECK_STATUS(status
, NT_STATUS_OK
);
1068 CHECK_CREATE_OUT(&io1
, &ref1
);
1069 CHECK_VAL(break_info
.count
, 0);
1072 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
1075 smb2_util_close(tree
, *h1
);
1078 smb2_util_close(tree
, *h2
);
1080 smb2_deltree(tree
, BASEDIR
);
1083 talloc_free(mem_ctx
);
1089 * Test durability v2 create replay detection on single channel.
1090 * create with a lease, and replay with a different lease key
1092 static bool test_replay_dhv2_lease3(struct torture_context
*tctx
,
1093 struct smb2_tree
*tree
)
1096 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
1097 struct smb2_handle _h1
;
1098 struct smb2_handle
*h1
= NULL
;
1099 struct smb2_handle _h2
;
1100 struct smb2_handle
*h2
= NULL
;
1101 struct smb2_create io1
, io2
;
1102 struct GUID create_guid
= GUID_random();
1104 const char *fname
= BASEDIR
"\\replay2_lease2.dat";
1105 struct smb2_transport
*transport
= tree
->session
->transport
;
1106 uint32_t share_capabilities
;
1108 uint32_t server_capabilities
;
1109 struct smb2_lease ls1
, ls2
;
1112 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
1113 torture_skip(tctx
, "SMB 3.X Dialect family required for "
1117 server_capabilities
= smb2cli_conn_server_capabilities(transport
->conn
);
1118 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
1119 torture_skip(tctx
, "leases are not supported");
1122 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
1123 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
1125 torture_reset_break_info(tctx
, &break_info
);
1126 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
1127 tree
->session
->transport
->oplock
.private_data
= tree
;
1129 torture_comment(tctx
, "Replay of DurableHandleReqV2 with Lease "
1130 "on Single Channel\n");
1131 smb2_util_unlink(tree
, fname
);
1132 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h1
);
1133 CHECK_STATUS(status
, NT_STATUS_OK
);
1134 smb2_util_close(tree
, _h1
);
1135 CHECK_VAL(break_info
.count
, 0);
1137 lease_key
= random();
1139 smb2_lease_create(&io1
, &ls1
, false /* dir */, fname
,
1140 lease_key
, smb2_util_lease_state("RH"));
1141 io1
.in
.durable_open
= false;
1142 io1
.in
.durable_open_v2
= true;
1143 io1
.in
.persistent_open
= false;
1144 io1
.in
.create_guid
= create_guid
;
1145 io1
.in
.timeout
= UINT32_MAX
;
1147 status
= smb2_create(tree
, mem_ctx
, &io1
);
1148 CHECK_STATUS(status
, NT_STATUS_OK
);
1149 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
1150 CHECK_VAL(io1
.out
.durable_open
, false);
1151 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_LEASE
);
1152 CHECK_VAL(io1
.out
.lease_response
.lease_key
.data
[0], lease_key
);
1153 CHECK_VAL(io1
.out
.lease_response
.lease_key
.data
[1], ~lease_key
);
1155 CHECK_VAL(io1
.out
.lease_response
.lease_state
,
1156 smb2_util_lease_state("R"));
1157 CHECK_VAL(io1
.out
.durable_open_v2
, false);
1158 CHECK_VAL(io1
.out
.timeout
, 0);
1160 CHECK_VAL(io1
.out
.lease_response
.lease_state
,
1161 smb2_util_lease_state("RH"));
1162 CHECK_VAL(io1
.out
.durable_open_v2
, true);
1163 CHECK_VAL(io1
.out
.timeout
, 300*1000);
1165 _h1
= io1
.out
.file
.handle
;
1169 * Upgrade the lease to RWH
1171 smb2_lease_create(&io2
, &ls2
, false /* dir */, fname
,
1172 lease_key
, smb2_util_lease_state("RHW"));
1173 io2
.in
.durable_open
= false;
1174 io2
.in
.durable_open_v2
= true;
1175 io2
.in
.persistent_open
= false;
1176 io2
.in
.create_guid
= GUID_random(); /* new guid... */
1177 io2
.in
.timeout
= UINT32_MAX
;
1179 status
= smb2_create(tree
, mem_ctx
, &io2
);
1180 CHECK_STATUS(status
, NT_STATUS_OK
);
1181 _h2
= io2
.out
.file
.handle
;
1185 * Replay Durable V2 Create on single channel.
1186 * use a different lease key.
1189 smb2_lease_create(&io1
, &ls1
, false /* dir */, fname
,
1190 random() /* lease key */,
1191 smb2_util_lease_state("RH"));
1192 io1
.in
.durable_open
= false;
1193 io1
.in
.durable_open_v2
= true;
1194 io1
.in
.persistent_open
= false;
1195 io1
.in
.create_guid
= create_guid
;
1196 io1
.in
.timeout
= UINT32_MAX
;
1198 smb2cli_session_start_replay(tree
->session
->smbXcli
);
1199 status
= smb2_create(tree
, mem_ctx
, &io1
);
1200 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
1201 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1204 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
1207 smb2_util_close(tree
, *h1
);
1210 smb2_util_close(tree
, *h2
);
1212 smb2_deltree(tree
, BASEDIR
);
1215 talloc_free(mem_ctx
);
1221 * Test durability v2 create replay detection on single channel.
1222 * Do the original create with a lease, and do the replay
1225 static bool test_replay_dhv2_lease_oplock(struct torture_context
*tctx
,
1226 struct smb2_tree
*tree
)
1229 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
1230 struct smb2_handle _h1
;
1231 struct smb2_handle
*h1
= NULL
;
1232 struct smb2_handle _h2
;
1233 struct smb2_handle
*h2
= NULL
;
1234 struct smb2_create io1
, io2
, ref1
;
1235 struct GUID create_guid
= GUID_random();
1237 const char *fname
= BASEDIR
"\\replay2_lease1.dat";
1238 struct smb2_transport
*transport
= tree
->session
->transport
;
1239 uint32_t share_capabilities
;
1241 uint32_t server_capabilities
;
1242 struct smb2_lease ls1
, ls2
;
1245 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
1246 torture_skip(tctx
, "SMB 3.X Dialect family required for "
1250 server_capabilities
= smb2cli_conn_server_capabilities(transport
->conn
);
1251 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
1252 torture_skip(tctx
, "leases are not supported");
1255 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
1256 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
1258 torture_reset_break_info(tctx
, &break_info
);
1259 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
1260 tree
->session
->transport
->oplock
.private_data
= tree
;
1262 torture_comment(tctx
, "Replay of DurableHandleReqV2 with Lease "
1263 "on Single Channel\n");
1264 smb2_util_unlink(tree
, fname
);
1265 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h1
);
1266 CHECK_STATUS(status
, NT_STATUS_OK
);
1267 smb2_util_close(tree
, _h1
);
1268 CHECK_VAL(break_info
.count
, 0);
1270 lease_key
= random();
1272 smb2_lease_create(&io1
, &ls1
, false /* dir */, fname
,
1273 lease_key
, smb2_util_lease_state("RH"));
1274 io1
.in
.durable_open
= false;
1275 io1
.in
.durable_open_v2
= true;
1276 io1
.in
.persistent_open
= false;
1277 io1
.in
.create_guid
= create_guid
;
1278 io1
.in
.timeout
= UINT32_MAX
;
1280 status
= smb2_create(tree
, mem_ctx
, &io1
);
1281 CHECK_STATUS(status
, NT_STATUS_OK
);
1283 _h1
= io1
.out
.file
.handle
;
1285 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
1286 CHECK_VAL(io1
.out
.durable_open
, false);
1287 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_LEASE
);
1288 CHECK_VAL(io1
.out
.lease_response
.lease_key
.data
[0], lease_key
);
1289 CHECK_VAL(io1
.out
.lease_response
.lease_key
.data
[1], ~lease_key
);
1291 CHECK_VAL(io1
.out
.lease_response
.lease_state
,
1292 smb2_util_lease_state("R"));
1293 CHECK_VAL(io1
.out
.durable_open_v2
, false);
1294 CHECK_VAL(io1
.out
.timeout
, 0);
1296 CHECK_VAL(io1
.out
.lease_response
.lease_state
,
1297 smb2_util_lease_state("RH"));
1298 CHECK_VAL(io1
.out
.durable_open_v2
, true);
1299 CHECK_VAL(io1
.out
.timeout
, 300*1000);
1303 * Upgrade the lease to RWH
1305 smb2_lease_create(&io2
, &ls2
, false /* dir */, fname
,
1306 lease_key
, smb2_util_lease_state("RHW"));
1307 io2
.in
.durable_open
= false;
1308 io2
.in
.durable_open_v2
= true;
1309 io2
.in
.persistent_open
= false;
1310 io2
.in
.create_guid
= GUID_random(); /* new guid... */
1311 io2
.in
.timeout
= UINT32_MAX
;
1313 status
= smb2_create(tree
, mem_ctx
, &io2
);
1314 CHECK_STATUS(status
, NT_STATUS_OK
);
1315 _h2
= io2
.out
.file
.handle
;
1319 * Replay Durable V2 Create on single channel.
1320 * We get the io from open #1 but with the
1324 smb2_oplock_create_share(&io2
, fname
,
1325 smb2_util_share_access(""),
1326 smb2_util_oplock_level("b"));
1327 io2
.in
.durable_open
= false;
1328 io2
.in
.durable_open_v2
= true;
1329 io2
.in
.persistent_open
= false;
1330 io2
.in
.create_guid
= create_guid
;
1331 io2
.in
.timeout
= UINT32_MAX
;
1333 /* adapt expected lease in response */
1335 ref1
.out
.lease_response
.lease_state
=
1336 smb2_util_lease_state("RHW");
1339 smb2cli_session_start_replay(tree
->session
->smbXcli
);
1340 status
= smb2_create(tree
, mem_ctx
, &io1
);
1341 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
1342 CHECK_STATUS(status
, NT_STATUS_OK
);
1343 CHECK_CREATE_OUT(&io1
, &ref1
);
1344 CHECK_VAL(break_info
.count
, 0);
1347 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
1350 smb2_util_close(tree
, *h1
);
1353 smb2_util_close(tree
, *h2
);
1355 smb2_deltree(tree
, BASEDIR
);
1358 talloc_free(mem_ctx
);
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.
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.
1378 * While another client holds a batch oplock or
1379 * RWH lease. (client1_level => LEASE or BATCH).
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).
1385 * Windows doesn't detect replays in this case and
1386 * always result in NT_STATUS_SHARING_VIOLATION.
1388 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1390 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
,
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
)
1402 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
1403 struct smb2_handle _h1
;
1404 struct smb2_handle
*h1
= NULL
;
1405 struct smb2_handle
*h2f
= NULL
;
1406 struct smb2_handle _h21
;
1407 struct smb2_handle
*h21
= NULL
;
1408 struct smb2_handle _h23
;
1409 struct smb2_handle
*h23
= NULL
;
1410 struct smb2_handle _h24
;
1411 struct smb2_handle
*h24
= NULL
;
1412 struct smb2_create io1
, io21
, io22
, io23
, io24
;
1413 struct GUID create_guid1
= GUID_random();
1414 struct GUID create_guid2
= GUID_random();
1415 struct smb2_request
*req21
= NULL
;
1416 struct smb2_request
*req22
= NULL
;
1419 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 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 uint16_t lease_epoch2
= 0;
1431 struct smb2_transport
*transport2
= tree2
->session
->transport
;
1432 int request_timeout2
= transport2
->options
.request_timeout
;
1433 struct smb2_session
*session2
= tree2
->session
;
1434 const char *hold_name
= NULL
;
1436 switch (client1_level
) {
1437 case SMB2_OPLOCK_LEVEL_LEASE
:
1438 hold_name
= "RWH Lease";
1440 case SMB2_OPLOCK_LEVEL_BATCH
:
1441 hold_name
= "BATCH Oplock";
1444 smb_panic(__location__
);
1448 if (smbXcli_conn_protocol(transport1
->conn
) < PROTOCOL_SMB3_00
) {
1449 torture_skip(tctx
, "SMB 3.X Dialect family required for "
1453 server_capabilities
= smb2cli_conn_server_capabilities(transport1
->conn
);
1454 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
1455 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
||
1456 client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1457 torture_skip(tctx
, "leases are not supported");
1461 share_capabilities
= smb2cli_tcon_capabilities(tree1
->smbXcli
);
1462 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
1464 torture_skip(tctx
, talloc_asprintf(tctx
,
1465 "%s not supported on SCALEOUT share",
1469 /* Add some random component to the file name. */
1470 snprintf(fname
, sizeof(fname
), "%s\\%s_%s.dat",
1471 BASEDIR
, testname
, generate_random_str(tctx
, 8));
1473 torture_reset_break_info(tctx
, &break_info
);
1474 break_info
.oplock_skip_ack
= true;
1475 ZERO_STRUCT(op_ack1
);
1476 torture_reset_lease_break_info(tctx
, &lease_break_info
);
1477 lease_break_info
.lease_skip_ack
= true;
1478 ZERO_STRUCT(lb_ack1
);
1479 transport1
->oplock
.handler
= torture_oplock_ack_handler
;
1480 transport1
->oplock
.private_data
= tree1
;
1481 transport1
->lease
.handler
= torture_lease_handler
;
1482 transport1
->lease
.private_data
= tree1
;
1483 smb2_keepalive(transport1
);
1484 transport2
->oplock
.handler
= torture_oplock_ack_handler
;
1485 transport2
->oplock
.private_data
= tree2
;
1486 transport2
->lease
.handler
= torture_lease_handler
;
1487 transport2
->lease
.private_data
= tree2
;
1488 smb2_keepalive(transport2
);
1490 smb2_util_unlink(tree1
, fname
);
1491 status
= torture_smb2_testdir(tree1
, BASEDIR
, &_h1
);
1492 CHECK_STATUS(status
, NT_STATUS_OK
);
1493 smb2_util_close(tree1
, _h1
);
1494 CHECK_VAL(break_info
.count
, 0);
1496 lease_key1
= random();
1497 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1498 smb2_lease_v2_create(&io1
, &ls1
, false /* dir */, fname
,
1499 lease_key1
, NULL
, smb2_util_lease_state("RWH"), lease_epoch1
++);
1501 smb2_oplock_create(&io1
, fname
, SMB2_OPLOCK_LEVEL_BATCH
);
1503 io1
.in
.share_access
= 0;
1504 io1
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1505 io1
.in
.durable_open
= false;
1506 io1
.in
.durable_open_v2
= true;
1507 io1
.in
.persistent_open
= false;
1508 io1
.in
.create_guid
= create_guid1
;
1509 io1
.in
.timeout
= UINT32_MAX
;
1511 status
= smb2_create(tree1
, mem_ctx
, &io1
);
1512 CHECK_STATUS(status
, NT_STATUS_OK
);
1513 _h1
= io1
.out
.file
.handle
;
1515 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
1516 CHECK_VAL(io1
.out
.durable_open
, false);
1517 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1518 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_LEASE
);
1519 CHECK_VAL(io1
.out
.lease_response_v2
.lease_key
.data
[0], lease_key1
);
1520 CHECK_VAL(io1
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key1
);
1521 CHECK_VAL(io1
.out
.lease_response_v2
.lease_epoch
, lease_epoch1
);
1522 CHECK_VAL(io1
.out
.lease_response_v2
.lease_state
,
1523 smb2_util_lease_state("RWH"));
1525 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_BATCH
);
1527 CHECK_VAL(io1
.out
.durable_open_v2
, true);
1528 CHECK_VAL(io1
.out
.timeout
, 300*1000);
1530 lease_key2
= random();
1531 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1532 smb2_lease_v2_create(&io21
, &ls2
, false /* dir */, fname
,
1533 lease_key2
, NULL
, smb2_util_lease_state("RWH"), lease_epoch2
++);
1535 smb2_oplock_create(&io21
, fname
, client2_level
);
1537 io21
.in
.share_access
= 0;
1538 io21
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1539 io21
.in
.desired_access
= SEC_RIGHTS_FILE_READ
;
1540 io21
.in
.durable_open
= false;
1541 io21
.in
.durable_open_v2
= true;
1542 io21
.in
.persistent_open
= false;
1543 io21
.in
.create_guid
= create_guid2
;
1544 io21
.in
.timeout
= UINT32_MAX
;
1545 io24
= io23
= io22
= io21
;
1547 req21
= smb2_create_send(tree2
, &io21
);
1548 torture_assert(tctx
, req21
!= NULL
, "req21");
1550 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1551 const struct smb2_lease_break
*lb
=
1552 &lease_break_info
.lease_break
;
1553 const struct smb2_lease
*l
= &lb
->current_lease
;
1554 const struct smb2_lease_key
*k
= &l
->lease_key
;
1556 torture_wait_for_lease_break(tctx
);
1557 CHECK_VAL(break_info
.count
, 0);
1558 CHECK_VAL(lease_break_info
.count
, 1);
1560 torture_assert(tctx
,
1561 lease_break_info
.lease_transport
== transport1
,
1562 "expect lease break on transport1\n");
1563 CHECK_VAL(k
->data
[0], lease_key1
);
1564 CHECK_VAL(k
->data
[1], ~lease_key1
);
1566 * With share none the handle lease
1569 CHECK_VAL(lb
->new_lease_state
,
1570 smb2_util_lease_state("RW"));
1571 CHECK_VAL(lb
->break_flags
,
1572 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED
);
1573 CHECK_VAL(lb
->new_epoch
, lease_epoch1
+1);
1576 lb_ack1
.in
.lease
.lease_key
= lb
->current_lease
.lease_key
;
1577 lb_ack1
.in
.lease
.lease_state
= lb
->new_lease_state
;
1579 torture_wait_for_oplock_break(tctx
);
1580 CHECK_VAL(break_info
.count
, 1);
1581 CHECK_VAL(lease_break_info
.count
, 0);
1583 torture_assert(tctx
,
1584 break_info
.received_transport
== transport1
,
1585 "expect oplock break on transport1\n");
1586 CHECK_VAL(break_info
.handle
.data
[0], _h1
.data
[0]);
1587 CHECK_VAL(break_info
.handle
.data
[1], _h1
.data
[1]);
1588 CHECK_VAL(break_info
.level
, SMB2_OPLOCK_LEVEL_II
);
1590 op_ack1
.in
= break_info
.br
.in
;
1593 torture_reset_break_info(tctx
, &break_info
);
1594 break_info
.oplock_skip_ack
= true;
1595 torture_reset_lease_break_info(tctx
, &lease_break_info
);
1596 lease_break_info
.lease_skip_ack
= true;
1598 WAIT_FOR_ASYNC_RESPONSE(tctx
, req21
);
1600 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1601 torture_wait_for_lease_break(tctx
);
1603 torture_wait_for_oplock_break(tctx
);
1605 CHECK_VAL(break_info
.count
, 0);
1606 CHECK_VAL(lease_break_info
.count
, 0);
1608 if (NT_STATUS_EQUAL(replay22_reject_status
, NT_STATUS_SHARING_VIOLATION
)) {
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.
1616 torture_comment(tctx
, "Starting ASYNC Replay req22 expecting %s\n",
1617 nt_errstr(replay22_reject_status
));
1618 smb2cli_session_start_replay(session2
->smbXcli
);
1619 transport2
->options
.request_timeout
= 15;
1620 req22
= smb2_create_send(tree2
, &io22
);
1621 torture_assert(tctx
, req22
!= NULL
, "req22");
1622 transport2
->options
.request_timeout
= request_timeout2
;
1623 smb2cli_session_stop_replay(session2
->smbXcli
);
1625 WAIT_FOR_ASYNC_RESPONSE(tctx
, req22
);
1627 torture_comment(tctx
, "SYNC Replay io22 expecting %s\n",
1628 nt_errstr(replay22_reject_status
));
1629 smb2cli_session_start_replay(session2
->smbXcli
);
1630 transport2
->options
.request_timeout
= 5;
1631 status
= smb2_create(tree2
, tctx
, &io22
);
1632 CHECK_STATUS(status
, replay22_reject_status
);
1633 transport2
->options
.request_timeout
= request_timeout2
;
1634 smb2cli_session_stop_replay(session2
->smbXcli
);
1638 * We don't expect any action for 35 seconds
1640 * But we sleep just 5 seconds before we
1643 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1644 torture_wait_for_lease_break(tctx
);
1645 torture_wait_for_lease_break(tctx
);
1646 torture_wait_for_lease_break(tctx
);
1647 torture_wait_for_lease_break(tctx
);
1648 torture_wait_for_lease_break(tctx
);
1649 CHECK_VAL(break_info
.count
, 0);
1650 CHECK_VAL(lease_break_info
.count
, 0);
1652 if (release_op
== SMB2_OP_CLOSE
) {
1653 torture_comment(tctx
, "Closing h1\n");
1654 smb2_util_close(tree1
, _h1
);
1657 torture_comment(tctx
, "Acking lease_key1\n");
1658 status
= smb2_lease_break_ack(tree1
, &lb_ack1
);
1659 CHECK_STATUS(status
, NT_STATUS_OK
);
1660 CHECK_VAL(lb_ack1
.out
.lease
.lease_flags
, 0);
1661 CHECK_VAL(lb_ack1
.out
.lease
.lease_state
, lb_ack1
.in
.lease
.lease_state
);
1662 CHECK_VAL(lb_ack1
.out
.lease
.lease_key
.data
[0], lease_key1
);
1663 CHECK_VAL(lb_ack1
.out
.lease
.lease_key
.data
[1], ~lease_key1
);
1664 CHECK_VAL(lb_ack1
.out
.lease
.lease_duration
, 0);
1667 torture_wait_for_oplock_break(tctx
);
1668 torture_wait_for_oplock_break(tctx
);
1669 torture_wait_for_oplock_break(tctx
);
1670 torture_wait_for_oplock_break(tctx
);
1671 torture_wait_for_oplock_break(tctx
);
1672 CHECK_VAL(break_info
.count
, 0);
1673 CHECK_VAL(lease_break_info
.count
, 0);
1675 if (release_op
== SMB2_OP_CLOSE
) {
1676 torture_comment(tctx
, "Closing h1\n");
1677 smb2_util_close(tree1
, _h1
);
1680 torture_comment(tctx
, "Acking break h1\n");
1681 status
= smb2_break(tree1
, &op_ack1
);
1682 CHECK_STATUS(status
, NT_STATUS_OK
);
1683 CHECK_VAL(op_ack1
.out
.oplock_level
, op_ack1
.in
.oplock_level
);
1687 torture_comment(tctx
, "Checking req21 expecting %s\n",
1688 nt_errstr(orig21_reject_status
));
1689 status
= smb2_create_recv(req21
, tctx
, &io21
);
1690 CHECK_STATUS(status
, orig21_reject_status
);
1691 if (NT_STATUS_IS_OK(orig21_reject_status
)) {
1692 _h21
= io21
.out
.file
.handle
;
1697 CHECK_VAL(h21
->data
[0], h2f
->data
[0]);
1698 CHECK_VAL(h21
->data
[1], h2f
->data
[1]);
1699 CHECK_CREATED(&io21
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
1700 CHECK_VAL(io21
.out
.oplock_level
, client2_level
);
1701 CHECK_VAL(io21
.out
.durable_open
, false);
1702 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1703 CHECK_VAL(io21
.out
.lease_response_v2
.lease_key
.data
[0], lease_key2
);
1704 CHECK_VAL(io21
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key2
);
1705 CHECK_VAL(io21
.out
.lease_response_v2
.lease_epoch
, lease_epoch2
);
1706 CHECK_VAL(io21
.out
.lease_response_v2
.lease_state
,
1707 smb2_util_lease_state("RHW"));
1708 CHECK_VAL(io21
.out
.durable_open_v2
, true);
1709 CHECK_VAL(io21
.out
.timeout
, 300*1000);
1710 } else if (client2_level
== SMB2_OPLOCK_LEVEL_BATCH
) {
1711 CHECK_VAL(io21
.out
.durable_open_v2
, true);
1712 CHECK_VAL(io21
.out
.timeout
, 300*1000);
1714 CHECK_VAL(io21
.out
.durable_open_v2
, false);
1718 if (NT_STATUS_EQUAL(replay22_reject_status
, NT_STATUS_SHARING_VIOLATION
)) {
1719 torture_comment(tctx
, "Checking req22 expecting %s\n",
1720 nt_errstr(replay22_reject_status
));
1721 status
= smb2_create_recv(req22
, tctx
, &io22
);
1722 CHECK_STATUS(status
, replay22_reject_status
);
1725 torture_comment(tctx
, "SYNC Replay io23 expecting %s\n",
1726 nt_errstr(replay23_reject_status
));
1727 smb2cli_session_start_replay(session2
->smbXcli
);
1728 transport2
->options
.request_timeout
= 5;
1729 status
= smb2_create(tree2
, tctx
, &io23
);
1730 transport2
->options
.request_timeout
= request_timeout2
;
1731 CHECK_STATUS(status
, replay23_reject_status
);
1732 smb2cli_session_stop_replay(session2
->smbXcli
);
1733 if (NT_STATUS_IS_OK(replay23_reject_status
)) {
1734 _h23
= io23
.out
.file
.handle
;
1739 CHECK_VAL(h23
->data
[0], h2f
->data
[0]);
1740 CHECK_VAL(h23
->data
[1], h2f
->data
[1]);
1741 CHECK_CREATED(&io23
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
1742 CHECK_VAL(io23
.out
.oplock_level
, client2_level
);
1743 CHECK_VAL(io23
.out
.durable_open
, false);
1744 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1745 CHECK_VAL(io23
.out
.lease_response_v2
.lease_key
.data
[0], lease_key2
);
1746 CHECK_VAL(io23
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key2
);
1747 CHECK_VAL(io23
.out
.lease_response_v2
.lease_epoch
, lease_epoch2
);
1748 CHECK_VAL(io23
.out
.lease_response_v2
.lease_state
,
1749 smb2_util_lease_state("RHW"));
1750 CHECK_VAL(io23
.out
.durable_open_v2
, true);
1751 CHECK_VAL(io23
.out
.timeout
, 300*1000);
1752 } else if (client2_level
== SMB2_OPLOCK_LEVEL_BATCH
) {
1753 CHECK_VAL(io23
.out
.durable_open_v2
, true);
1754 CHECK_VAL(io23
.out
.timeout
, 300*1000);
1756 CHECK_VAL(io23
.out
.durable_open_v2
, false);
1760 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1761 torture_wait_for_lease_break(tctx
);
1763 torture_wait_for_oplock_break(tctx
);
1765 CHECK_VAL(break_info
.count
, 0);
1766 CHECK_VAL(lease_break_info
.count
, 0);
1768 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1769 torture_wait_for_lease_break(tctx
);
1771 torture_wait_for_oplock_break(tctx
);
1773 CHECK_VAL(break_info
.count
, 0);
1774 CHECK_VAL(lease_break_info
.count
, 0);
1777 torture_comment(tctx
, "Closing h1\n");
1778 smb2_util_close(tree1
, _h1
);
1782 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1783 torture_wait_for_lease_break(tctx
);
1785 torture_wait_for_oplock_break(tctx
);
1787 CHECK_VAL(break_info
.count
, 0);
1788 CHECK_VAL(lease_break_info
.count
, 0);
1790 torture_comment(tctx
, "SYNC Replay io24 expecting %s\n",
1791 nt_errstr(NT_STATUS_OK
));
1792 smb2cli_session_start_replay(session2
->smbXcli
);
1793 transport2
->options
.request_timeout
= 5;
1794 status
= smb2_create(tree2
, tctx
, &io24
);
1795 transport2
->options
.request_timeout
= request_timeout2
;
1796 smb2cli_session_stop_replay(session2
->smbXcli
);
1797 CHECK_STATUS(status
, NT_STATUS_OK
);
1798 _h24
= io24
.out
.file
.handle
;
1803 CHECK_VAL(h24
->data
[0], h2f
->data
[0]);
1804 CHECK_VAL(h24
->data
[1], h2f
->data
[1]);
1805 CHECK_CREATED(&io24
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
1806 CHECK_VAL(io24
.out
.oplock_level
, client2_level
);
1807 CHECK_VAL(io24
.out
.durable_open
, false);
1808 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1809 CHECK_VAL(io24
.out
.lease_response_v2
.lease_key
.data
[0], lease_key2
);
1810 CHECK_VAL(io24
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key2
);
1811 CHECK_VAL(io24
.out
.lease_response_v2
.lease_epoch
, lease_epoch2
);
1812 CHECK_VAL(io24
.out
.lease_response_v2
.lease_state
,
1813 smb2_util_lease_state("RHW"));
1814 CHECK_VAL(io24
.out
.durable_open_v2
, true);
1815 CHECK_VAL(io24
.out
.timeout
, 300*1000);
1816 } else if (client2_level
== SMB2_OPLOCK_LEVEL_BATCH
) {
1817 CHECK_VAL(io24
.out
.durable_open_v2
, true);
1818 CHECK_VAL(io24
.out
.timeout
, 300*1000);
1820 CHECK_VAL(io24
.out
.durable_open_v2
, false);
1823 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1824 torture_wait_for_lease_break(tctx
);
1826 torture_wait_for_oplock_break(tctx
);
1828 CHECK_VAL(break_info
.count
, 0);
1829 CHECK_VAL(lease_break_info
.count
, 0);
1830 status
= smb2_util_close(tree2
, *h24
);
1831 CHECK_STATUS(status
, NT_STATUS_OK
);
1834 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
1835 torture_wait_for_lease_break(tctx
);
1837 torture_wait_for_oplock_break(tctx
);
1839 CHECK_VAL(break_info
.count
, 0);
1840 CHECK_VAL(lease_break_info
.count
, 0);
1844 smbXcli_conn_disconnect(transport2
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
1847 smb2_util_close(tree1
, *h1
);
1850 smb2_deltree(tree1
, BASEDIR
);
1853 talloc_free(mem_ctx
);
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.
1865 * With a durablev2 request containing a create_guid,
1866 * but without asking for an oplock nor a lease.
1868 * While another client holds an RWH lease,
1869 * which is released by a close.
1871 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1873 * This expects the sane reject status of
1874 * NT_STATUS_FILE_NOT_AVAILABLE.
1876 * It won't pass against Windows as it returns
1877 * NT_STATUS_SHARING_VIOLATION to the replay (after
1878 * 35 seconds), and this tests reports NT_STATUS_IO_TIMEOUT,
1879 * as it expects a NT_STATUS_FILE_NOT_AVAILABLE within 5 seconds.
1880 * see test_dhv2_pending1n_vs_violation_lease_close_windows().
1882 static bool test_dhv2_pending1n_vs_violation_lease_close_sane(struct torture_context
*tctx
,
1883 struct smb2_tree
*tree1
,
1884 struct smb2_tree
*tree2
)
1886 return _test_dhv2_pending1_vs_violation(tctx
, __func__
,
1888 SMB2_OPLOCK_LEVEL_LEASE
,
1891 SMB2_OPLOCK_LEVEL_NONE
,
1893 NT_STATUS_FILE_NOT_AVAILABLE
,
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.
1904 * With a durablev2 request containing a create_guid,
1905 * but without asking for an oplock nor a lease.
1907 * While another client holds an RWH lease,
1908 * which is released by a close.
1910 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1912 * This expects the strange behavior of ignoring the
1913 * replay, which is returned done by Windows Servers.
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().
1919 static bool test_dhv2_pending1n_vs_violation_lease_close_windows(struct torture_context
*tctx
,
1920 struct smb2_tree
*tree1
,
1921 struct smb2_tree
*tree2
)
1923 return _test_dhv2_pending1_vs_violation(tctx
, __func__
,
1925 SMB2_OPLOCK_LEVEL_LEASE
,
1928 SMB2_OPLOCK_LEVEL_NONE
,
1930 NT_STATUS_SHARING_VIOLATION
,
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.
1941 * With a durablev2 request containing a create_guid,
1942 * but without asking for an oplock nor a lease.
1944 * While another client holds an RWH lease,
1945 * which is released by a lease break ack.
1947 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1949 * This expects the sane reject status of
1950 * NT_STATUS_FILE_NOT_AVAILABLE.
1952 * It won't pass against Windows as it returns
1953 * NT_STATUS_SHARING_VIOLATION to the replay (after
1954 * 35 seconds), and this tests reports NT_STATUS_IO_TIMEOUT,
1955 * as it expects a NT_STATUS_FILE_NOT_AVAILABLE within 5 seconds.
1956 * see test_dhv2_pending1n_vs_violation_lease_ack_windows().
1958 static bool test_dhv2_pending1n_vs_violation_lease_ack_sane(struct torture_context
*tctx
,
1959 struct smb2_tree
*tree1
,
1960 struct smb2_tree
*tree2
)
1962 return _test_dhv2_pending1_vs_violation(tctx
, __func__
,
1964 SMB2_OPLOCK_LEVEL_LEASE
,
1967 SMB2_OPLOCK_LEVEL_NONE
,
1968 NT_STATUS_SHARING_VIOLATION
,
1969 NT_STATUS_FILE_NOT_AVAILABLE
,
1970 NT_STATUS_SHARING_VIOLATION
);
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.
1980 * With a durablev2 request containing a create_guid,
1981 * but without asking for an oplock nor a lease.
1983 * While another client holds an RWH lease,
1984 * which is released by a close.
1986 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
1988 * This expects the strange behavior of ignoring the
1989 * replay, which is returned done by Windows Servers.
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().
1995 static bool test_dhv2_pending1n_vs_violation_lease_ack_windows(struct torture_context
*tctx
,
1996 struct smb2_tree
*tree1
,
1997 struct smb2_tree
*tree2
)
1999 return _test_dhv2_pending1_vs_violation(tctx
, __func__
,
2001 SMB2_OPLOCK_LEVEL_LEASE
,
2004 SMB2_OPLOCK_LEVEL_NONE
,
2005 NT_STATUS_SHARING_VIOLATION
,
2006 NT_STATUS_SHARING_VIOLATION
,
2007 NT_STATUS_SHARING_VIOLATION
);
2011 * This tests replay with a pending open on a single
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.
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.
2027 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2029 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
)
2038 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
2039 struct smb2_handle _h1
;
2040 struct smb2_handle
*h1
= NULL
;
2041 struct smb2_handle _h21
;
2042 struct smb2_handle
*h21
= NULL
;
2043 struct smb2_handle _h24
;
2044 struct smb2_handle
*h24
= NULL
;
2045 struct smb2_create io1
, io21
, io22
, io23
, io24
;
2046 struct GUID create_guid1
= GUID_random();
2047 struct GUID create_guid2
= GUID_random();
2048 struct smb2_request
*req21
= NULL
;
2051 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 uint16_t lease_epoch1
= 0;
2057 struct smb2_lease ls2
;
2058 uint64_t lease_key2
;
2059 uint16_t lease_epoch2
= 0;
2061 struct smb2_transport
*transport2
= tree2
->session
->transport
;
2062 int request_timeout2
= transport2
->options
.request_timeout
;
2063 struct smb2_session
*session2
= tree2
->session
;
2064 const char *hold_name
= NULL
;
2066 switch (client1_level
) {
2067 case SMB2_OPLOCK_LEVEL_LEASE
:
2068 hold_name
= "RWH Lease";
2070 case SMB2_OPLOCK_LEVEL_BATCH
:
2071 hold_name
= "BATCH Oplock";
2074 smb_panic(__location__
);
2078 if (smbXcli_conn_protocol(transport1
->conn
) < PROTOCOL_SMB3_00
) {
2079 torture_skip(tctx
, "SMB 3.X Dialect family required for "
2083 server_capabilities
= smb2cli_conn_server_capabilities(transport1
->conn
);
2084 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
2085 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
||
2086 client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2087 torture_skip(tctx
, "leases are not supported");
2091 share_capabilities
= smb2cli_tcon_capabilities(tree1
->smbXcli
);
2092 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
2094 torture_skip(tctx
, talloc_asprintf(tctx
,
2095 "%s not supported on SCALEOUT share",
2099 /* Add some random component to the file name. */
2100 snprintf(fname
, sizeof(fname
), "%s\\%s_%s.dat",
2101 BASEDIR
, testname
, generate_random_str(tctx
, 8));
2103 torture_reset_break_info(tctx
, &break_info
);
2104 break_info
.oplock_skip_ack
= true;
2105 torture_reset_lease_break_info(tctx
, &lease_break_info
);
2106 lease_break_info
.lease_skip_ack
= true;
2107 transport1
->oplock
.handler
= torture_oplock_ack_handler
;
2108 transport1
->oplock
.private_data
= tree1
;
2109 transport1
->lease
.handler
= torture_lease_handler
;
2110 transport1
->lease
.private_data
= tree1
;
2111 smb2_keepalive(transport1
);
2112 transport2
->oplock
.handler
= torture_oplock_ack_handler
;
2113 transport2
->oplock
.private_data
= tree2
;
2114 transport2
->lease
.handler
= torture_lease_handler
;
2115 transport2
->lease
.private_data
= tree2
;
2116 smb2_keepalive(transport2
);
2118 smb2_util_unlink(tree1
, fname
);
2119 status
= torture_smb2_testdir(tree1
, BASEDIR
, &_h1
);
2120 CHECK_STATUS(status
, NT_STATUS_OK
);
2121 smb2_util_close(tree1
, _h1
);
2122 CHECK_VAL(break_info
.count
, 0);
2124 lease_key1
= random();
2125 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2126 smb2_lease_v2_create(&io1
, &ls1
, false /* dir */, fname
,
2127 lease_key1
, NULL
, smb2_util_lease_state("RWH"), lease_epoch1
++);
2129 smb2_oplock_create(&io1
, fname
, SMB2_OPLOCK_LEVEL_BATCH
);
2131 io1
.in
.share_access
= smb2_util_share_access("RWD");
2132 io1
.in
.durable_open
= false;
2133 io1
.in
.durable_open_v2
= true;
2134 io1
.in
.persistent_open
= false;
2135 io1
.in
.create_guid
= create_guid1
;
2136 io1
.in
.timeout
= UINT32_MAX
;
2138 status
= smb2_create(tree1
, mem_ctx
, &io1
);
2139 CHECK_STATUS(status
, NT_STATUS_OK
);
2140 _h1
= io1
.out
.file
.handle
;
2142 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
2143 CHECK_VAL(io1
.out
.durable_open
, false);
2144 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2145 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_LEASE
);
2146 CHECK_VAL(io1
.out
.lease_response_v2
.lease_key
.data
[0], lease_key1
);
2147 CHECK_VAL(io1
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key1
);
2148 CHECK_VAL(io1
.out
.lease_response_v2
.lease_epoch
, lease_epoch1
);
2149 CHECK_VAL(io1
.out
.lease_response_v2
.lease_state
,
2150 smb2_util_lease_state("RHW"));
2152 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_BATCH
);
2154 CHECK_VAL(io1
.out
.durable_open_v2
, true);
2155 CHECK_VAL(io1
.out
.timeout
, 300*1000);
2157 lease_key2
= random();
2158 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2159 smb2_lease_v2_create(&io21
, &ls2
, false /* dir */, fname
,
2160 lease_key2
, NULL
, smb2_util_lease_state("RWH"), lease_epoch2
++);
2162 smb2_oplock_create(&io21
, fname
, client2_level
);
2164 io21
.in
.share_access
= smb2_util_share_access("RWD");
2165 io21
.in
.durable_open
= false;
2166 io21
.in
.durable_open_v2
= true;
2167 io21
.in
.persistent_open
= false;
2168 io21
.in
.create_guid
= create_guid2
;
2169 io21
.in
.timeout
= UINT32_MAX
;
2170 io24
= io23
= io22
= io21
;
2172 req21
= smb2_create_send(tree2
, &io21
);
2173 torture_assert(tctx
, req21
!= NULL
, "req21");
2175 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2176 const struct smb2_lease_break
*lb
=
2177 &lease_break_info
.lease_break
;
2178 const struct smb2_lease
*l
= &lb
->current_lease
;
2179 const struct smb2_lease_key
*k
= &l
->lease_key
;
2181 torture_wait_for_lease_break(tctx
);
2182 CHECK_VAL(break_info
.count
, 0);
2183 CHECK_VAL(lease_break_info
.count
, 1);
2185 torture_assert(tctx
,
2186 lease_break_info
.lease_transport
== transport1
,
2187 "expect lease break on transport1\n");
2188 CHECK_VAL(k
->data
[0], lease_key1
);
2189 CHECK_VAL(k
->data
[1], ~lease_key1
);
2190 CHECK_VAL(lb
->new_lease_state
,
2191 smb2_util_lease_state("RH"));
2192 CHECK_VAL(lb
->break_flags
,
2193 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED
);
2194 CHECK_VAL(lb
->new_epoch
, lease_epoch1
+1);
2197 torture_wait_for_oplock_break(tctx
);
2198 CHECK_VAL(break_info
.count
, 1);
2199 CHECK_VAL(lease_break_info
.count
, 0);
2201 torture_assert(tctx
,
2202 break_info
.received_transport
== transport1
,
2203 "expect oplock break on transport1\n");
2204 CHECK_VAL(break_info
.handle
.data
[0], _h1
.data
[0]);
2205 CHECK_VAL(break_info
.handle
.data
[1], _h1
.data
[1]);
2206 CHECK_VAL(break_info
.level
, SMB2_OPLOCK_LEVEL_II
);
2209 torture_reset_break_info(tctx
, &break_info
);
2210 break_info
.oplock_skip_ack
= true;
2211 torture_reset_lease_break_info(tctx
, &lease_break_info
);
2212 lease_break_info
.lease_skip_ack
= true;
2214 WAIT_FOR_ASYNC_RESPONSE(tctx
, req21
);
2216 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2217 torture_wait_for_lease_break(tctx
);
2219 torture_wait_for_oplock_break(tctx
);
2221 CHECK_VAL(break_info
.count
, 0);
2222 CHECK_VAL(lease_break_info
.count
, 0);
2224 smb2cli_session_start_replay(session2
->smbXcli
);
2225 transport2
->options
.request_timeout
= 5;
2226 status
= smb2_create(tree2
, tctx
, &io22
);
2227 transport2
->options
.request_timeout
= request_timeout2
;
2228 CHECK_STATUS(status
, reject_status
);
2229 smb2cli_session_stop_replay(session2
->smbXcli
);
2231 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2232 torture_wait_for_lease_break(tctx
);
2234 torture_wait_for_oplock_break(tctx
);
2236 CHECK_VAL(break_info
.count
, 0);
2237 CHECK_VAL(lease_break_info
.count
, 0);
2239 smb2cli_session_start_replay(session2
->smbXcli
);
2240 transport2
->options
.request_timeout
= 5;
2241 status
= smb2_create(tree2
, tctx
, &io23
);
2242 transport2
->options
.request_timeout
= request_timeout2
;
2243 CHECK_STATUS(status
, reject_status
);
2244 smb2cli_session_stop_replay(session2
->smbXcli
);
2246 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2247 torture_wait_for_lease_break(tctx
);
2249 torture_wait_for_oplock_break(tctx
);
2251 CHECK_VAL(break_info
.count
, 0);
2252 CHECK_VAL(lease_break_info
.count
, 0);
2254 smb2_util_close(tree1
, _h1
);
2257 status
= smb2_create_recv(req21
, tctx
, &io21
);
2258 CHECK_STATUS(status
, NT_STATUS_OK
);
2259 _h21
= io21
.out
.file
.handle
;
2261 CHECK_CREATED(&io21
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
2262 CHECK_VAL(io21
.out
.oplock_level
, client2_level
);
2263 CHECK_VAL(io21
.out
.durable_open
, false);
2264 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2265 CHECK_VAL(io21
.out
.lease_response_v2
.lease_key
.data
[0], lease_key2
);
2266 CHECK_VAL(io21
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key2
);
2267 CHECK_VAL(io21
.out
.lease_response_v2
.lease_epoch
, lease_epoch2
);
2268 CHECK_VAL(io21
.out
.lease_response_v2
.lease_state
,
2269 smb2_util_lease_state("RHW"));
2270 CHECK_VAL(io21
.out
.durable_open_v2
, true);
2271 CHECK_VAL(io21
.out
.timeout
, 300*1000);
2272 } else if (client2_level
== SMB2_OPLOCK_LEVEL_BATCH
) {
2273 CHECK_VAL(io21
.out
.durable_open_v2
, true);
2274 CHECK_VAL(io21
.out
.timeout
, 300*1000);
2276 CHECK_VAL(io21
.out
.durable_open_v2
, false);
2279 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2280 torture_wait_for_lease_break(tctx
);
2282 torture_wait_for_oplock_break(tctx
);
2284 CHECK_VAL(break_info
.count
, 0);
2285 CHECK_VAL(lease_break_info
.count
, 0);
2287 smb2cli_session_start_replay(session2
->smbXcli
);
2288 status
= smb2_create(tree2
, tctx
, &io24
);
2289 smb2cli_session_stop_replay(session2
->smbXcli
);
2290 CHECK_STATUS(status
, NT_STATUS_OK
);
2291 _h24
= io24
.out
.file
.handle
;
2293 CHECK_CREATED(&io24
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
2294 CHECK_VAL(h24
->data
[0], h21
->data
[0]);
2295 CHECK_VAL(h24
->data
[1], h21
->data
[1]);
2296 CHECK_VAL(io24
.out
.oplock_level
, client2_level
);
2297 CHECK_VAL(io24
.out
.durable_open
, false);
2298 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2299 CHECK_VAL(io24
.out
.lease_response_v2
.lease_key
.data
[0], lease_key2
);
2300 CHECK_VAL(io24
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key2
);
2301 CHECK_VAL(io24
.out
.lease_response_v2
.lease_epoch
, lease_epoch2
);
2302 CHECK_VAL(io24
.out
.lease_response_v2
.lease_state
,
2303 smb2_util_lease_state("RHW"));
2304 CHECK_VAL(io24
.out
.durable_open_v2
, true);
2305 CHECK_VAL(io24
.out
.timeout
, 300*1000);
2306 } else if (client2_level
== SMB2_OPLOCK_LEVEL_BATCH
) {
2307 CHECK_VAL(io24
.out
.durable_open_v2
, true);
2308 CHECK_VAL(io24
.out
.timeout
, 300*1000);
2310 CHECK_VAL(io24
.out
.durable_open_v2
, false);
2313 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2314 torture_wait_for_lease_break(tctx
);
2316 torture_wait_for_oplock_break(tctx
);
2318 CHECK_VAL(break_info
.count
, 0);
2319 CHECK_VAL(lease_break_info
.count
, 0);
2320 status
= smb2_util_close(tree2
, *h24
);
2321 CHECK_STATUS(status
, NT_STATUS_OK
);
2324 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2325 torture_wait_for_lease_break(tctx
);
2327 torture_wait_for_oplock_break(tctx
);
2329 CHECK_VAL(break_info
.count
, 0);
2330 CHECK_VAL(lease_break_info
.count
, 0);
2334 smbXcli_conn_disconnect(transport2
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
2337 smb2_util_close(tree1
, *h1
);
2340 smb2_deltree(tree1
, BASEDIR
);
2343 talloc_free(mem_ctx
);
2349 * This tests replay with a pending open on a single
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.
2356 * While another client holds a batch oplock.
2357 * And allows share_access of READ/WRITE/DELETE.
2359 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2361 * This expects the sane reject status of
2362 * NT_STATUS_FILE_NOT_AVAILABLE.
2364 * It won't pass against Windows as it returns
2365 * NT_STATUS_ACCESS_DENIED see
2366 * test_dhv2_pending1n_vs_oplock_windows().
2368 static bool test_dhv2_pending1n_vs_oplock_sane(struct torture_context
*tctx
,
2369 struct smb2_tree
*tree1
,
2370 struct smb2_tree
*tree2
)
2372 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2373 SMB2_OPLOCK_LEVEL_BATCH
,
2374 SMB2_OPLOCK_LEVEL_NONE
,
2375 NT_STATUS_FILE_NOT_AVAILABLE
,
2380 * This tests replay with a pending open on a single
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.
2387 * While another client holds a batch oplock.
2388 * And allows share_access of READ/WRITE/DELETE.
2390 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2392 * This expects the strange reject status of
2393 * NT_STATUS_ACCESS_DENIED, which is returned
2394 * by Windows Servers.
2396 * It won't pass against Samba as it returns
2397 * NT_STATUS_FILE_NOT_AVAILABLE. see
2398 * test_dhv2_pending1n_vs_oplock_sane.
2400 static bool test_dhv2_pending1n_vs_oplock_windows(struct torture_context
*tctx
,
2401 struct smb2_tree
*tree1
,
2402 struct smb2_tree
*tree2
)
2404 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2405 SMB2_OPLOCK_LEVEL_BATCH
,
2406 SMB2_OPLOCK_LEVEL_NONE
,
2407 NT_STATUS_ACCESS_DENIED
,
2412 * This tests replay with a pending open on a single
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.
2419 * While another client holds an RWH lease.
2420 * And allows share_access of READ/WRITE/DELETE.
2422 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2424 * This expects the sane reject status of
2425 * NT_STATUS_FILE_NOT_AVAILABLE.
2427 * It won't pass against Windows as it returns
2428 * NT_STATUS_ACCESS_DENIED see
2429 * test_dhv2_pending1n_vs_lease_windows().
2431 static bool test_dhv2_pending1n_vs_lease_sane(struct torture_context
*tctx
,
2432 struct smb2_tree
*tree1
,
2433 struct smb2_tree
*tree2
)
2435 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2436 SMB2_OPLOCK_LEVEL_LEASE
,
2437 SMB2_OPLOCK_LEVEL_NONE
,
2438 NT_STATUS_FILE_NOT_AVAILABLE
,
2443 * This tests replay with a pending open on a single
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.
2450 * While another client holds an RWH lease.
2451 * And allows share_access of READ/WRITE/DELETE.
2453 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2455 * This expects the strange reject status of
2456 * NT_STATUS_ACCESS_DENIED, which is returned
2457 * by Windows Servers.
2459 * It won't pass against Samba as it returns
2460 * NT_STATUS_FILE_NOT_AVAILABLE. see
2461 * test_dhv2_pending1n_vs_lease_sane.
2463 static bool test_dhv2_pending1n_vs_lease_windows(struct torture_context
*tctx
,
2464 struct smb2_tree
*tree1
,
2465 struct smb2_tree
*tree2
)
2467 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2468 SMB2_OPLOCK_LEVEL_LEASE
,
2469 SMB2_OPLOCK_LEVEL_NONE
,
2470 NT_STATUS_ACCESS_DENIED
,
2475 * This tests replay with a pending open on a single
2478 * With a durablev2 request containing a create_guid,
2479 * a share_access of READ/WRITE/DELETE,
2480 * and asking for a v2 lease.
2482 * While another client holds a batch oplock.
2483 * And allows share_access of READ/WRITE/DELETE.
2485 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2487 * This expects the sane reject status of
2488 * NT_STATUS_FILE_NOT_AVAILABLE.
2490 * It won't pass against Windows as it returns
2491 * NT_STATUS_ACCESS_DENIED see
2492 * test_dhv2_pending1l_vs_oplock_windows().
2494 static bool test_dhv2_pending1l_vs_oplock_sane(struct torture_context
*tctx
,
2495 struct smb2_tree
*tree1
,
2496 struct smb2_tree
*tree2
)
2498 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2499 SMB2_OPLOCK_LEVEL_BATCH
,
2500 SMB2_OPLOCK_LEVEL_LEASE
,
2501 NT_STATUS_FILE_NOT_AVAILABLE
,
2506 * This tests replay with a pending open on a single
2509 * With a durablev2 request containing a create_guid,
2510 * a share_access of READ/WRITE/DELETE,
2511 * and asking for a v2 lease.
2513 * While another client holds a batch oplock.
2514 * And allows share_access of READ/WRITE/DELETE.
2516 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2518 * This expects the strange reject status of
2519 * NT_STATUS_ACCESS_DENIED, which is returned
2520 * by Windows Servers.
2522 * It won't pass against Samba as it returns
2523 * NT_STATUS_FILE_NOT_AVAILABLE. see
2524 * test_dhv2_pending1l_vs_oplock_sane.
2526 static bool test_dhv2_pending1l_vs_oplock_windows(struct torture_context
*tctx
,
2527 struct smb2_tree
*tree1
,
2528 struct smb2_tree
*tree2
)
2530 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2531 SMB2_OPLOCK_LEVEL_BATCH
,
2532 SMB2_OPLOCK_LEVEL_LEASE
,
2533 NT_STATUS_ACCESS_DENIED
,
2538 * This tests replay with a pending open on a single
2541 * With a durablev2 request containing a create_guid,
2542 * a share_access of READ/WRITE/DELETE,
2543 * and asking for a v2 lease.
2545 * While another client holds an RWH lease.
2546 * And allows share_access of READ/WRITE/DELETE.
2548 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2550 * This expects the sane reject status of
2551 * NT_STATUS_FILE_NOT_AVAILABLE.
2553 * It won't pass against Windows as it returns
2554 * NT_STATUS_ACCESS_DENIED see
2555 * test_dhv2_pending1l_vs_lease_windows().
2557 static bool test_dhv2_pending1l_vs_lease_sane(struct torture_context
*tctx
,
2558 struct smb2_tree
*tree1
,
2559 struct smb2_tree
*tree2
)
2561 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2562 SMB2_OPLOCK_LEVEL_LEASE
,
2563 SMB2_OPLOCK_LEVEL_LEASE
,
2564 NT_STATUS_FILE_NOT_AVAILABLE
,
2569 * This tests replay with a pending open on a single
2572 * With a durablev2 request containing a create_guid,
2573 * a share_access of READ/WRITE/DELETE,
2574 * and asking for a v2 lease.
2576 * While another client holds an RWH lease.
2577 * And allows share_access of READ/WRITE/DELETE.
2579 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2581 * This expects the strange reject status of
2582 * NT_STATUS_ACCESS_DENIED, which is returned
2583 * by Windows Servers.
2585 * It won't pass against Samba as it returns
2586 * NT_STATUS_FILE_NOT_AVAILABLE. see
2587 * test_dhv2_pending1l_vs_lease_sane.
2589 static bool test_dhv2_pending1l_vs_lease_windows(struct torture_context
*tctx
,
2590 struct smb2_tree
*tree1
,
2591 struct smb2_tree
*tree2
)
2593 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2594 SMB2_OPLOCK_LEVEL_LEASE
,
2595 SMB2_OPLOCK_LEVEL_LEASE
,
2596 NT_STATUS_ACCESS_DENIED
,
2601 * This tests replay with a pending open on a single
2604 * With a durablev2 request containing a create_guid,
2605 * a share_access of READ/WRITE/DELETE,
2606 * and asking for a batch oplock.
2608 * While another client holds a batch oplock.
2609 * And allows share_access of READ/WRITE/DELETE.
2611 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2613 * This expects the sane reject status of
2614 * NT_STATUS_FILE_NOT_AVAILABLE.
2616 * It won't pass against Windows as it returns
2617 * NT_STATUS_ACCESS_DENIED see
2618 * test_dhv2_pending1o_vs_oplock_windows().
2620 static bool test_dhv2_pending1o_vs_oplock_sane(struct torture_context
*tctx
,
2621 struct smb2_tree
*tree1
,
2622 struct smb2_tree
*tree2
)
2624 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2625 SMB2_OPLOCK_LEVEL_BATCH
,
2626 SMB2_OPLOCK_LEVEL_BATCH
,
2627 NT_STATUS_FILE_NOT_AVAILABLE
,
2632 * This tests replay with a pending open on a single
2635 * With a durablev2 request containing a create_guid,
2636 * a share_access of READ/WRITE/DELETE,
2637 * and asking for a batch oplock.
2639 * While another client holds a batch oplock.
2640 * And allows share_access of READ/WRITE/DELETE.
2642 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2644 * This expects the strange reject status of
2645 * NT_STATUS_ACCESS_DENIED, which is returned
2646 * by Windows Servers.
2648 * It won't pass against Samba as it returns
2649 * NT_STATUS_FILE_NOT_AVAILABLE. see
2650 * test_dhv2_pending1o_vs_oplock_sane.
2652 static bool test_dhv2_pending1o_vs_oplock_windows(struct torture_context
*tctx
,
2653 struct smb2_tree
*tree1
,
2654 struct smb2_tree
*tree2
)
2656 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2657 SMB2_OPLOCK_LEVEL_BATCH
,
2658 SMB2_OPLOCK_LEVEL_BATCH
,
2659 NT_STATUS_ACCESS_DENIED
,
2664 * This tests replay with a pending open on a single
2667 * With a durablev2 request containing a create_guid,
2668 * a share_access of READ/WRITE/DELETE,
2669 * and asking for a batch oplock.
2671 * While another client holds an RWH lease.
2672 * And allows share_access of READ/WRITE/DELETE.
2674 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2676 * This expects the sane reject status of
2677 * NT_STATUS_FILE_NOT_AVAILABLE.
2679 * It won't pass against Windows as it returns
2680 * NT_STATUS_ACCESS_DENIED see
2681 * test_dhv2_pending1o_vs_lease_windows().
2683 static bool test_dhv2_pending1o_vs_lease_sane(struct torture_context
*tctx
,
2684 struct smb2_tree
*tree1
,
2685 struct smb2_tree
*tree2_1
)
2687 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2688 SMB2_OPLOCK_LEVEL_LEASE
,
2689 SMB2_OPLOCK_LEVEL_BATCH
,
2690 NT_STATUS_FILE_NOT_AVAILABLE
,
2695 * This tests replay with a pending open on a single
2698 * With a durablev2 request containing a create_guid,
2699 * a share_access of READ/WRITE/DELETE,
2700 * and asking for a batch oplock.
2702 * While another client holds an RWH lease.
2703 * And allows share_access of READ/WRITE/DELETE.
2705 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2707 * This expects the strange reject status of
2708 * NT_STATUS_ACCESS_DENIED, which is returned
2709 * by Windows Servers.
2711 * It won't pass against Samba as it returns
2712 * NT_STATUS_FILE_NOT_AVAILABLE. see
2713 * test_dhv2_pending1o_vs_lease_sane.
2715 static bool test_dhv2_pending1o_vs_lease_windows(struct torture_context
*tctx
,
2716 struct smb2_tree
*tree1
,
2717 struct smb2_tree
*tree2
)
2719 return _test_dhv2_pending1_vs_hold(tctx
, __func__
,
2720 SMB2_OPLOCK_LEVEL_LEASE
,
2721 SMB2_OPLOCK_LEVEL_BATCH
,
2722 NT_STATUS_ACCESS_DENIED
,
2727 * This tests replay with a pending open with 4 channels
2728 * and closed transports on the client and server side.
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.
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.
2743 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
2745 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
)
2753 const char *host
= torture_setting_string(tctx
, "host", NULL
);
2754 const char *share
= torture_setting_string(tctx
, "share", NULL
);
2755 struct cli_credentials
*credentials
= samba_cmdline_get_creds();
2757 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
2758 struct smb2_handle _h1
;
2759 struct smb2_handle
*h1
= NULL
;
2760 struct smb2_handle _h24
;
2761 struct smb2_handle
*h24
= NULL
;
2762 struct smb2_create io1
, io21
, io22
, io23
, io24
;
2763 struct GUID create_guid1
= GUID_random();
2764 struct GUID create_guid2
= GUID_random();
2765 struct smb2_request
*req21
= NULL
;
2768 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 uint16_t lease_epoch1
= 0;
2774 struct smb2_lease ls2
;
2775 uint64_t lease_key2
;
2776 uint16_t lease_epoch2
= 0;
2778 struct smb2_transport
*transport2_1
= tree2_1
->session
->transport
;
2779 int request_timeout2
= transport2_1
->options
.request_timeout
;
2780 struct smbcli_options options2x
;
2781 struct smb2_tree
*tree2_2
= NULL
;
2782 struct smb2_tree
*tree2_3
= NULL
;
2783 struct smb2_tree
*tree2_4
= NULL
;
2784 struct smb2_transport
*transport2_2
= NULL
;
2785 struct smb2_transport
*transport2_3
= NULL
;
2786 struct smb2_transport
*transport2_4
= NULL
;
2787 struct smb2_session
*session2_1
= tree2_1
->session
;
2788 struct smb2_session
*session2_2
= NULL
;
2789 struct smb2_session
*session2_3
= NULL
;
2790 struct smb2_session
*session2_4
= NULL
;
2792 const char *hold_name
= NULL
;
2794 switch (client1_level
) {
2795 case SMB2_OPLOCK_LEVEL_LEASE
:
2796 hold_name
= "RWH Lease";
2798 case SMB2_OPLOCK_LEVEL_BATCH
:
2799 hold_name
= "BATCH Oplock";
2802 smb_panic(__location__
);
2806 if (smbXcli_conn_protocol(transport1
->conn
) < PROTOCOL_SMB3_00
) {
2807 torture_skip(tctx
, "SMB 3.X Dialect family required for "
2811 server_capabilities
= smb2cli_conn_server_capabilities(transport1
->conn
);
2812 if (!(server_capabilities
& SMB2_CAP_MULTI_CHANNEL
)) {
2813 torture_skip(tctx
, "MULTI_CHANNEL are not supported");
2815 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
2816 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
||
2817 client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2818 torture_skip(tctx
, "leases are not supported");
2822 share_capabilities
= smb2cli_tcon_capabilities(tree1
->smbXcli
);
2823 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
2825 torture_skip(tctx
, talloc_asprintf(tctx
,
2826 "%s not supported on SCALEOUT share",
2830 /* Add some random component to the file name. */
2831 snprintf(fname
, sizeof(fname
), "%s\\%s_%s.dat",
2832 BASEDIR
, testname
, generate_random_str(tctx
, 8));
2834 options2x
= transport2_1
->options
;
2835 options2x
.only_negprot
= true;
2837 status
= smb2_connect(tctx
,
2839 lpcfg_smb_ports(tctx
->lp_ctx
),
2841 lpcfg_resolve_context(tctx
->lp_ctx
),
2846 lpcfg_socket_options(tctx
->lp_ctx
),
2847 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
2849 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2850 "smb2_connect failed");
2851 transport2_2
= tree2_2
->session
->transport
;
2853 session2_2
= smb2_session_channel(transport2_2
,
2854 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
2857 torture_assert(tctx
, session2_2
!= NULL
, "smb2_session_channel failed");
2859 status
= smb2_session_setup_spnego(session2_2
,
2861 0 /* previous_session_id */);
2862 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2863 "smb2_session_setup_spnego failed");
2864 tree2_2
->smbXcli
= tree2_1
->smbXcli
;
2865 tree2_2
->session
= session2_2
;
2867 status
= smb2_connect(tctx
,
2869 lpcfg_smb_ports(tctx
->lp_ctx
),
2871 lpcfg_resolve_context(tctx
->lp_ctx
),
2876 lpcfg_socket_options(tctx
->lp_ctx
),
2877 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
2879 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2880 "smb2_connect failed");
2881 transport2_3
= tree2_3
->session
->transport
;
2883 session2_3
= smb2_session_channel(transport2_3
,
2884 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
2887 torture_assert(tctx
, session2_3
!= NULL
, "smb2_session_channel failed");
2889 status
= smb2_session_setup_spnego(session2_3
,
2891 0 /* previous_session_id */);
2892 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2893 "smb2_session_setup_spnego failed");
2894 tree2_3
->smbXcli
= tree2_1
->smbXcli
;
2895 tree2_3
->session
= session2_3
;
2897 status
= smb2_connect(tctx
,
2899 lpcfg_smb_ports(tctx
->lp_ctx
),
2901 lpcfg_resolve_context(tctx
->lp_ctx
),
2906 lpcfg_socket_options(tctx
->lp_ctx
),
2907 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
2909 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2910 "smb2_connect failed");
2911 transport2_4
= tree2_4
->session
->transport
;
2913 session2_4
= smb2_session_channel(transport2_4
,
2914 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
2917 torture_assert(tctx
, session2_4
!= NULL
, "smb2_session_channel failed");
2919 status
= smb2_session_setup_spnego(session2_4
,
2921 0 /* previous_session_id */);
2922 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2923 "smb2_session_setup_spnego failed");
2924 tree2_4
->smbXcli
= tree2_1
->smbXcli
;
2925 tree2_4
->session
= session2_4
;
2927 smb2cli_session_reset_channel_sequence(session2_2
->smbXcli
, csn2
++);
2929 torture_reset_break_info(tctx
, &break_info
);
2930 break_info
.oplock_skip_ack
= true;
2931 torture_reset_lease_break_info(tctx
, &lease_break_info
);
2932 lease_break_info
.lease_skip_ack
= true;
2933 transport1
->oplock
.handler
= torture_oplock_ack_handler
;
2934 transport1
->oplock
.private_data
= tree1
;
2935 transport1
->lease
.handler
= torture_lease_handler
;
2936 transport1
->lease
.private_data
= tree1
;
2937 smb2_keepalive(transport1
);
2938 transport2_1
->oplock
.handler
= torture_oplock_ack_handler
;
2939 transport2_1
->oplock
.private_data
= tree2_1
;
2940 transport2_1
->lease
.handler
= torture_lease_handler
;
2941 transport2_1
->lease
.private_data
= tree2_1
;
2942 smb2_keepalive(transport2_1
);
2943 transport2_2
->oplock
.handler
= torture_oplock_ack_handler
;
2944 transport2_2
->oplock
.private_data
= tree2_2
;
2945 transport2_2
->lease
.handler
= torture_lease_handler
;
2946 transport2_2
->lease
.private_data
= tree2_2
;
2947 smb2_keepalive(transport2_2
);
2948 transport2_3
->oplock
.handler
= torture_oplock_ack_handler
;
2949 transport2_3
->oplock
.private_data
= tree2_3
;
2950 transport2_3
->lease
.handler
= torture_lease_handler
;
2951 transport2_3
->lease
.private_data
= tree2_3
;
2952 smb2_keepalive(transport2_3
);
2953 transport2_4
->oplock
.handler
= torture_oplock_ack_handler
;
2954 transport2_4
->oplock
.private_data
= tree2_4
;
2955 transport2_4
->lease
.handler
= torture_lease_handler
;
2956 transport2_4
->lease
.private_data
= tree2_4
;
2957 smb2_keepalive(transport2_4
);
2959 smb2_util_unlink(tree1
, fname
);
2960 status
= torture_smb2_testdir(tree1
, BASEDIR
, &_h1
);
2961 CHECK_STATUS(status
, NT_STATUS_OK
);
2962 smb2_util_close(tree1
, _h1
);
2963 CHECK_VAL(break_info
.count
, 0);
2965 lease_key1
= random();
2966 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2967 smb2_lease_v2_create(&io1
, &ls1
, false /* dir */, fname
,
2968 lease_key1
, NULL
, smb2_util_lease_state("RWH"), lease_epoch1
++);
2970 smb2_oplock_create(&io1
, fname
, SMB2_OPLOCK_LEVEL_BATCH
);
2972 io1
.in
.durable_open
= false;
2973 io1
.in
.durable_open_v2
= true;
2974 io1
.in
.persistent_open
= false;
2975 io1
.in
.create_guid
= create_guid1
;
2976 io1
.in
.timeout
= UINT32_MAX
;
2978 status
= smb2_create(tree1
, mem_ctx
, &io1
);
2979 CHECK_STATUS(status
, NT_STATUS_OK
);
2980 _h1
= io1
.out
.file
.handle
;
2982 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
2983 CHECK_VAL(io1
.out
.durable_open
, false);
2984 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2985 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_LEASE
);
2986 CHECK_VAL(io1
.out
.lease_response_v2
.lease_key
.data
[0], lease_key1
);
2987 CHECK_VAL(io1
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key1
);
2988 CHECK_VAL(io1
.out
.lease_response_v2
.lease_epoch
, lease_epoch1
);
2989 CHECK_VAL(io1
.out
.lease_response_v2
.lease_state
,
2990 smb2_util_lease_state("RHW"));
2992 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_BATCH
);
2994 CHECK_VAL(io1
.out
.durable_open_v2
, true);
2995 CHECK_VAL(io1
.out
.timeout
, 300*1000);
2997 lease_key2
= random();
2998 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
2999 smb2_lease_v2_create(&io21
, &ls2
, false /* dir */, fname
,
3000 lease_key2
, NULL
, smb2_util_lease_state("RWH"), lease_epoch2
++);
3002 smb2_oplock_create(&io21
, fname
, client2_level
);
3004 io21
.in
.durable_open
= false;
3005 io21
.in
.durable_open_v2
= true;
3006 io21
.in
.persistent_open
= false;
3007 io21
.in
.create_guid
= create_guid2
;
3008 io21
.in
.timeout
= UINT32_MAX
;
3009 io24
= io23
= io22
= io21
;
3011 req21
= smb2_create_send(tree2_1
, &io21
);
3012 torture_assert(tctx
, req21
!= NULL
, "req21");
3014 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3015 const struct smb2_lease_break
*lb
=
3016 &lease_break_info
.lease_break
;
3017 const struct smb2_lease
*l
= &lb
->current_lease
;
3018 const struct smb2_lease_key
*k
= &l
->lease_key
;
3020 torture_wait_for_lease_break(tctx
);
3021 CHECK_VAL(break_info
.count
, 0);
3022 CHECK_VAL(lease_break_info
.count
, 1);
3024 torture_assert(tctx
,
3025 lease_break_info
.lease_transport
== transport1
,
3026 "expect lease break on transport1\n");
3027 CHECK_VAL(k
->data
[0], lease_key1
);
3028 CHECK_VAL(k
->data
[1], ~lease_key1
);
3029 CHECK_VAL(lb
->new_lease_state
,
3030 smb2_util_lease_state("RH"));
3031 CHECK_VAL(lb
->break_flags
,
3032 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED
);
3033 CHECK_VAL(lb
->new_epoch
, lease_epoch1
+1);
3036 torture_wait_for_oplock_break(tctx
);
3037 CHECK_VAL(break_info
.count
, 1);
3038 CHECK_VAL(lease_break_info
.count
, 0);
3040 torture_assert(tctx
,
3041 break_info
.received_transport
== transport1
,
3042 "expect oplock break on transport1\n");
3043 CHECK_VAL(break_info
.handle
.data
[0], _h1
.data
[0]);
3044 CHECK_VAL(break_info
.handle
.data
[1], _h1
.data
[1]);
3045 CHECK_VAL(break_info
.level
, SMB2_OPLOCK_LEVEL_II
);
3048 torture_reset_break_info(tctx
, &break_info
);
3049 break_info
.oplock_skip_ack
= true;
3050 torture_reset_lease_break_info(tctx
, &lease_break_info
);
3051 lease_break_info
.lease_skip_ack
= true;
3053 WAIT_FOR_ASYNC_RESPONSE(tctx
, req21
);
3055 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3056 torture_wait_for_lease_break(tctx
);
3058 torture_wait_for_oplock_break(tctx
);
3060 CHECK_VAL(break_info
.count
, 0);
3061 CHECK_VAL(lease_break_info
.count
, 0);
3063 smbXcli_conn_disconnect(transport2_1
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
3064 smb2cli_session_reset_channel_sequence(session2_1
->smbXcli
, csn2
++);
3066 smb2cli_session_start_replay(session2_2
->smbXcli
);
3067 transport2_2
->options
.request_timeout
= 5;
3068 status
= smb2_create(tree2_2
, tctx
, &io22
);
3069 transport2_2
->options
.request_timeout
= request_timeout2
;
3070 CHECK_STATUS(status
, reject_status
);
3071 smb2cli_session_stop_replay(session2_2
->smbXcli
);
3073 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3074 torture_wait_for_lease_break(tctx
);
3076 torture_wait_for_oplock_break(tctx
);
3078 CHECK_VAL(break_info
.count
, 0);
3079 CHECK_VAL(lease_break_info
.count
, 0);
3081 smbXcli_conn_disconnect(transport2_2
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
3082 smb2cli_session_reset_channel_sequence(session2_2
->smbXcli
, csn2
++);
3084 smb2cli_session_start_replay(session2_3
->smbXcli
);
3085 transport2_3
->options
.request_timeout
= 5;
3086 status
= smb2_create(tree2_3
, tctx
, &io23
);
3087 transport2_3
->options
.request_timeout
= request_timeout2
;
3088 CHECK_STATUS(status
, reject_status
);
3089 smb2cli_session_stop_replay(session2_3
->smbXcli
);
3091 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3092 torture_wait_for_lease_break(tctx
);
3094 torture_wait_for_oplock_break(tctx
);
3096 CHECK_VAL(break_info
.count
, 0);
3097 CHECK_VAL(lease_break_info
.count
, 0);
3099 smb2_util_close(tree1
, _h1
);
3102 status
= smb2_create_recv(req21
, tctx
, &io21
);
3103 CHECK_STATUS(status
, NT_STATUS_LOCAL_DISCONNECT
);
3105 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3106 torture_wait_for_lease_break(tctx
);
3108 torture_wait_for_oplock_break(tctx
);
3110 CHECK_VAL(break_info
.count
, 0);
3111 CHECK_VAL(lease_break_info
.count
, 0);
3113 smbXcli_conn_disconnect(transport2_3
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
3114 smb2cli_session_reset_channel_sequence(session2_3
->smbXcli
, csn2
++);
3116 smb2cli_session_start_replay(session2_4
->smbXcli
);
3117 status
= smb2_create(tree2_4
, tctx
, &io24
);
3118 smb2cli_session_stop_replay(session2_4
->smbXcli
);
3119 CHECK_STATUS(status
, NT_STATUS_OK
);
3120 _h24
= io24
.out
.file
.handle
;
3122 CHECK_CREATED(&io24
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
3123 CHECK_VAL(io24
.out
.oplock_level
, client2_level
);
3124 CHECK_VAL(io24
.out
.durable_open
, false);
3125 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3126 CHECK_VAL(io24
.out
.lease_response_v2
.lease_key
.data
[0], lease_key2
);
3127 CHECK_VAL(io24
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key2
);
3128 CHECK_VAL(io24
.out
.lease_response_v2
.lease_epoch
, lease_epoch2
);
3129 CHECK_VAL(io24
.out
.lease_response_v2
.lease_state
,
3130 smb2_util_lease_state("RHW"));
3131 CHECK_VAL(io24
.out
.durable_open_v2
, true);
3132 CHECK_VAL(io24
.out
.timeout
, 300*1000);
3133 } else if (client2_level
== SMB2_OPLOCK_LEVEL_BATCH
) {
3134 CHECK_VAL(io24
.out
.durable_open_v2
, true);
3135 CHECK_VAL(io24
.out
.timeout
, 300*1000);
3137 CHECK_VAL(io24
.out
.durable_open_v2
, false);
3140 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3141 torture_wait_for_lease_break(tctx
);
3143 torture_wait_for_oplock_break(tctx
);
3145 CHECK_VAL(break_info
.count
, 0);
3146 CHECK_VAL(lease_break_info
.count
, 0);
3147 status
= smb2_util_close(tree2_4
, *h24
);
3148 CHECK_STATUS(status
, NT_STATUS_OK
);
3151 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3152 torture_wait_for_lease_break(tctx
);
3154 torture_wait_for_oplock_break(tctx
);
3156 CHECK_VAL(break_info
.count
, 0);
3157 CHECK_VAL(lease_break_info
.count
, 0);
3161 smbXcli_conn_disconnect(transport2_1
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
3162 smbXcli_conn_disconnect(transport2_2
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
3163 smbXcli_conn_disconnect(transport2_3
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
3164 smbXcli_conn_disconnect(transport2_4
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
3167 smb2_util_close(tree1
, *h1
);
3170 smb2_deltree(tree1
, BASEDIR
);
3173 talloc_free(mem_ctx
);
3179 * This tests replay with a pending open with 4 channels
3180 * and closed transports on the client and server side.
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.
3186 * While another client holds an RWH lease.
3187 * And allows share_access of READ/WRITE/DELETE.
3189 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3191 * This expects the sane reject status of
3192 * NT_STATUS_FILE_NOT_AVAILABLE.
3194 * It won't pass against Windows as it returns
3195 * NT_STATUS_ACCESS_DENIED see
3196 * test_dhv2_pending2n_vs_lease_windows().
3198 static bool test_dhv2_pending2n_vs_lease_sane(struct torture_context
*tctx
,
3199 struct smb2_tree
*tree1
,
3200 struct smb2_tree
*tree2_1
)
3202 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3203 SMB2_OPLOCK_LEVEL_LEASE
,
3204 SMB2_OPLOCK_LEVEL_NONE
,
3205 NT_STATUS_FILE_NOT_AVAILABLE
,
3210 * This tests replay with a pending open with 4 channels
3211 * and closed transports on the client and server side.
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.
3217 * While another client holds an RWH lease.
3218 * And allows share_access of READ/WRITE/DELETE.
3220 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3222 * This expects the strange reject status of
3223 * NT_STATUS_ACCESS_DENIED, which is returned
3224 * by Windows Servers.
3226 * It won't pass against Samba as it returns
3227 * NT_STATUS_FILE_NOT_AVAILABLE. see
3228 * test_dhv2_pending2n_vs_lease_sane().
3230 static bool test_dhv2_pending2n_vs_lease_windows(struct torture_context
*tctx
,
3231 struct smb2_tree
*tree1
,
3232 struct smb2_tree
*tree2_1
)
3234 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3235 SMB2_OPLOCK_LEVEL_LEASE
,
3236 SMB2_OPLOCK_LEVEL_NONE
,
3237 NT_STATUS_ACCESS_DENIED
,
3242 * This tests replay with a pending open with 4 channels
3243 * and closed transports on the client and server side.
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.
3249 * While another client holds a batch oplock.
3250 * And allows share_access of READ/WRITE/DELETE.
3252 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3254 * This expects the sane reject status of
3255 * NT_STATUS_FILE_NOT_AVAILABLE.
3257 * It won't pass against Windows as it returns
3258 * NT_STATUS_ACCESS_DENIED see
3259 * test_dhv2_pending2n_vs_oplock_windows().
3261 static bool test_dhv2_pending2n_vs_oplock_sane(struct torture_context
*tctx
,
3262 struct smb2_tree
*tree1
,
3263 struct smb2_tree
*tree2_1
)
3265 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3266 SMB2_OPLOCK_LEVEL_BATCH
,
3267 SMB2_OPLOCK_LEVEL_NONE
,
3268 NT_STATUS_FILE_NOT_AVAILABLE
,
3273 * This tests replay with a pending open with 4 channels
3274 * and closed transports on the client and server side.
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.
3280 * While another client holds a batch oplock.
3281 * And allows share_access of READ/WRITE/DELETE.
3283 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3285 * This expects the strange reject status of
3286 * NT_STATUS_ACCESS_DENIED, which is returned
3287 * by Windows Servers.
3289 * It won't pass against Samba as it returns
3290 * NT_STATUS_FILE_NOT_AVAILABLE. see
3291 * test_dhv2_pending2n_vs_oplock_sane().
3293 static bool test_dhv2_pending2n_vs_oplock_windows(struct torture_context
*tctx
,
3294 struct smb2_tree
*tree1
,
3295 struct smb2_tree
*tree2_1
)
3297 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3298 SMB2_OPLOCK_LEVEL_BATCH
,
3299 SMB2_OPLOCK_LEVEL_NONE
,
3300 NT_STATUS_ACCESS_DENIED
,
3305 * This tests replay with a pending open with 4 channels
3306 * and closed transports on the client and server side.
3308 * With a durablev2 request containing a create_guid,
3309 * a share_access of READ/WRITE/DELETE,
3310 * and asking for a v2 lease.
3312 * While another client holds a batch oplock.
3313 * And allows share_access of READ/WRITE/DELETE.
3315 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3317 * This expects the sane reject status of
3318 * NT_STATUS_FILE_NOT_AVAILABLE.
3320 * It won't pass against Windows as it returns
3321 * NT_STATUS_ACCESS_DENIED see
3322 * test_dhv2_pending2l_vs_oplock_windows().
3324 static bool test_dhv2_pending2l_vs_oplock_sane(struct torture_context
*tctx
,
3325 struct smb2_tree
*tree1
,
3326 struct smb2_tree
*tree2_1
)
3328 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3329 SMB2_OPLOCK_LEVEL_BATCH
,
3330 SMB2_OPLOCK_LEVEL_LEASE
,
3331 NT_STATUS_FILE_NOT_AVAILABLE
,
3336 * This tests replay with a pending open with 4 channels
3337 * and closed transports on the client and server side.
3339 * With a durablev2 request containing a create_guid,
3340 * a share_access of READ/WRITE/DELETE,
3341 * and asking for a v2 lease.
3343 * While another client holds a batch oplock.
3344 * And allows share_access of READ/WRITE/DELETE.
3346 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3348 * This expects the strange reject status of
3349 * NT_STATUS_ACCESS_DENIED, which is returned
3350 * by Windows Servers.
3352 * It won't pass against Samba as it returns
3353 * NT_STATUS_FILE_NOT_AVAILABLE. see
3354 * test_dhv2_pending2l_vs_oplock_sane().
3356 static bool test_dhv2_pending2l_vs_oplock_windows(struct torture_context
*tctx
,
3357 struct smb2_tree
*tree1
,
3358 struct smb2_tree
*tree2_1
)
3360 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3361 SMB2_OPLOCK_LEVEL_BATCH
,
3362 SMB2_OPLOCK_LEVEL_LEASE
,
3363 NT_STATUS_ACCESS_DENIED
,
3368 * This tests replay with a pending open with 4 channels
3369 * and closed transports on the client and server side.
3371 * With a durablev2 request containing a create_guid,
3372 * a share_access of READ/WRITE/DELETE,
3373 * and asking for a v2 lease.
3375 * While another client holds an RWH lease.
3376 * And allows share_access of READ/WRITE/DELETE.
3378 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3380 * This expects the sane reject status of
3381 * NT_STATUS_FILE_NOT_AVAILABLE.
3383 * It won't pass against Windows as it returns
3384 * NT_STATUS_ACCESS_DENIED see
3385 * test_dhv2_pending2l_vs_oplock_windows().
3387 static bool test_dhv2_pending2l_vs_lease_sane(struct torture_context
*tctx
,
3388 struct smb2_tree
*tree1
,
3389 struct smb2_tree
*tree2_1
)
3391 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3392 SMB2_OPLOCK_LEVEL_LEASE
,
3393 SMB2_OPLOCK_LEVEL_LEASE
,
3394 NT_STATUS_FILE_NOT_AVAILABLE
,
3399 * This tests replay with a pending open with 4 channels
3400 * and closed transports on the client and server side.
3402 * With a durablev2 request containing a create_guid,
3403 * a share_access of READ/WRITE/DELETE,
3404 * and asking for a v2 lease.
3406 * While another client holds an RWH lease.
3407 * And allows share_access of READ/WRITE/DELETE.
3409 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3411 * This expects the strange reject status of
3412 * NT_STATUS_ACCESS_DENIED, which is returned
3413 * by Windows Servers.
3415 * It won't pass against Samba as it returns
3416 * NT_STATUS_FILE_NOT_AVAILABLE. see
3417 * test_dhv2_pending2l_vs_oplock_sane().
3419 static bool test_dhv2_pending2l_vs_lease_windows(struct torture_context
*tctx
,
3420 struct smb2_tree
*tree1
,
3421 struct smb2_tree
*tree2_1
)
3423 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3424 SMB2_OPLOCK_LEVEL_LEASE
,
3425 SMB2_OPLOCK_LEVEL_LEASE
,
3426 NT_STATUS_ACCESS_DENIED
,
3431 * This tests replay with a pending open with 4 channels
3432 * and closed transports on the client and server side.
3434 * With a durablev2 request containing a create_guid,
3435 * a share_access of READ/WRITE/DELETE,
3436 * and asking for a batch oplock
3438 * While another client holds a batch oplock.
3439 * And allows share_access of READ/WRITE/DELETE.
3441 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3443 * This expects the sane reject status of
3444 * NT_STATUS_FILE_NOT_AVAILABLE.
3446 * It won't pass against Windows as it returns
3447 * NT_STATUS_ACCESS_DENIED see
3448 * test_dhv2_pending2o_vs_oplock_windows().
3450 static bool test_dhv2_pending2o_vs_oplock_sane(struct torture_context
*tctx
,
3451 struct smb2_tree
*tree1
,
3452 struct smb2_tree
*tree2_1
)
3454 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3455 SMB2_OPLOCK_LEVEL_BATCH
,
3456 SMB2_OPLOCK_LEVEL_BATCH
,
3457 NT_STATUS_FILE_NOT_AVAILABLE
,
3462 * This tests replay with a pending open with 4 channels
3463 * and closed transports on the client and server side.
3465 * With a durablev2 request containing a create_guid,
3466 * a share_access of READ/WRITE/DELETE,
3467 * and asking for a batch oplock.
3469 * While another client holds a batch oplock.
3470 * And allows share_access of READ/WRITE/DELETE.
3472 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3474 * This expects the strange reject status of
3475 * NT_STATUS_ACCESS_DENIED, which is returned
3476 * by Windows Servers.
3478 * It won't pass against Samba as it returns
3479 * NT_STATUS_FILE_NOT_AVAILABLE. see
3480 * test_dhv2_pending2o_vs_oplock_sane().
3482 static bool test_dhv2_pending2o_vs_oplock_windows(struct torture_context
*tctx
,
3483 struct smb2_tree
*tree1
,
3484 struct smb2_tree
*tree2_1
)
3486 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3487 SMB2_OPLOCK_LEVEL_BATCH
,
3488 SMB2_OPLOCK_LEVEL_BATCH
,
3489 NT_STATUS_ACCESS_DENIED
,
3494 * This tests replay with a pending open with 4 channels
3495 * and closed transports on the client and server side.
3497 * With a durablev2 request containing a create_guid,
3498 * a share_access of READ/WRITE/DELETE,
3499 * and asking for a batch oplock
3501 * While another client holds an RWH lease.
3502 * And allows share_access of READ/WRITE/DELETE.
3504 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3506 * This expects the sane reject status of
3507 * NT_STATUS_FILE_NOT_AVAILABLE.
3509 * It won't pass against Windows as it returns
3510 * NT_STATUS_ACCESS_DENIED see
3511 * test_dhv2_pending2o_vs_lease_windows().
3513 static bool test_dhv2_pending2o_vs_lease_sane(struct torture_context
*tctx
,
3514 struct smb2_tree
*tree1
,
3515 struct smb2_tree
*tree2_1
)
3517 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3518 SMB2_OPLOCK_LEVEL_LEASE
,
3519 SMB2_OPLOCK_LEVEL_BATCH
,
3520 NT_STATUS_FILE_NOT_AVAILABLE
,
3525 * This tests replay with a pending open with 4 channels
3526 * and closed transports on the client and server side.
3528 * With a durablev2 request containing a create_guid,
3529 * a share_access of READ/WRITE/DELETE,
3530 * and asking for a batch oplock.
3532 * While another client holds an RWH lease.
3533 * And allows share_access of READ/WRITE/DELETE.
3535 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3537 * This expects the strange reject status of
3538 * NT_STATUS_ACCESS_DENIED, which is returned
3539 * by Windows Servers.
3541 * It won't pass against Samba as it returns
3542 * NT_STATUS_FILE_NOT_AVAILABLE. see
3543 * test_dhv2_pending2o_vs_lease_sane().
3545 static bool test_dhv2_pending2o_vs_lease_windows(struct torture_context
*tctx
,
3546 struct smb2_tree
*tree1
,
3547 struct smb2_tree
*tree2_1
)
3549 return _test_dhv2_pending2_vs_hold(tctx
, __func__
,
3550 SMB2_OPLOCK_LEVEL_LEASE
,
3551 SMB2_OPLOCK_LEVEL_BATCH
,
3552 NT_STATUS_ACCESS_DENIED
,
3557 * This tests replay with a pending open with 4 channels
3558 * and blocked transports on the client side.
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.
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.
3573 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
3575 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
)
3583 const char *host
= torture_setting_string(tctx
, "host", NULL
);
3584 const char *share
= torture_setting_string(tctx
, "share", NULL
);
3585 struct cli_credentials
*credentials
= samba_cmdline_get_creds();
3587 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
3588 struct smb2_handle _h1
;
3589 struct smb2_handle
*h1
= NULL
;
3590 struct smb2_handle _h21
;
3591 struct smb2_handle
*h21
= NULL
;
3592 struct smb2_handle _h24
;
3593 struct smb2_handle
*h24
= NULL
;
3594 struct smb2_create io1
, io21
, io22
, io23
, io24
;
3595 struct GUID create_guid1
= GUID_random();
3596 struct GUID create_guid2
= GUID_random();
3597 struct smb2_request
*req21
= NULL
;
3600 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 uint16_t lease_epoch1
= 0;
3606 struct smb2_lease ls2
;
3607 uint64_t lease_key2
;
3608 uint16_t lease_epoch2
= 0;
3610 struct smb2_transport
*transport2_1
= tree2_1
->session
->transport
;
3611 int request_timeout2
= transport2_1
->options
.request_timeout
;
3612 struct smbcli_options options2x
;
3613 struct smb2_tree
*tree2_2
= NULL
;
3614 struct smb2_tree
*tree2_3
= NULL
;
3615 struct smb2_tree
*tree2_4
= NULL
;
3616 struct smb2_transport
*transport2_2
= NULL
;
3617 struct smb2_transport
*transport2_3
= NULL
;
3618 struct smb2_transport
*transport2_4
= NULL
;
3619 struct smb2_session
*session2_1
= tree2_1
->session
;
3620 struct smb2_session
*session2_2
= NULL
;
3621 struct smb2_session
*session2_3
= NULL
;
3622 struct smb2_session
*session2_4
= NULL
;
3623 bool block_setup
= false;
3624 bool blocked2_1
= false;
3625 bool blocked2_2
= false;
3626 bool blocked2_3
= false;
3628 const char *hold_name
= NULL
;
3630 switch (client1_level
) {
3631 case SMB2_OPLOCK_LEVEL_LEASE
:
3632 hold_name
= "RWH Lease";
3634 case SMB2_OPLOCK_LEVEL_BATCH
:
3635 hold_name
= "BATCH Oplock";
3638 smb_panic(__location__
);
3642 if (smbXcli_conn_protocol(transport1
->conn
) < PROTOCOL_SMB3_00
) {
3643 torture_skip(tctx
, "SMB 3.X Dialect family required for "
3647 server_capabilities
= smb2cli_conn_server_capabilities(transport1
->conn
);
3648 if (!(server_capabilities
& SMB2_CAP_MULTI_CHANNEL
)) {
3649 torture_skip(tctx
, "MULTI_CHANNEL are not supported");
3651 if (!(server_capabilities
& SMB2_CAP_LEASING
)) {
3652 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
||
3653 client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3654 torture_skip(tctx
, "leases are not supported");
3658 share_capabilities
= smb2cli_tcon_capabilities(tree1
->smbXcli
);
3659 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
3661 torture_skip(tctx
, talloc_asprintf(tctx
,
3662 "%s not supported on SCALEOUT share",
3666 /* Add some random component to the file name. */
3667 snprintf(fname
, sizeof(fname
), "%s\\%s_%s.dat",
3668 BASEDIR
, testname
, generate_random_str(tctx
, 8));
3670 options2x
= transport2_1
->options
;
3671 options2x
.only_negprot
= true;
3673 status
= smb2_connect(tctx
,
3675 lpcfg_smb_ports(tctx
->lp_ctx
),
3677 lpcfg_resolve_context(tctx
->lp_ctx
),
3682 lpcfg_socket_options(tctx
->lp_ctx
),
3683 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
3685 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3686 "smb2_connect failed");
3687 transport2_2
= tree2_2
->session
->transport
;
3689 session2_2
= smb2_session_channel(transport2_2
,
3690 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
3693 torture_assert(tctx
, session2_2
!= NULL
, "smb2_session_channel failed");
3695 status
= smb2_session_setup_spnego(session2_2
,
3697 0 /* previous_session_id */);
3698 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3699 "smb2_session_setup_spnego failed");
3700 tree2_2
->smbXcli
= tree2_1
->smbXcli
;
3701 tree2_2
->session
= session2_2
;
3703 status
= smb2_connect(tctx
,
3705 lpcfg_smb_ports(tctx
->lp_ctx
),
3707 lpcfg_resolve_context(tctx
->lp_ctx
),
3712 lpcfg_socket_options(tctx
->lp_ctx
),
3713 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
3715 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3716 "smb2_connect failed");
3717 transport2_3
= tree2_3
->session
->transport
;
3719 session2_3
= smb2_session_channel(transport2_3
,
3720 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
3723 torture_assert(tctx
, session2_3
!= NULL
, "smb2_session_channel failed");
3725 status
= smb2_session_setup_spnego(session2_3
,
3727 0 /* previous_session_id */);
3728 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3729 "smb2_session_setup_spnego failed");
3730 tree2_3
->smbXcli
= tree2_1
->smbXcli
;
3731 tree2_3
->session
= session2_3
;
3733 status
= smb2_connect(tctx
,
3735 lpcfg_smb_ports(tctx
->lp_ctx
),
3737 lpcfg_resolve_context(tctx
->lp_ctx
),
3742 lpcfg_socket_options(tctx
->lp_ctx
),
3743 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
3745 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3746 "smb2_connect failed");
3747 transport2_4
= tree2_4
->session
->transport
;
3749 session2_4
= smb2_session_channel(transport2_4
,
3750 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
3753 torture_assert(tctx
, session2_4
!= NULL
, "smb2_session_channel failed");
3755 status
= smb2_session_setup_spnego(session2_4
,
3757 0 /* previous_session_id */);
3758 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3759 "smb2_session_setup_spnego failed");
3760 tree2_4
->smbXcli
= tree2_1
->smbXcli
;
3761 tree2_4
->session
= session2_4
;
3763 smb2cli_session_reset_channel_sequence(session2_2
->smbXcli
, csn2
++);
3765 torture_reset_break_info(tctx
, &break_info
);
3766 break_info
.oplock_skip_ack
= true;
3767 torture_reset_lease_break_info(tctx
, &lease_break_info
);
3768 lease_break_info
.lease_skip_ack
= true;
3769 transport1
->oplock
.handler
= torture_oplock_ack_handler
;
3770 transport1
->oplock
.private_data
= tree1
;
3771 transport1
->lease
.handler
= torture_lease_handler
;
3772 transport1
->lease
.private_data
= tree1
;
3773 smb2_keepalive(transport1
);
3774 transport2_1
->oplock
.handler
= torture_oplock_ack_handler
;
3775 transport2_1
->oplock
.private_data
= tree2_1
;
3776 transport2_1
->lease
.handler
= torture_lease_handler
;
3777 transport2_1
->lease
.private_data
= tree2_1
;
3778 smb2_keepalive(transport2_1
);
3779 transport2_2
->oplock
.handler
= torture_oplock_ack_handler
;
3780 transport2_2
->oplock
.private_data
= tree2_2
;
3781 transport2_2
->lease
.handler
= torture_lease_handler
;
3782 transport2_2
->lease
.private_data
= tree2_2
;
3783 smb2_keepalive(transport2_2
);
3784 transport2_3
->oplock
.handler
= torture_oplock_ack_handler
;
3785 transport2_3
->oplock
.private_data
= tree2_3
;
3786 transport2_3
->lease
.handler
= torture_lease_handler
;
3787 transport2_3
->lease
.private_data
= tree2_3
;
3788 smb2_keepalive(transport2_3
);
3789 transport2_4
->oplock
.handler
= torture_oplock_ack_handler
;
3790 transport2_4
->oplock
.private_data
= tree2_4
;
3791 transport2_4
->lease
.handler
= torture_lease_handler
;
3792 transport2_4
->lease
.private_data
= tree2_4
;
3793 smb2_keepalive(transport2_4
);
3795 smb2_util_unlink(tree1
, fname
);
3796 status
= torture_smb2_testdir(tree1
, BASEDIR
, &_h1
);
3797 CHECK_STATUS(status
, NT_STATUS_OK
);
3798 smb2_util_close(tree1
, _h1
);
3799 CHECK_VAL(break_info
.count
, 0);
3801 lease_key1
= random();
3802 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3803 smb2_lease_v2_create(&io1
, &ls1
, false /* dir */, fname
,
3804 lease_key1
, NULL
, smb2_util_lease_state("RWH"), lease_epoch1
++);
3806 smb2_oplock_create(&io1
, fname
, SMB2_OPLOCK_LEVEL_BATCH
);
3808 io1
.in
.durable_open
= false;
3809 io1
.in
.durable_open_v2
= true;
3810 io1
.in
.persistent_open
= false;
3811 io1
.in
.create_guid
= create_guid1
;
3812 io1
.in
.timeout
= UINT32_MAX
;
3814 status
= smb2_create(tree1
, mem_ctx
, &io1
);
3815 CHECK_STATUS(status
, NT_STATUS_OK
);
3816 _h1
= io1
.out
.file
.handle
;
3818 CHECK_CREATED(&io1
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
3819 CHECK_VAL(io1
.out
.durable_open
, false);
3820 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3821 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_LEASE
);
3822 CHECK_VAL(io1
.out
.lease_response_v2
.lease_key
.data
[0], lease_key1
);
3823 CHECK_VAL(io1
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key1
);
3824 CHECK_VAL(io1
.out
.lease_response_v2
.lease_epoch
, lease_epoch1
);
3825 CHECK_VAL(io1
.out
.lease_response_v2
.lease_state
,
3826 smb2_util_lease_state("RHW"));
3828 CHECK_VAL(io1
.out
.oplock_level
, SMB2_OPLOCK_LEVEL_BATCH
);
3830 CHECK_VAL(io1
.out
.durable_open_v2
, true);
3831 CHECK_VAL(io1
.out
.timeout
, 300*1000);
3833 lease_key2
= random();
3834 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3835 smb2_lease_v2_create(&io21
, &ls2
, false /* dir */, fname
,
3836 lease_key2
, NULL
, smb2_util_lease_state("RWH"), lease_epoch2
++);
3838 smb2_oplock_create(&io21
, fname
, client2_level
);
3840 io21
.in
.durable_open
= false;
3841 io21
.in
.durable_open_v2
= true;
3842 io21
.in
.persistent_open
= false;
3843 io21
.in
.create_guid
= create_guid2
;
3844 io21
.in
.timeout
= UINT32_MAX
;
3845 io24
= io23
= io22
= io21
;
3847 req21
= smb2_create_send(tree2_1
, &io21
);
3848 torture_assert(tctx
, req21
!= NULL
, "req21");
3850 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3851 const struct smb2_lease_break
*lb
=
3852 &lease_break_info
.lease_break
;
3853 const struct smb2_lease
*l
= &lb
->current_lease
;
3854 const struct smb2_lease_key
*k
= &l
->lease_key
;
3856 torture_wait_for_lease_break(tctx
);
3857 CHECK_VAL(break_info
.count
, 0);
3858 CHECK_VAL(lease_break_info
.count
, 1);
3860 torture_assert(tctx
,
3861 lease_break_info
.lease_transport
== transport1
,
3862 "expect lease break on transport1\n");
3863 CHECK_VAL(k
->data
[0], lease_key1
);
3864 CHECK_VAL(k
->data
[1], ~lease_key1
);
3865 CHECK_VAL(lb
->new_lease_state
,
3866 smb2_util_lease_state("RH"));
3867 CHECK_VAL(lb
->break_flags
,
3868 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED
);
3869 CHECK_VAL(lb
->new_epoch
, lease_epoch1
+1);
3872 torture_wait_for_oplock_break(tctx
);
3873 CHECK_VAL(break_info
.count
, 1);
3874 CHECK_VAL(lease_break_info
.count
, 0);
3876 torture_assert(tctx
,
3877 break_info
.received_transport
== transport1
,
3878 "expect oplock break on transport1\n");
3879 CHECK_VAL(break_info
.handle
.data
[0], _h1
.data
[0]);
3880 CHECK_VAL(break_info
.handle
.data
[1], _h1
.data
[1]);
3881 CHECK_VAL(break_info
.level
, SMB2_OPLOCK_LEVEL_II
);
3884 torture_reset_break_info(tctx
, &break_info
);
3885 break_info
.oplock_skip_ack
= true;
3886 torture_reset_lease_break_info(tctx
, &lease_break_info
);
3887 lease_break_info
.lease_skip_ack
= true;
3889 WAIT_FOR_ASYNC_RESPONSE(tctx
, req21
);
3891 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3892 torture_wait_for_lease_break(tctx
);
3894 torture_wait_for_oplock_break(tctx
);
3896 CHECK_VAL(break_info
.count
, 0);
3897 CHECK_VAL(lease_break_info
.count
, 0);
3899 block_setup
= test_setup_blocked_transports(tctx
);
3900 torture_assert(tctx
, block_setup
, "test_setup_blocked_transports");
3902 blocked2_1
= _test_block_smb2_transport(tctx
, transport2_1
, "transport2_1");
3903 torture_assert_goto(tctx
, blocked2_1
, ret
, done
, "we could not block tcp transport");
3904 smb2cli_session_reset_channel_sequence(session2_1
->smbXcli
, csn2
++);
3906 smb2cli_session_start_replay(session2_2
->smbXcli
);
3907 transport2_2
->options
.request_timeout
= 5;
3908 status
= smb2_create(tree2_2
, tctx
, &io22
);
3909 transport2_2
->options
.request_timeout
= request_timeout2
;
3910 CHECK_STATUS(status
, reject_status
);
3911 smb2cli_session_stop_replay(session2_2
->smbXcli
);
3913 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3914 torture_wait_for_lease_break(tctx
);
3916 torture_wait_for_oplock_break(tctx
);
3918 CHECK_VAL(break_info
.count
, 0);
3919 CHECK_VAL(lease_break_info
.count
, 0);
3921 blocked2_2
= _test_block_smb2_transport(tctx
, transport2_2
, "transport2_2");
3922 torture_assert_goto(tctx
, blocked2_2
, ret
, done
, "we could not block tcp transport");
3923 smb2cli_session_reset_channel_sequence(session2_2
->smbXcli
, csn2
++);
3925 smb2cli_session_start_replay(session2_3
->smbXcli
);
3926 transport2_3
->options
.request_timeout
= 5;
3927 status
= smb2_create(tree2_3
, tctx
, &io23
);
3928 transport2_3
->options
.request_timeout
= request_timeout2
;
3929 CHECK_STATUS(status
, reject_status
);
3930 smb2cli_session_stop_replay(session2_3
->smbXcli
);
3932 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3933 torture_wait_for_lease_break(tctx
);
3935 torture_wait_for_oplock_break(tctx
);
3937 CHECK_VAL(break_info
.count
, 0);
3938 CHECK_VAL(lease_break_info
.count
, 0);
3940 smb2_util_close(tree1
, _h1
);
3943 status
= smb2_create_recv(req21
, tctx
, &io21
);
3944 CHECK_STATUS(status
, NT_STATUS_OK
);
3945 _h21
= io21
.out
.file
.handle
;
3947 CHECK_CREATED(&io21
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
3948 CHECK_VAL(io21
.out
.oplock_level
, client2_level
);
3949 CHECK_VAL(io21
.out
.durable_open
, false);
3950 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3951 CHECK_VAL(io21
.out
.lease_response_v2
.lease_key
.data
[0], lease_key2
);
3952 CHECK_VAL(io21
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key2
);
3953 CHECK_VAL(io21
.out
.lease_response_v2
.lease_epoch
, lease_epoch2
);
3954 CHECK_VAL(io21
.out
.lease_response_v2
.lease_state
,
3955 smb2_util_lease_state("RHW"));
3956 CHECK_VAL(io21
.out
.durable_open_v2
, true);
3957 CHECK_VAL(io21
.out
.timeout
, 300*1000);
3958 } else if (client2_level
== SMB2_OPLOCK_LEVEL_BATCH
) {
3959 CHECK_VAL(io21
.out
.durable_open_v2
, true);
3960 CHECK_VAL(io21
.out
.timeout
, 300*1000);
3962 CHECK_VAL(io21
.out
.durable_open_v2
, false);
3965 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3966 torture_wait_for_lease_break(tctx
);
3968 torture_wait_for_oplock_break(tctx
);
3970 CHECK_VAL(break_info
.count
, 0);
3971 CHECK_VAL(lease_break_info
.count
, 0);
3973 blocked2_3
= _test_block_smb2_transport(tctx
, transport2_3
, "transport2_3");
3974 torture_assert_goto(tctx
, blocked2_3
, ret
, done
, "we could not block tcp transport");
3975 smb2cli_session_reset_channel_sequence(session2_3
->smbXcli
, csn2
++);
3977 smb2cli_session_start_replay(session2_4
->smbXcli
);
3978 status
= smb2_create(tree2_4
, tctx
, &io24
);
3979 smb2cli_session_stop_replay(session2_4
->smbXcli
);
3980 CHECK_STATUS(status
, NT_STATUS_OK
);
3981 _h24
= io24
.out
.file
.handle
;
3983 CHECK_CREATED(&io24
, EXISTED
, FILE_ATTRIBUTE_ARCHIVE
);
3984 CHECK_VAL(h24
->data
[0], h21
->data
[0]);
3985 CHECK_VAL(h24
->data
[1], h21
->data
[1]);
3986 if (client2_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
3987 CHECK_VAL(io24
.out
.lease_response_v2
.lease_key
.data
[0], lease_key2
);
3988 CHECK_VAL(io24
.out
.lease_response_v2
.lease_key
.data
[1], ~lease_key2
);
3989 CHECK_VAL(io24
.out
.lease_response_v2
.lease_epoch
, lease_epoch2
);
3990 CHECK_VAL(io24
.out
.lease_response_v2
.lease_state
,
3991 smb2_util_lease_state("RHW"));
3992 CHECK_VAL(io24
.out
.durable_open_v2
, true);
3993 CHECK_VAL(io24
.out
.timeout
, 300*1000);
3994 } else if (client2_level
== SMB2_OPLOCK_LEVEL_BATCH
) {
3995 CHECK_VAL(io24
.out
.durable_open_v2
, true);
3996 CHECK_VAL(io24
.out
.timeout
, 300*1000);
3998 CHECK_VAL(io24
.out
.durable_open_v2
, false);
4001 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
4002 torture_wait_for_lease_break(tctx
);
4004 torture_wait_for_oplock_break(tctx
);
4006 CHECK_VAL(break_info
.count
, 0);
4007 CHECK_VAL(lease_break_info
.count
, 0);
4008 status
= smb2_util_close(tree2_4
, *h24
);
4009 CHECK_STATUS(status
, NT_STATUS_OK
);
4012 if (client1_level
== SMB2_OPLOCK_LEVEL_LEASE
) {
4013 torture_wait_for_lease_break(tctx
);
4015 torture_wait_for_oplock_break(tctx
);
4017 CHECK_VAL(break_info
.count
, 0);
4018 CHECK_VAL(lease_break_info
.count
, 0);
4023 _test_unblock_smb2_transport(tctx
, transport2_3
, "transport2_3");
4026 _test_unblock_smb2_transport(tctx
, transport2_2
, "transport2_2");
4029 _test_unblock_smb2_transport(tctx
, transport2_1
, "transport2_1");
4032 test_cleanup_blocked_transports(tctx
);
4035 smbXcli_conn_disconnect(transport2_1
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
4036 smbXcli_conn_disconnect(transport2_2
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
4037 smbXcli_conn_disconnect(transport2_3
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
4038 smbXcli_conn_disconnect(transport2_4
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
4041 smb2_util_close(tree1
, *h1
);
4044 smb2_deltree(tree1
, BASEDIR
);
4047 talloc_free(mem_ctx
);
4053 * This tests replay with a pending open with 4 channels
4054 * and blocked transports on the client side.
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.
4060 * While another client holds an RWH lease.
4061 * And allows share_access of READ/WRITE/DELETE.
4063 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4065 * This expects the sane reject status of
4066 * NT_STATUS_FILE_NOT_AVAILABLE.
4068 * It won't pass against Windows as it returns
4069 * NT_STATUS_ACCESS_DENIED see
4070 * test_dhv2_pending3n_vs_lease_windows().
4072 static bool test_dhv2_pending3n_vs_lease_sane(struct torture_context
*tctx
,
4073 struct smb2_tree
*tree1
,
4074 struct smb2_tree
*tree2_1
)
4076 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4077 SMB2_OPLOCK_LEVEL_LEASE
,
4078 SMB2_OPLOCK_LEVEL_NONE
,
4079 NT_STATUS_FILE_NOT_AVAILABLE
,
4084 * This tests replay with a pending open with 4 channels
4085 * and blocked transports on the client side.
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.
4091 * While another client holds an RWH lease.
4092 * And allows share_access of READ/WRITE/DELETE.
4094 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4096 * This expects the strange reject status of
4097 * NT_STATUS_ACCESS_DENIED, which is returned
4098 * by Windows Servers.
4100 * It won't pass against Samba as it returns
4101 * NT_STATUS_FILE_NOT_AVAILABLE. see
4102 * test_dhv2_pending3n_vs_lease_sane.
4104 static bool test_dhv2_pending3n_vs_lease_windows(struct torture_context
*tctx
,
4105 struct smb2_tree
*tree1
,
4106 struct smb2_tree
*tree2_1
)
4108 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4109 SMB2_OPLOCK_LEVEL_LEASE
,
4110 SMB2_OPLOCK_LEVEL_NONE
,
4111 NT_STATUS_ACCESS_DENIED
,
4116 * This tests replay with a pending open with 4 channels
4117 * and blocked transports on the client side.
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.
4123 * While another client holds a batch oplock.
4124 * And allows share_access of READ/WRITE/DELETE.
4126 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4128 * This expects the sane reject status of
4129 * NT_STATUS_FILE_NOT_AVAILABLE.
4131 * It won't pass against Windows as it returns
4132 * NT_STATUS_ACCESS_DENIED see
4133 * test_dhv2_pending3n_vs_oplock_windows().
4135 static bool test_dhv2_pending3n_vs_oplock_sane(struct torture_context
*tctx
,
4136 struct smb2_tree
*tree1
,
4137 struct smb2_tree
*tree2_1
)
4139 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4140 SMB2_OPLOCK_LEVEL_BATCH
,
4141 SMB2_OPLOCK_LEVEL_NONE
,
4142 NT_STATUS_FILE_NOT_AVAILABLE
,
4147 * This tests replay with a pending open with 4 channels
4148 * and blocked transports on the client side.
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.
4154 * While another client holds a batch oplock.
4155 * And allows share_access of READ/WRITE/DELETE.
4157 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4159 * This expects the strange reject status of
4160 * NT_STATUS_ACCESS_DENIED, which is returned
4161 * by Windows Servers.
4163 * It won't pass against Samba as it returns
4164 * NT_STATUS_FILE_NOT_AVAILABLE. see
4165 * test_dhv2_pending3n_vs_oplock_sane.
4167 static bool test_dhv2_pending3n_vs_oplock_windows(struct torture_context
*tctx
,
4168 struct smb2_tree
*tree1
,
4169 struct smb2_tree
*tree2_1
)
4171 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4172 SMB2_OPLOCK_LEVEL_BATCH
,
4173 SMB2_OPLOCK_LEVEL_NONE
,
4174 NT_STATUS_ACCESS_DENIED
,
4179 * This tests replay with a pending open with 4 channels
4180 * and blocked transports on the client side.
4182 * With a durablev2 request containing a create_guid,
4183 * a share_access of READ/WRITE/DELETE,
4184 * and asking for a v2 lease.
4186 * While another client holds a batch oplock.
4187 * And allows share_access of READ/WRITE/DELETE.
4189 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4191 * This expects the sane reject status of
4192 * NT_STATUS_FILE_NOT_AVAILABLE.
4194 * It won't pass against Windows as it returns
4195 * NT_STATUS_ACCESS_DENIED see
4196 * test_dhv2_pending3l_vs_oplock_windows().
4198 static bool test_dhv2_pending3l_vs_oplock_sane(struct torture_context
*tctx
,
4199 struct smb2_tree
*tree1
,
4200 struct smb2_tree
*tree2_1
)
4202 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4203 SMB2_OPLOCK_LEVEL_BATCH
,
4204 SMB2_OPLOCK_LEVEL_LEASE
,
4205 NT_STATUS_FILE_NOT_AVAILABLE
,
4210 * This tests replay with a pending open with 4 channels
4211 * and blocked transports on the client side.
4213 * With a durablev2 request containing a create_guid,
4214 * a share_access of READ/WRITE/DELETE,
4215 * and asking for a v2 lease.
4217 * While another client holds a batch oplock.
4218 * And allows share_access of READ/WRITE/DELETE.
4220 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4222 * This expects the strange reject status of
4223 * NT_STATUS_ACCESS_DENIED, which is returned
4224 * by Windows Servers.
4226 * It won't pass against Samba as it returns
4227 * NT_STATUS_FILE_NOT_AVAILABLE. see
4228 * test_dhv2_pending3l_vs_oplock_sane.
4230 static bool test_dhv2_pending3l_vs_oplock_windows(struct torture_context
*tctx
,
4231 struct smb2_tree
*tree1
,
4232 struct smb2_tree
*tree2_1
)
4234 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4235 SMB2_OPLOCK_LEVEL_BATCH
,
4236 SMB2_OPLOCK_LEVEL_LEASE
,
4237 NT_STATUS_ACCESS_DENIED
,
4242 * This tests replay with a pending open with 4 channels
4243 * and blocked transports on the client side.
4245 * With a durablev2 request containing a create_guid,
4246 * a share_access of READ/WRITE/DELETE,
4247 * and asking for a v2 lease.
4249 * While another client holds an RWH lease.
4250 * And allows share_access of READ/WRITE/DELETE.
4252 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4254 * This expects the sane reject status of
4255 * NT_STATUS_FILE_NOT_AVAILABLE.
4257 * It won't pass against Windows as it returns
4258 * NT_STATUS_ACCESS_DENIED see
4259 * test_dhv2_pending3l_vs_lease_windows().
4261 static bool test_dhv2_pending3l_vs_lease_sane(struct torture_context
*tctx
,
4262 struct smb2_tree
*tree1
,
4263 struct smb2_tree
*tree2_1
)
4265 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4266 SMB2_OPLOCK_LEVEL_LEASE
,
4267 SMB2_OPLOCK_LEVEL_LEASE
,
4268 NT_STATUS_FILE_NOT_AVAILABLE
,
4273 * This tests replay with a pending open with 4 channels
4274 * and blocked transports on the client side.
4276 * With a durablev2 request containing a create_guid,
4277 * a share_access of READ/WRITE/DELETE,
4278 * and asking for a v2 lease.
4280 * While another client holds an RWH lease.
4281 * And allows share_access of READ/WRITE/DELETE.
4283 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4285 * This expects the strange reject status of
4286 * NT_STATUS_ACCESS_DENIED, which is returned
4287 * by Windows Servers.
4289 * It won't pass against Samba as it returns
4290 * NT_STATUS_FILE_NOT_AVAILABLE. see
4291 * test_dhv2_pending3l_vs_lease_sane().
4293 static bool test_dhv2_pending3l_vs_lease_windows(struct torture_context
*tctx
,
4294 struct smb2_tree
*tree1
,
4295 struct smb2_tree
*tree2_1
)
4297 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4298 SMB2_OPLOCK_LEVEL_LEASE
,
4299 SMB2_OPLOCK_LEVEL_LEASE
,
4300 NT_STATUS_ACCESS_DENIED
,
4305 * This tests replay with a pending open with 4 channels
4306 * and blocked transports on the client side.
4308 * With a durablev2 request containing a create_guid,
4309 * a share_access of READ/WRITE/DELETE,
4310 * and asking for a batch oplock.
4312 * While another client holds a batch oplock.
4313 * And allows share_access of READ/WRITE/DELETE.
4315 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4317 * This expects the sane reject status of
4318 * NT_STATUS_FILE_NOT_AVAILABLE.
4320 * It won't pass against Windows as it returns
4321 * NT_STATUS_ACCESS_DENIED see
4322 * test_dhv2_pending3o_vs_oplock_windows().
4324 static bool test_dhv2_pending3o_vs_oplock_sane(struct torture_context
*tctx
,
4325 struct smb2_tree
*tree1
,
4326 struct smb2_tree
*tree2_1
)
4328 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4329 SMB2_OPLOCK_LEVEL_BATCH
,
4330 SMB2_OPLOCK_LEVEL_BATCH
,
4331 NT_STATUS_FILE_NOT_AVAILABLE
,
4336 * This tests replay with a pending open with 4 channels
4337 * and blocked transports on the client side.
4339 * With a durablev2 request containing a create_guid,
4340 * a share_access of READ/WRITE/DELETE,
4341 * and asking for a batch oplock.
4343 * While another client holds a batch oplock.
4344 * And allows share_access of READ/WRITE/DELETE.
4346 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4348 * This expects the strange reject status of
4349 * NT_STATUS_ACCESS_DENIED, which is returned
4350 * by Windows Servers.
4352 * It won't pass against Samba as it returns
4353 * NT_STATUS_FILE_NOT_AVAILABLE. see
4354 * test_dhv2_pending3o_vs_oplock_sane().
4356 static bool test_dhv2_pending3o_vs_oplock_windows(struct torture_context
*tctx
,
4357 struct smb2_tree
*tree1
,
4358 struct smb2_tree
*tree2_1
)
4360 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4361 SMB2_OPLOCK_LEVEL_BATCH
,
4362 SMB2_OPLOCK_LEVEL_BATCH
,
4363 NT_STATUS_ACCESS_DENIED
,
4368 * This tests replay with a pending open with 4 channels
4369 * and blocked transports on the client side.
4371 * With a durablev2 request containing a create_guid,
4372 * a share_access of READ/WRITE/DELETE,
4373 * and asking for a batch oplock.
4375 * While another client holds an RWH lease.
4376 * And allows share_access of READ/WRITE/DELETE.
4378 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4380 * This expects the sane reject status of
4381 * NT_STATUS_FILE_NOT_AVAILABLE.
4383 * It won't pass against Windows as it returns
4384 * NT_STATUS_ACCESS_DENIED see
4385 * test_dhv2_pending3o_vs_lease_windows().
4387 static bool test_dhv2_pending3o_vs_lease_sane(struct torture_context
*tctx
,
4388 struct smb2_tree
*tree1
,
4389 struct smb2_tree
*tree2_1
)
4391 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4392 SMB2_OPLOCK_LEVEL_LEASE
,
4393 SMB2_OPLOCK_LEVEL_BATCH
,
4394 NT_STATUS_FILE_NOT_AVAILABLE
,
4399 * This tests replay with a pending open with 4 channels
4400 * and blocked transports on the client side.
4402 * With a durablev2 request containing a create_guid,
4403 * a share_access of READ/WRITE/DELETE,
4404 * and asking for a batch oplock.
4406 * While another client holds an RWH lease.
4407 * And allows share_access of READ/WRITE/DELETE.
4409 * See https://bugzilla.samba.org/show_bug.cgi?id=14449
4411 * This expects the strange reject status of
4412 * NT_STATUS_ACCESS_DENIED, which is returned
4413 * by Windows Servers.
4415 * It won't pass against Samba as it returns
4416 * NT_STATUS_FILE_NOT_AVAILABLE. see
4417 * test_dhv2_pending3o_vs_lease_sane().
4419 static bool test_dhv2_pending3o_vs_lease_windows(struct torture_context
*tctx
,
4420 struct smb2_tree
*tree1
,
4421 struct smb2_tree
*tree2_1
)
4423 return _test_dhv2_pending3_vs_hold(tctx
, __func__
,
4424 SMB2_OPLOCK_LEVEL_LEASE
,
4425 SMB2_OPLOCK_LEVEL_BATCH
,
4426 NT_STATUS_ACCESS_DENIED
,
4430 static bool test_channel_sequence_table(struct torture_context
*tctx
,
4431 struct smb2_tree
*tree
,
4435 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
4436 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
4437 struct smb2_handle handle
;
4438 struct smb2_handle
*phandle
= NULL
;
4439 struct smb2_create io
;
4440 struct GUID create_guid
= GUID_random();
4442 const char *fname
= BASEDIR
"\\channel_sequence.dat";
4444 uint16_t limit
= UINT16_MAX
- 0x7fff;
4450 NTSTATUS expected_status
;
4454 .expected_status
= NT_STATUS_OK
,
4457 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4460 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4463 .csn_rand_high
= true,
4464 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4467 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4470 .expected_status
= NT_STATUS_OK
,
4473 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4476 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4479 .csn_rand_low
= true,
4480 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4483 .expected_status
= NT_STATUS_OK
,
4486 .expected_status
= NT_STATUS_OK
,
4489 .expected_status
= NT_STATUS_OK
,
4492 .expected_status
= NT_STATUS_OK
,
4495 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4498 .expected_status
= NT_STATUS_OK
,
4501 .expected_status
= NT_STATUS_FILE_NOT_AVAILABLE
,
4505 smb2cli_session_reset_channel_sequence(tree
->session
->smbXcli
, 0);
4507 csn
= smb2cli_session_current_channel_sequence(tree
->session
->smbXcli
);
4508 torture_comment(tctx
, "Testing create with channel sequence number: 0x%04x\n", csn
);
4510 smb2_oplock_create_share(&io
, fname
,
4511 smb2_util_share_access("RWD"),
4512 smb2_util_oplock_level("b"));
4513 io
.in
.durable_open
= false;
4514 io
.in
.durable_open_v2
= true;
4515 io
.in
.create_guid
= create_guid
;
4516 io
.in
.timeout
= UINT32_MAX
;
4518 torture_assert_ntstatus_ok_goto(tctx
,
4519 smb2_create(tree
, mem_ctx
, &io
),
4520 ret
, done
, "failed to call smb2_create");
4522 handle
= io
.out
.file
.handle
;
4525 for (i
=0; i
<ARRAY_SIZE(tests
); i
++) {
4527 const char *opstr
= "";
4528 union smb_fileinfo qfinfo
;
4532 if (tests
[i
].csn_rand_low
) {
4533 csn
= rand() % limit
;
4534 } else if (tests
[i
].csn_rand_high
) {
4535 csn
= rand() % limit
+ 0x7fff;
4545 case SMB2_OP_SETINFO
:
4552 smb2cli_session_reset_channel_sequence(tree
->session
->smbXcli
, csn
);
4553 csn
= smb2cli_session_current_channel_sequence(tree
->session
->smbXcli
);
4555 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
));
4560 smb2cli_session_start_replay(tree
->session
->smbXcli
);
4564 case SMB2_OP_WRITE
: {
4565 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, 255);
4567 generate_random_buffer(blob
.data
, blob
.length
);
4569 status
= smb2_util_write(tree
, handle
, blob
.data
, 0, blob
.length
);
4570 if (NT_STATUS_IS_OK(status
)) {
4571 struct smb2_read rd
;
4573 rd
= (struct smb2_read
) {
4574 .in
.file
.handle
= handle
,
4575 .in
.length
= blob
.length
,
4579 torture_assert_ntstatus_ok_goto(tctx
,
4580 smb2_read(tree
, tree
, &rd
),
4581 ret
, done
, "failed to read after write");
4583 torture_assert_data_blob_equal(tctx
,
4585 "read/write mismatch");
4589 case SMB2_OP_IOCTL
: {
4590 union smb_ioctl ioctl
;
4591 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
4598 status
= smb2_ioctl(tree
, mem_ctx
, &ioctl
.smb2
);
4601 case SMB2_OP_SETINFO
: {
4602 union smb_setfileinfo sfinfo
;
4603 ZERO_STRUCT(sfinfo
);
4604 sfinfo
.generic
.level
= RAW_SFILEINFO_POSITION_INFORMATION
;
4605 sfinfo
.generic
.in
.file
.handle
= handle
;
4606 sfinfo
.position_information
.in
.position
= 0x1000;
4607 status
= smb2_setinfo_file(tree
, &sfinfo
);
4614 qfinfo
= (union smb_fileinfo
) {
4615 .generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
,
4616 .generic
.in
.file
.handle
= handle
4619 torture_assert_ntstatus_ok_goto(tctx
,
4620 smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
),
4621 ret
, done
, "failed to read after write");
4624 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
4627 torture_assert_ntstatus_equal_goto(tctx
,
4628 status
, tests
[i
].expected_status
,
4629 ret
, done
, "got unexpected failure code");
4633 if (phandle
!= NULL
) {
4634 smb2_util_close(tree
, *phandle
);
4637 smb2_util_unlink(tree
, fname
);
4642 static bool test_channel_sequence(struct torture_context
*tctx
,
4643 struct smb2_tree
*tree
)
4645 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
4647 const char *fname
= BASEDIR
"\\channel_sequence.dat";
4648 struct smb2_transport
*transport1
= tree
->session
->transport
;
4649 struct smb2_handle handle
;
4650 uint16_t opcodes
[] = { SMB2_OP_WRITE
, SMB2_OP_IOCTL
, SMB2_OP_SETINFO
};
4653 if (smbXcli_conn_protocol(transport1
->conn
) < PROTOCOL_SMB3_00
) {
4654 torture_skip(tctx
, "SMB 3.X Dialect family required for "
4658 torture_comment(tctx
, "Testing channel sequence numbers\n");
4660 smbXcli_conn_set_force_channel_sequence(transport1
->conn
, true);
4662 torture_assert_ntstatus_ok_goto(tctx
,
4663 torture_smb2_testdir(tree
, BASEDIR
, &handle
),
4664 ret
, done
, "failed to setup test directory");
4666 smb2_util_close(tree
, handle
);
4667 smb2_util_unlink(tree
, fname
);
4669 for (i
=0; i
<ARRAY_SIZE(opcodes
); i
++) {
4670 torture_assert(tctx
,
4671 test_channel_sequence_table(tctx
, tree
, false, opcodes
[i
]),
4672 "failed to test CSN without replay flag");
4673 torture_assert(tctx
,
4674 test_channel_sequence_table(tctx
, tree
, true, opcodes
[i
]),
4675 "failed to test CSN with replay flag");
4680 smb2_util_unlink(tree
, fname
);
4681 smb2_deltree(tree
, BASEDIR
);
4684 talloc_free(mem_ctx
);
4690 * Test Durability V2 Create Replay Detection on Multi Channel
4692 static bool test_replay3(struct torture_context
*tctx
, struct smb2_tree
*tree1
)
4694 const char *host
= torture_setting_string(tctx
, "host", NULL
);
4695 const char *share
= torture_setting_string(tctx
, "share", NULL
);
4697 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
4698 struct smb2_handle _h
;
4699 struct smb2_handle
*h
= NULL
;
4700 struct smb2_create io
;
4701 struct GUID create_guid
= GUID_random();
4703 const char *fname
= BASEDIR
"\\replay3.dat";
4704 struct smb2_tree
*tree2
= NULL
;
4705 struct smb2_transport
*transport1
= tree1
->session
->transport
;
4706 struct smb2_transport
*transport2
= NULL
;
4707 struct smb2_session
*session1_1
= tree1
->session
;
4708 struct smb2_session
*session1_2
= NULL
;
4709 uint32_t share_capabilities
;
4711 uint32_t server_capabilities
;
4713 if (smbXcli_conn_protocol(transport1
->conn
) < PROTOCOL_SMB3_00
) {
4714 torture_skip(tctx
, "SMB 3.X Dialect family required for "
4718 server_capabilities
= smb2cli_conn_server_capabilities(
4719 tree1
->session
->transport
->conn
);
4720 if (!(server_capabilities
& SMB2_CAP_MULTI_CHANNEL
)) {
4722 "Server does not support multi-channel.");
4725 share_capabilities
= smb2cli_tcon_capabilities(tree1
->smbXcli
);
4726 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
4728 torture_reset_break_info(tctx
, &break_info
);
4729 transport1
->oplock
.handler
= torture_oplock_ack_handler
;
4730 transport1
->oplock
.private_data
= tree1
;
4732 torture_comment(tctx
, "Replay of DurableHandleReqV2 on Multi "
4734 status
= torture_smb2_testdir(tree1
, BASEDIR
, &_h
);
4735 CHECK_STATUS(status
, NT_STATUS_OK
);
4736 smb2_util_close(tree1
, _h
);
4737 smb2_util_unlink(tree1
, fname
);
4738 CHECK_VAL(break_info
.count
, 0);
4741 * use the 1st channel, 1st session
4743 smb2_oplock_create_share(&io
, fname
,
4744 smb2_util_share_access(""),
4745 smb2_util_oplock_level("b"));
4746 io
.in
.durable_open
= false;
4747 io
.in
.durable_open_v2
= true;
4748 io
.in
.persistent_open
= false;
4749 io
.in
.create_guid
= create_guid
;
4750 io
.in
.timeout
= UINT32_MAX
;
4752 tree1
->session
= session1_1
;
4753 status
= smb2_create(tree1
, mem_ctx
, &io
);
4754 CHECK_STATUS(status
, NT_STATUS_OK
);
4755 _h
= io
.out
.file
.handle
;
4757 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
4759 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("s"));
4760 CHECK_VAL(io
.out
.durable_open_v2
, false);
4761 CHECK_VAL(io
.out
.timeout
, 0);
4763 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("b"));
4764 CHECK_VAL(io
.out
.durable_open_v2
, true);
4765 CHECK_VAL(io
.out
.timeout
, 300*1000);
4767 CHECK_VAL(io
.out
.durable_open
, false);
4768 CHECK_VAL(break_info
.count
, 0);
4770 status
= smb2_connect(tctx
,
4772 lpcfg_smb_ports(tctx
->lp_ctx
),
4774 lpcfg_resolve_context(tctx
->lp_ctx
),
4775 samba_cmdline_get_creds(),
4778 &transport1
->options
,
4779 lpcfg_socket_options(tctx
->lp_ctx
),
4780 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
4782 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
4783 "smb2_connect failed");
4784 transport2
= tree2
->session
->transport
;
4786 transport2
->oplock
.handler
= torture_oplock_ack_handler
;
4787 transport2
->oplock
.private_data
= tree2
;
4790 * Now bind the 1st session to 2nd transport channel
4792 session1_2
= smb2_session_channel(transport2
,
4793 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
4795 torture_assert(tctx
, session1_2
!= NULL
, "smb2_session_channel failed");
4797 status
= smb2_session_setup_spnego(session1_2
,
4798 samba_cmdline_get_creds(),
4799 0 /* previous_session_id */);
4800 CHECK_STATUS(status
, NT_STATUS_OK
);
4803 * use the 2nd channel, 1st session
4805 tree1
->session
= session1_2
;
4806 smb2cli_session_start_replay(tree1
->session
->smbXcli
);
4807 status
= smb2_create(tree1
, mem_ctx
, &io
);
4808 smb2cli_session_stop_replay(tree1
->session
->smbXcli
);
4809 CHECK_STATUS(status
, NT_STATUS_OK
);
4810 _h
= io
.out
.file
.handle
;
4812 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
4814 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("s"));
4815 CHECK_VAL(io
.out
.durable_open_v2
, false);
4816 CHECK_VAL(io
.out
.timeout
, 0);
4818 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("b"));
4819 CHECK_VAL(io
.out
.durable_open_v2
, true);
4820 CHECK_VAL(io
.out
.timeout
, 300*1000);
4822 CHECK_VAL(io
.out
.durable_open
, false);
4823 CHECK_VAL(break_info
.count
, 0);
4825 tree1
->session
= session1_1
;
4826 smb2_util_close(tree1
, *h
);
4831 tree1
->session
= session1_1
;
4834 smb2_util_close(tree1
, *h
);
4837 smb2_util_unlink(tree1
, fname
);
4838 smb2_deltree(tree1
, BASEDIR
);
4841 talloc_free(mem_ctx
);
4847 * Test Multichannel IO Ordering using ChannelSequence/Channel Epoch number
4849 static bool test_replay4(struct torture_context
*tctx
, struct smb2_tree
*tree1
)
4851 const char *host
= torture_setting_string(tctx
, "host", NULL
);
4852 const char *share
= torture_setting_string(tctx
, "share", NULL
);
4854 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
4855 struct smb2_handle _h1
;
4856 struct smb2_handle
*h1
= NULL
;
4857 struct smb2_create io
;
4858 struct GUID create_guid
= GUID_random();
4860 struct smb2_read rd
;
4861 union smb_setfileinfo sfinfo
;
4863 const char *fname
= BASEDIR
"\\replay4.dat";
4864 struct smb2_tree
*tree2
= NULL
;
4865 struct smb2_transport
*transport1
= tree1
->session
->transport
;
4866 struct smb2_transport
*transport2
= NULL
;
4867 struct smb2_session
*session1_1
= tree1
->session
;
4868 struct smb2_session
*session1_2
= NULL
;
4870 uint32_t share_capabilities
;
4872 uint32_t server_capabilities
;
4874 if (smbXcli_conn_protocol(transport1
->conn
) < PROTOCOL_SMB3_00
) {
4875 torture_skip(tctx
, "SMB 3.X Dialect family required for "
4879 server_capabilities
= smb2cli_conn_server_capabilities(
4880 tree1
->session
->transport
->conn
);
4881 if (!(server_capabilities
& SMB2_CAP_MULTI_CHANNEL
)) {
4883 "Server does not support multi-channel.");
4886 share_capabilities
= smb2cli_tcon_capabilities(tree1
->smbXcli
);
4887 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
4889 torture_reset_break_info(tctx
, &break_info
);
4890 transport1
->oplock
.handler
= torture_oplock_ack_handler
;
4891 transport1
->oplock
.private_data
= tree1
;
4893 torture_comment(tctx
, "IO Ordering for Multi Channel\n");
4894 status
= torture_smb2_testdir(tree1
, BASEDIR
, &_h1
);
4895 CHECK_STATUS(status
, NT_STATUS_OK
);
4896 smb2_util_close(tree1
, _h1
);
4897 smb2_util_unlink(tree1
, fname
);
4898 CHECK_VAL(break_info
.count
, 0);
4901 * use the 1st channel, 1st session
4904 smb2_oplock_create_share(&io
, fname
,
4905 smb2_util_share_access(""),
4906 smb2_util_oplock_level("b"));
4907 io
.in
.durable_open
= false;
4908 io
.in
.durable_open_v2
= true;
4909 io
.in
.persistent_open
= false;
4910 io
.in
.create_guid
= create_guid
;
4911 io
.in
.timeout
= UINT32_MAX
;
4913 tree1
->session
= session1_1
;
4914 status
= smb2_create(tree1
, mem_ctx
, &io
);
4915 CHECK_STATUS(status
, NT_STATUS_OK
);
4916 _h1
= io
.out
.file
.handle
;
4918 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
4920 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("s"));
4921 CHECK_VAL(io
.out
.durable_open_v2
, false);
4922 CHECK_VAL(io
.out
.timeout
, 0);
4924 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("b"));
4925 CHECK_VAL(io
.out
.durable_open_v2
, true);
4926 CHECK_VAL(io
.out
.timeout
, 300*1000);
4928 CHECK_VAL(io
.out
.durable_open
, false);
4929 CHECK_VAL(break_info
.count
, 0);
4931 status
= smb2_util_write(tree1
, *h1
, buf
, 0, ARRAY_SIZE(buf
));
4932 CHECK_STATUS(status
, NT_STATUS_OK
);
4935 * Increment ChannelSequence so that server thinks that there's a
4938 smb2cli_session_increment_channel_sequence(tree1
->session
->smbXcli
);
4941 * Perform a Read with incremented ChannelSequence
4943 rd
= (struct smb2_read
) {
4944 .in
.file
.handle
= *h1
,
4945 .in
.length
= sizeof(buf
),
4948 status
= smb2_read(tree1
, tree1
, &rd
);
4949 CHECK_STATUS(status
, NT_STATUS_OK
);
4952 * Performing a Write with Stale ChannelSequence is not allowed by
4955 curr_cs
= smb2cli_session_reset_channel_sequence(
4956 tree1
->session
->smbXcli
, 0);
4957 status
= smb2_util_write(tree1
, *h1
, buf
, 0, ARRAY_SIZE(buf
));
4958 CHECK_STATUS(status
, NT_STATUS_FILE_NOT_AVAILABLE
);
4961 * Performing a Write Replay with Stale ChannelSequence is not allowed
4964 smb2cli_session_start_replay(tree1
->session
->smbXcli
);
4965 smb2cli_session_reset_channel_sequence(tree1
->session
->smbXcli
, 0);
4966 status
= smb2_util_write(tree1
, *h1
, buf
, 0, ARRAY_SIZE(buf
));
4967 smb2cli_session_stop_replay(tree1
->session
->smbXcli
);
4968 CHECK_STATUS(status
, NT_STATUS_FILE_NOT_AVAILABLE
);
4971 * Performing a SetInfo with stale ChannelSequence is not allowed by
4974 ZERO_STRUCT(sfinfo
);
4975 sfinfo
.generic
.level
= RAW_SFILEINFO_POSITION_INFORMATION
;
4976 sfinfo
.generic
.in
.file
.handle
= *h1
;
4977 sfinfo
.position_information
.in
.position
= 0x1000;
4978 status
= smb2_setinfo_file(tree1
, &sfinfo
);
4979 CHECK_STATUS(status
, NT_STATUS_FILE_NOT_AVAILABLE
);
4982 * Performing a Read with stale ChannelSequence is allowed
4984 rd
= (struct smb2_read
) {
4985 .in
.file
.handle
= *h1
,
4986 .in
.length
= ARRAY_SIZE(buf
),
4989 status
= smb2_read(tree1
, tree1
, &rd
);
4990 CHECK_STATUS(status
, NT_STATUS_OK
);
4992 status
= smb2_connect(tctx
,
4994 lpcfg_smb_ports(tctx
->lp_ctx
),
4996 lpcfg_resolve_context(tctx
->lp_ctx
),
4997 samba_cmdline_get_creds(),
5000 &transport1
->options
,
5001 lpcfg_socket_options(tctx
->lp_ctx
),
5002 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
5004 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
5005 "smb2_connect failed");
5006 transport2
= tree2
->session
->transport
;
5008 transport2
->oplock
.handler
= torture_oplock_ack_handler
;
5009 transport2
->oplock
.private_data
= tree2
;
5012 * Now bind the 1st session to 2nd transport channel
5014 session1_2
= smb2_session_channel(transport2
,
5015 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
5017 torture_assert(tctx
, session1_2
!= NULL
, "smb2_session_channel failed");
5019 status
= smb2_session_setup_spnego(session1_2
,
5020 samba_cmdline_get_creds(),
5021 0 /* previous_session_id */);
5022 CHECK_STATUS(status
, NT_STATUS_OK
);
5025 * use the 2nd channel, 1st session
5027 tree1
->session
= session1_2
;
5030 * Write Replay with Correct ChannelSequence is allowed by the server
5032 smb2cli_session_start_replay(tree1
->session
->smbXcli
);
5033 smb2cli_session_reset_channel_sequence(tree1
->session
->smbXcli
,
5035 status
= smb2_util_write(tree1
, *h1
, buf
, 0, ARRAY_SIZE(buf
));
5036 CHECK_STATUS(status
, NT_STATUS_OK
);
5037 smb2cli_session_stop_replay(tree1
->session
->smbXcli
);
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
5043 memset(buf
, 'r', ARRAY_SIZE(buf
));
5044 smb2cli_session_start_replay(tree1
->session
->smbXcli
);
5045 status
= smb2_util_write(tree1
, *h1
, buf
, 0, ARRAY_SIZE(buf
));
5046 CHECK_STATUS(status
, NT_STATUS_OK
);
5047 smb2cli_session_stop_replay(tree1
->session
->smbXcli
);
5050 * Read back from File to verify what was written
5052 rd
= (struct smb2_read
) {
5053 .in
.file
.handle
= *h1
,
5054 .in
.length
= ARRAY_SIZE(buf
),
5057 status
= smb2_read(tree1
, tree1
, &rd
);
5058 CHECK_STATUS(status
, NT_STATUS_OK
);
5060 if ((rd
.out
.data
.length
!= ARRAY_SIZE(buf
)) ||
5061 memcmp(rd
.out
.data
.data
, buf
, ARRAY_SIZE(buf
))) {
5062 torture_comment(tctx
, "Write Replay Data Mismatch\n");
5065 tree1
->session
= session1_1
;
5066 smb2_util_close(tree1
, *h1
);
5070 CHECK_VAL(break_info
.count
, 1);
5072 CHECK_VAL(break_info
.count
, 0);
5076 tree1
->session
= session1_1
;
5079 smb2_util_close(tree1
, *h1
);
5082 smb2_util_unlink(tree1
, fname
);
5083 smb2_deltree(tree1
, BASEDIR
);
5086 talloc_free(mem_ctx
);
5092 * Test Durability V2 Persistent Create Replay on a Single Channel
5094 static bool test_replay5(struct torture_context
*tctx
, struct smb2_tree
*tree
)
5097 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
5098 struct smb2_handle _h
;
5099 struct smb2_handle
*h
= NULL
;
5100 struct smb2_create io
;
5101 struct GUID create_guid
= GUID_random();
5103 uint32_t share_capabilities
;
5106 uint32_t server_capabilities
;
5107 const char *fname
= BASEDIR
"\\replay5.dat";
5108 struct smb2_transport
*transport
= tree
->session
->transport
;
5109 struct smbcli_options options
= tree
->session
->transport
->options
;
5110 uint8_t expect_oplock
= smb2_util_oplock_level("b");
5111 NTSTATUS expect_status
= NT_STATUS_DUPLICATE_OBJECTID
;
5113 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
5114 torture_skip(tctx
, "SMB 3.X Dialect family required for "
5118 server_capabilities
= smb2cli_conn_server_capabilities(
5119 tree
->session
->transport
->conn
);
5120 if (!(server_capabilities
& SMB2_CAP_PERSISTENT_HANDLES
)) {
5122 "Server does not support persistent handles.");
5125 share_capabilities
= smb2cli_tcon_capabilities(tree
->smbXcli
);
5127 share_is_ca
= share_capabilities
& SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY
;
5129 torture_skip(tctx
, "Share is not continuously available.");
5132 share_is_so
= share_capabilities
& SMB2_SHARE_CAP_SCALEOUT
;
5134 expect_oplock
= smb2_util_oplock_level("s");
5135 expect_status
= NT_STATUS_FILE_NOT_AVAILABLE
;
5138 torture_reset_break_info(tctx
, &break_info
);
5139 transport
->oplock
.handler
= torture_oplock_ack_handler
;
5140 transport
->oplock
.private_data
= tree
;
5142 torture_comment(tctx
, "Replay of Persistent DurableHandleReqV2 on Single "
5144 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h
);
5145 CHECK_STATUS(status
, NT_STATUS_OK
);
5146 smb2_util_close(tree
, _h
);
5147 smb2_util_unlink(tree
, fname
);
5148 CHECK_VAL(break_info
.count
, 0);
5150 smb2_oplock_create_share(&io
, fname
,
5151 smb2_util_share_access("RWD"),
5152 smb2_util_oplock_level("b"));
5153 io
.in
.durable_open
= false;
5154 io
.in
.durable_open_v2
= true;
5155 io
.in
.persistent_open
= true;
5156 io
.in
.create_guid
= create_guid
;
5157 io
.in
.timeout
= UINT32_MAX
;
5159 status
= smb2_create(tree
, mem_ctx
, &io
);
5160 CHECK_STATUS(status
, NT_STATUS_OK
);
5161 _h
= io
.out
.file
.handle
;
5163 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
5164 CHECK_VAL(io
.out
.oplock_level
, expect_oplock
);
5165 CHECK_VAL(io
.out
.durable_open
, false);
5166 CHECK_VAL(io
.out
.durable_open_v2
, true);
5167 CHECK_VAL(io
.out
.persistent_open
, true);
5168 CHECK_VAL(io
.out
.timeout
, 300*1000);
5169 CHECK_VAL(break_info
.count
, 0);
5171 /* disconnect, leaving the durable open */
5174 if (!torture_smb2_connection_ext(tctx
, 0, &options
, &tree
)) {
5175 torture_warning(tctx
, "couldn't reconnect, bailing\n");
5180 /* a re-open of a persistent handle causes an error */
5181 status
= smb2_create(tree
, mem_ctx
, &io
);
5182 CHECK_STATUS(status
, expect_status
);
5184 /* SMB2_FLAGS_REPLAY_OPERATION must be set to open the Persistent Handle */
5185 smb2cli_session_start_replay(tree
->session
->smbXcli
);
5186 smb2cli_session_increment_channel_sequence(tree
->session
->smbXcli
);
5187 status
= smb2_create(tree
, mem_ctx
, &io
);
5188 CHECK_STATUS(status
, NT_STATUS_OK
);
5189 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
5190 CHECK_VAL(io
.out
.durable_open
, false);
5191 CHECK_VAL(io
.out
.persistent_open
, true);
5192 CHECK_VAL(io
.out
.oplock_level
, expect_oplock
);
5193 _h
= io
.out
.file
.handle
;
5196 smb2_util_close(tree
, *h
);
5200 smb2_util_close(tree
, *h
);
5203 smb2_util_unlink(tree
, fname
);
5204 smb2_deltree(tree
, BASEDIR
);
5207 talloc_free(mem_ctx
);
5214 * Test Error Codes when a DurableHandleReqV2 with matching CreateGuid is
5215 * re-sent with or without SMB2_FLAGS_REPLAY_OPERATION
5217 static bool test_replay6(struct torture_context
*tctx
, struct smb2_tree
*tree
)
5220 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
5221 struct smb2_handle _h
;
5222 struct smb2_handle
*h
= NULL
;
5223 struct smb2_create io
, ref1
;
5224 union smb_fileinfo qfinfo
;
5225 struct GUID create_guid
= GUID_random();
5227 const char *fname
= BASEDIR
"\\replay6.dat";
5228 struct smb2_transport
*transport
= tree
->session
->transport
;
5230 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
5231 torture_skip(tctx
, "SMB 3.X Dialect family required for "
5235 torture_reset_break_info(tctx
, &break_info
);
5236 tree
->session
->transport
->oplock
.handler
= torture_oplock_ack_handler
;
5237 tree
->session
->transport
->oplock
.private_data
= tree
;
5239 torture_comment(tctx
, "Error Codes for DurableHandleReqV2 Replay\n");
5240 smb2_util_unlink(tree
, fname
);
5241 status
= torture_smb2_testdir(tree
, BASEDIR
, &_h
);
5242 CHECK_STATUS(status
, NT_STATUS_OK
);
5243 smb2_util_close(tree
, _h
);
5244 torture_wait_for_oplock_break(tctx
);
5245 CHECK_VAL(break_info
.count
, 0);
5246 torture_reset_break_info(tctx
, &break_info
);
5248 smb2_oplock_create_share(&io
, fname
,
5249 smb2_util_share_access("RWD"),
5250 smb2_util_oplock_level("b"));
5251 io
.in
.durable_open
= false;
5252 io
.in
.durable_open_v2
= true;
5253 io
.in
.persistent_open
= false;
5254 io
.in
.create_guid
= create_guid
;
5255 io
.in
.timeout
= UINT32_MAX
;
5257 status
= smb2_create(tree
, mem_ctx
, &io
);
5258 CHECK_STATUS(status
, NT_STATUS_OK
);
5260 _h
= io
.out
.file
.handle
;
5262 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
5263 CHECK_VAL(io
.out
.oplock_level
, smb2_util_oplock_level("b"));
5264 CHECK_VAL(io
.out
.durable_open
, false);
5265 CHECK_VAL(io
.out
.durable_open_v2
, true);
5267 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
5268 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
5269 smb2cli_session_start_replay(tree
->session
->smbXcli
);
5270 status
= smb2_create(tree
, mem_ctx
, &io
);
5271 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
5272 CHECK_STATUS(status
, NT_STATUS_OK
);
5273 CHECK_CREATE_OUT(&io
, &ref1
);
5274 torture_wait_for_oplock_break(tctx
);
5275 CHECK_VAL(break_info
.count
, 0);
5276 torture_reset_break_info(tctx
, &break_info
);
5278 qfinfo
= (union smb_fileinfo
) {
5279 .generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
,
5280 .generic
.in
.file
.handle
= *h
5282 torture_comment(tctx
, "Trying getinfo\n");
5283 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
5284 CHECK_STATUS(status
, NT_STATUS_OK
);
5285 CHECK_VAL(qfinfo
.position_information
.out
.position
, 0);
5287 smb2cli_session_start_replay(tree
->session
->smbXcli
);
5288 status
= smb2_create(tree
, mem_ctx
, &io
);
5289 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
5290 CHECK_STATUS(status
, NT_STATUS_OK
);
5291 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 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 torture_wait_for_oplock_break(tctx
);
5300 CHECK_VAL(break_info
.count
, 1);
5301 CHECK_VAL(break_info
.level
, smb2_util_oplock_level("s"));
5302 torture_reset_break_info(tctx
, &break_info
);
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
5309 status
= smb2_create(tree
, mem_ctx
, &io
);
5310 CHECK_STATUS(status
, NT_STATUS_DUPLICATE_OBJECTID
);
5311 torture_wait_for_oplock_break(tctx
);
5312 CHECK_VAL(break_info
.count
, 0);
5313 torture_reset_break_info(tctx
, &break_info
);
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.
5323 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
5324 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
5325 smb2cli_session_start_replay(tree
->session
->smbXcli
);
5326 status
= smb2_create(tree
, mem_ctx
, &io
);
5327 smb2cli_session_stop_replay(tree
->session
->smbXcli
);
5328 CHECK_STATUS(status
, NT_STATUS_OK
);
5329 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 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 torture_wait_for_oplock_break(tctx
);
5338 CHECK_VAL(break_info
.count
, 0);
5342 smb2_util_close(tree
, *h
);
5345 smb2_util_unlink(tree
, fname
);
5346 smb2_deltree(tree
, BASEDIR
);
5349 talloc_free(mem_ctx
);
5354 static bool test_replay7(struct torture_context
*tctx
, struct smb2_tree
*tree
)
5356 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
5357 struct smb2_transport
*transport
= tree
->session
->transport
;
5359 struct smb2_handle _dh
;
5360 struct smb2_handle
*dh
= NULL
;
5361 struct smb2_notify notify
;
5362 struct smb2_request
*req
;
5363 union smb_fileinfo qfinfo
;
5366 if (smbXcli_conn_protocol(transport
->conn
) < PROTOCOL_SMB3_00
) {
5367 torture_skip(tctx
, "SMB 3.X Dialect family required for "
5371 torture_comment(tctx
, "Notify across increment/decrement of csn\n");
5373 smbXcli_conn_set_force_channel_sequence(transport
->conn
, true);
5375 status
= torture_smb2_testdir(tree
, BASEDIR
, &_dh
);
5376 CHECK_STATUS(status
, NT_STATUS_OK
);
5379 notify
.in
.recursive
= 0x0000;
5380 notify
.in
.buffer_size
= 0xffff;
5381 notify
.in
.file
.handle
= _dh
;
5382 notify
.in
.completion_filter
= FILE_NOTIFY_CHANGE_FILE_NAME
;
5383 notify
.in
.unknown
= 0x00000000;
5386 * This posts a long-running request with csn==0 to "dh". Now
5387 * op->request_count==1 in smb2_server.c.
5389 smb2cli_session_reset_channel_sequence(tree
->session
->smbXcli
, 0);
5390 req
= smb2_notify_send(tree
, ¬ify
);
5392 qfinfo
= (union smb_fileinfo
) {
5393 .generic
.level
= RAW_FILEINFO_POSITION_INFORMATION
,
5394 .generic
.in
.file
.handle
= _dh
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.
5403 smb2cli_session_reset_channel_sequence(tree
->session
->smbXcli
, 30000);
5404 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
5405 CHECK_STATUS(status
, NT_STATUS_OK
);
5407 smb2cli_session_reset_channel_sequence(tree
->session
->smbXcli
, 60000);
5408 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
5409 CHECK_STATUS(status
, NT_STATUS_OK
);
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.
5418 smb2cli_session_reset_channel_sequence(tree
->session
->smbXcli
, 0);
5419 status
= smb2_getinfo_file(tree
, mem_ctx
, &qfinfo
);
5420 CHECK_STATUS(status
, NT_STATUS_OK
);
5423 * At this point op->request_count==0.
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.
5431 status
= smb2_cancel(req
);
5432 CHECK_STATUS(status
, NT_STATUS_OK
);
5434 status
= smb2_notify_recv(req
, mem_ctx
, ¬ify
);
5435 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
5441 smb2_util_close(tree
, _dh
);
5443 smb2_deltree(tree
, BASEDIR
);
5445 talloc_free(mem_ctx
);
5450 struct torture_suite
*torture_smb2_replay_init(TALLOC_CTX
*ctx
)
5452 struct torture_suite
*suite
=
5453 torture_suite_create(ctx
, "replay");
5455 torture_suite_add_1smb2_test(suite
, "replay-commands", test_replay_commands
);
5456 torture_suite_add_1smb2_test(suite
, "replay-regular", test_replay_regular
);
5457 torture_suite_add_1smb2_test(suite
, "replay-dhv2-oplock1", test_replay_dhv2_oplock1
);
5458 torture_suite_add_1smb2_test(suite
, "replay-dhv2-oplock2", test_replay_dhv2_oplock2
);
5459 torture_suite_add_1smb2_test(suite
, "replay-dhv2-oplock3", test_replay_dhv2_oplock3
);
5460 torture_suite_add_1smb2_test(suite
, "replay-dhv2-oplock-lease", test_replay_dhv2_oplock_lease
);
5461 torture_suite_add_1smb2_test(suite
, "replay-dhv2-lease1", test_replay_dhv2_lease1
);
5462 torture_suite_add_1smb2_test(suite
, "replay-dhv2-lease2", test_replay_dhv2_lease2
);
5463 torture_suite_add_1smb2_test(suite
, "replay-dhv2-lease3", test_replay_dhv2_lease3
);
5464 torture_suite_add_1smb2_test(suite
, "replay-dhv2-lease-oplock", test_replay_dhv2_lease_oplock
);
5465 torture_suite_add_2smb2_test(suite
, "dhv2-pending1n-vs-violation-lease-close-sane", test_dhv2_pending1n_vs_violation_lease_close_sane
);
5466 torture_suite_add_2smb2_test(suite
, "dhv2-pending1n-vs-violation-lease-ack-sane", test_dhv2_pending1n_vs_violation_lease_ack_sane
);
5467 torture_suite_add_2smb2_test(suite
, "dhv2-pending1n-vs-violation-lease-close-windows", test_dhv2_pending1n_vs_violation_lease_close_windows
);
5468 torture_suite_add_2smb2_test(suite
, "dhv2-pending1n-vs-violation-lease-ack-windows", test_dhv2_pending1n_vs_violation_lease_ack_windows
);
5469 torture_suite_add_2smb2_test(suite
, "dhv2-pending1n-vs-oplock-sane", test_dhv2_pending1n_vs_oplock_sane
);
5470 torture_suite_add_2smb2_test(suite
, "dhv2-pending1n-vs-oplock-windows", test_dhv2_pending1n_vs_oplock_windows
);
5471 torture_suite_add_2smb2_test(suite
, "dhv2-pending1n-vs-lease-sane", test_dhv2_pending1n_vs_lease_sane
);
5472 torture_suite_add_2smb2_test(suite
, "dhv2-pending1n-vs-lease-windows", test_dhv2_pending1n_vs_lease_windows
);
5473 torture_suite_add_2smb2_test(suite
, "dhv2-pending1l-vs-oplock-sane", test_dhv2_pending1l_vs_oplock_sane
);
5474 torture_suite_add_2smb2_test(suite
, "dhv2-pending1l-vs-oplock-windows", test_dhv2_pending1l_vs_oplock_windows
);
5475 torture_suite_add_2smb2_test(suite
, "dhv2-pending1l-vs-lease-sane", test_dhv2_pending1l_vs_lease_sane
);
5476 torture_suite_add_2smb2_test(suite
, "dhv2-pending1l-vs-lease-windows", test_dhv2_pending1l_vs_lease_windows
);
5477 torture_suite_add_2smb2_test(suite
, "dhv2-pending1o-vs-oplock-sane", test_dhv2_pending1o_vs_oplock_sane
);
5478 torture_suite_add_2smb2_test(suite
, "dhv2-pending1o-vs-oplock-windows", test_dhv2_pending1o_vs_oplock_windows
);
5479 torture_suite_add_2smb2_test(suite
, "dhv2-pending1o-vs-lease-sane", test_dhv2_pending1o_vs_lease_sane
);
5480 torture_suite_add_2smb2_test(suite
, "dhv2-pending1o-vs-lease-windows", test_dhv2_pending1o_vs_lease_windows
);
5481 torture_suite_add_2smb2_test(suite
, "dhv2-pending2n-vs-oplock-sane", test_dhv2_pending2n_vs_oplock_sane
);
5482 torture_suite_add_2smb2_test(suite
, "dhv2-pending2n-vs-oplock-windows", test_dhv2_pending2n_vs_oplock_windows
);
5483 torture_suite_add_2smb2_test(suite
, "dhv2-pending2n-vs-lease-sane", test_dhv2_pending2n_vs_lease_sane
);
5484 torture_suite_add_2smb2_test(suite
, "dhv2-pending2n-vs-lease-windows", test_dhv2_pending2n_vs_lease_windows
);
5485 torture_suite_add_2smb2_test(suite
, "dhv2-pending2l-vs-oplock-sane", test_dhv2_pending2l_vs_oplock_sane
);
5486 torture_suite_add_2smb2_test(suite
, "dhv2-pending2l-vs-oplock-windows", test_dhv2_pending2l_vs_oplock_windows
);
5487 torture_suite_add_2smb2_test(suite
, "dhv2-pending2l-vs-lease-sane", test_dhv2_pending2l_vs_lease_sane
);
5488 torture_suite_add_2smb2_test(suite
, "dhv2-pending2l-vs-lease-windows", test_dhv2_pending2l_vs_lease_windows
);
5489 torture_suite_add_2smb2_test(suite
, "dhv2-pending2o-vs-oplock-sane", test_dhv2_pending2o_vs_oplock_sane
);
5490 torture_suite_add_2smb2_test(suite
, "dhv2-pending2o-vs-oplock-windows", test_dhv2_pending2o_vs_oplock_windows
);
5491 torture_suite_add_2smb2_test(suite
, "dhv2-pending2o-vs-lease-sane", test_dhv2_pending2o_vs_lease_sane
);
5492 torture_suite_add_2smb2_test(suite
, "dhv2-pending2o-vs-lease-windows", test_dhv2_pending2o_vs_lease_windows
);
5493 torture_suite_add_2smb2_test(suite
, "dhv2-pending3n-vs-oplock-sane", test_dhv2_pending3n_vs_oplock_sane
);
5494 torture_suite_add_2smb2_test(suite
, "dhv2-pending3n-vs-oplock-windows", test_dhv2_pending3n_vs_oplock_windows
);
5495 torture_suite_add_2smb2_test(suite
, "dhv2-pending3n-vs-lease-sane", test_dhv2_pending3n_vs_lease_sane
);
5496 torture_suite_add_2smb2_test(suite
, "dhv2-pending3n-vs-lease-windows", test_dhv2_pending3n_vs_lease_windows
);
5497 torture_suite_add_2smb2_test(suite
, "dhv2-pending3l-vs-oplock-sane", test_dhv2_pending3l_vs_oplock_sane
);
5498 torture_suite_add_2smb2_test(suite
, "dhv2-pending3l-vs-oplock-windows", test_dhv2_pending3l_vs_oplock_windows
);
5499 torture_suite_add_2smb2_test(suite
, "dhv2-pending3l-vs-lease-sane", test_dhv2_pending3l_vs_lease_sane
);
5500 torture_suite_add_2smb2_test(suite
, "dhv2-pending3l-vs-lease-windows", test_dhv2_pending3l_vs_lease_windows
);
5501 torture_suite_add_2smb2_test(suite
, "dhv2-pending3o-vs-oplock-sane", test_dhv2_pending3o_vs_oplock_sane
);
5502 torture_suite_add_2smb2_test(suite
, "dhv2-pending3o-vs-oplock-windows", test_dhv2_pending3o_vs_oplock_windows
);
5503 torture_suite_add_2smb2_test(suite
, "dhv2-pending3o-vs-lease-sane", test_dhv2_pending3o_vs_lease_sane
);
5504 torture_suite_add_2smb2_test(suite
, "dhv2-pending3o-vs-lease-windows", test_dhv2_pending3o_vs_lease_windows
);
5505 torture_suite_add_1smb2_test(suite
, "channel-sequence", test_channel_sequence
);
5506 torture_suite_add_1smb2_test(suite
, "replay3", test_replay3
);
5507 torture_suite_add_1smb2_test(suite
, "replay4", test_replay4
);
5508 torture_suite_add_1smb2_test(suite
, "replay5", test_replay5
);
5509 torture_suite_add_1smb2_test(suite
, "replay6", test_replay6
);
5510 torture_suite_add_1smb2_test(suite
, "replay7", test_replay7
);
5512 suite
->description
= talloc_strdup(suite
, "SMB2 REPLAY tests");