2 Unix SMB/CIFS implementation.
4 test suite for SMB2 leases
6 Copyright (C) Zachary Loafman 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
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 "torture/util.h"
29 #include "libcli/smb/smbXcli_base.h"
30 #include "lib/param/param.h"
32 #define CHECK_VAL(v, correct) do { \
33 if ((v) != (correct)) { \
34 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
35 __location__, #v, (int)(v), (int)(correct)); \
39 #define CHECK_STATUS(status, correct) do { \
40 if (!NT_STATUS_EQUAL(status, correct)) { \
41 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
42 nt_errstr(status), nt_errstr(correct)); \
47 #define CHECK_CREATED(__io, __created, __attribute) \
49 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
50 CHECK_VAL((__io)->out.alloc_size, 0); \
51 CHECK_VAL((__io)->out.size, 0); \
52 CHECK_VAL((__io)->out.file_attr, (__attribute)); \
53 CHECK_VAL((__io)->out.reserved2, 0); \
56 #define CHECK_LEASE(__io, __state, __oplevel, __key, __flags) \
58 CHECK_VAL((__io)->out.lease_response.lease_version, 1); \
60 CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \
61 CHECK_VAL((__io)->out.lease_response.lease_key.data[0], (__key)); \
62 CHECK_VAL((__io)->out.lease_response.lease_key.data[1], ~(__key)); \
63 CHECK_VAL((__io)->out.lease_response.lease_state, smb2_util_lease_state(__state)); \
65 CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); \
66 CHECK_VAL((__io)->out.lease_response.lease_key.data[0], 0); \
67 CHECK_VAL((__io)->out.lease_response.lease_key.data[1], 0); \
68 CHECK_VAL((__io)->out.lease_response.lease_state, 0); \
71 CHECK_VAL((__io)->out.lease_response.lease_flags, (__flags)); \
72 CHECK_VAL((__io)->out.lease_response.lease_duration, 0); \
73 CHECK_VAL((__io)->out.lease_response.lease_epoch, 0); \
76 #define CHECK_LEASE_V2(__io, __state, __oplevel, __key, __flags, __parent, __epoch) \
78 CHECK_VAL((__io)->out.lease_response_v2.lease_version, 2); \
80 CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \
81 CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], (__key)); \
82 CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[1], ~(__key)); \
83 CHECK_VAL((__io)->out.lease_response_v2.lease_state, smb2_util_lease_state(__state)); \
85 CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); \
86 CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], 0); \
87 CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[1], 0); \
88 CHECK_VAL((__io)->out.lease_response_v2.lease_state, 0); \
91 CHECK_VAL((__io)->out.lease_response_v2.lease_flags, __flags); \
92 if (__flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET) { \
93 CHECK_VAL((__io)->out.lease_response_v2.parent_lease_key.data[0], (__parent)); \
94 CHECK_VAL((__io)->out.lease_response_v2.parent_lease_key.data[1], ~(__parent)); \
96 CHECK_VAL((__io)->out.lease_response_v2.lease_duration, 0); \
97 CHECK_VAL((__io)->out.lease_response_v2.lease_epoch, (__epoch)); \
100 static const uint64_t LEASE1 = 0xBADC0FFEE0DDF00Dull;
101 static const uint64_t LEASE2 = 0xDEADBEEFFEEDBEADull;
102 static const uint64_t LEASE3 = 0xDAD0FFEDD00DF00Dull;
103 static const uint64_t LEASE4 = 0xBAD0FFEDD00DF00Dull;
105 #define NREQUEST_RESULTS 8
106 static const char *request_results[NREQUEST_RESULTS][2] = {
117 static bool test_lease_request(struct torture_context *tctx,
118 struct smb2_tree *tree)
120 TALLOC_CTX *mem_ctx = talloc_new(tctx);
121 struct smb2_create io;
122 struct smb2_lease ls;
123 struct smb2_handle h1, h2;
125 const char *fname = "lease_request.dat";
126 const char *fname2 = "lease_request.2.dat";
127 const char *sname = "lease_request.dat:stream";
128 const char *dname = "lease_request.dir";
133 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
134 if (!(caps & SMB2_CAP_LEASING)) {
135 torture_skip(tctx, "leases are not supported");
138 smb2_util_unlink(tree, fname);
139 smb2_util_unlink(tree, fname2);
140 smb2_util_rmdir(tree, dname);
142 /* Win7 is happy to grant RHW leases on files. */
143 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
144 status = smb2_create(tree, mem_ctx, &io);
145 CHECK_STATUS(status, NT_STATUS_OK);
146 h1 = io.out.file.handle;
147 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
148 CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
150 /* But will reject leases on directories. */
151 if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
152 smb2_lease_create(&io, &ls, true, dname, LEASE2, smb2_util_lease_state("RHW"));
153 status = smb2_create(tree, mem_ctx, &io);
154 CHECK_STATUS(status, NT_STATUS_OK);
155 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY);
156 CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
157 smb2_util_close(tree, io.out.file.handle);
160 /* Also rejects multiple files leased under the same key. */
161 smb2_lease_create(&io, &ls, true, fname2, LEASE1, smb2_util_lease_state("RHW"));
162 status = smb2_create(tree, mem_ctx, &io);
163 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
165 /* And grants leases on streams (with separate leasekey). */
166 smb2_lease_create(&io, &ls, false, sname, LEASE2, smb2_util_lease_state("RHW"));
167 status = smb2_create(tree, mem_ctx, &io);
168 h2 = io.out.file.handle;
169 CHECK_STATUS(status, NT_STATUS_OK);
170 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
171 CHECK_LEASE(&io, "RHW", true, LEASE2, 0);
172 smb2_util_close(tree, h2);
174 smb2_util_close(tree, h1);
176 /* Now see what combos are actually granted. */
177 for (i = 0; i < NREQUEST_RESULTS; i++) {
178 torture_comment(tctx, "Requesting lease type %s(%x),"
179 " expecting %s(%x)\n",
180 request_results[i][0], smb2_util_lease_state(request_results[i][0]),
181 request_results[i][1], smb2_util_lease_state(request_results[i][1]));
182 smb2_lease_create(&io, &ls, false, fname, LEASE1,
183 smb2_util_lease_state(request_results[i][0]));
184 status = smb2_create(tree, mem_ctx, &io);
185 h2 = io.out.file.handle;
186 CHECK_STATUS(status, NT_STATUS_OK);
187 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
188 CHECK_LEASE(&io, request_results[i][1], true, LEASE1, 0);
189 smb2_util_close(tree, io.out.file.handle);
193 smb2_util_close(tree, h1);
194 smb2_util_close(tree, h2);
196 smb2_util_unlink(tree, fname);
197 smb2_util_unlink(tree, fname2);
198 smb2_util_rmdir(tree, dname);
200 talloc_free(mem_ctx);
205 static bool test_lease_upgrade(struct torture_context *tctx,
206 struct smb2_tree *tree)
208 TALLOC_CTX *mem_ctx = talloc_new(tctx);
209 struct smb2_create io;
210 struct smb2_lease ls;
211 struct smb2_handle h, hnew;
213 const char *fname = "lease_upgrade.dat";
217 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
218 if (!(caps & SMB2_CAP_LEASING)) {
219 torture_skip(tctx, "leases are not supported");
222 smb2_util_unlink(tree, fname);
224 /* Grab a RH lease. */
225 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
226 status = smb2_create(tree, mem_ctx, &io);
227 CHECK_STATUS(status, NT_STATUS_OK);
228 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
229 CHECK_LEASE(&io, "RH", true, LEASE1, 0);
230 h = io.out.file.handle;
232 /* Upgrades (sidegrades?) to RW leave us with an RH. */
233 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RW"));
234 status = smb2_create(tree, mem_ctx, &io);
235 CHECK_STATUS(status, NT_STATUS_OK);
236 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
237 CHECK_LEASE(&io, "RH", true, LEASE1, 0);
238 hnew = io.out.file.handle;
240 smb2_util_close(tree, hnew);
242 /* Upgrade to RHW lease. */
243 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
244 status = smb2_create(tree, mem_ctx, &io);
245 CHECK_STATUS(status, NT_STATUS_OK);
246 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
247 CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
248 hnew = io.out.file.handle;
250 smb2_util_close(tree, h);
253 /* Attempt to downgrade - original lease state is maintained. */
254 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
255 status = smb2_create(tree, mem_ctx, &io);
256 CHECK_STATUS(status, NT_STATUS_OK);
257 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
258 CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
259 hnew = io.out.file.handle;
261 smb2_util_close(tree, hnew);
264 smb2_util_close(tree, h);
265 smb2_util_close(tree, hnew);
267 smb2_util_unlink(tree, fname);
269 talloc_free(mem_ctx);
276 * full matrix of lease upgrade combinations
277 * (non-contended case)
279 * The summary of the behaviour is this:
280 * -------------------------------------
281 * An uncontended lease upgrade results in a change
282 * if and only if the requested lease state is
284 * - strictly a superset of the lease state already held.
286 * In that case the resulting lease state is the one
287 * requested in the upgrade.
289 struct lease_upgrade2_test {
291 const char *upgrade_to;
292 const char *expected;
295 #define NUM_LEASE_TYPES 5
296 #define NUM_UPGRADE_TESTS ( NUM_LEASE_TYPES * NUM_LEASE_TYPES )
297 struct lease_upgrade2_test lease_upgrade2_tests[NUM_UPGRADE_TESTS] = {
302 { "", "RWH", "RWH" },
308 { "R", "RWH", "RWH" },
312 { "RH", "RH", "RH" },
313 { "RH", "RW", "RH" },
314 { "RH", "RWH", "RWH" },
318 { "RW", "RH", "RW" },
319 { "RW", "RW", "RW" },
320 { "RW", "RWH", "RWH" },
322 { "RWH", "", "RWH" },
323 { "RWH", "R", "RWH" },
324 { "RWH", "RH", "RWH" },
325 { "RWH", "RW", "RWH" },
326 { "RWH", "RWH", "RWH" },
329 static bool test_lease_upgrade2(struct torture_context *tctx,
330 struct smb2_tree *tree)
332 TALLOC_CTX *mem_ctx = talloc_new(tctx);
333 struct smb2_handle h, hnew;
335 struct smb2_create io;
336 struct smb2_lease ls;
337 const char *fname = "lease_upgrade2.dat";
342 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
343 if (!(caps & SMB2_CAP_LEASING)) {
344 torture_skip(tctx, "leases are not supported");
347 for (i = 0; i < NUM_UPGRADE_TESTS; i++) {
348 struct lease_upgrade2_test t = lease_upgrade2_tests[i];
350 smb2_util_unlink(tree, fname);
353 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.initial));
354 status = smb2_create(tree, mem_ctx, &io);
355 CHECK_STATUS(status, NT_STATUS_OK);
356 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
357 CHECK_LEASE(&io, t.initial, true, LEASE1, 0);
358 h = io.out.file.handle;
361 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
362 status = smb2_create(tree, mem_ctx, &io);
363 CHECK_STATUS(status, NT_STATUS_OK);
364 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
365 CHECK_LEASE(&io, t.expected, true, LEASE1, 0);
366 hnew = io.out.file.handle;
368 smb2_util_close(tree, hnew);
369 smb2_util_close(tree, h);
373 smb2_util_close(tree, h);
374 smb2_util_close(tree, hnew);
376 smb2_util_unlink(tree, fname);
378 talloc_free(mem_ctx);
384 #define CHECK_LEASE_BREAK(__lb, __oldstate, __state, __key) \
386 uint16_t __new = smb2_util_lease_state(__state); \
387 uint16_t __old = smb2_util_lease_state(__oldstate); \
388 CHECK_VAL((__lb)->new_lease_state, __new); \
389 CHECK_VAL((__lb)->current_lease.lease_state, __old); \
390 CHECK_VAL((__lb)->current_lease.lease_key.data[0], (__key)); \
391 CHECK_VAL((__lb)->current_lease.lease_key.data[1], ~(__key)); \
392 if (__old & (SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE)) { \
393 CHECK_VAL((__lb)->break_flags, \
394 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); \
396 CHECK_VAL((__lb)->break_flags, 0); \
400 #define CHECK_LEASE_BREAK_ACK(__lba, __state, __key) \
402 CHECK_VAL((__lba)->out.reserved, 0); \
403 CHECK_VAL((__lba)->out.lease.lease_key.data[0], (__key)); \
404 CHECK_VAL((__lba)->out.lease.lease_key.data[1], ~(__key)); \
405 CHECK_VAL((__lba)->out.lease.lease_state, smb2_util_lease_state(__state)); \
406 CHECK_VAL((__lba)->out.lease.lease_flags, 0); \
407 CHECK_VAL((__lba)->out.lease.lease_duration, 0); \
410 static struct torture_lease_break {
411 struct smb2_lease_break lease_break;
412 struct smb2_transport *lease_transport;
414 struct smb2_lease_break_ack lease_break_ack;
418 struct smb2_handle oplock_handle;
419 uint8_t held_oplock_level;
420 uint8_t oplock_level;
425 #define CHECK_NO_BREAK(tctx) \
427 torture_wait_for_lease_break(tctx); \
428 CHECK_VAL(break_info.failures, 0); \
429 CHECK_VAL(break_info.count, 0); \
430 CHECK_VAL(break_info.oplock_failures, 0); \
431 CHECK_VAL(break_info.oplock_count, 0); \
434 #define CHECK_OPLOCK_BREAK(__brokento) \
436 torture_wait_for_lease_break(tctx); \
437 CHECK_VAL(break_info.oplock_count, 1); \
438 CHECK_VAL(break_info.oplock_failures, 0); \
439 CHECK_VAL(break_info.oplock_level, \
440 smb2_util_oplock_level(__brokento)); \
441 break_info.held_oplock_level = break_info.oplock_level; \
444 #define _CHECK_BREAK_INFO(__oldstate, __state, __key) \
446 torture_wait_for_lease_break(tctx); \
447 CHECK_VAL(break_info.failures, 0); \
448 CHECK_VAL(break_info.count, 1); \
449 CHECK_LEASE_BREAK(&break_info.lease_break, (__oldstate), \
450 (__state), (__key)); \
451 if (!break_info.lease_skip_ack && \
452 (break_info.lease_break.break_flags & \
453 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED)) \
455 torture_wait_for_lease_break(tctx); \
456 CHECK_LEASE_BREAK_ACK(&break_info.lease_break_ack, \
457 (__state), (__key)); \
461 #define CHECK_BREAK_INFO(__oldstate, __state, __key) \
463 _CHECK_BREAK_INFO(__oldstate, __state, __key); \
464 CHECK_VAL(break_info.lease_break.new_epoch, 0); \
467 #define CHECK_BREAK_INFO_V2(__transport, __oldstate, __state, __key, __epoch) \
469 _CHECK_BREAK_INFO(__oldstate, __state, __key); \
470 CHECK_VAL(break_info.lease_break.new_epoch, __epoch); \
471 if (!TARGET_IS_SAMBA3(tctx)) { \
472 CHECK_VAL((uintptr_t)break_info.lease_transport, \
473 (uintptr_t)__transport); \
477 static void torture_lease_break_callback(struct smb2_request *req)
481 status = smb2_lease_break_ack_recv(req, &break_info.lease_break_ack);
482 if (!NT_STATUS_IS_OK(status))
483 break_info.failures++;
488 /* a lease break request handler */
489 static bool torture_lease_handler(struct smb2_transport *transport,
490 const struct smb2_lease_break *lb,
493 struct smb2_tree *tree = private_data;
494 struct smb2_lease_break_ack io;
495 struct smb2_request *req;
497 break_info.lease_transport = transport;
498 break_info.lease_break = *lb;
501 if (break_info.lease_skip_ack) {
505 if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) {
507 io.in.lease.lease_key = lb->current_lease.lease_key;
508 io.in.lease.lease_state = lb->new_lease_state;
510 req = smb2_lease_break_ack_send(tree, &io);
511 req->async.fn = torture_lease_break_callback;
512 req->async.private_data = NULL;
520 * full matrix of lease upgrade combinations
523 * We start with 2 leases, and check how one can
526 * The summary of the behaviour is this:
527 * -------------------------------------
529 * If we have two leases (lease1 and lease2) on the same file,
530 * then attempt to upgrade lease1 results in a change if and only
531 * if the requested lease state:
533 * - is strictly a superset of lease1, and
534 * - can held together with lease2.
536 * In that case, the resuling lease state of the upgraded lease1
537 * is the state requested in the upgrade. lease2 is not broken
538 * and remains unchanged.
540 * Note that this contrasts the case of directly opening with
541 * an initial requested lease state, in which case you get that
542 * portion of the requested state that can be shared with the
543 * already existing leases (or the states that they get broken to).
545 struct lease_upgrade3_test {
548 const char *upgrade_to;
549 const char *upgraded_to;
552 #define NUM_UPGRADE3_TESTS ( 20 )
553 struct lease_upgrade3_test lease_upgrade3_tests[NUM_UPGRADE3_TESTS] = {
554 {"R", "R", "", "R" },
555 {"R", "R", "R", "R" },
556 {"R", "R", "RW", "R" },
557 {"R", "R", "RH", "RH" },
558 {"R", "R", "RHW", "R" },
560 {"R", "RH", "", "R" },
561 {"R", "RH", "R", "R" },
562 {"R", "RH", "RW", "R" },
563 {"R", "RH", "RH", "RH" },
564 {"R", "RH", "RHW", "R" },
566 {"RH", "R", "", "RH" },
567 {"RH", "R", "R", "RH" },
568 {"RH", "R", "RW", "RH" },
569 {"RH", "R", "RH", "RH" },
570 {"RH", "R", "RHW", "RH" },
572 {"RH", "RH", "", "RH" },
573 {"RH", "RH", "R", "RH" },
574 {"RH", "RH", "RW", "RH" },
575 {"RH", "RH", "RH", "RH" },
576 {"RH", "RH", "RHW", "RH" },
579 static bool test_lease_upgrade3(struct torture_context *tctx,
580 struct smb2_tree *tree)
582 TALLOC_CTX *mem_ctx = talloc_new(tctx);
583 struct smb2_handle h, h2, hnew;
585 struct smb2_create io;
586 struct smb2_lease ls;
587 const char *fname = "lease_upgrade3.dat";
592 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
593 if (!(caps & SMB2_CAP_LEASING)) {
594 torture_skip(tctx, "leases are not supported");
597 tree->session->transport->lease.handler = torture_lease_handler;
598 tree->session->transport->lease.private_data = tree;
600 smb2_util_unlink(tree, fname);
602 for (i = 0; i < NUM_UPGRADE3_TESTS; i++) {
603 struct lease_upgrade3_test t = lease_upgrade3_tests[i];
605 smb2_util_unlink(tree, fname);
607 ZERO_STRUCT(break_info);
609 /* grab first lease */
610 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.held1));
611 status = smb2_create(tree, mem_ctx, &io);
612 CHECK_STATUS(status, NT_STATUS_OK);
613 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
614 CHECK_LEASE(&io, t.held1, true, LEASE1, 0);
615 h = io.out.file.handle;
617 /* grab second lease */
618 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(t.held2));
619 status = smb2_create(tree, mem_ctx, &io);
620 CHECK_STATUS(status, NT_STATUS_OK);
621 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
622 CHECK_LEASE(&io, t.held2, true, LEASE2, 0);
623 h2 = io.out.file.handle;
625 /* no break has happened */
626 CHECK_VAL(break_info.count, 0);
627 CHECK_VAL(break_info.failures, 0);
629 /* try to upgrade lease1 */
630 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
631 status = smb2_create(tree, mem_ctx, &io);
632 CHECK_STATUS(status, NT_STATUS_OK);
633 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
634 CHECK_LEASE(&io, t.upgraded_to, true, LEASE1, 0);
635 hnew = io.out.file.handle;
637 /* no break has happened */
638 CHECK_VAL(break_info.count, 0);
639 CHECK_VAL(break_info.failures, 0);
641 smb2_util_close(tree, hnew);
642 smb2_util_close(tree, h);
643 smb2_util_close(tree, h2);
647 smb2_util_close(tree, h);
648 smb2_util_close(tree, hnew);
649 smb2_util_close(tree, h2);
651 smb2_util_unlink(tree, fname);
653 talloc_free(mem_ctx);
661 Timer handler function notifies the registering function that time is up
663 static void timeout_cb(struct tevent_context *ev,
664 struct tevent_timer *te,
665 struct timeval current_time,
668 bool *timesup = (bool *)private_data;
674 Wait a short period of time to receive a single oplock break request
676 static void torture_wait_for_lease_break(struct torture_context *tctx)
678 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
679 struct tevent_timer *te = NULL;
681 bool timesup = false;
682 int old_count = break_info.count;
684 /* Wait .1 seconds for an lease break */
685 ne = tevent_timeval_current_ofs(0, 100000);
687 te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up);
689 torture_comment(tctx, "Failed to wait for an oplock break. "
690 "test results may not be accurate.");
694 while (!timesup && break_info.count < old_count + 1) {
695 if (tevent_loop_once(tctx->ev) != 0) {
696 torture_comment(tctx, "Failed to wait for an oplock "
697 "break. test results may not be "
704 /* We don't know if the timed event fired and was freed, we received
705 * our oplock break, or some other event triggered the loop. Thus,
706 * we create a tmp_ctx to be able to safely free/remove the timed
707 * event in all 3 cases. */
708 talloc_free(tmp_ctx);
714 break_results should be read as "held lease, new lease, hold broken to, new
715 grant", i.e. { "RH", "RW", "RH", "R" } means that if key1 holds RH and key2
716 tries for RW, key1 will be broken to RH (in this case, not broken at all)
717 and key2 will be granted R.
719 Note: break_results only includes things that Win7 will actually grant (see
720 request_results above).
722 #define NBREAK_RESULTS 16
723 static const char *break_results[NBREAK_RESULTS][4] = {
724 {"R", "R", "R", "R"},
725 {"R", "RH", "R", "RH"},
726 {"R", "RW", "R", "R"},
727 {"R", "RHW", "R", "RH"},
729 {"RH", "R", "RH", "R"},
730 {"RH", "RH", "RH", "RH"},
731 {"RH", "RW", "RH", "R"},
732 {"RH", "RHW", "RH", "RH"},
734 {"RW", "R", "R", "R"},
735 {"RW", "RH", "R", "RH"},
736 {"RW", "RW", "R", "R"},
737 {"RW", "RHW", "R", "RH"},
739 {"RHW", "R", "RH", "R"},
740 {"RHW", "RH", "RH", "RH"},
741 {"RHW", "RW", "RH", "R"},
742 {"RHW", "RHW", "RH", "RH"},
745 static bool test_lease_break(struct torture_context *tctx,
746 struct smb2_tree *tree)
748 TALLOC_CTX *mem_ctx = talloc_new(tctx);
749 struct smb2_create io;
750 struct smb2_lease ls;
751 struct smb2_handle h, h2, h3;
753 const char *fname = "lease_break.dat";
758 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
759 if (!(caps & SMB2_CAP_LEASING)) {
760 torture_skip(tctx, "leases are not supported");
763 tree->session->transport->lease.handler = torture_lease_handler;
764 tree->session->transport->lease.private_data = tree;
766 smb2_util_unlink(tree, fname);
768 for (i = 0; i < NBREAK_RESULTS; i++) {
769 const char *held = break_results[i][0];
770 const char *contend = break_results[i][1];
771 const char *brokento = break_results[i][2];
772 const char *granted = break_results[i][3];
773 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
774 "expecting break to %s(%x) and grant of %s(%x)\n",
775 held, smb2_util_lease_state(held), contend, smb2_util_lease_state(contend),
776 brokento, smb2_util_lease_state(brokento), granted, smb2_util_lease_state(granted));
778 ZERO_STRUCT(break_info);
781 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(held));
782 status = smb2_create(tree, mem_ctx, &io);
783 CHECK_STATUS(status, NT_STATUS_OK);
784 h = io.out.file.handle;
785 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
786 CHECK_LEASE(&io, held, true, LEASE1, 0);
788 /* Possibly contend lease. */
789 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(contend));
790 status = smb2_create(tree, mem_ctx, &io);
791 CHECK_STATUS(status, NT_STATUS_OK);
792 h2 = io.out.file.handle;
793 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
794 CHECK_LEASE(&io, granted, true, LEASE2, 0);
796 if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) {
797 CHECK_BREAK_INFO(held, brokento, LEASE1);
799 CHECK_NO_BREAK(tctx);
802 ZERO_STRUCT(break_info);
805 Now verify that an attempt to upgrade LEASE1 results in no
806 break and no change in LEASE1.
808 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
809 status = smb2_create(tree, mem_ctx, &io);
810 CHECK_STATUS(status, NT_STATUS_OK);
811 h3 = io.out.file.handle;
812 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
813 CHECK_LEASE(&io, brokento, true, LEASE1, 0);
814 CHECK_VAL(break_info.count, 0);
815 CHECK_VAL(break_info.failures, 0);
817 smb2_util_close(tree, h);
818 smb2_util_close(tree, h2);
819 smb2_util_close(tree, h3);
821 status = smb2_util_unlink(tree, fname);
822 CHECK_STATUS(status, NT_STATUS_OK);
826 smb2_util_close(tree, h);
827 smb2_util_close(tree, h2);
829 smb2_util_unlink(tree, fname);
831 talloc_free(mem_ctx);
836 static bool test_lease_nobreakself(struct torture_context *tctx,
837 struct smb2_tree *tree)
839 TALLOC_CTX *mem_ctx = talloc_new(tctx);
840 struct smb2_create io;
841 struct smb2_lease ls;
842 struct smb2_handle h1, h2;
844 const char *fname = "lease_nobreakself.dat";
849 caps = smb2cli_conn_server_capabilities(
850 tree->session->transport->conn);
851 if (!(caps & SMB2_CAP_LEASING)) {
852 torture_skip(tctx, "leases are not supported");
855 smb2_util_unlink(tree, fname);
857 /* Win7 is happy to grant RHW leases on files. */
858 smb2_lease_create(&io, &ls, false, fname, LEASE1,
859 smb2_util_lease_state("R"));
860 status = smb2_create(tree, mem_ctx, &io);
861 CHECK_STATUS(status, NT_STATUS_OK);
862 h1 = io.out.file.handle;
863 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
864 CHECK_LEASE(&io, "R", true, LEASE1, 0);
866 smb2_lease_create(&io, &ls, false, fname, LEASE2,
867 smb2_util_lease_state("R"));
868 status = smb2_create(tree, mem_ctx, &io);
869 CHECK_STATUS(status, NT_STATUS_OK);
870 h2 = io.out.file.handle;
871 CHECK_LEASE(&io, "R", true, LEASE2, 0);
873 ZERO_STRUCT(break_info);
875 tree->session->transport->lease.handler = torture_lease_handler;
876 tree->session->transport->lease.private_data = tree;
878 /* Make sure we don't break ourselves on write */
880 status = smb2_util_write(tree, h1, &c, 0, 1);
881 CHECK_STATUS(status, NT_STATUS_OK);
882 CHECK_BREAK_INFO("R", "", LEASE2);
884 /* Try the other way round. First, upgrade LEASE2 to R again */
886 smb2_lease_create(&io, &ls, false, fname, LEASE2,
887 smb2_util_lease_state("R"));
888 status = smb2_create(tree, mem_ctx, &io);
889 CHECK_STATUS(status, NT_STATUS_OK);
890 CHECK_LEASE(&io, "R", true, LEASE2, 0);
891 smb2_util_close(tree, io.out.file.handle);
893 /* Now break LEASE1 via h2 */
895 ZERO_STRUCT(break_info);
896 status = smb2_util_write(tree, h2, &c, 0, 1);
897 CHECK_STATUS(status, NT_STATUS_OK);
898 CHECK_BREAK_INFO("R", "", LEASE1);
900 /* .. and break LEASE2 via h1 */
902 ZERO_STRUCT(break_info);
903 status = smb2_util_write(tree, h1, &c, 0, 1);
904 CHECK_STATUS(status, NT_STATUS_OK);
905 CHECK_BREAK_INFO("R", "", LEASE2);
908 smb2_util_close(tree, h2);
909 smb2_util_close(tree, h1);
910 smb2_util_unlink(tree, fname);
911 talloc_free(mem_ctx);
915 static void torture_oplock_break_callback(struct smb2_request *req)
918 struct smb2_break br;
921 status = smb2_break_recv(req, &br);
922 if (!NT_STATUS_IS_OK(status))
923 break_info.oplock_failures++;
928 /* a oplock break request handler */
929 static bool torture_oplock_handler(struct smb2_transport *transport,
930 const struct smb2_handle *handle,
931 uint8_t level, void *private_data)
933 struct smb2_tree *tree = private_data;
934 struct smb2_request *req;
935 struct smb2_break br;
937 break_info.oplock_handle = *handle;
938 break_info.oplock_level = level;
939 break_info.oplock_count++;
942 br.in.file.handle = *handle;
943 br.in.oplock_level = level;
945 if (break_info.held_oplock_level > SMB2_OPLOCK_LEVEL_II) {
946 req = smb2_break_send(tree, &br);
947 req->async.fn = torture_oplock_break_callback;
948 req->async.private_data = NULL;
950 break_info.held_oplock_level = level;
955 #define NOPLOCK_RESULTS 12
956 static const char *oplock_results[NOPLOCK_RESULTS][4] = {
957 {"R", "s", "R", "s"},
958 {"R", "x", "R", "s"},
959 {"R", "b", "R", "s"},
961 {"RH", "s", "RH", ""},
962 {"RH", "x", "RH", ""},
963 {"RH", "b", "RH", ""},
965 {"RW", "s", "R", "s"},
966 {"RW", "x", "R", "s"},
967 {"RW", "b", "R", "s"},
969 {"RHW", "s", "RH", ""},
970 {"RHW", "x", "RH", ""},
971 {"RHW", "b", "RH", ""},
974 static const char *oplock_results_2[NOPLOCK_RESULTS][4] = {
975 {"s", "R", "s", "R"},
976 {"s", "RH", "s", "R"},
977 {"s", "RW", "s", "R"},
978 {"s", "RHW", "s", "R"},
980 {"x", "R", "s", "R"},
981 {"x", "RH", "s", "R"},
982 {"x", "RW", "s", "R"},
983 {"x", "RHW", "s", "R"},
985 {"b", "R", "s", "R"},
986 {"b", "RH", "s", "R"},
987 {"b", "RW", "s", "R"},
988 {"b", "RHW", "s", "R"},
991 static bool test_lease_oplock(struct torture_context *tctx,
992 struct smb2_tree *tree)
994 TALLOC_CTX *mem_ctx = talloc_new(tctx);
995 struct smb2_create io;
996 struct smb2_lease ls;
997 struct smb2_handle h, h2;
999 const char *fname = "lease_oplock.dat";
1004 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1005 if (!(caps & SMB2_CAP_LEASING)) {
1006 torture_skip(tctx, "leases are not supported");
1009 tree->session->transport->lease.handler = torture_lease_handler;
1010 tree->session->transport->lease.private_data = tree;
1011 tree->session->transport->oplock.handler = torture_oplock_handler;
1012 tree->session->transport->oplock.private_data = tree;
1014 smb2_util_unlink(tree, fname);
1016 for (i = 0; i < NOPLOCK_RESULTS; i++) {
1017 const char *held = oplock_results[i][0];
1018 const char *contend = oplock_results[i][1];
1019 const char *brokento = oplock_results[i][2];
1020 const char *granted = oplock_results[i][3];
1021 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
1022 "expecting break to %s(%x) and grant of %s(%x)\n",
1023 held, smb2_util_lease_state(held), contend, smb2_util_oplock_level(contend),
1024 brokento, smb2_util_lease_state(brokento), granted, smb2_util_oplock_level(granted));
1026 ZERO_STRUCT(break_info);
1029 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(held));
1030 status = smb2_create(tree, mem_ctx, &io);
1031 CHECK_STATUS(status, NT_STATUS_OK);
1032 h = io.out.file.handle;
1033 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1034 CHECK_LEASE(&io, held, true, LEASE1, 0);
1036 /* Does an oplock contend the lease? */
1037 smb2_oplock_create(&io, fname, smb2_util_oplock_level(contend));
1038 status = smb2_create(tree, mem_ctx, &io);
1039 CHECK_STATUS(status, NT_STATUS_OK);
1040 h2 = io.out.file.handle;
1041 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1042 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(granted));
1043 break_info.held_oplock_level = io.out.oplock_level;
1045 if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) {
1046 CHECK_BREAK_INFO(held, brokento, LEASE1);
1048 CHECK_NO_BREAK(tctx);
1051 smb2_util_close(tree, h);
1052 smb2_util_close(tree, h2);
1054 status = smb2_util_unlink(tree, fname);
1055 CHECK_STATUS(status, NT_STATUS_OK);
1058 for (i = 0; i < NOPLOCK_RESULTS; i++) {
1059 const char *held = oplock_results_2[i][0];
1060 const char *contend = oplock_results_2[i][1];
1061 const char *brokento = oplock_results_2[i][2];
1062 const char *granted = oplock_results_2[i][3];
1063 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
1064 "expecting break to %s(%x) and grant of %s(%x)\n",
1065 held, smb2_util_oplock_level(held), contend, smb2_util_lease_state(contend),
1066 brokento, smb2_util_oplock_level(brokento), granted, smb2_util_lease_state(granted));
1068 ZERO_STRUCT(break_info);
1070 /* Grab an oplock. */
1071 smb2_oplock_create(&io, fname, smb2_util_oplock_level(held));
1072 status = smb2_create(tree, mem_ctx, &io);
1073 CHECK_STATUS(status, NT_STATUS_OK);
1074 h = io.out.file.handle;
1075 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1076 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(held));
1077 break_info.held_oplock_level = io.out.oplock_level;
1080 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(contend));
1081 status = smb2_create(tree, mem_ctx, &io);
1082 CHECK_STATUS(status, NT_STATUS_OK);
1083 h2 = io.out.file.handle;
1084 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1085 CHECK_LEASE(&io, granted, true, LEASE1, 0);
1087 if (smb2_util_oplock_level(held) != smb2_util_oplock_level(brokento)) {
1088 CHECK_OPLOCK_BREAK(brokento);
1090 CHECK_NO_BREAK(tctx);
1093 smb2_util_close(tree, h);
1094 smb2_util_close(tree, h2);
1096 status = smb2_util_unlink(tree, fname);
1097 CHECK_STATUS(status, NT_STATUS_OK);
1101 smb2_util_close(tree, h);
1102 smb2_util_close(tree, h2);
1104 smb2_util_unlink(tree, fname);
1106 talloc_free(mem_ctx);
1111 static bool test_lease_multibreak(struct torture_context *tctx,
1112 struct smb2_tree *tree)
1114 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1115 struct smb2_create io;
1116 struct smb2_lease ls;
1117 struct smb2_handle h, h2, h3;
1118 struct smb2_write w;
1120 const char *fname = "lease_multibreak.dat";
1124 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1125 if (!(caps & SMB2_CAP_LEASING)) {
1126 torture_skip(tctx, "leases are not supported");
1129 tree->session->transport->lease.handler = torture_lease_handler;
1130 tree->session->transport->lease.private_data = tree;
1131 tree->session->transport->oplock.handler = torture_oplock_handler;
1132 tree->session->transport->oplock.private_data = tree;
1134 smb2_util_unlink(tree, fname);
1136 ZERO_STRUCT(break_info);
1138 /* Grab lease, upgrade to RHW .. */
1139 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
1140 status = smb2_create(tree, mem_ctx, &io);
1141 CHECK_STATUS(status, NT_STATUS_OK);
1142 h = io.out.file.handle;
1143 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1144 CHECK_LEASE(&io, "RH", true, LEASE1, 0);
1146 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
1147 status = smb2_create(tree, mem_ctx, &io);
1148 CHECK_STATUS(status, NT_STATUS_OK);
1149 h2 = io.out.file.handle;
1150 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1151 CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
1153 /* Contend with LEASE2. */
1154 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state("RHW"));
1155 status = smb2_create(tree, mem_ctx, &io);
1156 CHECK_STATUS(status, NT_STATUS_OK);
1157 h3 = io.out.file.handle;
1158 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1159 CHECK_LEASE(&io, "RH", true, LEASE2, 0);
1161 /* Verify that we were only sent one break. */
1162 CHECK_BREAK_INFO("RHW", "RH", LEASE1);
1164 /* Drop LEASE1 / LEASE2 */
1165 status = smb2_util_close(tree, h);
1166 CHECK_STATUS(status, NT_STATUS_OK);
1167 status = smb2_util_close(tree, h2);
1168 CHECK_STATUS(status, NT_STATUS_OK);
1169 status = smb2_util_close(tree, h3);
1170 CHECK_STATUS(status, NT_STATUS_OK);
1172 ZERO_STRUCT(break_info);
1174 /* Grab an R lease. */
1175 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("R"));
1176 status = smb2_create(tree, mem_ctx, &io);
1177 CHECK_STATUS(status, NT_STATUS_OK);
1178 h = io.out.file.handle;
1179 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1180 CHECK_LEASE(&io, "R", true, LEASE1, 0);
1182 /* Grab a level-II oplock. */
1183 smb2_oplock_create(&io, fname, smb2_util_oplock_level("s"));
1184 status = smb2_create(tree, mem_ctx, &io);
1185 CHECK_STATUS(status, NT_STATUS_OK);
1186 h2 = io.out.file.handle;
1187 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1188 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1189 break_info.held_oplock_level = io.out.oplock_level;
1191 /* Verify no breaks. */
1192 CHECK_NO_BREAK(tctx);
1194 /* Open for truncate, force a break. */
1195 smb2_generic_create(&io, NULL, false, fname,
1196 NTCREATEX_DISP_OVERWRITE_IF, smb2_util_oplock_level(""), 0, 0);
1197 status = smb2_create(tree, mem_ctx, &io);
1198 CHECK_STATUS(status, NT_STATUS_OK);
1199 h3 = io.out.file.handle;
1200 CHECK_CREATED(&io, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
1201 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(""));
1202 break_info.held_oplock_level = io.out.oplock_level;
1204 /* Sleep, use a write to clear the recv queue. */
1207 w.in.file.handle = h3;
1209 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
1210 memset(w.in.data.data, 'o', w.in.data.length);
1211 status = smb2_write(tree, &w);
1212 CHECK_STATUS(status, NT_STATUS_OK);
1214 /* Verify one oplock break, one lease break. */
1215 CHECK_OPLOCK_BREAK("");
1216 CHECK_BREAK_INFO("R", "", LEASE1);
1219 smb2_util_close(tree, h);
1220 smb2_util_close(tree, h2);
1221 smb2_util_close(tree, h3);
1223 smb2_util_unlink(tree, fname);
1225 talloc_free(mem_ctx);
1230 static bool test_lease_v2_request_parent(struct torture_context *tctx,
1231 struct smb2_tree *tree)
1233 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1234 struct smb2_create io;
1235 struct smb2_lease ls;
1236 struct smb2_handle h1;
1237 uint64_t parent = LEASE2;
1239 const char *fname = "lease_v2_request_parent.dat";
1242 enum protocol_types protocol;
1244 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1245 if (!(caps & SMB2_CAP_LEASING)) {
1246 torture_skip(tctx, "leases are not supported");
1248 if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
1249 torture_skip(tctx, "directory leases are not supported");
1252 protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1253 if (protocol < PROTOCOL_SMB3_00) {
1254 torture_skip(tctx, "v2 leases are not supported");
1257 smb2_util_unlink(tree, fname);
1259 ZERO_STRUCT(break_info);
1262 smb2_lease_v2_create_share(&io, &ls, false, fname,
1263 smb2_util_share_access("RWD"),
1265 smb2_util_lease_state("RHW"),
1268 status = smb2_create(tree, mem_ctx, &io);
1269 CHECK_STATUS(status, NT_STATUS_OK);
1270 h1 = io.out.file.handle;
1271 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1272 CHECK_LEASE_V2(&io, "RHW", true, LEASE1,
1273 SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2,
1274 ls.lease_epoch + 1);
1277 smb2_util_close(tree, h1);
1278 smb2_util_unlink(tree, fname);
1280 talloc_free(mem_ctx);
1285 static bool test_lease_break_twice(struct torture_context *tctx,
1286 struct smb2_tree *tree)
1288 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1289 struct smb2_create io;
1290 struct smb2_lease ls1;
1291 struct smb2_lease ls2;
1292 struct smb2_handle h1;
1294 const char *fname = "lease_break_twice.dat";
1297 enum protocol_types protocol;
1299 caps = smb2cli_conn_server_capabilities(
1300 tree->session->transport->conn);
1301 if (!(caps & SMB2_CAP_LEASING)) {
1302 torture_skip(tctx, "leases are not supported");
1305 protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1306 if (protocol < PROTOCOL_SMB3_00) {
1307 torture_skip(tctx, "v2 leases are not supported");
1310 smb2_util_unlink(tree, fname);
1312 ZERO_STRUCT(break_info);
1315 smb2_lease_v2_create_share(
1316 &io, &ls1, false, fname, smb2_util_share_access("RWD"),
1317 LEASE1, NULL, smb2_util_lease_state("RWH"), 0x11);
1319 status = smb2_create(tree, mem_ctx, &io);
1320 CHECK_STATUS(status, NT_STATUS_OK);
1321 h1 = io.out.file.handle;
1322 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1323 CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch + 1);
1325 tree->session->transport->lease.handler = torture_lease_handler;
1326 tree->session->transport->lease.private_data = tree;
1328 ZERO_STRUCT(break_info);
1330 smb2_lease_v2_create_share(
1331 &io, &ls2, false, fname, smb2_util_share_access("R"),
1332 LEASE2, NULL, smb2_util_lease_state("RWH"), 0x22);
1334 status = smb2_create(tree, mem_ctx, &io);
1335 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
1336 CHECK_BREAK_INFO_V2(tree->session->transport,
1337 "RWH", "RW", LEASE1, ls1.lease_epoch + 2);
1339 smb2_lease_v2_create_share(
1340 &io, &ls2, false, fname, smb2_util_share_access("RWD"),
1341 LEASE2, NULL, smb2_util_lease_state("RWH"), 0x22);
1343 ZERO_STRUCT(break_info);
1345 status = smb2_create(tree, mem_ctx, &io);
1346 CHECK_STATUS(status, NT_STATUS_OK);
1347 CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch + 1);
1348 CHECK_BREAK_INFO_V2(tree->session->transport,
1349 "RW", "R", LEASE1, ls1.lease_epoch + 3);
1352 smb2_util_close(tree, h1);
1353 smb2_util_unlink(tree, fname);
1354 talloc_free(mem_ctx);
1358 static bool test_lease_v2_request(struct torture_context *tctx,
1359 struct smb2_tree *tree)
1361 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1362 struct smb2_create io;
1363 struct smb2_lease ls1, ls2, ls2t, ls3, ls4;
1364 struct smb2_handle h1, h2, h3, h4, h5;
1365 struct smb2_write w;
1367 const char *fname = "lease_v2_request.dat";
1368 const char *dname = "lease_v2_request.dir";
1369 const char *dnamefname = "lease_v2_request.dir\\lease.dat";
1370 const char *dnamefname2 = "lease_v2_request.dir\\lease2.dat";
1373 enum protocol_types protocol;
1375 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1376 if (!(caps & SMB2_CAP_LEASING)) {
1377 torture_skip(tctx, "leases are not supported");
1379 if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
1380 torture_skip(tctx, "directory leases are not supported");
1383 protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1384 if (protocol < PROTOCOL_SMB3_00) {
1385 torture_skip(tctx, "v2 leases are not supported");
1388 smb2_util_unlink(tree, fname);
1389 smb2_deltree(tree, dname);
1391 tree->session->transport->lease.handler = torture_lease_handler;
1392 tree->session->transport->lease.private_data = tree;
1393 tree->session->transport->oplock.handler = torture_oplock_handler;
1394 tree->session->transport->oplock.private_data = tree;
1396 ZERO_STRUCT(break_info);
1399 smb2_lease_v2_create_share(&io, &ls1, false, fname,
1400 smb2_util_share_access("RWD"),
1402 smb2_util_lease_state("RHW"),
1405 status = smb2_create(tree, mem_ctx, &io);
1406 CHECK_STATUS(status, NT_STATUS_OK);
1407 h1 = io.out.file.handle;
1408 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1409 CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch + 1);
1412 smb2_lease_v2_create_share(&io, &ls2, true, dname,
1413 smb2_util_share_access("RWD"),
1415 smb2_util_lease_state("RHW"),
1417 status = smb2_create(tree, mem_ctx, &io);
1418 CHECK_STATUS(status, NT_STATUS_OK);
1419 h2 = io.out.file.handle;
1420 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY);
1421 CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch + 1);
1424 smb2_lease_v2_create_share(&io, &ls3, false, dnamefname,
1425 smb2_util_share_access("RWD"),
1427 smb2_util_lease_state("RHW"),
1429 status = smb2_create(tree, mem_ctx, &io);
1430 CHECK_STATUS(status, NT_STATUS_OK);
1431 h3 = io.out.file.handle;
1432 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1433 CHECK_LEASE_V2(&io, "RHW", true, LEASE3,
1434 SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2,
1435 ls3.lease_epoch + 1);
1437 CHECK_NO_BREAK(tctx);
1440 smb2_lease_v2_create_share(&io, &ls4, false, dnamefname2,
1441 smb2_util_share_access("RWD"),
1443 smb2_util_lease_state("RHW"),
1445 status = smb2_create(tree, mem_ctx, &io);
1446 CHECK_STATUS(status, NT_STATUS_OK);
1447 h4 = io.out.file.handle;
1448 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1449 CHECK_LEASE_V2(&io, "RHW", true, LEASE4, 0, 0, ls4.lease_epoch + 1);
1451 CHECK_BREAK_INFO_V2(tree->session->transport,
1452 "RH", "", LEASE2, ls2.lease_epoch + 2);
1454 ZERO_STRUCT(break_info);
1457 smb2_lease_v2_create_share(&io, &ls2t, true, dname,
1458 smb2_util_share_access("RWD"),
1460 smb2_util_lease_state("RHW"),
1462 io.in.create_disposition = NTCREATEX_DISP_OPEN;
1463 status = smb2_create(tree, mem_ctx, &io);
1464 CHECK_STATUS(status, NT_STATUS_OK);
1465 h5 = io.out.file.handle;
1466 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_DIRECTORY);
1467 CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch+3);
1468 smb2_util_close(tree, h5);
1471 w.in.file.handle = h4;
1473 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
1474 memset(w.in.data.data, 'o', w.in.data.length);
1475 status = smb2_write(tree, &w);
1476 CHECK_STATUS(status, NT_STATUS_OK);
1479 * Wait 4 seconds in order to check if the write time
1480 * was updated (after 2 seconds).
1483 CHECK_NO_BREAK(tctx);
1486 * only the close on the modified file break the
1489 smb2_util_close(tree, h4);
1491 CHECK_BREAK_INFO_V2(tree->session->transport,
1492 "RH", "", LEASE2, ls2.lease_epoch+4);
1495 smb2_util_close(tree, h1);
1496 smb2_util_close(tree, h2);
1497 smb2_util_close(tree, h3);
1498 smb2_util_close(tree, h4);
1499 smb2_util_close(tree, h5);
1501 smb2_util_unlink(tree, fname);
1502 smb2_deltree(tree, dname);
1504 talloc_free(mem_ctx);
1509 static bool test_lease_v2_epoch1(struct torture_context *tctx,
1510 struct smb2_tree *tree)
1512 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1513 struct smb2_create io;
1514 struct smb2_lease ls;
1515 struct smb2_handle h;
1516 const char *fname = "lease_v2_epoch1.dat";
1520 enum protocol_types protocol;
1522 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1523 if (!(caps & SMB2_CAP_LEASING)) {
1524 torture_skip(tctx, "leases are not supported");
1527 protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1528 if (protocol < PROTOCOL_SMB3_00) {
1529 torture_skip(tctx, "v2 leases are not supported");
1532 smb2_util_unlink(tree, fname);
1534 tree->session->transport->lease.handler = torture_lease_handler;
1535 tree->session->transport->lease.private_data = tree;
1536 tree->session->transport->oplock.handler = torture_oplock_handler;
1537 tree->session->transport->oplock.private_data = tree;
1539 ZERO_STRUCT(break_info);
1542 smb2_lease_v2_create_share(&io, &ls, false, fname,
1543 smb2_util_share_access("RWD"),
1545 smb2_util_lease_state("RHW"),
1547 status = smb2_create(tree, mem_ctx, &io);
1548 CHECK_STATUS(status, NT_STATUS_OK);
1549 h = io.out.file.handle;
1550 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1551 CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls.lease_epoch + 1);
1552 smb2_util_close(tree, h);
1553 smb2_util_unlink(tree, fname);
1555 smb2_lease_v2_create_share(&io, &ls, false, fname,
1556 smb2_util_share_access("RWD"),
1558 smb2_util_lease_state("RHW"),
1561 status = smb2_create(tree, mem_ctx, &io);
1562 CHECK_STATUS(status, NT_STATUS_OK);
1563 h = io.out.file.handle;
1564 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1565 CHECK_LEASE_V2(&io, "RWH", true, LEASE1, 0, 0, ls.lease_epoch + 1);
1566 smb2_util_close(tree, h);
1569 smb2_util_unlink(tree, fname);
1570 talloc_free(mem_ctx);
1574 static bool test_lease_v2_epoch2(struct torture_context *tctx,
1575 struct smb2_tree *tree)
1577 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1578 struct smb2_create io;
1579 struct smb2_lease ls1v2, ls1v2t, ls1v1;
1580 struct smb2_handle hv2 = {}, hv1 = {};
1581 const char *fname = "lease_v2_epoch2.dat";
1585 enum protocol_types protocol;
1587 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1588 if (!(caps & SMB2_CAP_LEASING)) {
1589 torture_skip(tctx, "leases are not supported");
1592 protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1593 if (protocol < PROTOCOL_SMB3_00) {
1594 torture_skip(tctx, "v2 leases are not supported");
1597 smb2_util_unlink(tree, fname);
1599 tree->session->transport->lease.handler = torture_lease_handler;
1600 tree->session->transport->lease.private_data = tree;
1601 tree->session->transport->oplock.handler = torture_oplock_handler;
1602 tree->session->transport->oplock.private_data = tree;
1604 ZERO_STRUCT(break_info);
1607 smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1608 smb2_util_share_access("RWD"),
1610 smb2_util_lease_state("R"),
1612 status = smb2_create(tree, mem_ctx, &io);
1613 CHECK_STATUS(status, NT_STATUS_OK);
1614 hv2 = io.out.file.handle;
1615 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1616 CHECK_LEASE_V2(&io, "R", true, LEASE1, 0, 0, ls1v2.lease_epoch + 1);
1619 smb2_lease_create_share(&io, &ls1v1, false, fname,
1620 smb2_util_share_access("RWD"),
1622 smb2_util_lease_state("RH"));
1623 status = smb2_create(tree, mem_ctx, &io);
1624 CHECK_STATUS(status, NT_STATUS_OK);
1625 hv1 = io.out.file.handle;
1626 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1627 CHECK_LEASE_V2(&io, "RH", true, LEASE1, 0, 0, ls1v2.lease_epoch + 2);
1629 smb2_util_close(tree, hv2);
1632 smb2_lease_v2_create_share(&io, &ls1v2t, false, fname,
1633 smb2_util_share_access("RWD"),
1635 smb2_util_lease_state("RHW"),
1637 status = smb2_create(tree, mem_ctx, &io);
1638 CHECK_STATUS(status, NT_STATUS_OK);
1639 hv2 = io.out.file.handle;
1640 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1641 CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1v2.lease_epoch + 3);
1643 smb2_util_close(tree, hv2);
1645 smb2_oplock_create(&io, fname, SMB2_OPLOCK_LEVEL_NONE);
1646 status = smb2_create(tree, mem_ctx, &io);
1647 CHECK_STATUS(status, NT_STATUS_OK);
1648 hv2 = io.out.file.handle;
1649 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1650 CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1652 CHECK_BREAK_INFO_V2(tree->session->transport,
1653 "RWH", "RH", LEASE1, ls1v2.lease_epoch + 4);
1655 smb2_util_close(tree, hv2);
1656 smb2_util_close(tree, hv1);
1659 smb2_lease_create_share(&io, &ls1v1, false, fname,
1660 smb2_util_share_access("RWD"),
1662 smb2_util_lease_state("RHW"));
1663 status = smb2_create(tree, mem_ctx, &io);
1664 CHECK_STATUS(status, NT_STATUS_OK);
1665 hv1 = io.out.file.handle;
1666 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1667 CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
1669 smb2_util_close(tree, hv1);
1672 smb2_util_close(tree, hv2);
1673 smb2_util_close(tree, hv1);
1674 smb2_util_unlink(tree, fname);
1675 talloc_free(mem_ctx);
1679 static bool test_lease_v2_epoch3(struct torture_context *tctx,
1680 struct smb2_tree *tree)
1682 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1683 struct smb2_create io;
1684 struct smb2_lease ls1v1 = {}, ls1v1t = {},ls1v2 = {};
1685 struct smb2_handle hv1 = {}, hv2 = {};
1686 const char *fname = "lease_v2_epoch3.dat";
1690 enum protocol_types protocol;
1692 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1693 if (!(caps & SMB2_CAP_LEASING)) {
1694 torture_skip(tctx, "leases are not supported");
1697 protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1698 if (protocol < PROTOCOL_SMB3_00) {
1699 torture_skip(tctx, "v2 leases are not supported");
1702 smb2_util_unlink(tree, fname);
1704 tree->session->transport->lease.handler = torture_lease_handler;
1705 tree->session->transport->lease.private_data = tree;
1706 tree->session->transport->oplock.handler = torture_oplock_handler;
1707 tree->session->transport->oplock.private_data = tree;
1709 ZERO_STRUCT(break_info);
1712 smb2_lease_create_share(&io, &ls1v1, false, fname,
1713 smb2_util_share_access("RWD"),
1715 smb2_util_lease_state("R"));
1716 status = smb2_create(tree, mem_ctx, &io);
1717 CHECK_STATUS(status, NT_STATUS_OK);
1718 hv1 = io.out.file.handle;
1719 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1720 CHECK_LEASE(&io, "R", true, LEASE1, 0);
1723 smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1724 smb2_util_share_access("RWD"),
1726 smb2_util_lease_state("RW"),
1728 status = smb2_create(tree, mem_ctx, &io);
1729 CHECK_STATUS(status, NT_STATUS_OK);
1730 hv2 = io.out.file.handle;
1731 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1732 CHECK_LEASE(&io, "RW", true, LEASE1, 0);
1734 smb2_util_close(tree, hv1);
1737 smb2_lease_create_share(&io, &ls1v1t, false, fname,
1738 smb2_util_share_access("RWD"),
1740 smb2_util_lease_state("RWH"));
1741 status = smb2_create(tree, mem_ctx, &io);
1742 CHECK_STATUS(status, NT_STATUS_OK);
1743 hv1 = io.out.file.handle;
1744 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1745 CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
1747 smb2_util_close(tree, hv1);
1749 smb2_oplock_create(&io, fname, SMB2_OPLOCK_LEVEL_NONE);
1750 status = smb2_create(tree, mem_ctx, &io);
1751 CHECK_STATUS(status, NT_STATUS_OK);
1752 hv1 = io.out.file.handle;
1753 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1754 CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1756 CHECK_BREAK_INFO("RWH", "RH", LEASE1);
1758 smb2_util_close(tree, hv1);
1759 smb2_util_close(tree, hv2);
1762 smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1763 smb2_util_share_access("RWD"),
1765 smb2_util_lease_state("RWH"),
1767 status = smb2_create(tree, mem_ctx, &io);
1768 CHECK_STATUS(status, NT_STATUS_OK);
1769 hv2 = io.out.file.handle;
1770 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1771 CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1v2.lease_epoch + 1);
1772 smb2_util_close(tree, hv2);
1775 smb2_util_close(tree, hv2);
1776 smb2_util_close(tree, hv1);
1777 smb2_util_unlink(tree, fname);
1778 talloc_free(mem_ctx);
1782 static bool test_lease_breaking1(struct torture_context *tctx,
1783 struct smb2_tree *tree)
1785 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1786 struct smb2_create io1 = {};
1787 struct smb2_create io2 = {};
1788 struct smb2_lease ls1 = {};
1789 struct smb2_handle h1a = {};
1790 struct smb2_handle h1b = {};
1791 struct smb2_handle h2 = {};
1792 struct smb2_request *req2 = NULL;
1793 struct smb2_lease_break_ack ack = {};
1794 const char *fname = "lease_breaking1.dat";
1799 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1800 if (!(caps & SMB2_CAP_LEASING)) {
1801 torture_skip(tctx, "leases are not supported");
1804 smb2_util_unlink(tree, fname);
1806 tree->session->transport->lease.handler = torture_lease_handler;
1807 tree->session->transport->lease.private_data = tree;
1808 tree->session->transport->oplock.handler = torture_oplock_handler;
1809 tree->session->transport->oplock.private_data = tree;
1812 * we defer acking the lease break.
1814 ZERO_STRUCT(break_info);
1815 break_info.lease_skip_ack = true;
1817 smb2_lease_create_share(&io1, &ls1, false, fname,
1818 smb2_util_share_access("RWD"),
1820 smb2_util_lease_state("RWH"));
1821 status = smb2_create(tree, mem_ctx, &io1);
1822 CHECK_STATUS(status, NT_STATUS_OK);
1823 h1a = io1.out.file.handle;
1824 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1825 CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
1828 * a conflicting open is blocked until we ack the
1831 smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
1832 req2 = smb2_create_send(tree, &io2);
1833 torture_assert(tctx, req2 != NULL, "smb2_create_send");
1836 * we got the lease break, but defer the ack.
1838 CHECK_BREAK_INFO("RWH", "RH", LEASE1);
1840 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1842 ack.in.lease.lease_key =
1843 break_info.lease_break.current_lease.lease_key;
1844 ack.in.lease.lease_state =
1845 break_info.lease_break.new_lease_state;
1846 ZERO_STRUCT(break_info);
1849 * a open using the same lease key is still works,
1850 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
1852 status = smb2_create(tree, mem_ctx, &io1);
1853 CHECK_STATUS(status, NT_STATUS_OK);
1854 h1b = io1.out.file.handle;
1855 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1856 CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
1857 smb2_util_close(tree, h1b);
1859 CHECK_NO_BREAK(tctx);
1861 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1864 * We ack the lease break.
1866 status = smb2_lease_break_ack(tree, &ack);
1867 CHECK_STATUS(status, NT_STATUS_OK);
1868 CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
1870 torture_assert(tctx, req2->cancel.can_cancel,
1873 status = smb2_create_recv(req2, tctx, &io2);
1874 CHECK_STATUS(status, NT_STATUS_OK);
1875 h2 = io2.out.file.handle;
1876 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1877 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1879 CHECK_NO_BREAK(tctx);
1881 smb2_util_close(tree, h1a);
1882 smb2_util_close(tree, h1b);
1883 smb2_util_close(tree, h2);
1884 smb2_util_unlink(tree, fname);
1885 talloc_free(mem_ctx);
1889 static bool test_lease_breaking2(struct torture_context *tctx,
1890 struct smb2_tree *tree)
1892 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1893 struct smb2_create io1 = {};
1894 struct smb2_create io2 = {};
1895 struct smb2_lease ls1 = {};
1896 struct smb2_handle h1a = {};
1897 struct smb2_handle h1b = {};
1898 struct smb2_handle h2 = {};
1899 struct smb2_request *req2 = NULL;
1900 struct smb2_lease_break_ack ack = {};
1901 const char *fname = "lease_breaking2.dat";
1906 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1907 if (!(caps & SMB2_CAP_LEASING)) {
1908 torture_skip(tctx, "leases are not supported");
1911 smb2_util_unlink(tree, fname);
1913 tree->session->transport->lease.handler = torture_lease_handler;
1914 tree->session->transport->lease.private_data = tree;
1915 tree->session->transport->oplock.handler = torture_oplock_handler;
1916 tree->session->transport->oplock.private_data = tree;
1919 * we defer acking the lease break.
1921 ZERO_STRUCT(break_info);
1922 break_info.lease_skip_ack = true;
1924 smb2_lease_create_share(&io1, &ls1, false, fname,
1925 smb2_util_share_access("RWD"),
1927 smb2_util_lease_state("RWH"));
1928 status = smb2_create(tree, mem_ctx, &io1);
1929 CHECK_STATUS(status, NT_STATUS_OK);
1930 h1a = io1.out.file.handle;
1931 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1932 CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
1935 * a conflicting open is blocked until we ack the
1938 smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
1939 io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1940 req2 = smb2_create_send(tree, &io2);
1941 torture_assert(tctx, req2 != NULL, "smb2_create_send");
1944 * we got the lease break, but defer the ack.
1946 CHECK_BREAK_INFO("RWH", "", LEASE1);
1948 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1950 ack.in.lease.lease_key =
1951 break_info.lease_break.current_lease.lease_key;
1952 ZERO_STRUCT(break_info);
1955 * a open using the same lease key is still works,
1956 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
1958 status = smb2_create(tree, mem_ctx, &io1);
1959 CHECK_STATUS(status, NT_STATUS_OK);
1960 h1b = io1.out.file.handle;
1961 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1962 CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
1963 smb2_util_close(tree, h1b);
1965 CHECK_NO_BREAK(tctx);
1967 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1970 * We ack the lease break.
1972 ack.in.lease.lease_state =
1973 SMB2_LEASE_READ | SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE;
1974 status = smb2_lease_break_ack(tree, &ack);
1975 CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
1977 ack.in.lease.lease_state =
1978 SMB2_LEASE_READ | SMB2_LEASE_WRITE;
1979 status = smb2_lease_break_ack(tree, &ack);
1980 CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
1982 ack.in.lease.lease_state =
1983 SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE;
1984 status = smb2_lease_break_ack(tree, &ack);
1985 CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
1987 ack.in.lease.lease_state =
1988 SMB2_LEASE_READ | SMB2_LEASE_HANDLE;
1989 status = smb2_lease_break_ack(tree, &ack);
1990 CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
1992 ack.in.lease.lease_state = SMB2_LEASE_WRITE;
1993 status = smb2_lease_break_ack(tree, &ack);
1994 CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
1996 ack.in.lease.lease_state = SMB2_LEASE_HANDLE;
1997 status = smb2_lease_break_ack(tree, &ack);
1998 CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2000 ack.in.lease.lease_state = SMB2_LEASE_READ;
2001 status = smb2_lease_break_ack(tree, &ack);
2002 CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2004 /* Try again with the correct state this time. */
2005 ack.in.lease.lease_state = SMB2_LEASE_NONE;;
2006 status = smb2_lease_break_ack(tree, &ack);
2007 CHECK_STATUS(status, NT_STATUS_OK);
2008 CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2010 status = smb2_lease_break_ack(tree, &ack);
2011 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
2013 torture_assert(tctx, req2->cancel.can_cancel,
2016 status = smb2_create_recv(req2, tctx, &io2);
2017 CHECK_STATUS(status, NT_STATUS_OK);
2018 h2 = io2.out.file.handle;
2019 CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2020 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2022 CHECK_NO_BREAK(tctx);
2024 /* Get state of the original handle. */
2025 smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state(""));
2026 status = smb2_create(tree, mem_ctx, &io1);
2027 CHECK_STATUS(status, NT_STATUS_OK);
2028 CHECK_LEASE(&io1, "", true, LEASE1, 0);
2029 smb2_util_close(tree, io1.out.file.handle);
2032 smb2_util_close(tree, h1a);
2033 smb2_util_close(tree, h1b);
2034 smb2_util_close(tree, h2);
2035 smb2_util_unlink(tree, fname);
2036 talloc_free(mem_ctx);
2040 static bool test_lease_breaking3(struct torture_context *tctx,
2041 struct smb2_tree *tree)
2043 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2044 struct smb2_create io1 = {};
2045 struct smb2_create io2 = {};
2046 struct smb2_create io3 = {};
2047 struct smb2_lease ls1 = {};
2048 struct smb2_handle h1a = {};
2049 struct smb2_handle h1b = {};
2050 struct smb2_handle h2 = {};
2051 struct smb2_handle h3 = {};
2052 struct smb2_request *req2 = NULL;
2053 struct smb2_request *req3 = NULL;
2054 struct torture_lease_break break_info_tmp = {};
2055 struct smb2_lease_break_ack ack = {};
2056 const char *fname = "lease_breaking3.dat";
2061 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2062 if (!(caps & SMB2_CAP_LEASING)) {
2063 torture_skip(tctx, "leases are not supported");
2066 smb2_util_unlink(tree, fname);
2068 tree->session->transport->lease.handler = torture_lease_handler;
2069 tree->session->transport->lease.private_data = tree;
2070 tree->session->transport->oplock.handler = torture_oplock_handler;
2071 tree->session->transport->oplock.private_data = tree;
2074 * we defer acking the lease break.
2076 ZERO_STRUCT(break_info);
2077 break_info.lease_skip_ack = true;
2079 smb2_lease_create_share(&io1, &ls1, false, fname,
2080 smb2_util_share_access("RWD"),
2082 smb2_util_lease_state("RWH"));
2083 status = smb2_create(tree, mem_ctx, &io1);
2084 CHECK_STATUS(status, NT_STATUS_OK);
2085 h1a = io1.out.file.handle;
2086 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2087 CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2090 * a conflicting open is blocked until we ack the
2093 smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2094 req2 = smb2_create_send(tree, &io2);
2095 torture_assert(tctx, req2 != NULL, "smb2_create_send");
2098 * we got the lease break, but defer the ack.
2100 CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2102 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2105 * a open using the same lease key is still works,
2106 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2108 status = smb2_create(tree, mem_ctx, &io1);
2109 CHECK_STATUS(status, NT_STATUS_OK);
2110 h1b = io1.out.file.handle;
2111 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2112 CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2113 smb2_util_close(tree, h1b);
2116 * a conflicting open with NTCREATEX_DISP_OVERWRITE
2117 * doesn't trigger an immediate lease break to none.
2119 break_info_tmp = break_info;
2120 ZERO_STRUCT(break_info);
2121 smb2_oplock_create(&io3, fname, SMB2_OPLOCK_LEVEL_NONE);
2122 io3.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2123 req3 = smb2_create_send(tree, &io3);
2124 torture_assert(tctx, req3 != NULL, "smb2_create_send");
2125 CHECK_NO_BREAK(tctx);
2126 break_info = break_info_tmp;
2128 torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2130 ack.in.lease.lease_key =
2131 break_info.lease_break.current_lease.lease_key;
2132 ack.in.lease.lease_state =
2133 break_info.lease_break.new_lease_state;
2134 ZERO_STRUCT(break_info);
2137 * a open using the same lease key is still works,
2138 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2140 status = smb2_create(tree, mem_ctx, &io1);
2141 CHECK_STATUS(status, NT_STATUS_OK);
2142 h1b = io1.out.file.handle;
2143 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2144 CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2145 smb2_util_close(tree, h1b);
2147 CHECK_NO_BREAK(tctx);
2150 * We ack the lease break, but defer acking the next break (to "R")
2152 break_info.lease_skip_ack = true;
2153 status = smb2_lease_break_ack(tree, &ack);
2154 CHECK_STATUS(status, NT_STATUS_OK);
2155 CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
2158 * We got an additional break downgrading to just "R"
2159 * while we defer the ack.
2161 CHECK_BREAK_INFO("RH", "R", LEASE1);
2163 ack.in.lease.lease_key =
2164 break_info.lease_break.current_lease.lease_key;
2165 ack.in.lease.lease_state =
2166 break_info.lease_break.new_lease_state;
2167 ZERO_STRUCT(break_info);
2170 * a open using the same lease key is still works,
2171 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2173 status = smb2_create(tree, mem_ctx, &io1);
2174 CHECK_STATUS(status, NT_STATUS_OK);
2175 h1b = io1.out.file.handle;
2176 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2177 CHECK_LEASE(&io1, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2178 smb2_util_close(tree, h1b);
2180 CHECK_NO_BREAK(tctx);
2182 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2183 torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2186 * We ack the downgrade to "R" and get an immediate break to none
2188 status = smb2_lease_break_ack(tree, &ack);
2189 CHECK_STATUS(status, NT_STATUS_OK);
2190 CHECK_LEASE_BREAK_ACK(&ack, "R", LEASE1);
2193 * We get the downgrade to none.
2195 CHECK_BREAK_INFO("R", "", LEASE1);
2197 torture_assert(tctx, req2->cancel.can_cancel,
2199 torture_assert(tctx, req3->cancel.can_cancel,
2202 ZERO_STRUCT(break_info);
2204 status = smb2_create_recv(req2, tctx, &io2);
2205 CHECK_STATUS(status, NT_STATUS_OK);
2206 h2 = io2.out.file.handle;
2207 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2208 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2210 status = smb2_create_recv(req3, tctx, &io3);
2211 CHECK_STATUS(status, NT_STATUS_OK);
2212 h3 = io3.out.file.handle;
2213 CHECK_CREATED(&io3, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2214 CHECK_VAL(io3.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2216 CHECK_NO_BREAK(tctx);
2218 smb2_util_close(tree, h1a);
2219 smb2_util_close(tree, h1b);
2220 smb2_util_close(tree, h2);
2221 smb2_util_close(tree, h3);
2223 smb2_util_unlink(tree, fname);
2224 talloc_free(mem_ctx);
2228 static bool test_lease_v2_breaking3(struct torture_context *tctx,
2229 struct smb2_tree *tree)
2231 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2232 struct smb2_create io1 = {};
2233 struct smb2_create io2 = {};
2234 struct smb2_create io3 = {};
2235 struct smb2_lease ls1 = {};
2236 struct smb2_handle h1a = {};
2237 struct smb2_handle h1b = {};
2238 struct smb2_handle h2 = {};
2239 struct smb2_handle h3 = {};
2240 struct smb2_request *req2 = NULL;
2241 struct smb2_request *req3 = NULL;
2242 struct torture_lease_break break_info_tmp = {};
2243 struct smb2_lease_break_ack ack = {};
2244 const char *fname = "v2_lease_breaking3.dat";
2248 enum protocol_types protocol;
2250 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2251 if (!(caps & SMB2_CAP_LEASING)) {
2252 torture_skip(tctx, "leases are not supported");
2255 protocol = smbXcli_conn_protocol(tree->session->transport->conn);
2256 if (protocol < PROTOCOL_SMB3_00) {
2257 torture_skip(tctx, "v2 leases are not supported");
2260 smb2_util_unlink(tree, fname);
2262 tree->session->transport->lease.handler = torture_lease_handler;
2263 tree->session->transport->lease.private_data = tree;
2264 tree->session->transport->oplock.handler = torture_oplock_handler;
2265 tree->session->transport->oplock.private_data = tree;
2268 * we defer acking the lease break.
2270 ZERO_STRUCT(break_info);
2271 break_info.lease_skip_ack = true;
2273 smb2_lease_v2_create_share(&io1, &ls1, false, fname,
2274 smb2_util_share_access("RWD"),
2276 smb2_util_lease_state("RHW"),
2278 status = smb2_create(tree, mem_ctx, &io1);
2279 CHECK_STATUS(status, NT_STATUS_OK);
2280 h1a = io1.out.file.handle;
2281 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2282 /* Epoch increases on open. */
2283 ls1.lease_epoch += 1;
2284 CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch);
2287 * a conflicting open is blocked until we ack the
2290 smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2291 req2 = smb2_create_send(tree, &io2);
2292 torture_assert(tctx, req2 != NULL, "smb2_create_send");
2295 * we got the lease break, but defer the ack.
2297 CHECK_BREAK_INFO_V2(tree->session->transport,
2298 "RWH", "RH", LEASE1, ls1.lease_epoch + 1);
2300 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2302 /* On receiving a lease break, we must sync the new epoch. */
2303 ls1.lease_epoch = break_info.lease_break.new_epoch;
2306 * a open using the same lease key is still works,
2307 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2309 status = smb2_create(tree, mem_ctx, &io1);
2310 CHECK_STATUS(status, NT_STATUS_OK);
2311 h1b = io1.out.file.handle;
2312 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2313 CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2314 smb2_util_close(tree, h1b);
2317 * a conflicting open with NTCREATEX_DISP_OVERWRITE
2318 * doesn't trigger an immediate lease break to none.
2320 break_info_tmp = break_info;
2321 ZERO_STRUCT(break_info);
2322 smb2_oplock_create(&io3, fname, SMB2_OPLOCK_LEVEL_NONE);
2323 io3.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2324 req3 = smb2_create_send(tree, &io3);
2325 torture_assert(tctx, req3 != NULL, "smb2_create_send");
2326 CHECK_NO_BREAK(tctx);
2327 break_info = break_info_tmp;
2329 torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2331 ack.in.lease.lease_key =
2332 break_info.lease_break.current_lease.lease_key;
2333 ack.in.lease.lease_state =
2334 break_info.lease_break.new_lease_state;
2335 ZERO_STRUCT(break_info);
2338 * a open using the same lease key is still works,
2339 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2341 status = smb2_create(tree, mem_ctx, &io1);
2342 CHECK_STATUS(status, NT_STATUS_OK);
2343 h1b = io1.out.file.handle;
2344 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2345 CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2346 smb2_util_close(tree, h1b);
2348 CHECK_NO_BREAK(tctx);
2351 * We ack the lease break, but defer acking the next break (to "R")
2353 break_info.lease_skip_ack = true;
2354 status = smb2_lease_break_ack(tree, &ack);
2355 CHECK_STATUS(status, NT_STATUS_OK);
2356 CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
2359 * We got an additional break downgrading to just "R"
2360 * while we defer the ack.
2362 CHECK_BREAK_INFO_V2(tree->session->transport,
2363 "RH", "R", LEASE1, ls1.lease_epoch);
2364 /* On receiving a lease break, we must sync the new epoch. */
2365 ls1.lease_epoch = break_info.lease_break.new_epoch;
2367 ack.in.lease.lease_key =
2368 break_info.lease_break.current_lease.lease_key;
2369 ack.in.lease.lease_state =
2370 break_info.lease_break.new_lease_state;
2371 ZERO_STRUCT(break_info);
2374 * a open using the same lease key is still works,
2375 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2377 status = smb2_create(tree, mem_ctx, &io1);
2378 CHECK_STATUS(status, NT_STATUS_OK);
2379 h1b = io1.out.file.handle;
2380 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2381 CHECK_LEASE_V2(&io1, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2382 smb2_util_close(tree, h1b);
2384 CHECK_NO_BREAK(tctx);
2386 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2387 torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2390 * We ack the downgrade to "R" and get an immediate break to none
2392 status = smb2_lease_break_ack(tree, &ack);
2393 CHECK_STATUS(status, NT_STATUS_OK);
2394 CHECK_LEASE_BREAK_ACK(&ack, "R", LEASE1);
2397 * We get the downgrade to none.
2399 CHECK_BREAK_INFO_V2(tree->session->transport,
2400 "R", "", LEASE1, ls1.lease_epoch);
2402 torture_assert(tctx, req2->cancel.can_cancel,
2404 torture_assert(tctx, req3->cancel.can_cancel,
2407 ZERO_STRUCT(break_info);
2409 status = smb2_create_recv(req2, tctx, &io2);
2410 CHECK_STATUS(status, NT_STATUS_OK);
2411 h2 = io2.out.file.handle;
2412 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2413 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2415 status = smb2_create_recv(req3, tctx, &io3);
2416 CHECK_STATUS(status, NT_STATUS_OK);
2417 h3 = io3.out.file.handle;
2418 CHECK_CREATED(&io3, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2419 CHECK_VAL(io3.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2421 CHECK_NO_BREAK(tctx);
2423 smb2_util_close(tree, h1a);
2424 smb2_util_close(tree, h1b);
2425 smb2_util_close(tree, h2);
2426 smb2_util_close(tree, h3);
2428 smb2_util_unlink(tree, fname);
2429 talloc_free(mem_ctx);
2434 static bool test_lease_breaking4(struct torture_context *tctx,
2435 struct smb2_tree *tree)
2437 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2438 struct smb2_create io1 = {};
2439 struct smb2_create io2 = {};
2440 struct smb2_create io3 = {};
2441 struct smb2_lease ls1 = {};
2442 struct smb2_lease ls1t = {};
2443 struct smb2_handle h1 = {};
2444 struct smb2_handle h2 = {};
2445 struct smb2_handle h3 = {};
2446 struct smb2_request *req2 = NULL;
2447 struct torture_lease_break break_info_tmp = {};
2448 struct smb2_lease_break_ack ack = {};
2449 const char *fname = "lease_breaking4.dat";
2454 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2455 if (!(caps & SMB2_CAP_LEASING)) {
2456 torture_skip(tctx, "leases are not supported");
2459 smb2_util_unlink(tree, fname);
2461 tree->session->transport->lease.handler = torture_lease_handler;
2462 tree->session->transport->lease.private_data = tree;
2463 tree->session->transport->oplock.handler = torture_oplock_handler;
2464 tree->session->transport->oplock.private_data = tree;
2467 * we defer acking the lease break.
2469 ZERO_STRUCT(break_info);
2470 break_info.lease_skip_ack = true;
2472 smb2_lease_create_share(&io1, &ls1, false, fname,
2473 smb2_util_share_access("RWD"),
2475 smb2_util_lease_state("RH"));
2476 status = smb2_create(tree, mem_ctx, &io1);
2477 CHECK_STATUS(status, NT_STATUS_OK);
2478 h1 = io1.out.file.handle;
2479 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2480 CHECK_LEASE(&io1, "RH", true, LEASE1, 0);
2482 CHECK_NO_BREAK(tctx);
2485 * a conflicting open is *not* blocked until we ack the
2488 smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2489 io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2490 req2 = smb2_create_send(tree, &io2);
2491 torture_assert(tctx, req2 != NULL, "smb2_create_send");
2494 * We got a break from RH to NONE, we're supported to ack
2497 CHECK_BREAK_INFO("RH", "", LEASE1);
2499 break_info_tmp = break_info;
2500 ZERO_STRUCT(break_info);
2501 CHECK_NO_BREAK(tctx);
2503 torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2505 status = smb2_create_recv(req2, tctx, &io2);
2506 CHECK_STATUS(status, NT_STATUS_OK);
2507 h2 = io2.out.file.handle;
2508 CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2509 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2510 smb2_util_close(tree, h2);
2512 CHECK_NO_BREAK(tctx);
2515 * a conflicting open is *not* blocked until we ack the
2516 * lease break, even if the lease is in breaking state.
2518 smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2519 io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2520 req2 = smb2_create_send(tree, &io2);
2521 torture_assert(tctx, req2 != NULL, "smb2_create_send");
2523 CHECK_NO_BREAK(tctx);
2525 torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2527 status = smb2_create_recv(req2, tctx, &io2);
2528 CHECK_STATUS(status, NT_STATUS_OK);
2529 h2 = io2.out.file.handle;
2530 CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2531 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2532 smb2_util_close(tree, h2);
2534 CHECK_NO_BREAK(tctx);
2537 * We now ask the server about the current lease state
2538 * which should still be "RH", but with
2539 * SMB2_LEASE_FLAG_BREAK_IN_PROGRESS.
2541 smb2_lease_create_share(&io3, &ls1t, false, fname,
2542 smb2_util_share_access("RWD"),
2544 smb2_util_lease_state(""));
2545 status = smb2_create(tree, mem_ctx, &io3);
2546 CHECK_STATUS(status, NT_STATUS_OK);
2547 h3 = io3.out.file.handle;
2548 CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2549 CHECK_LEASE(&io3, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2552 * We finally ack the lease break...
2554 CHECK_NO_BREAK(tctx);
2555 break_info = break_info_tmp;
2556 ack.in.lease.lease_key =
2557 break_info.lease_break.current_lease.lease_key;
2558 ack.in.lease.lease_state =
2559 break_info.lease_break.new_lease_state;
2560 ZERO_STRUCT(break_info);
2561 break_info.lease_skip_ack = true;
2563 status = smb2_lease_break_ack(tree, &ack);
2564 CHECK_STATUS(status, NT_STATUS_OK);
2565 CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2567 CHECK_NO_BREAK(tctx);
2570 smb2_util_close(tree, h1);
2571 smb2_util_close(tree, h2);
2572 smb2_util_close(tree, h3);
2574 smb2_util_unlink(tree, fname);
2575 talloc_free(mem_ctx);
2579 static bool test_lease_breaking5(struct torture_context *tctx,
2580 struct smb2_tree *tree)
2582 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2583 struct smb2_create io1 = {};
2584 struct smb2_create io2 = {};
2585 struct smb2_create io3 = {};
2586 struct smb2_lease ls1 = {};
2587 struct smb2_lease ls1t = {};
2588 struct smb2_handle h1 = {};
2589 struct smb2_handle h2 = {};
2590 struct smb2_handle h3 = {};
2591 struct smb2_request *req2 = NULL;
2592 struct torture_lease_break break_info_tmp = {};
2593 struct smb2_lease_break_ack ack = {};
2594 const char *fname = "lease_breaking5.dat";
2599 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2600 if (!(caps & SMB2_CAP_LEASING)) {
2601 torture_skip(tctx, "leases are not supported");
2604 smb2_util_unlink(tree, fname);
2606 tree->session->transport->lease.handler = torture_lease_handler;
2607 tree->session->transport->lease.private_data = tree;
2608 tree->session->transport->oplock.handler = torture_oplock_handler;
2609 tree->session->transport->oplock.private_data = tree;
2612 * we defer acking the lease break.
2614 ZERO_STRUCT(break_info);
2615 break_info.lease_skip_ack = true;
2617 smb2_lease_create_share(&io1, &ls1, false, fname,
2618 smb2_util_share_access("RWD"),
2620 smb2_util_lease_state("R"));
2621 status = smb2_create(tree, mem_ctx, &io1);
2622 CHECK_STATUS(status, NT_STATUS_OK);
2623 h1 = io1.out.file.handle;
2624 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2625 CHECK_LEASE(&io1, "R", true, LEASE1, 0);
2627 CHECK_NO_BREAK(tctx);
2630 * a conflicting open is *not* blocked until we ack the
2633 smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2634 io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2635 req2 = smb2_create_send(tree, &io2);
2636 torture_assert(tctx, req2 != NULL, "smb2_create_send");
2639 * We got a break from RH to NONE, we're supported to ack
2642 CHECK_BREAK_INFO("R", "", LEASE1);
2644 break_info_tmp = break_info;
2645 ZERO_STRUCT(break_info);
2646 CHECK_NO_BREAK(tctx);
2648 torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2650 status = smb2_create_recv(req2, tctx, &io2);
2651 CHECK_STATUS(status, NT_STATUS_OK);
2652 h2 = io2.out.file.handle;
2653 CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2654 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2656 CHECK_NO_BREAK(tctx);
2659 * We now ask the server about the current lease state
2660 * which should still be "RH", but with
2661 * SMB2_LEASE_FLAG_BREAK_IN_PROGRESS.
2663 smb2_lease_create_share(&io3, &ls1t, false, fname,
2664 smb2_util_share_access("RWD"),
2666 smb2_util_lease_state(""));
2667 status = smb2_create(tree, mem_ctx, &io3);
2668 CHECK_STATUS(status, NT_STATUS_OK);
2669 h3 = io3.out.file.handle;
2670 CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2671 CHECK_LEASE(&io3, "", true, LEASE1, 0);
2674 * We send an ack without without being asked.
2676 CHECK_NO_BREAK(tctx);
2677 break_info = break_info_tmp;
2678 ack.in.lease.lease_key =
2679 break_info.lease_break.current_lease.lease_key;
2680 ack.in.lease.lease_state =
2681 break_info.lease_break.new_lease_state;
2682 ZERO_STRUCT(break_info);
2683 status = smb2_lease_break_ack(tree, &ack);
2684 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
2686 CHECK_NO_BREAK(tctx);
2689 smb2_util_close(tree, h1);
2690 smb2_util_close(tree, h2);
2691 smb2_util_close(tree, h3);
2693 smb2_util_unlink(tree, fname);
2694 talloc_free(mem_ctx);
2698 static bool test_lease_breaking6(struct torture_context *tctx,
2699 struct smb2_tree *tree)
2701 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2702 struct smb2_create io1 = {};
2703 struct smb2_create io2 = {};
2704 struct smb2_lease ls1 = {};
2705 struct smb2_handle h1a = {};
2706 struct smb2_handle h1b = {};
2707 struct smb2_handle h2 = {};
2708 struct smb2_request *req2 = NULL;
2709 struct smb2_lease_break_ack ack = {};
2710 const char *fname = "lease_breaking6.dat";
2715 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2716 if (!(caps & SMB2_CAP_LEASING)) {
2717 torture_skip(tctx, "leases are not supported");
2720 smb2_util_unlink(tree, fname);
2722 tree->session->transport->lease.handler = torture_lease_handler;
2723 tree->session->transport->lease.private_data = tree;
2724 tree->session->transport->oplock.handler = torture_oplock_handler;
2725 tree->session->transport->oplock.private_data = tree;
2728 * we defer acking the lease break.
2730 ZERO_STRUCT(break_info);
2731 break_info.lease_skip_ack = true;
2733 smb2_lease_create_share(&io1, &ls1, false, fname,
2734 smb2_util_share_access("RWD"),
2736 smb2_util_lease_state("RWH"));
2737 status = smb2_create(tree, mem_ctx, &io1);
2738 CHECK_STATUS(status, NT_STATUS_OK);
2739 h1a = io1.out.file.handle;
2740 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2741 CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2744 * a conflicting open is blocked until we ack the
2747 smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2748 req2 = smb2_create_send(tree, &io2);
2749 torture_assert(tctx, req2 != NULL, "smb2_create_send");
2752 * we got the lease break, but defer the ack.
2754 CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2756 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2758 ack.in.lease.lease_key =
2759 break_info.lease_break.current_lease.lease_key;
2760 ZERO_STRUCT(break_info);
2763 * a open using the same lease key is still works,
2764 * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2766 status = smb2_create(tree, mem_ctx, &io1);
2767 CHECK_STATUS(status, NT_STATUS_OK);
2768 h1b = io1.out.file.handle;
2769 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2770 CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2771 smb2_util_close(tree, h1b);
2773 CHECK_NO_BREAK(tctx);
2775 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2778 * We are asked to break to "RH", but we are allowed to
2779 * break to any of "RH", "R" or NONE.
2781 ack.in.lease.lease_state = SMB2_LEASE_NONE;
2782 status = smb2_lease_break_ack(tree, &ack);
2783 CHECK_STATUS(status, NT_STATUS_OK);
2784 CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2786 torture_assert(tctx, req2->cancel.can_cancel,
2789 status = smb2_create_recv(req2, tctx, &io2);
2790 CHECK_STATUS(status, NT_STATUS_OK);
2791 h2 = io2.out.file.handle;
2792 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2793 CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2795 CHECK_NO_BREAK(tctx);
2797 smb2_util_close(tree, h1a);
2798 smb2_util_close(tree, h1b);
2799 smb2_util_close(tree, h2);
2800 smb2_util_unlink(tree, fname);
2801 talloc_free(mem_ctx);
2805 static bool test_lease_lock1(struct torture_context *tctx,
2806 struct smb2_tree *tree1a,
2807 struct smb2_tree *tree2)
2809 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2810 struct smb2_create io1 = {};
2811 struct smb2_create io2 = {};
2812 struct smb2_create io3 = {};
2813 struct smb2_lease ls1 = {};
2814 struct smb2_lease ls2 = {};
2815 struct smb2_lease ls3 = {};
2816 struct smb2_handle h1 = {};
2817 struct smb2_handle h2 = {};
2818 struct smb2_handle h3 = {};
2819 struct smb2_lock lck;
2820 struct smb2_lock_element el[1];
2821 const char *fname = "locktest.dat";
2825 struct smbcli_options options1;
2826 struct smb2_tree *tree1b = NULL;
2828 options1 = tree1a->session->transport->options;
2830 caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
2831 if (!(caps & SMB2_CAP_LEASING)) {
2832 torture_skip(tctx, "leases are not supported");
2835 /* Set up handlers. */
2836 tree2->session->transport->lease.handler = torture_lease_handler;
2837 tree2->session->transport->lease.private_data = tree2;
2838 tree2->session->transport->oplock.handler = torture_oplock_handler;
2839 tree2->session->transport->oplock.private_data = tree2;
2841 tree1a->session->transport->lease.handler = torture_lease_handler;
2842 tree1a->session->transport->lease.private_data = tree1a;
2843 tree1a->session->transport->oplock.handler = torture_oplock_handler;
2844 tree1a->session->transport->oplock.private_data = tree1a;
2846 /* create a new connection (same client_guid) */
2847 if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
2848 torture_warning(tctx, "couldn't reconnect, bailing\n");
2853 tree1b->session->transport->lease.handler = torture_lease_handler;
2854 tree1b->session->transport->lease.private_data = tree1b;
2855 tree1b->session->transport->oplock.handler = torture_oplock_handler;
2856 tree1b->session->transport->oplock.private_data = tree1b;
2858 smb2_util_unlink(tree1a, fname);
2860 ZERO_STRUCT(break_info);
2863 /* Open a handle on tree1a. */
2864 smb2_lease_create_share(&io1, &ls1, false, fname,
2865 smb2_util_share_access("RWD"),
2867 smb2_util_lease_state("RWH"));
2868 status = smb2_create(tree1a, mem_ctx, &io1);
2869 CHECK_STATUS(status, NT_STATUS_OK);
2870 h1 = io1.out.file.handle;
2871 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2872 CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2874 /* Open a second handle on tree1b. */
2875 smb2_lease_create_share(&io2, &ls2, false, fname,
2876 smb2_util_share_access("RWD"),
2878 smb2_util_lease_state("RWH"));
2879 status = smb2_create(tree1b, mem_ctx, &io2);
2880 CHECK_STATUS(status, NT_STATUS_OK);
2881 h2 = io2.out.file.handle;
2882 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2883 CHECK_LEASE(&io2, "RH", true, LEASE2, 0);
2884 /* And LEASE1 got broken to RH. */
2885 CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2886 ZERO_STRUCT(break_info);
2888 /* Now open a lease on a different client guid. */
2889 smb2_lease_create_share(&io3, &ls3, false, fname,
2890 smb2_util_share_access("RWD"),
2892 smb2_util_lease_state("RWH"));
2893 status = smb2_create(tree2, mem_ctx, &io3);
2894 CHECK_STATUS(status, NT_STATUS_OK);
2895 h3 = io3.out.file.handle;
2896 CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2897 CHECK_LEASE(&io3, "RH", true, LEASE3, 0);
2898 /* Doesn't break. */
2899 CHECK_NO_BREAK(tctx);
2903 * Try and get get an exclusive byte
2904 * range lock on H1 (LEASE1).
2907 lck.in.lock_count = 1;
2908 lck.in.lock_sequence = 1;
2909 lck.in.file.handle = h1;
2913 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
2914 status = smb2_lock(tree1a, &lck);
2915 CHECK_STATUS(status, NT_STATUS_OK);
2917 /* LEASE2 and LEASE3 should get broken to NONE. */
2918 torture_wait_for_lease_break(tctx);
2919 torture_wait_for_lease_break(tctx);
2920 torture_wait_for_lease_break(tctx);
2921 torture_wait_for_lease_break(tctx);
2923 CHECK_VAL(break_info.failures, 0); \
2924 CHECK_VAL(break_info.count, 2); \
2926 /* Get state of the H1 (LEASE1) */
2927 smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state(""));
2928 status = smb2_create(tree1a, mem_ctx, &io1);
2929 CHECK_STATUS(status, NT_STATUS_OK);
2930 /* Should still be RH. */
2931 CHECK_LEASE(&io1, "RH", true, LEASE1, 0);
2932 smb2_util_close(tree1a, io1.out.file.handle);
2934 /* Get state of the H2 (LEASE2) */
2935 smb2_lease_create(&io2, &ls2, false, fname, LEASE2, smb2_util_lease_state(""));
2936 status = smb2_create(tree1b, mem_ctx, &io2);
2937 CHECK_STATUS(status, NT_STATUS_OK);
2938 CHECK_LEASE(&io2, "", true, LEASE2, 0);
2939 smb2_util_close(tree1b, io2.out.file.handle);
2941 /* Get state of the H3 (LEASE3) */
2942 smb2_lease_create(&io3, &ls3, false, fname, LEASE3, smb2_util_lease_state(""));
2943 status = smb2_create(tree2, mem_ctx, &io3);
2944 CHECK_STATUS(status, NT_STATUS_OK);
2945 CHECK_LEASE(&io3, "", true, LEASE3, 0);
2946 smb2_util_close(tree2, io3.out.file.handle);
2948 ZERO_STRUCT(break_info);
2951 * Try and get get an exclusive byte
2952 * range lock on H3 (LEASE3).
2954 lck.in.lock_count = 1;
2955 lck.in.lock_sequence = 2;
2956 lck.in.file.handle = h3;
2960 el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE;
2961 status = smb2_lock(tree2, &lck);
2962 CHECK_STATUS(status, NT_STATUS_OK);
2963 /* LEASE1 got broken to NONE. */
2964 CHECK_BREAK_INFO("RH", "", LEASE1);
2965 ZERO_STRUCT(break_info);
2968 smb2_util_close(tree1a, h1);
2969 smb2_util_close(tree1b, h2);
2970 smb2_util_close(tree2, h3);
2972 smb2_util_unlink(tree1a, fname);
2973 talloc_free(mem_ctx);
2977 static bool test_lease_complex1(struct torture_context *tctx,
2978 struct smb2_tree *tree1a)
2980 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2981 struct smb2_create io1;
2982 struct smb2_create io2;
2983 struct smb2_lease ls1;
2984 struct smb2_lease ls2;
2985 struct smb2_handle h, h2, h3;
2986 struct smb2_write w;
2988 const char *fname = "lease_complex1.dat";
2991 struct smb2_tree *tree1b = NULL;
2992 struct smbcli_options options1;
2994 options1 = tree1a->session->transport->options;
2996 caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
2997 if (!(caps & SMB2_CAP_LEASING)) {
2998 torture_skip(tctx, "leases are not supported");
3001 tree1a->session->transport->lease.handler = torture_lease_handler;
3002 tree1a->session->transport->lease.private_data = tree1a;
3003 tree1a->session->transport->oplock.handler = torture_oplock_handler;
3004 tree1a->session->transport->oplock.private_data = tree1a;
3006 /* create a new connection (same client_guid) */
3007 if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
3008 torture_warning(tctx, "couldn't reconnect, bailing\n");
3013 tree1b->session->transport->lease.handler = torture_lease_handler;
3014 tree1b->session->transport->lease.private_data = tree1b;
3015 tree1b->session->transport->oplock.handler = torture_oplock_handler;
3016 tree1b->session->transport->oplock.private_data = tree1b;
3018 smb2_util_unlink(tree1a, fname);
3020 ZERO_STRUCT(break_info);
3022 /* Grab R lease over connection 1a */
3023 smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state("R"));
3024 status = smb2_create(tree1a, mem_ctx, &io1);
3025 CHECK_STATUS(status, NT_STATUS_OK);
3026 h = io1.out.file.handle;
3027 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3028 CHECK_LEASE(&io1, "R", true, LEASE1, 0);
3030 /* Upgrade to RWH over connection 1b */
3031 ls1.lease_state = smb2_util_lease_state("RWH");
3032 status = smb2_create(tree1b, mem_ctx, &io1);
3033 CHECK_STATUS(status, NT_STATUS_OK);
3034 h2 = io1.out.file.handle;
3035 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3036 CHECK_LEASE(&io1, "RHW", true, LEASE1, 0);
3038 /* close over connection 1b */
3039 status = smb2_util_close(tree1b, h2);
3040 CHECK_STATUS(status, NT_STATUS_OK);
3042 /* Contend with LEASE2. */
3043 smb2_lease_create(&io2, &ls2, false, fname, LEASE2, smb2_util_lease_state("R"));
3044 status = smb2_create(tree1b, mem_ctx, &io2);
3045 CHECK_STATUS(status, NT_STATUS_OK);
3046 h3 = io2.out.file.handle;
3047 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3048 CHECK_LEASE(&io2, "R", true, LEASE2, 0);
3050 /* Verify that we were only sent one break. */
3051 CHECK_BREAK_INFO("RHW", "RH", LEASE1);
3053 /* again RH over connection 1b doesn't change the epoch */
3054 ls1.lease_state = smb2_util_lease_state("RH");
3055 status = smb2_create(tree1b, mem_ctx, &io1);
3056 CHECK_STATUS(status, NT_STATUS_OK);
3057 h2 = io1.out.file.handle;
3058 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3059 CHECK_LEASE(&io1, "RH", true, LEASE1, 0);
3061 /* close over connection 1b */
3062 status = smb2_util_close(tree1b, h2);
3063 CHECK_STATUS(status, NT_STATUS_OK);
3065 ZERO_STRUCT(break_info);
3068 w.in.file.handle = h;
3070 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
3071 memset(w.in.data.data, 'o', w.in.data.length);
3072 status = smb2_write(tree1a, &w);
3073 CHECK_STATUS(status, NT_STATUS_OK);
3075 ls2.lease_epoch += 1;
3076 CHECK_BREAK_INFO("R", "", LEASE2);
3078 ZERO_STRUCT(break_info);
3081 w.in.file.handle = h3;
3083 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
3084 memset(w.in.data.data, 'o', w.in.data.length);
3085 status = smb2_write(tree1b, &w);
3086 CHECK_STATUS(status, NT_STATUS_OK);
3088 ls1.lease_epoch += 1;
3089 CHECK_BREAK_INFO("RH", "", LEASE1);
3092 smb2_util_close(tree1a, h);
3093 smb2_util_close(tree1b, h2);
3094 smb2_util_close(tree1b, h3);
3096 smb2_util_unlink(tree1a, fname);
3098 talloc_free(mem_ctx);
3103 static bool test_lease_v2_complex1(struct torture_context *tctx,
3104 struct smb2_tree *tree1a)
3106 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3107 struct smb2_create io1;
3108 struct smb2_create io2;
3109 struct smb2_lease ls1;
3110 struct smb2_lease ls2;
3111 struct smb2_handle h, h2, h3;
3112 struct smb2_write w;
3114 const char *fname = "lease_v2_complex1.dat";
3117 enum protocol_types protocol;
3118 struct smb2_tree *tree1b = NULL;
3119 struct smbcli_options options1;
3121 options1 = tree1a->session->transport->options;
3123 caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
3124 if (!(caps & SMB2_CAP_LEASING)) {
3125 torture_skip(tctx, "leases are not supported");
3128 protocol = smbXcli_conn_protocol(tree1a->session->transport->conn);
3129 if (protocol < PROTOCOL_SMB3_00) {
3130 torture_skip(tctx, "v2 leases are not supported");
3133 tree1a->session->transport->lease.handler = torture_lease_handler;
3134 tree1a->session->transport->lease.private_data = tree1a;
3135 tree1a->session->transport->oplock.handler = torture_oplock_handler;
3136 tree1a->session->transport->oplock.private_data = tree1a;
3138 /* create a new connection (same client_guid) */
3139 if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
3140 torture_warning(tctx, "couldn't reconnect, bailing\n");
3145 tree1b->session->transport->lease.handler = torture_lease_handler;
3146 tree1b->session->transport->lease.private_data = tree1b;
3147 tree1b->session->transport->oplock.handler = torture_oplock_handler;
3148 tree1b->session->transport->oplock.private_data = tree1b;
3150 smb2_util_unlink(tree1a, fname);
3152 ZERO_STRUCT(break_info);
3154 /* Grab R lease over connection 1a */
3155 smb2_lease_v2_create(&io1, &ls1, false, fname, LEASE1, NULL,
3156 smb2_util_lease_state("R"), 0x4711);
3157 status = smb2_create(tree1a, mem_ctx, &io1);
3158 CHECK_STATUS(status, NT_STATUS_OK);
3159 h = io1.out.file.handle;
3160 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3161 ls1.lease_epoch += 1;
3162 CHECK_LEASE_V2(&io1, "R", true, LEASE1,
3163 0, 0, ls1.lease_epoch);
3165 /* Upgrade to RWH over connection 1b */
3166 ls1.lease_state = smb2_util_lease_state("RWH");
3167 status = smb2_create(tree1b, mem_ctx, &io1);
3168 CHECK_STATUS(status, NT_STATUS_OK);
3169 h2 = io1.out.file.handle;
3170 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3171 ls1.lease_epoch += 1;
3172 CHECK_LEASE_V2(&io1, "RHW", true, LEASE1,
3173 0, 0, ls1.lease_epoch);
3175 /* close over connection 1b */
3176 status = smb2_util_close(tree1b, h2);
3177 CHECK_STATUS(status, NT_STATUS_OK);
3179 /* Contend with LEASE2. */
3180 smb2_lease_v2_create(&io2, &ls2, false, fname, LEASE2, NULL,
3181 smb2_util_lease_state("R"), 0x11);
3182 status = smb2_create(tree1b, mem_ctx, &io2);
3183 CHECK_STATUS(status, NT_STATUS_OK);
3184 h3 = io2.out.file.handle;
3185 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3186 ls2.lease_epoch += 1;
3187 CHECK_LEASE_V2(&io2, "R", true, LEASE2,
3188 0, 0, ls2.lease_epoch);
3190 /* Verify that we were only sent one break. */
3191 ls1.lease_epoch += 1;
3192 CHECK_BREAK_INFO_V2(tree1a->session->transport,
3193 "RHW", "RH", LEASE1, ls1.lease_epoch);
3195 /* again RH over connection 1b doesn't change the epoch */
3196 ls1.lease_state = smb2_util_lease_state("RH");
3197 status = smb2_create(tree1b, mem_ctx, &io1);
3198 CHECK_STATUS(status, NT_STATUS_OK);
3199 h2 = io1.out.file.handle;
3200 CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3201 CHECK_LEASE_V2(&io1, "RH", true, LEASE1,
3202 0, 0, ls1.lease_epoch);
3204 /* close over connection 1b */
3205 status = smb2_util_close(tree1b, h2);
3206 CHECK_STATUS(status, NT_STATUS_OK);
3208 ZERO_STRUCT(break_info);
3211 w.in.file.handle = h;
3213 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
3214 memset(w.in.data.data, 'o', w.in.data.length);
3215 status = smb2_write(tree1a, &w);
3216 CHECK_STATUS(status, NT_STATUS_OK);
3218 ls2.lease_epoch += 1;
3219 CHECK_BREAK_INFO_V2(tree1a->session->transport,
3220 "R", "", LEASE2, ls2.lease_epoch);
3222 ZERO_STRUCT(break_info);
3225 w.in.file.handle = h3;
3227 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
3228 memset(w.in.data.data, 'o', w.in.data.length);
3229 status = smb2_write(tree1b, &w);
3230 CHECK_STATUS(status, NT_STATUS_OK);
3232 ls1.lease_epoch += 1;
3233 CHECK_BREAK_INFO_V2(tree1a->session->transport,
3234 "RH", "", LEASE1, ls1.lease_epoch);
3237 smb2_util_close(tree1a, h);
3238 smb2_util_close(tree1b, h2);
3239 smb2_util_close(tree1b, h3);
3241 smb2_util_unlink(tree1a, fname);
3243 talloc_free(mem_ctx);
3248 static bool test_lease_v2_complex2(struct torture_context *tctx,
3249 struct smb2_tree *tree1a)
3251 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3252 struct smb2_create io1;
3253 struct smb2_create io2;
3254 struct smb2_lease ls1;
3255 struct smb2_lease ls2;
3256 struct smb2_handle h, h2;
3257 struct smb2_request *req2 = NULL;
3258 struct smb2_lease_break_ack ack = {};
3260 const char *fname = "lease_v2_complex2.dat";
3263 enum protocol_types protocol;
3264 struct smb2_tree *tree1b = NULL;
3265 struct smbcli_options options1;
3267 options1 = tree1a->session->transport->options;
3269 caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
3270 if (!(caps & SMB2_CAP_LEASING)) {
3271 torture_skip(tctx, "leases are not supported");
3274 protocol = smbXcli_conn_protocol(tree1a->session->transport->conn);
3275 if (protocol < PROTOCOL_SMB3_00) {
3276 torture_skip(tctx, "v2 leases are not supported");
3279 tree1a->session->transport->lease.handler = torture_lease_handler;
3280 tree1a->session->transport->lease.private_data = tree1a;
3281 tree1a->session->transport->oplock.handler = torture_oplock_handler;
3282 tree1a->session->transport->oplock.private_data = tree1a;
3284 /* create a new connection (same client_guid) */
3285 if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
3286 torture_warning(tctx, "couldn't reconnect, bailing\n");
3291 tree1b->session->transport->lease.handler = torture_lease_handler;
3292 tree1b->session->transport->lease.private_data = tree1b;
3293 tree1b->session->transport->oplock.handler = torture_oplock_handler;
3294 tree1b->session->transport->oplock.private_data = tree1b;
3296 smb2_util_unlink(tree1a, fname);
3298 ZERO_STRUCT(break_info);
3300 /* Grab RWH lease over connection 1a */
3301 smb2_lease_v2_create(&io1, &ls1, false, fname, LEASE1, NULL,
3302 smb2_util_lease_state("RWH"), 0x4711);
3303 status = smb2_create(tree1a, mem_ctx, &io1);
3304 CHECK_STATUS(status, NT_STATUS_OK);
3305 h = io1.out.file.handle;
3306 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3307 ls1.lease_epoch += 1;
3308 CHECK_LEASE_V2(&io1, "RWH", true, LEASE1,
3309 0, 0, ls1.lease_epoch);
3312 * we defer acking the lease break.
3314 ZERO_STRUCT(break_info);
3315 break_info.lease_skip_ack = true;
3317 /* Ask for RWH on connection 1b, different lease. */
3318 smb2_lease_v2_create(&io2, &ls2, false, fname, LEASE2, NULL,
3319 smb2_util_lease_state("RWH"), 0x11);
3320 req2 = smb2_create_send(tree1b, &io2);
3321 torture_assert(tctx, req2 != NULL, "smb2_create_send");
3323 ls1.lease_epoch += 1;
3325 CHECK_BREAK_INFO_V2(tree1a->session->transport,
3326 "RWH", "RH", LEASE1, ls1.lease_epoch);
3328 /* Send the break ACK on tree1b. */
3329 ack.in.lease.lease_key =
3330 break_info.lease_break.current_lease.lease_key;
3331 ack.in.lease.lease_state = SMB2_LEASE_HANDLE|SMB2_LEASE_READ;
3333 status = smb2_lease_break_ack(tree1b, &ack);
3334 CHECK_STATUS(status, NT_STATUS_OK);
3335 CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
3337 ZERO_STRUCT(break_info);
3339 status = smb2_create_recv(req2, tctx, &io2);
3340 CHECK_STATUS(status, NT_STATUS_OK);
3341 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3342 CHECK_LEASE_V2(&io2, "RH", true, LEASE2,
3343 0, 0, ls2.lease_epoch+1);
3344 h2 = io2.out.file.handle;
3347 smb2_util_close(tree1a, h);
3348 smb2_util_close(tree1b, h2);
3350 smb2_util_unlink(tree1a, fname);
3352 talloc_free(mem_ctx);
3358 static bool test_lease_timeout(struct torture_context *tctx,
3359 struct smb2_tree *tree)
3361 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3362 struct smb2_create io;
3363 struct smb2_lease ls1;
3364 struct smb2_lease ls2;
3365 struct smb2_handle h, hnew, h1b;
3367 const char *fname = "lease_timeout.dat";
3369 struct smb2_lease_break_ack ack = {};
3370 struct smb2_request *req2 = NULL;
3371 struct smb2_write w;
3374 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
3375 if (!(caps & SMB2_CAP_LEASING)) {
3376 torture_skip(tctx, "leases are not supported");
3379 smb2_util_unlink(tree, fname);
3381 /* Grab a RWH lease. */
3382 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3383 status = smb2_create(tree, mem_ctx, &io);
3384 CHECK_STATUS(status, NT_STATUS_OK);
3385 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3386 CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3387 h = io.out.file.handle;
3389 tree->session->transport->lease.handler = torture_lease_handler;
3390 tree->session->transport->lease.private_data = tree;
3391 tree->session->transport->oplock.handler = torture_oplock_handler;
3392 tree->session->transport->oplock.private_data = tree;
3395 * Just don't ack the lease break.
3397 ZERO_STRUCT(break_info);
3398 break_info.lease_skip_ack = true;
3400 /* Break with a RWH request. */
3401 smb2_lease_create(&io, &ls2, false, fname, LEASE2, smb2_util_lease_state("RWH"));
3402 req2 = smb2_create_send(tree, &io);
3403 torture_assert(tctx, req2 != NULL, "smb2_create_send");
3404 torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
3406 CHECK_BREAK_INFO("RWH", "RH", LEASE1);
3408 /* Copy the break request. */
3409 ack.in.lease.lease_key =
3410 break_info.lease_break.current_lease.lease_key;
3411 ack.in.lease.lease_state =
3412 break_info.lease_break.new_lease_state;
3414 /* Now wait for the timeout and get the reply. */
3415 status = smb2_create_recv(req2, tctx, &io);
3416 CHECK_STATUS(status, NT_STATUS_OK);
3417 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3418 CHECK_LEASE(&io, "RH", true, LEASE2, 0);
3419 hnew = io.out.file.handle;
3421 /* Ack the break after the timeout... */
3422 status = smb2_lease_break_ack(tree, &ack);
3423 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
3425 /* Get state of the original handle. */
3426 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state(""));
3427 status = smb2_create(tree, mem_ctx, &io);
3428 CHECK_STATUS(status, NT_STATUS_OK);
3429 CHECK_LEASE(&io, "", true, LEASE1, 0);
3430 smb2_util_close(tree, io.out.file.handle);
3432 /* Write on the original handle and make sure it's still valid. */
3433 ZERO_STRUCT(break_info);
3435 w.in.file.handle = h;
3437 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
3438 memset(w.in.data.data, '1', w.in.data.length);
3439 status = smb2_write(tree, &w);
3440 CHECK_STATUS(status, NT_STATUS_OK);
3442 /* Causes new handle to break to NONE. */
3443 CHECK_BREAK_INFO("RH", "", LEASE2);
3445 /* Write on the new handle. */
3446 ZERO_STRUCT(break_info);
3448 w.in.file.handle = hnew;
3450 w.in.data = data_blob_talloc(mem_ctx, NULL, 1024);
3451 memset(w.in.data.data, '2', w.in.data.length);
3452 status = smb2_write(tree, &w);
3453 CHECK_STATUS(status, NT_STATUS_OK);
3454 /* No break - original handle was already NONE. */
3455 CHECK_NO_BREAK(tctx);
3456 smb2_util_close(tree, hnew);
3458 /* Upgrade to R on LEASE1. */
3459 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("R"));
3460 status = smb2_create(tree, mem_ctx, &io);
3461 CHECK_STATUS(status, NT_STATUS_OK);
3462 CHECK_LEASE(&io, "R", true, LEASE1, 0);
3463 h1b = io.out.file.handle;
3464 smb2_util_close(tree, h1b);
3466 /* Upgrade to RWH on LEASE1. */
3467 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3468 status = smb2_create(tree, mem_ctx, &io);
3469 CHECK_STATUS(status, NT_STATUS_OK);
3470 CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3471 h1b = io.out.file.handle;
3472 smb2_util_close(tree, h1b);
3475 smb2_util_close(tree, h);
3476 smb2_util_close(tree, hnew);
3477 smb2_util_close(tree, h1b);
3479 smb2_util_unlink(tree, fname);
3481 talloc_free(mem_ctx);
3486 static bool test_lease_dynamic_share(struct torture_context *tctx,
3487 struct smb2_tree *tree1a)
3489 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3490 struct smb2_create io;
3491 struct smb2_lease ls1;
3492 struct smb2_handle h, h1, h2;
3493 struct smb2_write w;
3495 const char *fname = "dynamic_path.dat";
3498 struct smb2_tree *tree_2_1 = NULL;
3499 struct smb2_tree *tree_3_0 = NULL;
3500 struct smbcli_options options2_1;
3501 struct smbcli_options options3_0;
3502 const char *orig_share = NULL;
3504 if (!TARGET_IS_SAMBA3(tctx)) {
3505 torture_skip(tctx, "dynamic shares are not supported");
3509 options2_1 = tree1a->session->transport->options;
3510 options3_0 = tree1a->session->transport->options;
3512 caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
3513 if (!(caps & SMB2_CAP_LEASING)) {
3514 torture_skip(tctx, "leases are not supported");
3518 * Save off original share name and change it to dynamic_share.
3519 * This must have been pre-created with a dynamic path containing
3523 orig_share = lpcfg_parm_string(tctx->lp_ctx, NULL, "torture", "share");
3524 orig_share = talloc_strdup(tctx->lp_ctx, orig_share);
3525 if (orig_share == NULL) {
3526 torture_result(tctx, TORTURE_FAIL, __location__ "no memory\n");
3530 lpcfg_set_cmdline(tctx->lp_ctx, "torture:share", "dynamic_share");
3532 /* Set max protocol to SMB2.1 */
3533 options2_1.max_protocol = PROTOCOL_SMB2_10;
3534 /* create a new connection (same client_guid) */
3535 if (!torture_smb2_connection_ext(tctx, 0, &options2_1, &tree_2_1)) {
3536 torture_warning(tctx, "couldn't reconnect max protocol 2.1, bailing\n");
3541 tree_2_1->session->transport->lease.handler = torture_lease_handler;
3542 tree_2_1->session->transport->lease.private_data = tree_2_1;
3543 tree_2_1->session->transport->oplock.handler = torture_oplock_handler;
3544 tree_2_1->session->transport->oplock.private_data = tree_2_1;
3546 smb2_util_unlink(tree_2_1, fname);
3548 /* Set max protocol to SMB3.0 */
3549 options3_0.max_protocol = PROTOCOL_SMB3_00;
3550 /* create a new connection (same client_guid) */
3551 if (!torture_smb2_connection_ext(tctx, 0, &options3_0, &tree_3_0)) {
3552 torture_warning(tctx, "couldn't reconnect max protocol 3.0, bailing\n");
3557 tree_3_0->session->transport->lease.handler = torture_lease_handler;
3558 tree_3_0->session->transport->lease.private_data = tree_3_0;
3559 tree_3_0->session->transport->oplock.handler = torture_oplock_handler;
3560 tree_3_0->session->transport->oplock.private_data = tree_3_0;
3562 smb2_util_unlink(tree_3_0, fname);
3564 ZERO_STRUCT(break_info);
3566 /* Get RWH lease over connection 2_1 */
3567 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3568 status = smb2_create(tree_2_1, mem_ctx, &io);
3569 CHECK_STATUS(status, NT_STATUS_OK);
3570 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3571 CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3572 h = io.out.file.handle;
3574 /* Write some data into it. */
3575 w.in.file.handle = h;
3577 w.in.data = data_blob_talloc(mem_ctx, NULL, 4096);
3578 memset(w.in.data.data, '1', w.in.data.length);
3579 status = smb2_write(tree_2_1, &w);
3580 CHECK_STATUS(status, NT_STATUS_OK);
3582 /* Open the same name over connection 3_0. */
3583 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3584 status = smb2_create(tree_3_0, mem_ctx, &io);
3585 CHECK_STATUS(status, NT_STATUS_OK);
3586 h1 = io.out.file.handle;
3587 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3589 /* h1 should have replied with NONE. */
3590 CHECK_LEASE(&io, "", true, LEASE1, 0);
3592 /* We should have broken h to NONE. */
3593 CHECK_BREAK_INFO("RWH", "", LEASE1);
3595 /* Try to upgrade to RWH over connection 2_1 */
3596 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3597 status = smb2_create(tree_2_1, mem_ctx, &io);
3598 CHECK_STATUS(status, NT_STATUS_OK);
3599 h2 = io.out.file.handle;
3600 CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
3601 CHECK_VAL(io.out.size, 4096);
3602 CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
3603 /* Should have been denied. */
3604 CHECK_LEASE(&io, "", true, LEASE1, 0);
3605 smb2_util_close(tree_2_1, h2);
3607 /* Try to upgrade to RWH over connection 3_0 */
3608 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3609 status = smb2_create(tree_3_0, mem_ctx, &io);
3610 CHECK_STATUS(status, NT_STATUS_OK);
3611 h2 = io.out.file.handle;
3612 CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
3613 CHECK_VAL(io.out.size, 0);
3614 CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
3615 /* Should have been denied. */
3616 CHECK_LEASE(&io, "", true, LEASE1, 0);
3617 smb2_util_close(tree_3_0, h2);
3619 /* Write some data into it. */
3620 w.in.file.handle = h1;
3622 w.in.data = data_blob_talloc(mem_ctx, NULL, 1024);
3623 memset(w.in.data.data, '2', w.in.data.length);
3624 status = smb2_write(tree_3_0, &w);
3625 CHECK_STATUS(status, NT_STATUS_OK);
3627 /* Close everything.. */
3628 smb2_util_close(tree_2_1, h);
3629 smb2_util_close(tree_3_0, h1);
3631 /* And ensure we can get a lease ! */
3632 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3633 status = smb2_create(tree_2_1, mem_ctx, &io);
3634 CHECK_STATUS(status, NT_STATUS_OK);
3635 CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
3636 CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
3637 CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3638 h = io.out.file.handle;
3639 /* And the file is the right size. */
3640 CHECK_VAL(io.out.size, 4096); \
3642 smb2_util_close(tree_2_1, h);
3644 /* And ensure we can get a lease ! */
3645 smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3646 status = smb2_create(tree_3_0, mem_ctx, &io);
3647 CHECK_STATUS(status, NT_STATUS_OK);
3648 CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
3649 CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
3650 CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3651 h = io.out.file.handle;
3652 /* And the file is the right size. */
3653 CHECK_VAL(io.out.size, 1024); \
3655 smb2_util_close(tree_3_0, h);
3659 smb2_util_close(tree_2_1, h);
3660 smb2_util_close(tree_3_0, h1);
3661 smb2_util_close(tree_3_0, h2);
3663 smb2_util_unlink(tree_2_1, fname);
3664 smb2_util_unlink(tree_3_0, fname);
3666 /* Set sharename back. */
3667 lpcfg_set_cmdline(tctx->lp_ctx, "torture:share", orig_share);
3669 talloc_free(mem_ctx);
3674 struct torture_suite *torture_smb2_lease_init(void)
3676 struct torture_suite *suite =
3677 torture_suite_create(talloc_autofree_context(), "lease");
3679 torture_suite_add_1smb2_test(suite, "request", test_lease_request);
3680 torture_suite_add_1smb2_test(suite, "break_twice",
3681 test_lease_break_twice);
3682 torture_suite_add_1smb2_test(suite, "nobreakself",
3683 test_lease_nobreakself);
3684 torture_suite_add_1smb2_test(suite, "upgrade", test_lease_upgrade);
3685 torture_suite_add_1smb2_test(suite, "upgrade2", test_lease_upgrade2);
3686 torture_suite_add_1smb2_test(suite, "upgrade3", test_lease_upgrade3);
3687 torture_suite_add_1smb2_test(suite, "break", test_lease_break);
3688 torture_suite_add_1smb2_test(suite, "oplock", test_lease_oplock);
3689 torture_suite_add_1smb2_test(suite, "multibreak", test_lease_multibreak);
3690 torture_suite_add_1smb2_test(suite, "breaking1", test_lease_breaking1);
3691 torture_suite_add_1smb2_test(suite, "breaking2", test_lease_breaking2);
3692 torture_suite_add_1smb2_test(suite, "breaking3", test_lease_breaking3);
3693 torture_suite_add_1smb2_test(suite, "v2_breaking3", test_lease_v2_breaking3);
3694 torture_suite_add_1smb2_test(suite, "breaking4", test_lease_breaking4);
3695 torture_suite_add_1smb2_test(suite, "breaking5", test_lease_breaking5);
3696 torture_suite_add_1smb2_test(suite, "breaking6", test_lease_breaking6);
3697 torture_suite_add_2smb2_test(suite, "lock1", test_lease_lock1);
3698 torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1);
3699 torture_suite_add_1smb2_test(suite, "v2_request_parent",
3700 test_lease_v2_request_parent);
3701 torture_suite_add_1smb2_test(suite, "v2_request", test_lease_v2_request);
3702 torture_suite_add_1smb2_test(suite, "v2_epoch1", test_lease_v2_epoch1);
3703 torture_suite_add_1smb2_test(suite, "v2_epoch2", test_lease_v2_epoch2);
3704 torture_suite_add_1smb2_test(suite, "v2_epoch3", test_lease_v2_epoch3);
3705 torture_suite_add_1smb2_test(suite, "v2_complex1", test_lease_v2_complex1);
3706 torture_suite_add_1smb2_test(suite, "v2_complex2", test_lease_v2_complex2);
3707 torture_suite_add_1smb2_test(suite, "dynamic_share", test_lease_dynamic_share);
3708 torture_suite_add_1smb2_test(suite, "timeout", test_lease_timeout);
3710 suite->description = talloc_strdup(suite, "SMB2-LEASE tests");