s4:torture: Do not check if the alloc_size is 0 on empty files
[amitay/samba.git] / source4 / torture / smb2 / lease.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    test suite for SMB2 leases
5
6    Copyright (C) Zachary Loafman 2009
7
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.
12
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.
17
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/>.
20 */
21
22 #include "includes.h"
23 #include <tevent.h>
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "torture/util.h"
29 #include "libcli/smb/smbXcli_base.h"
30 #include "libcli/security/security.h"
31 #include "lib/param/param.h"
32 #include "lease_break_handler.h"
33
34 #define CHECK_VAL(v, correct) do { \
35         if ((v) != (correct)) { \
36                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
37                                 __location__, #v, (int)(v), (int)(correct)); \
38                 ret = false; \
39         }} while (0)
40
41 #define CHECK_STATUS(status, correct) do { \
42         if (!NT_STATUS_EQUAL(status, correct)) { \
43                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
44                        nt_errstr(status), nt_errstr(correct)); \
45                 ret = false; \
46                 goto done; \
47         }} while (0)
48
49 #define CHECK_CREATED(__io, __created, __attribute)                     \
50         do {                                                            \
51                 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
52                 CHECK_VAL((__io)->out.size, 0);                         \
53                 CHECK_VAL((__io)->out.file_attr, (__attribute));        \
54                 CHECK_VAL((__io)->out.reserved2, 0);                    \
55         } while(0)
56
57 #define CHECK_LEASE(__io, __state, __oplevel, __key, __flags)           \
58         do {                                                            \
59                 CHECK_VAL((__io)->out.lease_response.lease_version, 1); \
60                 if (__oplevel) {                                        \
61                         CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \
62                         CHECK_VAL((__io)->out.lease_response.lease_key.data[0], (__key)); \
63                         CHECK_VAL((__io)->out.lease_response.lease_key.data[1], ~(__key)); \
64                         CHECK_VAL((__io)->out.lease_response.lease_state, smb2_util_lease_state(__state)); \
65                 } else {                                                \
66                         CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); \
67                         CHECK_VAL((__io)->out.lease_response.lease_key.data[0], 0); \
68                         CHECK_VAL((__io)->out.lease_response.lease_key.data[1], 0); \
69                         CHECK_VAL((__io)->out.lease_response.lease_state, 0); \
70                 }                                                       \
71                                                                         \
72                 CHECK_VAL((__io)->out.lease_response.lease_flags, (__flags));   \
73                 CHECK_VAL((__io)->out.lease_response.lease_duration, 0); \
74                 CHECK_VAL((__io)->out.lease_response.lease_epoch, 0); \
75         } while(0)
76
77 #define CHECK_LEASE_V2(__io, __state, __oplevel, __key, __flags, __parent, __epoch) \
78         do {                                                            \
79                 CHECK_VAL((__io)->out.lease_response_v2.lease_version, 2); \
80                 if (__oplevel) {                                        \
81                         CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \
82                         CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], (__key)); \
83                         CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[1], ~(__key)); \
84                         CHECK_VAL((__io)->out.lease_response_v2.lease_state, smb2_util_lease_state(__state)); \
85                 } else {                                                \
86                         CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); \
87                         CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], 0); \
88                         CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[1], 0); \
89                         CHECK_VAL((__io)->out.lease_response_v2.lease_state, 0); \
90                 }                                                       \
91                                                                         \
92                 CHECK_VAL((__io)->out.lease_response_v2.lease_flags, __flags); \
93                 if (__flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET) { \
94                         CHECK_VAL((__io)->out.lease_response_v2.parent_lease_key.data[0], (__parent)); \
95                         CHECK_VAL((__io)->out.lease_response_v2.parent_lease_key.data[1], ~(__parent)); \
96                 } \
97                 CHECK_VAL((__io)->out.lease_response_v2.lease_duration, 0); \
98                 CHECK_VAL((__io)->out.lease_response_v2.lease_epoch, (__epoch)); \
99         } while(0)
100
101 static const uint64_t LEASE1 = 0xBADC0FFEE0DDF00Dull;
102 static const uint64_t LEASE2 = 0xDEADBEEFFEEDBEADull;
103 static const uint64_t LEASE3 = 0xDAD0FFEDD00DF00Dull;
104 static const uint64_t LEASE4 = 0xBAD0FFEDD00DF00Dull;
105
106 #define NREQUEST_RESULTS 8
107 static const char *request_results[NREQUEST_RESULTS][2] = {
108         { "", "" },
109         { "R", "R" },
110         { "H", "" },
111         { "W", "" },
112         { "RH", "RH" },
113         { "RW", "RW" },
114         { "HW", "" },
115         { "RHW", "RHW" },
116 };
117
118 static bool test_lease_request(struct torture_context *tctx,
119                                struct smb2_tree *tree)
120 {
121         TALLOC_CTX *mem_ctx = talloc_new(tctx);
122         struct smb2_create io;
123         struct smb2_lease ls;
124         struct smb2_handle h1 = {{0}};
125         struct smb2_handle h2 = {{0}};
126         NTSTATUS status;
127         const char *fname = "lease_request.dat";
128         const char *fname2 = "lease_request.2.dat";
129         const char *sname = "lease_request.dat:stream";
130         const char *dname = "lease_request.dir";
131         bool ret = true;
132         int i;
133         uint32_t caps;
134
135         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
136         if (!(caps & SMB2_CAP_LEASING)) {
137                 torture_skip(tctx, "leases are not supported");
138         }
139
140         smb2_util_unlink(tree, fname);
141         smb2_util_unlink(tree, fname2);
142         smb2_util_rmdir(tree, dname);
143
144         /* Win7 is happy to grant RHW leases on files. */
145         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
146         status = smb2_create(tree, mem_ctx, &io);
147         CHECK_STATUS(status, NT_STATUS_OK);
148         h1 = io.out.file.handle;
149         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
150         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
151
152         /* But will reject leases on directories. */
153         if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
154                 smb2_lease_create(&io, &ls, true, dname, LEASE2, smb2_util_lease_state("RHW"));
155                 status = smb2_create(tree, mem_ctx, &io);
156                 CHECK_STATUS(status, NT_STATUS_OK);
157                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY);
158                 CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
159                 smb2_util_close(tree, io.out.file.handle);
160         }
161
162         /* Also rejects multiple files leased under the same key. */
163         smb2_lease_create(&io, &ls, true, fname2, LEASE1, smb2_util_lease_state("RHW"));
164         status = smb2_create(tree, mem_ctx, &io);
165         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
166
167         /* And grants leases on streams (with separate leasekey). */
168         smb2_lease_create(&io, &ls, false, sname, LEASE2, smb2_util_lease_state("RHW"));
169         status = smb2_create(tree, mem_ctx, &io);
170         h2 = io.out.file.handle;
171         CHECK_STATUS(status, NT_STATUS_OK);
172         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
173         CHECK_LEASE(&io, "RHW", true, LEASE2, 0);
174         smb2_util_close(tree, h2);
175
176         smb2_util_close(tree, h1);
177
178         /* Now see what combos are actually granted. */
179         for (i = 0; i < NREQUEST_RESULTS; i++) {
180                 torture_comment(tctx, "Requesting lease type %s(%x),"
181                     " expecting %s(%x)\n",
182                     request_results[i][0], smb2_util_lease_state(request_results[i][0]),
183                     request_results[i][1], smb2_util_lease_state(request_results[i][1]));
184                 smb2_lease_create(&io, &ls, false, fname, LEASE1,
185                     smb2_util_lease_state(request_results[i][0]));
186                 status = smb2_create(tree, mem_ctx, &io);
187                 h2 = io.out.file.handle;
188                 CHECK_STATUS(status, NT_STATUS_OK);
189                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
190                 CHECK_LEASE(&io, request_results[i][1], true, LEASE1, 0);
191                 smb2_util_close(tree, io.out.file.handle);
192         }
193
194  done:
195         smb2_util_close(tree, h1);
196         smb2_util_close(tree, h2);
197
198         smb2_util_unlink(tree, fname);
199         smb2_util_unlink(tree, fname2);
200         smb2_util_rmdir(tree, dname);
201
202         talloc_free(mem_ctx);
203
204         return ret;
205 }
206
207 static bool test_lease_upgrade(struct torture_context *tctx,
208                                struct smb2_tree *tree)
209 {
210         TALLOC_CTX *mem_ctx = talloc_new(tctx);
211         struct smb2_create io;
212         struct smb2_lease ls;
213         struct smb2_handle h = {{0}};
214         struct smb2_handle hnew = {{0}};
215         NTSTATUS status;
216         const char *fname = "lease_upgrade.dat";
217         bool ret = true;
218         uint32_t caps;
219
220         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
221         if (!(caps & SMB2_CAP_LEASING)) {
222                 torture_skip(tctx, "leases are not supported");
223         }
224
225         smb2_util_unlink(tree, fname);
226
227         /* Grab a RH lease. */
228         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
229         status = smb2_create(tree, mem_ctx, &io);
230         CHECK_STATUS(status, NT_STATUS_OK);
231         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
232         CHECK_LEASE(&io, "RH", true, LEASE1, 0);
233         h = io.out.file.handle;
234
235         /* Upgrades (sidegrades?) to RW leave us with an RH. */
236         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RW"));
237         status = smb2_create(tree, mem_ctx, &io);
238         CHECK_STATUS(status, NT_STATUS_OK);
239         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
240         CHECK_LEASE(&io, "RH", true, LEASE1, 0);
241         hnew = io.out.file.handle;
242
243         smb2_util_close(tree, hnew);
244
245         /* Upgrade to RHW lease. */
246         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
247         status = smb2_create(tree, mem_ctx, &io);
248         CHECK_STATUS(status, NT_STATUS_OK);
249         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
250         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
251         hnew = io.out.file.handle;
252
253         smb2_util_close(tree, h);
254         h = hnew;
255
256         /* Attempt to downgrade - original lease state is maintained. */
257         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
258         status = smb2_create(tree, mem_ctx, &io);
259         CHECK_STATUS(status, NT_STATUS_OK);
260         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
261         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
262         hnew = io.out.file.handle;
263
264         smb2_util_close(tree, hnew);
265
266  done:
267         smb2_util_close(tree, h);
268         smb2_util_close(tree, hnew);
269
270         smb2_util_unlink(tree, fname);
271
272         talloc_free(mem_ctx);
273
274         return ret;
275 }
276
277 /**
278  * upgrade2 test.
279  * full matrix of lease upgrade combinations
280  * (non-contended case)
281  *
282  * The summary of the behaviour is this:
283  * -------------------------------------
284  * An uncontended lease upgrade results in a change
285  * if and only if the requested lease state is
286  * - valid, and
287  * - strictly a superset of the lease state already held.
288  *
289  * In that case the resulting lease state is the one
290  * requested in the upgrade.
291  */
292 struct lease_upgrade2_test {
293         const char *initial;
294         const char *upgrade_to;
295         const char *expected;
296 };
297
298 #define NUM_LEASE_TYPES 5
299 #define NUM_UPGRADE_TESTS ( NUM_LEASE_TYPES * NUM_LEASE_TYPES )
300 struct lease_upgrade2_test lease_upgrade2_tests[NUM_UPGRADE_TESTS] = {
301         { "", "", "" },
302         { "", "R", "R" },
303         { "", "RH", "RH" },
304         { "", "RW", "RW" },
305         { "", "RWH", "RWH" },
306
307         { "R", "", "R" },
308         { "R", "R", "R" },
309         { "R", "RH", "RH" },
310         { "R", "RW", "RW" },
311         { "R", "RWH", "RWH" },
312
313         { "RH", "", "RH" },
314         { "RH", "R", "RH" },
315         { "RH", "RH", "RH" },
316         { "RH", "RW", "RH" },
317         { "RH", "RWH", "RWH" },
318
319         { "RW", "", "RW" },
320         { "RW", "R", "RW" },
321         { "RW", "RH", "RW" },
322         { "RW", "RW", "RW" },
323         { "RW", "RWH", "RWH" },
324
325         { "RWH", "", "RWH" },
326         { "RWH", "R", "RWH" },
327         { "RWH", "RH", "RWH" },
328         { "RWH", "RW", "RWH" },
329         { "RWH", "RWH", "RWH" },
330 };
331
332 static bool test_lease_upgrade2(struct torture_context *tctx,
333                                 struct smb2_tree *tree)
334 {
335         TALLOC_CTX *mem_ctx = talloc_new(tctx);
336         struct smb2_handle h, hnew;
337         NTSTATUS status;
338         struct smb2_create io;
339         struct smb2_lease ls;
340         const char *fname = "lease_upgrade2.dat";
341         bool ret = true;
342         int i;
343         uint32_t caps;
344
345         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
346         if (!(caps & SMB2_CAP_LEASING)) {
347                 torture_skip(tctx, "leases are not supported");
348         }
349
350         for (i = 0; i < NUM_UPGRADE_TESTS; i++) {
351                 struct lease_upgrade2_test t = lease_upgrade2_tests[i];
352
353                 smb2_util_unlink(tree, fname);
354
355                 /* Grab a lease. */
356                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.initial));
357                 status = smb2_create(tree, mem_ctx, &io);
358                 CHECK_STATUS(status, NT_STATUS_OK);
359                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
360                 CHECK_LEASE(&io, t.initial, true, LEASE1, 0);
361                 h = io.out.file.handle;
362
363                 /* Upgrade. */
364                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
365                 status = smb2_create(tree, mem_ctx, &io);
366                 CHECK_STATUS(status, NT_STATUS_OK);
367                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
368                 CHECK_LEASE(&io, t.expected, true, LEASE1, 0);
369                 hnew = io.out.file.handle;
370
371                 smb2_util_close(tree, hnew);
372                 smb2_util_close(tree, h);
373         }
374
375  done:
376         smb2_util_close(tree, h);
377         smb2_util_close(tree, hnew);
378
379         smb2_util_unlink(tree, fname);
380
381         talloc_free(mem_ctx);
382
383         return ret;
384 }
385
386
387 /**
388  * upgrade3:
389  * full matrix of lease upgrade combinations
390  * (contended case)
391  *
392  * We start with 2 leases, and check how one can
393  * be upgraded
394  *
395  * The summary of the behaviour is this:
396  * -------------------------------------
397  *
398  * If we have two leases (lease1 and lease2) on the same file,
399  * then attempt to upgrade lease1 results in a change if and only
400  * if the requested lease state:
401  * - is valid,
402  * - is strictly a superset of lease1, and
403  * - can held together with lease2.
404  *
405  * In that case, the resuling lease state of the upgraded lease1
406  * is the state requested in the upgrade. lease2 is not broken
407  * and remains unchanged.
408  *
409  * Note that this contrasts the case of directly opening with
410  * an initial requested lease state, in which case you get that
411  * portion of the requested state that can be shared with the
412  * already existing leases (or the states that they get broken to).
413  */
414 struct lease_upgrade3_test {
415         const char *held1;
416         const char *held2;
417         const char *upgrade_to;
418         const char *upgraded_to;
419 };
420
421 #define NUM_UPGRADE3_TESTS ( 20 )
422 struct lease_upgrade3_test lease_upgrade3_tests[NUM_UPGRADE3_TESTS] = {
423         {"R", "R", "", "R" },
424         {"R", "R", "R", "R" },
425         {"R", "R", "RW", "R" },
426         {"R", "R", "RH", "RH" },
427         {"R", "R", "RHW", "R" },
428
429         {"R", "RH", "", "R" },
430         {"R", "RH", "R", "R" },
431         {"R", "RH", "RW", "R" },
432         {"R", "RH", "RH", "RH" },
433         {"R", "RH", "RHW", "R" },
434
435         {"RH", "R", "", "RH" },
436         {"RH", "R", "R", "RH" },
437         {"RH", "R", "RW", "RH" },
438         {"RH", "R", "RH", "RH" },
439         {"RH", "R", "RHW", "RH" },
440
441         {"RH", "RH", "", "RH" },
442         {"RH", "RH", "R", "RH" },
443         {"RH", "RH", "RW", "RH" },
444         {"RH", "RH", "RH", "RH" },
445         {"RH", "RH", "RHW", "RH" },
446 };
447
448 static bool test_lease_upgrade3(struct torture_context *tctx,
449                                 struct smb2_tree *tree)
450 {
451         TALLOC_CTX *mem_ctx = talloc_new(tctx);
452         struct smb2_handle h, h2, hnew;
453         NTSTATUS status;
454         struct smb2_create io;
455         struct smb2_lease ls;
456         const char *fname = "lease_upgrade3.dat";
457         bool ret = true;
458         int i;
459         uint32_t caps;
460
461         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
462         if (!(caps & SMB2_CAP_LEASING)) {
463                 torture_skip(tctx, "leases are not supported");
464         }
465
466         tree->session->transport->lease.handler = torture_lease_handler;
467         tree->session->transport->lease.private_data = tree;
468
469         smb2_util_unlink(tree, fname);
470
471         for (i = 0; i < NUM_UPGRADE3_TESTS; i++) {
472                 struct lease_upgrade3_test t = lease_upgrade3_tests[i];
473
474                 smb2_util_unlink(tree, fname);
475
476                 ZERO_STRUCT(lease_break_info);
477
478                 /* grab first lease */
479                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.held1));
480                 status = smb2_create(tree, mem_ctx, &io);
481                 CHECK_STATUS(status, NT_STATUS_OK);
482                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
483                 CHECK_LEASE(&io, t.held1, true, LEASE1, 0);
484                 h = io.out.file.handle;
485
486                 /* grab second lease */
487                 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(t.held2));
488                 status = smb2_create(tree, mem_ctx, &io);
489                 CHECK_STATUS(status, NT_STATUS_OK);
490                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
491                 CHECK_LEASE(&io, t.held2, true, LEASE2, 0);
492                 h2 = io.out.file.handle;
493
494                 /* no break has happened */
495                 CHECK_VAL(lease_break_info.count, 0);
496                 CHECK_VAL(lease_break_info.failures, 0);
497
498                 /* try to upgrade lease1 */
499                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
500                 status = smb2_create(tree, mem_ctx, &io);
501                 CHECK_STATUS(status, NT_STATUS_OK);
502                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
503                 CHECK_LEASE(&io, t.upgraded_to, true, LEASE1, 0);
504                 hnew = io.out.file.handle;
505
506                 /* no break has happened */
507                 CHECK_VAL(lease_break_info.count, 0);
508                 CHECK_VAL(lease_break_info.failures, 0);
509
510                 smb2_util_close(tree, hnew);
511                 smb2_util_close(tree, h);
512                 smb2_util_close(tree, h2);
513         }
514
515  done:
516         smb2_util_close(tree, h);
517         smb2_util_close(tree, hnew);
518         smb2_util_close(tree, h2);
519
520         smb2_util_unlink(tree, fname);
521
522         talloc_free(mem_ctx);
523
524         return ret;
525 }
526
527
528
529 /*
530   break_results should be read as "held lease, new lease, hold broken to, new
531   grant", i.e. { "RH", "RW", "RH", "R" } means that if key1 holds RH and key2
532   tries for RW, key1 will be broken to RH (in this case, not broken at all)
533   and key2 will be granted R.
534
535   Note: break_results only includes things that Win7 will actually grant (see
536   request_results above).
537  */
538 #define NBREAK_RESULTS 16
539 static const char *break_results[NBREAK_RESULTS][4] = {
540         {"R",   "R",    "R",    "R"},
541         {"R",   "RH",   "R",    "RH"},
542         {"R",   "RW",   "R",    "R"},
543         {"R",   "RHW",  "R",    "RH"},
544
545         {"RH",  "R",    "RH",   "R"},
546         {"RH",  "RH",   "RH",   "RH"},
547         {"RH",  "RW",   "RH",   "R"},
548         {"RH",  "RHW",  "RH",   "RH"},
549
550         {"RW",  "R",    "R",    "R"},
551         {"RW",  "RH",   "R",    "RH"},
552         {"RW",  "RW",   "R",    "R"},
553         {"RW",  "RHW",  "R",    "RH"},
554
555         {"RHW", "R",    "RH",   "R"},
556         {"RHW", "RH",   "RH",   "RH"},
557         {"RHW", "RW",   "RH",   "R"},
558         {"RHW", "RHW",  "RH",   "RH"},
559 };
560
561 static bool test_lease_break(struct torture_context *tctx,
562                                struct smb2_tree *tree)
563 {
564         TALLOC_CTX *mem_ctx = talloc_new(tctx);
565         struct smb2_create io;
566         struct smb2_lease ls;
567         struct smb2_handle h, h2, h3;
568         NTSTATUS status;
569         const char *fname = "lease_break.dat";
570         bool ret = true;
571         int i;
572         uint32_t caps;
573
574         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
575         if (!(caps & SMB2_CAP_LEASING)) {
576                 torture_skip(tctx, "leases are not supported");
577         }
578
579         tree->session->transport->lease.handler = torture_lease_handler;
580         tree->session->transport->lease.private_data = tree;
581
582         smb2_util_unlink(tree, fname);
583
584         for (i = 0; i < NBREAK_RESULTS; i++) {
585                 const char *held = break_results[i][0];
586                 const char *contend = break_results[i][1];
587                 const char *brokento = break_results[i][2];
588                 const char *granted = break_results[i][3];
589                 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
590                     "expecting break to %s(%x) and grant of %s(%x)\n",
591                     held, smb2_util_lease_state(held), contend, smb2_util_lease_state(contend),
592                     brokento, smb2_util_lease_state(brokento), granted, smb2_util_lease_state(granted));
593
594                 ZERO_STRUCT(lease_break_info);
595
596                 /* Grab lease. */
597                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(held));
598                 status = smb2_create(tree, mem_ctx, &io);
599                 CHECK_STATUS(status, NT_STATUS_OK);
600                 h = io.out.file.handle;
601                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
602                 CHECK_LEASE(&io, held, true, LEASE1, 0);
603
604                 /* Possibly contend lease. */
605                 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(contend));
606                 status = smb2_create(tree, mem_ctx, &io);
607                 CHECK_STATUS(status, NT_STATUS_OK);
608                 h2 = io.out.file.handle;
609                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
610                 CHECK_LEASE(&io, granted, true, LEASE2, 0);
611
612                 if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) {
613                         CHECK_BREAK_INFO(held, brokento, LEASE1);
614                 } else {
615                         CHECK_NO_BREAK(tctx);
616                 }
617
618                 ZERO_STRUCT(lease_break_info);
619
620                 /*
621                   Now verify that an attempt to upgrade LEASE1 results in no
622                   break and no change in LEASE1.
623                  */
624                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
625                 status = smb2_create(tree, mem_ctx, &io);
626                 CHECK_STATUS(status, NT_STATUS_OK);
627                 h3 = io.out.file.handle;
628                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
629                 CHECK_LEASE(&io, brokento, true, LEASE1, 0);
630                 CHECK_VAL(lease_break_info.count, 0);
631                 CHECK_VAL(lease_break_info.failures, 0);
632
633                 smb2_util_close(tree, h);
634                 smb2_util_close(tree, h2);
635                 smb2_util_close(tree, h3);
636
637                 status = smb2_util_unlink(tree, fname);
638                 CHECK_STATUS(status, NT_STATUS_OK);
639         }
640
641  done:
642         smb2_util_close(tree, h);
643         smb2_util_close(tree, h2);
644
645         smb2_util_unlink(tree, fname);
646
647         talloc_free(mem_ctx);
648
649         return ret;
650 }
651
652 static bool test_lease_nobreakself(struct torture_context *tctx,
653                                    struct smb2_tree *tree)
654 {
655         TALLOC_CTX *mem_ctx = talloc_new(tctx);
656         struct smb2_create io;
657         struct smb2_lease ls;
658         struct smb2_handle h1 = {{0}};
659         struct smb2_handle h2 = {{0}};
660         NTSTATUS status;
661         const char *fname = "lease_nobreakself.dat";
662         bool ret = true;
663         uint32_t caps;
664         char c = 0;
665
666         caps = smb2cli_conn_server_capabilities(
667                 tree->session->transport->conn);
668         if (!(caps & SMB2_CAP_LEASING)) {
669                 torture_skip(tctx, "leases are not supported");
670         }
671
672         smb2_util_unlink(tree, fname);
673
674         /* Win7 is happy to grant RHW leases on files. */
675         smb2_lease_create(&io, &ls, false, fname, LEASE1,
676                           smb2_util_lease_state("R"));
677         status = smb2_create(tree, mem_ctx, &io);
678         CHECK_STATUS(status, NT_STATUS_OK);
679         h1 = io.out.file.handle;
680         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
681         CHECK_LEASE(&io, "R", true, LEASE1, 0);
682
683         smb2_lease_create(&io, &ls, false, fname, LEASE2,
684                           smb2_util_lease_state("R"));
685         status = smb2_create(tree, mem_ctx, &io);
686         CHECK_STATUS(status, NT_STATUS_OK);
687         h2 = io.out.file.handle;
688         CHECK_LEASE(&io, "R", true, LEASE2, 0);
689
690         ZERO_STRUCT(lease_break_info);
691
692         tree->session->transport->lease.handler = torture_lease_handler;
693         tree->session->transport->lease.private_data = tree;
694
695         /* Make sure we don't break ourselves on write */
696
697         status = smb2_util_write(tree, h1, &c, 0, 1);
698         CHECK_STATUS(status, NT_STATUS_OK);
699         CHECK_BREAK_INFO("R", "", LEASE2);
700
701         /* Try the other way round. First, upgrade LEASE2 to R again */
702
703         smb2_lease_create(&io, &ls, false, fname, LEASE2,
704                           smb2_util_lease_state("R"));
705         status = smb2_create(tree, mem_ctx, &io);
706         CHECK_STATUS(status, NT_STATUS_OK);
707         CHECK_LEASE(&io, "R", true, LEASE2, 0);
708         smb2_util_close(tree, io.out.file.handle);
709
710         /* Now break LEASE1 via h2 */
711
712         ZERO_STRUCT(lease_break_info);
713         status = smb2_util_write(tree, h2, &c, 0, 1);
714         CHECK_STATUS(status, NT_STATUS_OK);
715         CHECK_BREAK_INFO("R", "", LEASE1);
716
717         /* .. and break LEASE2 via h1 */
718
719         ZERO_STRUCT(lease_break_info);
720         status = smb2_util_write(tree, h1, &c, 0, 1);
721         CHECK_STATUS(status, NT_STATUS_OK);
722         CHECK_BREAK_INFO("R", "", LEASE2);
723
724 done:
725         smb2_util_close(tree, h2);
726         smb2_util_close(tree, h1);
727         smb2_util_unlink(tree, fname);
728         talloc_free(mem_ctx);
729         return ret;
730 }
731
732 static bool test_lease_statopen(struct torture_context *tctx,
733                                    struct smb2_tree *tree)
734 {
735         TALLOC_CTX *mem_ctx = talloc_new(tctx);
736         struct smb2_create io;
737         struct smb2_lease ls;
738         struct smb2_handle h1 = {{0}};
739         struct smb2_handle h2 = {{0}};
740         NTSTATUS status;
741         const char *fname = "lease_statopen.dat";
742         bool ret = true;
743         uint32_t caps;
744
745         caps = smb2cli_conn_server_capabilities(
746                 tree->session->transport->conn);
747         if (!(caps & SMB2_CAP_LEASING)) {
748                 torture_skip(tctx, "leases are not supported");
749         }
750
751         smb2_util_unlink(tree, fname);
752
753         /* Create file. */
754         smb2_lease_create(&io, &ls, false, fname, LEASE1,
755                           smb2_util_lease_state("RWH"));
756         status = smb2_create(tree, mem_ctx, &io);
757         CHECK_STATUS(status, NT_STATUS_OK);
758         h1 = io.out.file.handle;
759         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
760         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
761         smb2_util_close(tree, h1);
762
763         /* Stat open file with RWH lease. */
764         smb2_lease_create_share(&io, &ls, false, fname, 0, LEASE1,
765                           smb2_util_lease_state("RWH"));
766         io.in.desired_access = FILE_READ_ATTRIBUTES;
767         status = smb2_create(tree, mem_ctx, &io);
768         CHECK_STATUS(status, NT_STATUS_OK);
769         h2 = io.out.file.handle;
770         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
771
772         ZERO_STRUCT(lease_break_info);
773
774         tree->session->transport->lease.handler = torture_lease_handler;
775         tree->session->transport->lease.private_data = tree;
776
777         /* Ensure non-stat open doesn't break and gets same lease
778            state as existing stat open. */
779         smb2_lease_create(&io, &ls, false, fname, LEASE1,
780                           smb2_util_lease_state(""));
781         status = smb2_create(tree, mem_ctx, &io);
782         CHECK_STATUS(status, NT_STATUS_OK);
783         h1 = io.out.file.handle;
784         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
785         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
786
787         CHECK_NO_BREAK(tctx);
788         smb2_util_close(tree, h1);
789
790         /* Open with conflicting lease. stat open should break down to RH */
791         smb2_lease_create(&io, &ls, false, fname, LEASE2,
792                           smb2_util_lease_state("RWH"));
793         status = smb2_create(tree, mem_ctx, &io);
794         CHECK_STATUS(status, NT_STATUS_OK);
795         h1 = io.out.file.handle;
796         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
797         CHECK_LEASE(&io, "RH", true, LEASE2, 0);
798
799         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
800
801 done:
802         smb2_util_close(tree, h2);
803         smb2_util_close(tree, h1);
804         smb2_util_unlink(tree, fname);
805         talloc_free(mem_ctx);
806         return ret;
807 }
808
809 static bool test_lease_statopen2(struct torture_context *tctx,
810                                  struct smb2_tree *tree)
811 {
812         TALLOC_CTX *mem_ctx = talloc_new(tctx);
813         struct smb2_create io;
814         struct smb2_lease ls;
815         struct smb2_handle h1 = {{0}};
816         struct smb2_handle h2 = {{0}};
817         struct smb2_handle h3 = {{0}};
818         NTSTATUS status;
819         const char *fname = "lease_statopen2.dat";
820         bool ret = true;
821         uint32_t caps;
822
823         caps = smb2cli_conn_server_capabilities(
824                 tree->session->transport->conn);
825         if (!(caps & SMB2_CAP_LEASING)) {
826                 torture_skip(tctx, "leases are not supported");
827         }
828
829         smb2_util_unlink(tree, fname);
830         ZERO_STRUCT(lease_break_info);
831         tree->session->transport->lease.handler = torture_lease_handler;
832         tree->session->transport->lease.private_data = tree;
833
834         status = torture_smb2_testfile(tree, fname, &h1);
835         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
836                                         "smb2_create failed\n");
837         smb2_util_close(tree, h1);
838         ZERO_STRUCT(h1);
839
840         /* Open file with RWH lease. */
841         smb2_lease_create_share(&io, &ls, false, fname,
842                                 smb2_util_share_access("RWD"),
843                                 LEASE1,
844                                 smb2_util_lease_state("RWH"));
845         io.in.desired_access = SEC_FILE_WRITE_DATA;
846         status = smb2_create(tree, mem_ctx, &io);
847         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
848                                         "smb2_create failed\n");
849         h1 = io.out.file.handle;
850         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
851
852         /* Stat open */
853         ZERO_STRUCT(io);
854         io.in.desired_access = FILE_READ_ATTRIBUTES;
855         io.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
856         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
857         io.in.create_disposition = NTCREATEX_DISP_OPEN;
858         io.in.fname = fname;
859         status = smb2_create(tree, mem_ctx, &io);
860         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
861                                         "smb2_create failed\n");
862         h2 = io.out.file.handle;
863
864         /* Open file with RWH lease. */
865         smb2_lease_create_share(&io, &ls, false, fname,
866                                 smb2_util_share_access("RWD"),
867                                 LEASE1,
868                                 smb2_util_lease_state("RWH"));
869         io.in.desired_access = SEC_FILE_WRITE_DATA;
870         status = smb2_create(tree, mem_ctx, &io);
871         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
872                                         "smb2_create failed\n");
873         h3 = io.out.file.handle;
874         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
875
876 done:
877         if (!smb2_util_handle_empty(h3)) {
878                 smb2_util_close(tree, h3);
879         }
880         if (!smb2_util_handle_empty(h2)) {
881                 smb2_util_close(tree, h2);
882         }
883         if (!smb2_util_handle_empty(h1)) {
884                 smb2_util_close(tree, h1);
885         }
886         smb2_util_unlink(tree, fname);
887         talloc_free(mem_ctx);
888         return ret;
889 }
890
891 static bool test_lease_statopen3(struct torture_context *tctx,
892                                  struct smb2_tree *tree)
893 {
894         TALLOC_CTX *mem_ctx = talloc_new(tctx);
895         struct smb2_create io;
896         struct smb2_lease ls;
897         struct smb2_handle h1 = {{0}};
898         struct smb2_handle h2 = {{0}};
899         NTSTATUS status;
900         const char *fname = "lease_statopen3.dat";
901         bool ret = true;
902         uint32_t caps;
903
904         caps = smb2cli_conn_server_capabilities(
905                 tree->session->transport->conn);
906         if (!(caps & SMB2_CAP_LEASING)) {
907                 torture_skip(tctx, "leases are not supported");
908         }
909
910         smb2_util_unlink(tree, fname);
911         ZERO_STRUCT(lease_break_info);
912         tree->session->transport->lease.handler = torture_lease_handler;
913         tree->session->transport->lease.private_data = tree;
914
915         status = torture_smb2_testfile(tree, fname, &h1);
916         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
917                                         "smb2_create failed\n");
918         smb2_util_close(tree, h1);
919         ZERO_STRUCT(h1);
920
921         /* Stat open */
922         ZERO_STRUCT(io);
923         io.in.desired_access = FILE_READ_ATTRIBUTES;
924         io.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
925         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
926         io.in.create_disposition = NTCREATEX_DISP_OPEN;
927         io.in.fname = fname;
928         status = smb2_create(tree, mem_ctx, &io);
929         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
930                                         "smb2_create failed\n");
931         h1 = io.out.file.handle;
932
933         /* Open file with RWH lease. */
934         smb2_lease_create_share(&io, &ls, false, fname,
935                                 smb2_util_share_access("RWD"),
936                                 LEASE1,
937                                 smb2_util_lease_state("RWH"));
938         io.in.desired_access = SEC_FILE_WRITE_DATA;
939         status = smb2_create(tree, mem_ctx, &io);
940         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
941                                         "smb2_create failed\n");
942         h2 = io.out.file.handle;
943         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
944
945 done:
946         if (!smb2_util_handle_empty(h1)) {
947                 smb2_util_close(tree, h1);
948         }
949         if (!smb2_util_handle_empty(h2)) {
950                 smb2_util_close(tree, h2);
951         }
952         smb2_util_unlink(tree, fname);
953         talloc_free(mem_ctx);
954         return ret;
955 }
956
957 static void torture_oplock_break_callback(struct smb2_request *req)
958 {
959         NTSTATUS status;
960         struct smb2_break br;
961
962         ZERO_STRUCT(br);
963         status = smb2_break_recv(req, &br);
964         if (!NT_STATUS_IS_OK(status))
965                 lease_break_info.oplock_failures++;
966
967         return;
968 }
969
970 /* a oplock break request handler */
971 static bool torture_oplock_handler(struct smb2_transport *transport,
972                                    const struct smb2_handle *handle,
973                                    uint8_t level, void *private_data)
974 {
975         struct smb2_tree *tree = private_data;
976         struct smb2_request *req;
977         struct smb2_break br;
978
979         lease_break_info.oplock_handle = *handle;
980         lease_break_info.oplock_level   = level;
981         lease_break_info.oplock_count++;
982
983         ZERO_STRUCT(br);
984         br.in.file.handle = *handle;
985         br.in.oplock_level = level;
986
987         if (lease_break_info.held_oplock_level > SMB2_OPLOCK_LEVEL_II) {
988                 req = smb2_break_send(tree, &br);
989                 req->async.fn = torture_oplock_break_callback;
990                 req->async.private_data = NULL;
991         }
992         lease_break_info.held_oplock_level = level;
993
994         return true;
995 }
996
997 #define NOPLOCK_RESULTS 12
998 static const char *oplock_results[NOPLOCK_RESULTS][4] = {
999         {"R",   "s",    "R",    "s"},
1000         {"R",   "x",    "R",    "s"},
1001         {"R",   "b",    "R",    "s"},
1002
1003         {"RH",  "s",    "RH",   ""},
1004         {"RH",  "x",    "RH",   ""},
1005         {"RH",  "b",    "RH",   ""},
1006
1007         {"RW",  "s",    "R",    "s"},
1008         {"RW",  "x",    "R",    "s"},
1009         {"RW",  "b",    "R",    "s"},
1010
1011         {"RHW", "s",    "RH",   ""},
1012         {"RHW", "x",    "RH",   ""},
1013         {"RHW", "b",    "RH",   ""},
1014 };
1015
1016 static const char *oplock_results_2[NOPLOCK_RESULTS][4] = {
1017         {"s",   "R",    "s",    "R"},
1018         {"s",   "RH",   "s",    "R"},
1019         {"s",   "RW",   "s",    "R"},
1020         {"s",   "RHW",  "s",    "R"},
1021
1022         {"x",   "R",    "s",    "R"},
1023         {"x",   "RH",   "s",    "R"},
1024         {"x",   "RW",   "s",    "R"},
1025         {"x",   "RHW",  "s",    "R"},
1026
1027         {"b",   "R",    "s",    "R"},
1028         {"b",   "RH",   "s",    "R"},
1029         {"b",   "RW",   "s",    "R"},
1030         {"b",   "RHW",  "s",    "R"},
1031 };
1032
1033 static bool test_lease_oplock(struct torture_context *tctx,
1034                               struct smb2_tree *tree)
1035 {
1036         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1037         struct smb2_create io;
1038         struct smb2_lease ls;
1039         struct smb2_handle h, h2;
1040         NTSTATUS status;
1041         const char *fname = "lease_oplock.dat";
1042         bool ret = true;
1043         int i;
1044         uint32_t caps;
1045
1046         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1047         if (!(caps & SMB2_CAP_LEASING)) {
1048                 torture_skip(tctx, "leases are not supported");
1049         }
1050
1051         tree->session->transport->lease.handler = torture_lease_handler;
1052         tree->session->transport->lease.private_data = tree;
1053         tree->session->transport->oplock.handler = torture_oplock_handler;
1054         tree->session->transport->oplock.private_data = tree;
1055
1056         smb2_util_unlink(tree, fname);
1057
1058         for (i = 0; i < NOPLOCK_RESULTS; i++) {
1059                 const char *held = oplock_results[i][0];
1060                 const char *contend = oplock_results[i][1];
1061                 const char *brokento = oplock_results[i][2];
1062                 const char *granted = oplock_results[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_lease_state(held), contend, smb2_util_oplock_level(contend),
1066                     brokento, smb2_util_lease_state(brokento), granted, smb2_util_oplock_level(granted));
1067
1068                 ZERO_STRUCT(lease_break_info);
1069
1070                 /* Grab lease. */
1071                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(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_LEASE(&io, held, true, LEASE1, 0);
1077
1078                 /* Does an oplock contend the lease? */
1079                 smb2_oplock_create(&io, fname, smb2_util_oplock_level(contend));
1080                 status = smb2_create(tree, mem_ctx, &io);
1081                 CHECK_STATUS(status, NT_STATUS_OK);
1082                 h2 = io.out.file.handle;
1083                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1084                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(granted));
1085                 lease_break_info.held_oplock_level = io.out.oplock_level;
1086
1087                 if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) {
1088                         CHECK_BREAK_INFO(held, brokento, LEASE1);
1089                 } else {
1090                         CHECK_NO_BREAK(tctx);
1091                 }
1092
1093                 smb2_util_close(tree, h);
1094                 smb2_util_close(tree, h2);
1095
1096                 status = smb2_util_unlink(tree, fname);
1097                 CHECK_STATUS(status, NT_STATUS_OK);
1098         }
1099
1100         for (i = 0; i < NOPLOCK_RESULTS; i++) {
1101                 const char *held = oplock_results_2[i][0];
1102                 const char *contend = oplock_results_2[i][1];
1103                 const char *brokento = oplock_results_2[i][2];
1104                 const char *granted = oplock_results_2[i][3];
1105                 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
1106                     "expecting break to %s(%x) and grant of %s(%x)\n",
1107                     held, smb2_util_oplock_level(held), contend, smb2_util_lease_state(contend),
1108                     brokento, smb2_util_oplock_level(brokento), granted, smb2_util_lease_state(granted));
1109
1110                 ZERO_STRUCT(lease_break_info);
1111
1112                 /* Grab an oplock. */
1113                 smb2_oplock_create(&io, fname, smb2_util_oplock_level(held));
1114                 status = smb2_create(tree, mem_ctx, &io);
1115                 CHECK_STATUS(status, NT_STATUS_OK);
1116                 h = io.out.file.handle;
1117                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1118                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(held));
1119                 lease_break_info.held_oplock_level = io.out.oplock_level;
1120
1121                 /* Grab lease. */
1122                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(contend));
1123                 status = smb2_create(tree, mem_ctx, &io);
1124                 CHECK_STATUS(status, NT_STATUS_OK);
1125                 h2 = io.out.file.handle;
1126                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1127                 CHECK_LEASE(&io, granted, true, LEASE1, 0);
1128
1129                 if (smb2_util_oplock_level(held) != smb2_util_oplock_level(brokento)) {
1130                         CHECK_OPLOCK_BREAK(brokento);
1131                 } else {
1132                         CHECK_NO_BREAK(tctx);
1133                 }
1134
1135                 smb2_util_close(tree, h);
1136                 smb2_util_close(tree, h2);
1137
1138                 status = smb2_util_unlink(tree, fname);
1139                 CHECK_STATUS(status, NT_STATUS_OK);
1140         }
1141
1142  done:
1143         smb2_util_close(tree, h);
1144         smb2_util_close(tree, h2);
1145
1146         smb2_util_unlink(tree, fname);
1147
1148         talloc_free(mem_ctx);
1149
1150         return ret;
1151 }
1152
1153 static bool test_lease_multibreak(struct torture_context *tctx,
1154                                   struct smb2_tree *tree)
1155 {
1156         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1157         struct smb2_create io;
1158         struct smb2_lease ls;
1159         struct smb2_handle h = {{0}};
1160         struct smb2_handle h2 = {{0}};
1161         struct smb2_handle h3 = {{0}};
1162         struct smb2_write w;
1163         NTSTATUS status;
1164         const char *fname = "lease_multibreak.dat";
1165         bool ret = true;
1166         uint32_t caps;
1167
1168         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1169         if (!(caps & SMB2_CAP_LEASING)) {
1170                 torture_skip(tctx, "leases are not supported");
1171         }
1172
1173         tree->session->transport->lease.handler = torture_lease_handler;
1174         tree->session->transport->lease.private_data = tree;
1175         tree->session->transport->oplock.handler = torture_oplock_handler;
1176         tree->session->transport->oplock.private_data = tree;
1177
1178         smb2_util_unlink(tree, fname);
1179
1180         ZERO_STRUCT(lease_break_info);
1181
1182         /* Grab lease, upgrade to RHW .. */
1183         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
1184         status = smb2_create(tree, mem_ctx, &io);
1185         CHECK_STATUS(status, NT_STATUS_OK);
1186         h = io.out.file.handle;
1187         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1188         CHECK_LEASE(&io, "RH", true, LEASE1, 0);
1189
1190         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
1191         status = smb2_create(tree, mem_ctx, &io);
1192         CHECK_STATUS(status, NT_STATUS_OK);
1193         h2 = io.out.file.handle;
1194         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1195         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
1196
1197         /* Contend with LEASE2. */
1198         smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state("RHW"));
1199         status = smb2_create(tree, mem_ctx, &io);
1200         CHECK_STATUS(status, NT_STATUS_OK);
1201         h3 = io.out.file.handle;
1202         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1203         CHECK_LEASE(&io, "RH", true, LEASE2, 0);
1204
1205         /* Verify that we were only sent one break. */
1206         CHECK_BREAK_INFO("RHW", "RH", LEASE1);
1207
1208         /* Drop LEASE1 / LEASE2 */
1209         status = smb2_util_close(tree, h);
1210         CHECK_STATUS(status, NT_STATUS_OK);
1211         status = smb2_util_close(tree, h2);
1212         CHECK_STATUS(status, NT_STATUS_OK);
1213         status = smb2_util_close(tree, h3);
1214         CHECK_STATUS(status, NT_STATUS_OK);
1215
1216         ZERO_STRUCT(lease_break_info);
1217
1218         /* Grab an R lease. */
1219         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("R"));
1220         status = smb2_create(tree, mem_ctx, &io);
1221         CHECK_STATUS(status, NT_STATUS_OK);
1222         h = io.out.file.handle;
1223         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1224         CHECK_LEASE(&io, "R", true, LEASE1, 0);
1225
1226         /* Grab a level-II oplock. */
1227         smb2_oplock_create(&io, fname, smb2_util_oplock_level("s"));
1228         status = smb2_create(tree, mem_ctx, &io);
1229         CHECK_STATUS(status, NT_STATUS_OK);
1230         h2 = io.out.file.handle;
1231         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1232         CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1233         lease_break_info.held_oplock_level = io.out.oplock_level;
1234
1235         /* Verify no breaks. */
1236         CHECK_NO_BREAK(tctx);
1237
1238         /* Open for truncate, force a break. */
1239         smb2_generic_create(&io, NULL, false, fname,
1240             NTCREATEX_DISP_OVERWRITE_IF, smb2_util_oplock_level(""), 0, 0);
1241         status = smb2_create(tree, mem_ctx, &io);
1242         CHECK_STATUS(status, NT_STATUS_OK);
1243         h3 = io.out.file.handle;
1244         CHECK_CREATED(&io, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
1245         CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(""));
1246         lease_break_info.held_oplock_level = io.out.oplock_level;
1247
1248         /* Sleep, use a write to clear the recv queue. */
1249         smb_msleep(250);
1250         ZERO_STRUCT(w);
1251         w.in.file.handle = h3;
1252         w.in.offset      = 0;
1253         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
1254         memset(w.in.data.data, 'o', w.in.data.length);
1255         status = smb2_write(tree, &w);
1256         CHECK_STATUS(status, NT_STATUS_OK);
1257
1258         /* Verify one oplock break, one lease break. */
1259         CHECK_OPLOCK_BREAK("");
1260         CHECK_BREAK_INFO("R", "", LEASE1);
1261
1262  done:
1263         smb2_util_close(tree, h);
1264         smb2_util_close(tree, h2);
1265         smb2_util_close(tree, h3);
1266
1267         smb2_util_unlink(tree, fname);
1268
1269         talloc_free(mem_ctx);
1270
1271         return ret;
1272 }
1273
1274 static bool test_lease_v2_request_parent(struct torture_context *tctx,
1275                                          struct smb2_tree *tree)
1276 {
1277         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1278         struct smb2_create io;
1279         struct smb2_lease ls;
1280         struct smb2_handle h1 = {{0}};
1281         uint64_t parent = LEASE2;
1282         NTSTATUS status;
1283         const char *fname = "lease_v2_request_parent.dat";
1284         bool ret = true;
1285         uint32_t caps;
1286         enum protocol_types protocol;
1287
1288         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1289         if (!(caps & SMB2_CAP_LEASING)) {
1290                 torture_skip(tctx, "leases are not supported");
1291         }
1292         if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
1293                 torture_skip(tctx, "directory leases are not supported");
1294         }
1295
1296         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1297         if (protocol < PROTOCOL_SMB3_00) {
1298                 torture_skip(tctx, "v2 leases are not supported");
1299         }
1300
1301         smb2_util_unlink(tree, fname);
1302
1303         ZERO_STRUCT(lease_break_info);
1304
1305         ZERO_STRUCT(io);
1306         smb2_lease_v2_create_share(&io, &ls, false, fname,
1307                                    smb2_util_share_access("RWD"),
1308                                    LEASE1, &parent,
1309                                    smb2_util_lease_state("RHW"),
1310                                    0x11);
1311
1312         status = smb2_create(tree, mem_ctx, &io);
1313         CHECK_STATUS(status, NT_STATUS_OK);
1314         h1 = io.out.file.handle;
1315         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1316         CHECK_LEASE_V2(&io, "RHW", true, LEASE1,
1317                        SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2,
1318                        ls.lease_epoch + 1);
1319
1320  done:
1321         smb2_util_close(tree, h1);
1322         smb2_util_unlink(tree, fname);
1323
1324         talloc_free(mem_ctx);
1325
1326         return ret;
1327 }
1328
1329 static bool test_lease_break_twice(struct torture_context *tctx,
1330                                    struct smb2_tree *tree)
1331 {
1332         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1333         struct smb2_create io;
1334         struct smb2_lease ls1;
1335         struct smb2_lease ls2;
1336         struct smb2_handle h1 = {{0}};
1337         NTSTATUS status;
1338         const char *fname = "lease_break_twice.dat";
1339         bool ret = true;
1340         uint32_t caps;
1341         enum protocol_types protocol;
1342
1343         caps = smb2cli_conn_server_capabilities(
1344                 tree->session->transport->conn);
1345         if (!(caps & SMB2_CAP_LEASING)) {
1346                 torture_skip(tctx, "leases are not supported");
1347         }
1348
1349         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1350         if (protocol < PROTOCOL_SMB3_00) {
1351                 torture_skip(tctx, "v2 leases are not supported");
1352         }
1353
1354         smb2_util_unlink(tree, fname);
1355
1356         ZERO_STRUCT(lease_break_info);
1357         ZERO_STRUCT(io);
1358
1359         smb2_lease_v2_create_share(
1360                 &io, &ls1, false, fname, smb2_util_share_access("RWD"),
1361                 LEASE1, NULL, smb2_util_lease_state("RWH"), 0x11);
1362
1363         status = smb2_create(tree, mem_ctx, &io);
1364         CHECK_STATUS(status, NT_STATUS_OK);
1365         h1 = io.out.file.handle;
1366         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1367         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch + 1);
1368
1369         tree->session->transport->lease.handler = torture_lease_handler;
1370         tree->session->transport->lease.private_data = tree;
1371
1372         ZERO_STRUCT(lease_break_info);
1373
1374         smb2_lease_v2_create_share(
1375                 &io, &ls2, false, fname, smb2_util_share_access("R"),
1376                 LEASE2, NULL, smb2_util_lease_state("RWH"), 0x22);
1377
1378         status = smb2_create(tree, mem_ctx, &io);
1379         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
1380         CHECK_BREAK_INFO_V2(tree->session->transport,
1381                             "RWH", "RW", LEASE1, ls1.lease_epoch + 2);
1382
1383         smb2_lease_v2_create_share(
1384                 &io, &ls2, false, fname, smb2_util_share_access("RWD"),
1385                 LEASE2, NULL, smb2_util_lease_state("RWH"), 0x22);
1386
1387         ZERO_STRUCT(lease_break_info);
1388
1389         status = smb2_create(tree, mem_ctx, &io);
1390         CHECK_STATUS(status, NT_STATUS_OK);
1391         CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch + 1);
1392         CHECK_BREAK_INFO_V2(tree->session->transport,
1393                             "RW", "R", LEASE1, ls1.lease_epoch + 3);
1394
1395 done:
1396         smb2_util_close(tree, h1);
1397         smb2_util_unlink(tree, fname);
1398         talloc_free(mem_ctx);
1399         return ret;
1400 }
1401
1402 static bool test_lease_v2_request(struct torture_context *tctx,
1403                                   struct smb2_tree *tree)
1404 {
1405         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1406         struct smb2_create io;
1407         struct smb2_lease ls1, ls2, ls2t, ls3, ls4;
1408         struct smb2_handle h1 = {{0}};
1409         struct smb2_handle h2 = {{0}};
1410         struct smb2_handle h3 = {{0}};
1411         struct smb2_handle h4 = {{0}};
1412         struct smb2_handle h5 = {{0}};
1413         struct smb2_write w;
1414         NTSTATUS status;
1415         const char *fname = "lease_v2_request.dat";
1416         const char *dname = "lease_v2_request.dir";
1417         const char *dnamefname = "lease_v2_request.dir\\lease.dat";
1418         const char *dnamefname2 = "lease_v2_request.dir\\lease2.dat";
1419         bool ret = true;
1420         uint32_t caps;
1421         enum protocol_types protocol;
1422
1423         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1424         if (!(caps & SMB2_CAP_LEASING)) {
1425                 torture_skip(tctx, "leases are not supported");
1426         }
1427         if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
1428                 torture_skip(tctx, "directory leases are not supported");
1429         }
1430
1431         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1432         if (protocol < PROTOCOL_SMB3_00) {
1433                 torture_skip(tctx, "v2 leases are not supported");
1434         }
1435
1436         smb2_util_unlink(tree, fname);
1437         smb2_deltree(tree, dname);
1438
1439         tree->session->transport->lease.handler = torture_lease_handler;
1440         tree->session->transport->lease.private_data = tree;
1441         tree->session->transport->oplock.handler = torture_oplock_handler;
1442         tree->session->transport->oplock.private_data = tree;
1443
1444         ZERO_STRUCT(lease_break_info);
1445
1446         ZERO_STRUCT(io);
1447         smb2_lease_v2_create_share(&io, &ls1, false, fname,
1448                                    smb2_util_share_access("RWD"),
1449                                    LEASE1, NULL,
1450                                    smb2_util_lease_state("RHW"),
1451                                    0x11);
1452
1453         status = smb2_create(tree, mem_ctx, &io);
1454         CHECK_STATUS(status, NT_STATUS_OK);
1455         h1 = io.out.file.handle;
1456         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1457         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch + 1);
1458
1459         ZERO_STRUCT(io);
1460         smb2_lease_v2_create_share(&io, &ls2, true, dname,
1461                                    smb2_util_share_access("RWD"),
1462                                    LEASE2, NULL,
1463                                    smb2_util_lease_state("RHW"),
1464                                    0x22);
1465         status = smb2_create(tree, mem_ctx, &io);
1466         CHECK_STATUS(status, NT_STATUS_OK);
1467         h2 = io.out.file.handle;
1468         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY);
1469         CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch + 1);
1470
1471         ZERO_STRUCT(io);
1472         smb2_lease_v2_create_share(&io, &ls3, false, dnamefname,
1473                                    smb2_util_share_access("RWD"),
1474                                    LEASE3, &LEASE2,
1475                                    smb2_util_lease_state("RHW"),
1476                                    0x33);
1477         status = smb2_create(tree, mem_ctx, &io);
1478         CHECK_STATUS(status, NT_STATUS_OK);
1479         h3 = io.out.file.handle;
1480         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1481         CHECK_LEASE_V2(&io, "RHW", true, LEASE3,
1482                        SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2,
1483                        ls3.lease_epoch + 1);
1484
1485         CHECK_NO_BREAK(tctx);
1486
1487         ZERO_STRUCT(io);
1488         smb2_lease_v2_create_share(&io, &ls4, false, dnamefname2,
1489                                    smb2_util_share_access("RWD"),
1490                                    LEASE4, NULL,
1491                                    smb2_util_lease_state("RHW"),
1492                                    0x44);
1493         status = smb2_create(tree, mem_ctx, &io);
1494         CHECK_STATUS(status, NT_STATUS_OK);
1495         h4 = io.out.file.handle;
1496         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1497         CHECK_LEASE_V2(&io, "RHW", true, LEASE4, 0, 0, ls4.lease_epoch + 1);
1498
1499         CHECK_BREAK_INFO_V2(tree->session->transport,
1500                             "RH", "", LEASE2, ls2.lease_epoch + 2);
1501
1502         ZERO_STRUCT(lease_break_info);
1503
1504         ZERO_STRUCT(io);
1505         smb2_lease_v2_create_share(&io, &ls2t, true, dname,
1506                                    smb2_util_share_access("RWD"),
1507                                    LEASE2, NULL,
1508                                    smb2_util_lease_state("RHW"),
1509                                    0x222);
1510         io.in.create_disposition = NTCREATEX_DISP_OPEN;
1511         status = smb2_create(tree, mem_ctx, &io);
1512         CHECK_STATUS(status, NT_STATUS_OK);
1513         h5 = io.out.file.handle;
1514         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_DIRECTORY);
1515         CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch+3);
1516         smb2_util_close(tree, h5);
1517
1518         ZERO_STRUCT(w);
1519         w.in.file.handle = h4;
1520         w.in.offset      = 0;
1521         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
1522         memset(w.in.data.data, 'o', w.in.data.length);
1523         status = smb2_write(tree, &w);
1524         CHECK_STATUS(status, NT_STATUS_OK);
1525
1526         /*
1527          * Wait 4 seconds in order to check if the write time
1528          * was updated (after 2 seconds).
1529          */
1530         smb_msleep(4000);
1531         CHECK_NO_BREAK(tctx);
1532
1533         /*
1534          * only the close on the modified file break the
1535          * directory lease.
1536          */
1537         smb2_util_close(tree, h4);
1538
1539         CHECK_BREAK_INFO_V2(tree->session->transport,
1540                             "RH", "", LEASE2, ls2.lease_epoch+4);
1541
1542  done:
1543         smb2_util_close(tree, h1);
1544         smb2_util_close(tree, h2);
1545         smb2_util_close(tree, h3);
1546         smb2_util_close(tree, h4);
1547         smb2_util_close(tree, h5);
1548
1549         smb2_util_unlink(tree, fname);
1550         smb2_deltree(tree, dname);
1551
1552         talloc_free(mem_ctx);
1553
1554         return ret;
1555 }
1556
1557 static bool test_lease_v2_epoch1(struct torture_context *tctx,
1558                                  struct smb2_tree *tree)
1559 {
1560         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1561         struct smb2_create io;
1562         struct smb2_lease ls;
1563         struct smb2_handle h;
1564         const char *fname = "lease_v2_epoch1.dat";
1565         bool ret = true;
1566         NTSTATUS status;
1567         uint32_t caps;
1568         enum protocol_types protocol;
1569
1570         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1571         if (!(caps & SMB2_CAP_LEASING)) {
1572                 torture_skip(tctx, "leases are not supported");
1573         }
1574
1575         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1576         if (protocol < PROTOCOL_SMB3_00) {
1577                 torture_skip(tctx, "v2 leases are not supported");
1578         }
1579
1580         smb2_util_unlink(tree, fname);
1581
1582         tree->session->transport->lease.handler = torture_lease_handler;
1583         tree->session->transport->lease.private_data = tree;
1584         tree->session->transport->oplock.handler = torture_oplock_handler;
1585         tree->session->transport->oplock.private_data = tree;
1586
1587         ZERO_STRUCT(lease_break_info);
1588
1589         ZERO_STRUCT(io);
1590         smb2_lease_v2_create_share(&io, &ls, false, fname,
1591                                    smb2_util_share_access("RWD"),
1592                                    LEASE1, NULL,
1593                                    smb2_util_lease_state("RHW"),
1594                                    0x4711);
1595         status = smb2_create(tree, mem_ctx, &io);
1596         CHECK_STATUS(status, NT_STATUS_OK);
1597         h = io.out.file.handle;
1598         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1599         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls.lease_epoch + 1);
1600         smb2_util_close(tree, h);
1601         smb2_util_unlink(tree, fname);
1602
1603         smb2_lease_v2_create_share(&io, &ls, false, fname,
1604                                    smb2_util_share_access("RWD"),
1605                                    LEASE1, NULL,
1606                                    smb2_util_lease_state("RHW"),
1607                                    0x11);
1608
1609         status = smb2_create(tree, mem_ctx, &io);
1610         CHECK_STATUS(status, NT_STATUS_OK);
1611         h = io.out.file.handle;
1612         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1613         CHECK_LEASE_V2(&io, "RWH", true, LEASE1, 0, 0, ls.lease_epoch + 1);
1614         smb2_util_close(tree, h);
1615
1616 done:
1617         smb2_util_unlink(tree, fname);
1618         talloc_free(mem_ctx);
1619         return ret;
1620 }
1621
1622 static bool test_lease_v2_epoch2(struct torture_context *tctx,
1623                                  struct smb2_tree *tree)
1624 {
1625         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1626         struct smb2_create io;
1627         struct smb2_lease ls1v2, ls1v2t, ls1v1;
1628         struct smb2_handle hv2 = {}, hv1 = {};
1629         const char *fname = "lease_v2_epoch2.dat";
1630         bool ret = true;
1631         NTSTATUS status;
1632         uint32_t caps;
1633         enum protocol_types protocol;
1634
1635         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1636         if (!(caps & SMB2_CAP_LEASING)) {
1637                 torture_skip(tctx, "leases are not supported");
1638         }
1639
1640         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1641         if (protocol < PROTOCOL_SMB3_00) {
1642                 torture_skip(tctx, "v2 leases are not supported");
1643         }
1644
1645         smb2_util_unlink(tree, fname);
1646
1647         tree->session->transport->lease.handler = torture_lease_handler;
1648         tree->session->transport->lease.private_data = tree;
1649         tree->session->transport->oplock.handler = torture_oplock_handler;
1650         tree->session->transport->oplock.private_data = tree;
1651
1652         ZERO_STRUCT(lease_break_info);
1653
1654         ZERO_STRUCT(io);
1655         smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1656                                    smb2_util_share_access("RWD"),
1657                                    LEASE1, NULL,
1658                                    smb2_util_lease_state("R"),
1659                                    0x4711);
1660         status = smb2_create(tree, mem_ctx, &io);
1661         CHECK_STATUS(status, NT_STATUS_OK);
1662         hv2 = io.out.file.handle;
1663         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1664         CHECK_LEASE_V2(&io, "R", true, LEASE1, 0, 0, ls1v2.lease_epoch + 1);
1665
1666         ZERO_STRUCT(io);
1667         smb2_lease_create_share(&io, &ls1v1, false, fname,
1668                                 smb2_util_share_access("RWD"),
1669                                 LEASE1,
1670                                 smb2_util_lease_state("RH"));
1671         status = smb2_create(tree, mem_ctx, &io);
1672         CHECK_STATUS(status, NT_STATUS_OK);
1673         hv1 = io.out.file.handle;
1674         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1675         CHECK_LEASE_V2(&io, "RH", true, LEASE1, 0, 0, ls1v2.lease_epoch + 2);
1676
1677         smb2_util_close(tree, hv2);
1678
1679         ZERO_STRUCT(io);
1680         smb2_lease_v2_create_share(&io, &ls1v2t, false, fname,
1681                                    smb2_util_share_access("RWD"),
1682                                    LEASE1, NULL,
1683                                    smb2_util_lease_state("RHW"),
1684                                    0x11);
1685         status = smb2_create(tree, mem_ctx, &io);
1686         CHECK_STATUS(status, NT_STATUS_OK);
1687         hv2 = io.out.file.handle;
1688         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1689         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1v2.lease_epoch + 3);
1690
1691         smb2_util_close(tree, hv2);
1692
1693         smb2_oplock_create(&io, fname, SMB2_OPLOCK_LEVEL_NONE);
1694         status = smb2_create(tree, mem_ctx, &io);
1695         CHECK_STATUS(status, NT_STATUS_OK);
1696         hv2 = io.out.file.handle;
1697         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1698         CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1699
1700         CHECK_BREAK_INFO_V2(tree->session->transport,
1701                             "RWH", "RH", LEASE1, ls1v2.lease_epoch + 4);
1702
1703         smb2_util_close(tree, hv2);
1704         smb2_util_close(tree, hv1);
1705
1706         ZERO_STRUCT(io);
1707         smb2_lease_create_share(&io, &ls1v1, false, fname,
1708                                 smb2_util_share_access("RWD"),
1709                                 LEASE1,
1710                                 smb2_util_lease_state("RHW"));
1711         status = smb2_create(tree, mem_ctx, &io);
1712         CHECK_STATUS(status, NT_STATUS_OK);
1713         hv1 = io.out.file.handle;
1714         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1715         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
1716
1717         smb2_util_close(tree, hv1);
1718
1719 done:
1720         smb2_util_close(tree, hv2);
1721         smb2_util_close(tree, hv1);
1722         smb2_util_unlink(tree, fname);
1723         talloc_free(mem_ctx);
1724         return ret;
1725 }
1726
1727 static bool test_lease_v2_epoch3(struct torture_context *tctx,
1728                                  struct smb2_tree *tree)
1729 {
1730         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1731         struct smb2_create io;
1732         struct smb2_lease ls1v1 = {}, ls1v1t = {},ls1v2 = {};
1733         struct smb2_handle hv1 = {}, hv2 = {};
1734         const char *fname = "lease_v2_epoch3.dat";
1735         bool ret = true;
1736         NTSTATUS status;
1737         uint32_t caps;
1738         enum protocol_types protocol;
1739
1740         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1741         if (!(caps & SMB2_CAP_LEASING)) {
1742                 torture_skip(tctx, "leases are not supported");
1743         }
1744
1745         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1746         if (protocol < PROTOCOL_SMB3_00) {
1747                 torture_skip(tctx, "v2 leases are not supported");
1748         }
1749
1750         smb2_util_unlink(tree, fname);
1751
1752         tree->session->transport->lease.handler = torture_lease_handler;
1753         tree->session->transport->lease.private_data = tree;
1754         tree->session->transport->oplock.handler = torture_oplock_handler;
1755         tree->session->transport->oplock.private_data = tree;
1756
1757         ZERO_STRUCT(lease_break_info);
1758
1759         ZERO_STRUCT(io);
1760         smb2_lease_create_share(&io, &ls1v1, false, fname,
1761                                 smb2_util_share_access("RWD"),
1762                                 LEASE1,
1763                                 smb2_util_lease_state("R"));
1764         status = smb2_create(tree, mem_ctx, &io);
1765         CHECK_STATUS(status, NT_STATUS_OK);
1766         hv1 = io.out.file.handle;
1767         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1768         CHECK_LEASE(&io, "R", true, LEASE1, 0);
1769
1770         ZERO_STRUCT(io);
1771         smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1772                                    smb2_util_share_access("RWD"),
1773                                    LEASE1, NULL,
1774                                    smb2_util_lease_state("RW"),
1775                                    0x4711);
1776         status = smb2_create(tree, mem_ctx, &io);
1777         CHECK_STATUS(status, NT_STATUS_OK);
1778         hv2 = io.out.file.handle;
1779         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1780         CHECK_LEASE(&io, "RW", true, LEASE1, 0);
1781
1782         smb2_util_close(tree, hv1);
1783
1784         ZERO_STRUCT(io);
1785         smb2_lease_create_share(&io, &ls1v1t, false, fname,
1786                                 smb2_util_share_access("RWD"),
1787                                 LEASE1,
1788                                 smb2_util_lease_state("RWH"));
1789         status = smb2_create(tree, mem_ctx, &io);
1790         CHECK_STATUS(status, NT_STATUS_OK);
1791         hv1 = io.out.file.handle;
1792         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1793         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
1794
1795         smb2_util_close(tree, hv1);
1796
1797         smb2_oplock_create(&io, fname, SMB2_OPLOCK_LEVEL_NONE);
1798         status = smb2_create(tree, mem_ctx, &io);
1799         CHECK_STATUS(status, NT_STATUS_OK);
1800         hv1 = io.out.file.handle;
1801         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1802         CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1803
1804         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
1805
1806         smb2_util_close(tree, hv1);
1807         smb2_util_close(tree, hv2);
1808
1809         ZERO_STRUCT(io);
1810         smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1811                                    smb2_util_share_access("RWD"),
1812                                    LEASE1, NULL,
1813                                    smb2_util_lease_state("RWH"),
1814                                    0x4711);
1815         status = smb2_create(tree, mem_ctx, &io);
1816         CHECK_STATUS(status, NT_STATUS_OK);
1817         hv2 = io.out.file.handle;
1818         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1819         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1v2.lease_epoch + 1);
1820         smb2_util_close(tree, hv2);
1821
1822 done:
1823         smb2_util_close(tree, hv2);
1824         smb2_util_close(tree, hv1);
1825         smb2_util_unlink(tree, fname);
1826         talloc_free(mem_ctx);
1827         return ret;
1828 }
1829
1830 static bool test_lease_breaking1(struct torture_context *tctx,
1831                                  struct smb2_tree *tree)
1832 {
1833         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1834         struct smb2_create io1 = {};
1835         struct smb2_create io2 = {};
1836         struct smb2_lease ls1 = {};
1837         struct smb2_handle h1a = {};
1838         struct smb2_handle h1b = {};
1839         struct smb2_handle h2 = {};
1840         struct smb2_request *req2 = NULL;
1841         struct smb2_lease_break_ack ack = {};
1842         const char *fname = "lease_breaking1.dat";
1843         bool ret = true;
1844         NTSTATUS status;
1845         uint32_t caps;
1846
1847         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1848         if (!(caps & SMB2_CAP_LEASING)) {
1849                 torture_skip(tctx, "leases are not supported");
1850         }
1851
1852         smb2_util_unlink(tree, fname);
1853
1854         tree->session->transport->lease.handler = torture_lease_handler;
1855         tree->session->transport->lease.private_data = tree;
1856         tree->session->transport->oplock.handler = torture_oplock_handler;
1857         tree->session->transport->oplock.private_data = tree;
1858
1859         /*
1860          * we defer acking the lease break.
1861          */
1862         ZERO_STRUCT(lease_break_info);
1863         lease_break_info.lease_skip_ack = true;
1864
1865         smb2_lease_create_share(&io1, &ls1, false, fname,
1866                                 smb2_util_share_access("RWD"),
1867                                 LEASE1,
1868                                 smb2_util_lease_state("RWH"));
1869         status = smb2_create(tree, mem_ctx, &io1);
1870         CHECK_STATUS(status, NT_STATUS_OK);
1871         h1a = io1.out.file.handle;
1872         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1873         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
1874
1875         /*
1876          * a conflicting open is blocked until we ack the
1877          * lease break
1878          */
1879         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
1880         req2 = smb2_create_send(tree, &io2);
1881         torture_assert(tctx, req2 != NULL, "smb2_create_send");
1882
1883         /*
1884          * we got the lease break, but defer the ack.
1885          */
1886         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
1887
1888         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1889
1890         ack.in.lease.lease_key =
1891                 lease_break_info.lease_break.current_lease.lease_key;
1892         ack.in.lease.lease_state =
1893                 lease_break_info.lease_break.new_lease_state;
1894         ZERO_STRUCT(lease_break_info);
1895
1896         /*
1897          * a open using the same lease key is still works,
1898          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
1899          */
1900         status = smb2_create(tree, mem_ctx, &io1);
1901         CHECK_STATUS(status, NT_STATUS_OK);
1902         h1b = io1.out.file.handle;
1903         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1904         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
1905         smb2_util_close(tree, h1b);
1906
1907         CHECK_NO_BREAK(tctx);
1908
1909         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1910
1911         /*
1912          * We ack the lease break.
1913          */
1914         status = smb2_lease_break_ack(tree, &ack);
1915         CHECK_STATUS(status, NT_STATUS_OK);
1916         CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
1917
1918         torture_assert(tctx, req2->cancel.can_cancel,
1919                        "req2 can_cancel");
1920
1921         status = smb2_create_recv(req2, tctx, &io2);
1922         CHECK_STATUS(status, NT_STATUS_OK);
1923         h2 = io2.out.file.handle;
1924         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1925         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1926
1927         CHECK_NO_BREAK(tctx);
1928 done:
1929         smb2_util_close(tree, h1a);
1930         smb2_util_close(tree, h1b);
1931         smb2_util_close(tree, h2);
1932         smb2_util_unlink(tree, fname);
1933         talloc_free(mem_ctx);
1934         return ret;
1935 }
1936
1937 static bool test_lease_breaking2(struct torture_context *tctx,
1938                                  struct smb2_tree *tree)
1939 {
1940         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1941         struct smb2_create io1 = {};
1942         struct smb2_create io2 = {};
1943         struct smb2_lease ls1 = {};
1944         struct smb2_handle h1a = {};
1945         struct smb2_handle h1b = {};
1946         struct smb2_handle h2 = {};
1947         struct smb2_request *req2 = NULL;
1948         struct smb2_lease_break_ack ack = {};
1949         const char *fname = "lease_breaking2.dat";
1950         bool ret = true;
1951         NTSTATUS status;
1952         uint32_t caps;
1953
1954         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1955         if (!(caps & SMB2_CAP_LEASING)) {
1956                 torture_skip(tctx, "leases are not supported");
1957         }
1958
1959         smb2_util_unlink(tree, fname);
1960
1961         tree->session->transport->lease.handler = torture_lease_handler;
1962         tree->session->transport->lease.private_data = tree;
1963         tree->session->transport->oplock.handler = torture_oplock_handler;
1964         tree->session->transport->oplock.private_data = tree;
1965
1966         /*
1967          * we defer acking the lease break.
1968          */
1969         ZERO_STRUCT(lease_break_info);
1970         lease_break_info.lease_skip_ack = true;
1971
1972         smb2_lease_create_share(&io1, &ls1, false, fname,
1973                                 smb2_util_share_access("RWD"),
1974                                 LEASE1,
1975                                 smb2_util_lease_state("RWH"));
1976         status = smb2_create(tree, mem_ctx, &io1);
1977         CHECK_STATUS(status, NT_STATUS_OK);
1978         h1a = io1.out.file.handle;
1979         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1980         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
1981
1982         /*
1983          * a conflicting open is blocked until we ack the
1984          * lease break
1985          */
1986         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
1987         io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1988         req2 = smb2_create_send(tree, &io2);
1989         torture_assert(tctx, req2 != NULL, "smb2_create_send");
1990
1991         /*
1992          * we got the lease break, but defer the ack.
1993          */
1994         CHECK_BREAK_INFO("RWH", "", LEASE1);
1995
1996         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1997
1998         ack.in.lease.lease_key =
1999                 lease_break_info.lease_break.current_lease.lease_key;
2000         ZERO_STRUCT(lease_break_info);
2001
2002         /*
2003          * a open using the same lease key is still works,
2004          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2005          */
2006         status = smb2_create(tree, mem_ctx, &io1);
2007         CHECK_STATUS(status, NT_STATUS_OK);
2008         h1b = io1.out.file.handle;
2009         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2010         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2011         smb2_util_close(tree, h1b);
2012
2013         CHECK_NO_BREAK(tctx);
2014
2015         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2016
2017         /*
2018          * We ack the lease break.
2019          */
2020         ack.in.lease.lease_state =
2021                 SMB2_LEASE_READ | SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE;
2022         status = smb2_lease_break_ack(tree, &ack);
2023         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2024
2025         ack.in.lease.lease_state =
2026                 SMB2_LEASE_READ | SMB2_LEASE_WRITE;
2027         status = smb2_lease_break_ack(tree, &ack);
2028         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2029
2030         ack.in.lease.lease_state =
2031                 SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE;
2032         status = smb2_lease_break_ack(tree, &ack);
2033         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2034
2035         ack.in.lease.lease_state =
2036                 SMB2_LEASE_READ | SMB2_LEASE_HANDLE;
2037         status = smb2_lease_break_ack(tree, &ack);
2038         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2039
2040         ack.in.lease.lease_state = SMB2_LEASE_WRITE;
2041         status = smb2_lease_break_ack(tree, &ack);
2042         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2043
2044         ack.in.lease.lease_state = SMB2_LEASE_HANDLE;
2045         status = smb2_lease_break_ack(tree, &ack);
2046         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2047
2048         ack.in.lease.lease_state = SMB2_LEASE_READ;
2049         status = smb2_lease_break_ack(tree, &ack);
2050         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2051
2052         /* Try again with the correct state this time. */
2053         ack.in.lease.lease_state = SMB2_LEASE_NONE;;
2054         status = smb2_lease_break_ack(tree, &ack);
2055         CHECK_STATUS(status, NT_STATUS_OK);
2056         CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2057
2058         status = smb2_lease_break_ack(tree, &ack);
2059         CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
2060
2061         torture_assert(tctx, req2->cancel.can_cancel,
2062                        "req2 can_cancel");
2063
2064         status = smb2_create_recv(req2, tctx, &io2);
2065         CHECK_STATUS(status, NT_STATUS_OK);
2066         h2 = io2.out.file.handle;
2067         CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2068         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2069
2070         CHECK_NO_BREAK(tctx);
2071
2072         /* Get state of the original handle. */
2073         smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state(""));
2074         status = smb2_create(tree, mem_ctx, &io1);
2075         CHECK_STATUS(status, NT_STATUS_OK);
2076         CHECK_LEASE(&io1, "", true, LEASE1, 0);
2077         smb2_util_close(tree, io1.out.file.handle);
2078
2079 done:
2080         smb2_util_close(tree, h1a);
2081         smb2_util_close(tree, h1b);
2082         smb2_util_close(tree, h2);
2083         smb2_util_unlink(tree, fname);
2084         talloc_free(mem_ctx);
2085         return ret;
2086 }
2087
2088 static bool test_lease_breaking3(struct torture_context *tctx,
2089                                  struct smb2_tree *tree)
2090 {
2091         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2092         struct smb2_create io1 = {};
2093         struct smb2_create io2 = {};
2094         struct smb2_create io3 = {};
2095         struct smb2_lease ls1 = {};
2096         struct smb2_handle h1a = {};
2097         struct smb2_handle h1b = {};
2098         struct smb2_handle h2 = {};
2099         struct smb2_handle h3 = {};
2100         struct smb2_request *req2 = NULL;
2101         struct smb2_request *req3 = NULL;
2102         struct lease_break_info lease_break_info_tmp = {};
2103         struct smb2_lease_break_ack ack = {};
2104         const char *fname = "lease_breaking3.dat";
2105         bool ret = true;
2106         NTSTATUS status;
2107         uint32_t caps;
2108
2109         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2110         if (!(caps & SMB2_CAP_LEASING)) {
2111                 torture_skip(tctx, "leases are not supported");
2112         }
2113
2114         smb2_util_unlink(tree, fname);
2115
2116         tree->session->transport->lease.handler = torture_lease_handler;
2117         tree->session->transport->lease.private_data = tree;
2118         tree->session->transport->oplock.handler = torture_oplock_handler;
2119         tree->session->transport->oplock.private_data = tree;
2120
2121         /*
2122          * we defer acking the lease break.
2123          */
2124         ZERO_STRUCT(lease_break_info);
2125         lease_break_info.lease_skip_ack = true;
2126
2127         smb2_lease_create_share(&io1, &ls1, false, fname,
2128                                 smb2_util_share_access("RWD"),
2129                                 LEASE1,
2130                                 smb2_util_lease_state("RWH"));
2131         status = smb2_create(tree, mem_ctx, &io1);
2132         CHECK_STATUS(status, NT_STATUS_OK);
2133         h1a = io1.out.file.handle;
2134         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2135         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2136
2137         /*
2138          * a conflicting open is blocked until we ack the
2139          * lease break
2140          */
2141         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2142         req2 = smb2_create_send(tree, &io2);
2143         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2144
2145         /*
2146          * we got the lease break, but defer the ack.
2147          */
2148         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2149
2150         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2151
2152         /*
2153          * a open using the same lease key is still works,
2154          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2155          */
2156         status = smb2_create(tree, mem_ctx, &io1);
2157         CHECK_STATUS(status, NT_STATUS_OK);
2158         h1b = io1.out.file.handle;
2159         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2160         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2161         smb2_util_close(tree, h1b);
2162
2163         /*
2164          * a conflicting open with NTCREATEX_DISP_OVERWRITE
2165          * doesn't trigger an immediate lease break to none.
2166          */
2167         lease_break_info_tmp = lease_break_info;
2168         ZERO_STRUCT(lease_break_info);
2169         smb2_oplock_create(&io3, fname, SMB2_OPLOCK_LEVEL_NONE);
2170         io3.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2171         req3 = smb2_create_send(tree, &io3);
2172         torture_assert(tctx, req3 != NULL, "smb2_create_send");
2173         CHECK_NO_BREAK(tctx);
2174         lease_break_info = lease_break_info_tmp;
2175
2176         torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2177
2178         ack.in.lease.lease_key =
2179                 lease_break_info.lease_break.current_lease.lease_key;
2180         ack.in.lease.lease_state =
2181                 lease_break_info.lease_break.new_lease_state;
2182         ZERO_STRUCT(lease_break_info);
2183
2184         /*
2185          * a open using the same lease key is still works,
2186          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2187          */
2188         status = smb2_create(tree, mem_ctx, &io1);
2189         CHECK_STATUS(status, NT_STATUS_OK);
2190         h1b = io1.out.file.handle;
2191         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2192         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2193         smb2_util_close(tree, h1b);
2194
2195         CHECK_NO_BREAK(tctx);
2196
2197         /*
2198          * We ack the lease break, but defer acking the next break (to "R")
2199          */
2200         lease_break_info.lease_skip_ack = true;
2201         status = smb2_lease_break_ack(tree, &ack);
2202         CHECK_STATUS(status, NT_STATUS_OK);
2203         CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
2204
2205         /*
2206          * We got an additional break downgrading to just "R"
2207          * while we defer the ack.
2208          */
2209         CHECK_BREAK_INFO("RH", "R", LEASE1);
2210
2211         ack.in.lease.lease_key =
2212                 lease_break_info.lease_break.current_lease.lease_key;
2213         ack.in.lease.lease_state =
2214                 lease_break_info.lease_break.new_lease_state;
2215         ZERO_STRUCT(lease_break_info);
2216
2217         /*
2218          * a open using the same lease key is still works,
2219          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2220          */
2221         status = smb2_create(tree, mem_ctx, &io1);
2222         CHECK_STATUS(status, NT_STATUS_OK);
2223         h1b = io1.out.file.handle;
2224         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2225         CHECK_LEASE(&io1, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2226         smb2_util_close(tree, h1b);
2227
2228         CHECK_NO_BREAK(tctx);
2229
2230         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2231         torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2232
2233         /*
2234          * We ack the downgrade to "R" and get an immediate break to none
2235          */
2236         status = smb2_lease_break_ack(tree, &ack);
2237         CHECK_STATUS(status, NT_STATUS_OK);
2238         CHECK_LEASE_BREAK_ACK(&ack, "R", LEASE1);
2239
2240         /*
2241          * We get the downgrade to none.
2242          */
2243         CHECK_BREAK_INFO("R", "", LEASE1);
2244
2245         torture_assert(tctx, req2->cancel.can_cancel,
2246                        "req2 can_cancel");
2247         torture_assert(tctx, req3->cancel.can_cancel,
2248                        "req3 can_cancel");
2249
2250         ZERO_STRUCT(lease_break_info);
2251
2252         status = smb2_create_recv(req2, tctx, &io2);
2253         CHECK_STATUS(status, NT_STATUS_OK);
2254         h2 = io2.out.file.handle;
2255         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2256         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2257
2258         status = smb2_create_recv(req3, tctx, &io3);
2259         CHECK_STATUS(status, NT_STATUS_OK);
2260         h3 = io3.out.file.handle;
2261         CHECK_CREATED(&io3, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2262         CHECK_VAL(io3.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2263
2264         CHECK_NO_BREAK(tctx);
2265 done:
2266         smb2_util_close(tree, h1a);
2267         smb2_util_close(tree, h1b);
2268         smb2_util_close(tree, h2);
2269         smb2_util_close(tree, h3);
2270
2271         smb2_util_unlink(tree, fname);
2272         talloc_free(mem_ctx);
2273         return ret;
2274 }
2275
2276 static bool test_lease_v2_breaking3(struct torture_context *tctx,
2277                                  struct smb2_tree *tree)
2278 {
2279         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2280         struct smb2_create io1 = {};
2281         struct smb2_create io2 = {};
2282         struct smb2_create io3 = {};
2283         struct smb2_lease ls1 = {};
2284         struct smb2_handle h1a = {};
2285         struct smb2_handle h1b = {};
2286         struct smb2_handle h2 = {};
2287         struct smb2_handle h3 = {};
2288         struct smb2_request *req2 = NULL;
2289         struct smb2_request *req3 = NULL;
2290         struct lease_break_info lease_break_info_tmp = {};
2291         struct smb2_lease_break_ack ack = {};
2292         const char *fname = "v2_lease_breaking3.dat";
2293         bool ret = true;
2294         NTSTATUS status;
2295         uint32_t caps;
2296         enum protocol_types protocol;
2297
2298         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2299         if (!(caps & SMB2_CAP_LEASING)) {
2300                 torture_skip(tctx, "leases are not supported");
2301         }
2302
2303         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
2304         if (protocol < PROTOCOL_SMB3_00) {
2305                 torture_skip(tctx, "v2 leases are not supported");
2306         }
2307
2308         smb2_util_unlink(tree, fname);
2309
2310         tree->session->transport->lease.handler = torture_lease_handler;
2311         tree->session->transport->lease.private_data = tree;
2312         tree->session->transport->oplock.handler = torture_oplock_handler;
2313         tree->session->transport->oplock.private_data = tree;
2314
2315         /*
2316          * we defer acking the lease break.
2317          */
2318         ZERO_STRUCT(lease_break_info);
2319         lease_break_info.lease_skip_ack = true;
2320
2321         smb2_lease_v2_create_share(&io1, &ls1, false, fname,
2322                                    smb2_util_share_access("RWD"),
2323                                    LEASE1, NULL,
2324                                    smb2_util_lease_state("RHW"),
2325                                    0x11);
2326         status = smb2_create(tree, mem_ctx, &io1);
2327         CHECK_STATUS(status, NT_STATUS_OK);
2328         h1a = io1.out.file.handle;
2329         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2330         /* Epoch increases on open. */
2331         ls1.lease_epoch += 1;
2332         CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch);
2333
2334         /*
2335          * a conflicting open is blocked until we ack the
2336          * lease break
2337          */
2338         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2339         req2 = smb2_create_send(tree, &io2);
2340         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2341
2342         /*
2343          * we got the lease break, but defer the ack.
2344          */
2345         CHECK_BREAK_INFO_V2(tree->session->transport,
2346                             "RWH", "RH", LEASE1, ls1.lease_epoch + 1);
2347
2348         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2349
2350         /* On receiving a lease break, we must sync the new epoch. */
2351         ls1.lease_epoch = lease_break_info.lease_break.new_epoch;
2352
2353         /*
2354          * a open using the same lease key is still works,
2355          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2356          */
2357         status = smb2_create(tree, mem_ctx, &io1);
2358         CHECK_STATUS(status, NT_STATUS_OK);
2359         h1b = io1.out.file.handle;
2360         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2361         CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2362         smb2_util_close(tree, h1b);
2363
2364         /*
2365          * a conflicting open with NTCREATEX_DISP_OVERWRITE
2366          * doesn't trigger an immediate lease break to none.
2367          */
2368         lease_break_info_tmp = lease_break_info;
2369         ZERO_STRUCT(lease_break_info);
2370         smb2_oplock_create(&io3, fname, SMB2_OPLOCK_LEVEL_NONE);
2371         io3.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2372         req3 = smb2_create_send(tree, &io3);
2373         torture_assert(tctx, req3 != NULL, "smb2_create_send");
2374         CHECK_NO_BREAK(tctx);
2375         lease_break_info = lease_break_info_tmp;
2376
2377         torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2378
2379         ack.in.lease.lease_key =
2380                 lease_break_info.lease_break.current_lease.lease_key;
2381         ack.in.lease.lease_state =
2382                 lease_break_info.lease_break.new_lease_state;
2383         ZERO_STRUCT(lease_break_info);
2384
2385         /*
2386          * a open using the same lease key is still works,
2387          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2388          */
2389         status = smb2_create(tree, mem_ctx, &io1);
2390         CHECK_STATUS(status, NT_STATUS_OK);
2391         h1b = io1.out.file.handle;
2392         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2393         CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2394         smb2_util_close(tree, h1b);
2395
2396         CHECK_NO_BREAK(tctx);
2397
2398         /*
2399          * We ack the lease break, but defer acking the next break (to "R")
2400          */
2401         lease_break_info.lease_skip_ack = true;
2402         status = smb2_lease_break_ack(tree, &ack);
2403         CHECK_STATUS(status, NT_STATUS_OK);
2404         CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
2405
2406         /*
2407          * We got an additional break downgrading to just "R"
2408          * while we defer the ack.
2409          */
2410         CHECK_BREAK_INFO_V2(tree->session->transport,
2411                             "RH", "R", LEASE1, ls1.lease_epoch);
2412         /* On receiving a lease break, we must sync the new epoch. */
2413         ls1.lease_epoch = lease_break_info.lease_break.new_epoch;
2414
2415         ack.in.lease.lease_key =
2416                 lease_break_info.lease_break.current_lease.lease_key;
2417         ack.in.lease.lease_state =
2418                 lease_break_info.lease_break.new_lease_state;
2419         ZERO_STRUCT(lease_break_info);
2420
2421         /*
2422          * a open using the same lease key is still works,
2423          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2424          */
2425         status = smb2_create(tree, mem_ctx, &io1);
2426         CHECK_STATUS(status, NT_STATUS_OK);
2427         h1b = io1.out.file.handle;
2428         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2429         CHECK_LEASE_V2(&io1, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2430         smb2_util_close(tree, h1b);
2431
2432         CHECK_NO_BREAK(tctx);
2433
2434         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2435         torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2436
2437         /*
2438          * We ack the downgrade to "R" and get an immediate break to none
2439          */
2440         status = smb2_lease_break_ack(tree, &ack);
2441         CHECK_STATUS(status, NT_STATUS_OK);
2442         CHECK_LEASE_BREAK_ACK(&ack, "R", LEASE1);
2443
2444         /*
2445          * We get the downgrade to none.
2446          */
2447         CHECK_BREAK_INFO_V2(tree->session->transport,
2448                             "R", "", LEASE1, ls1.lease_epoch);
2449
2450         torture_assert(tctx, req2->cancel.can_cancel,
2451                        "req2 can_cancel");
2452         torture_assert(tctx, req3->cancel.can_cancel,
2453                        "req3 can_cancel");
2454
2455         ZERO_STRUCT(lease_break_info);
2456
2457         status = smb2_create_recv(req2, tctx, &io2);
2458         CHECK_STATUS(status, NT_STATUS_OK);
2459         h2 = io2.out.file.handle;
2460         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2461         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2462
2463         status = smb2_create_recv(req3, tctx, &io3);
2464         CHECK_STATUS(status, NT_STATUS_OK);
2465         h3 = io3.out.file.handle;
2466         CHECK_CREATED(&io3, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2467         CHECK_VAL(io3.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2468
2469         CHECK_NO_BREAK(tctx);
2470 done:
2471         smb2_util_close(tree, h1a);
2472         smb2_util_close(tree, h1b);
2473         smb2_util_close(tree, h2);
2474         smb2_util_close(tree, h3);
2475
2476         smb2_util_unlink(tree, fname);
2477         talloc_free(mem_ctx);
2478         return ret;
2479 }
2480
2481
2482 static bool test_lease_breaking4(struct torture_context *tctx,
2483                                  struct smb2_tree *tree)
2484 {
2485         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2486         struct smb2_create io1 = {};
2487         struct smb2_create io2 = {};
2488         struct smb2_create io3 = {};
2489         struct smb2_lease ls1 = {};
2490         struct smb2_lease ls1t = {};
2491         struct smb2_handle h1 = {};
2492         struct smb2_handle h2 = {};
2493         struct smb2_handle h3 = {};
2494         struct smb2_request *req2 = NULL;
2495         struct lease_break_info lease_break_info_tmp = {};
2496         struct smb2_lease_break_ack ack = {};
2497         const char *fname = "lease_breaking4.dat";
2498         bool ret = true;
2499         NTSTATUS status;
2500         uint32_t caps;
2501
2502         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2503         if (!(caps & SMB2_CAP_LEASING)) {
2504                 torture_skip(tctx, "leases are not supported");
2505         }
2506
2507         smb2_util_unlink(tree, fname);
2508
2509         tree->session->transport->lease.handler = torture_lease_handler;
2510         tree->session->transport->lease.private_data = tree;
2511         tree->session->transport->oplock.handler = torture_oplock_handler;
2512         tree->session->transport->oplock.private_data = tree;
2513
2514         /*
2515          * we defer acking the lease break.
2516          */
2517         ZERO_STRUCT(lease_break_info);
2518         lease_break_info.lease_skip_ack = true;
2519
2520         smb2_lease_create_share(&io1, &ls1, false, fname,
2521                                 smb2_util_share_access("RWD"),
2522                                 LEASE1,
2523                                 smb2_util_lease_state("RH"));
2524         status = smb2_create(tree, mem_ctx, &io1);
2525         CHECK_STATUS(status, NT_STATUS_OK);
2526         h1 = io1.out.file.handle;
2527         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2528         CHECK_LEASE(&io1, "RH", true, LEASE1, 0);
2529
2530         CHECK_NO_BREAK(tctx);
2531
2532         /*
2533          * a conflicting open is *not* blocked until we ack the
2534          * lease break
2535          */
2536         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2537         io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2538         req2 = smb2_create_send(tree, &io2);
2539         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2540
2541         /*
2542          * We got a break from RH to NONE, we're supported to ack
2543          * this downgrade
2544          */
2545         CHECK_BREAK_INFO("RH", "", LEASE1);
2546
2547         lease_break_info_tmp = lease_break_info;
2548         ZERO_STRUCT(lease_break_info);
2549         CHECK_NO_BREAK(tctx);
2550
2551         torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2552
2553         status = smb2_create_recv(req2, tctx, &io2);
2554         CHECK_STATUS(status, NT_STATUS_OK);
2555         h2 = io2.out.file.handle;
2556         CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2557         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2558         smb2_util_close(tree, h2);
2559
2560         CHECK_NO_BREAK(tctx);
2561
2562         /*
2563          * a conflicting open is *not* blocked until we ack the
2564          * lease break, even if the lease is in breaking state.
2565          */
2566         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2567         io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2568         req2 = smb2_create_send(tree, &io2);
2569         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2570
2571         CHECK_NO_BREAK(tctx);
2572
2573         torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2574
2575         status = smb2_create_recv(req2, tctx, &io2);
2576         CHECK_STATUS(status, NT_STATUS_OK);
2577         h2 = io2.out.file.handle;
2578         CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2579         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2580         smb2_util_close(tree, h2);
2581
2582         CHECK_NO_BREAK(tctx);
2583
2584         /*
2585          * We now ask the server about the current lease state
2586          * which should still be "RH", but with
2587          * SMB2_LEASE_FLAG_BREAK_IN_PROGRESS.
2588          */
2589         smb2_lease_create_share(&io3, &ls1t, false, fname,
2590                                 smb2_util_share_access("RWD"),
2591                                 LEASE1,
2592                                 smb2_util_lease_state(""));
2593         status = smb2_create(tree, mem_ctx, &io3);
2594         CHECK_STATUS(status, NT_STATUS_OK);
2595         h3 = io3.out.file.handle;
2596         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2597         CHECK_LEASE(&io3, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2598
2599         /*
2600          * We finally ack the lease break...
2601          */
2602         CHECK_NO_BREAK(tctx);
2603         lease_break_info = lease_break_info_tmp;
2604         ack.in.lease.lease_key =
2605                 lease_break_info.lease_break.current_lease.lease_key;
2606         ack.in.lease.lease_state =
2607                 lease_break_info.lease_break.new_lease_state;
2608         ZERO_STRUCT(lease_break_info);
2609         lease_break_info.lease_skip_ack = true;
2610
2611         status = smb2_lease_break_ack(tree, &ack);
2612         CHECK_STATUS(status, NT_STATUS_OK);
2613         CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2614
2615         CHECK_NO_BREAK(tctx);
2616
2617 done:
2618         smb2_util_close(tree, h1);
2619         smb2_util_close(tree, h2);
2620         smb2_util_close(tree, h3);
2621
2622         smb2_util_unlink(tree, fname);
2623         talloc_free(mem_ctx);
2624         return ret;
2625 }
2626
2627 static bool test_lease_breaking5(struct torture_context *tctx,
2628                                  struct smb2_tree *tree)
2629 {
2630         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2631         struct smb2_create io1 = {};
2632         struct smb2_create io2 = {};
2633         struct smb2_create io3 = {};
2634         struct smb2_lease ls1 = {};
2635         struct smb2_lease ls1t = {};
2636         struct smb2_handle h1 = {};
2637         struct smb2_handle h2 = {};
2638         struct smb2_handle h3 = {};
2639         struct smb2_request *req2 = NULL;
2640         struct lease_break_info lease_break_info_tmp = {};
2641         struct smb2_lease_break_ack ack = {};
2642         const char *fname = "lease_breaking5.dat";
2643         bool ret = true;
2644         NTSTATUS status;
2645         uint32_t caps;
2646
2647         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2648         if (!(caps & SMB2_CAP_LEASING)) {
2649                 torture_skip(tctx, "leases are not supported");
2650         }
2651
2652         smb2_util_unlink(tree, fname);
2653
2654         tree->session->transport->lease.handler = torture_lease_handler;
2655         tree->session->transport->lease.private_data = tree;
2656         tree->session->transport->oplock.handler = torture_oplock_handler;
2657         tree->session->transport->oplock.private_data = tree;
2658
2659         /*
2660          * we defer acking the lease break.
2661          */
2662         ZERO_STRUCT(lease_break_info);
2663         lease_break_info.lease_skip_ack = true;
2664
2665         smb2_lease_create_share(&io1, &ls1, false, fname,
2666                                 smb2_util_share_access("RWD"),
2667                                 LEASE1,
2668                                 smb2_util_lease_state("R"));
2669         status = smb2_create(tree, mem_ctx, &io1);
2670         CHECK_STATUS(status, NT_STATUS_OK);
2671         h1 = io1.out.file.handle;
2672         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2673         CHECK_LEASE(&io1, "R", true, LEASE1, 0);
2674
2675         CHECK_NO_BREAK(tctx);
2676
2677         /*
2678          * a conflicting open is *not* blocked until we ack the
2679          * lease break
2680          */
2681         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2682         io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2683         req2 = smb2_create_send(tree, &io2);
2684         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2685
2686         /*
2687          * We got a break from RH to NONE, we're supported to ack
2688          * this downgrade
2689          */
2690         CHECK_BREAK_INFO("R", "", LEASE1);
2691
2692         lease_break_info_tmp = lease_break_info;
2693         ZERO_STRUCT(lease_break_info);
2694         CHECK_NO_BREAK(tctx);
2695
2696         torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2697
2698         status = smb2_create_recv(req2, tctx, &io2);
2699         CHECK_STATUS(status, NT_STATUS_OK);
2700         h2 = io2.out.file.handle;
2701         CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2702         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2703
2704         CHECK_NO_BREAK(tctx);
2705
2706         /*
2707          * We now ask the server about the current lease state
2708          * which should still be "RH", but with
2709          * SMB2_LEASE_FLAG_BREAK_IN_PROGRESS.
2710          */
2711         smb2_lease_create_share(&io3, &ls1t, false, fname,
2712                                 smb2_util_share_access("RWD"),
2713                                 LEASE1,
2714                                 smb2_util_lease_state(""));
2715         status = smb2_create(tree, mem_ctx, &io3);
2716         CHECK_STATUS(status, NT_STATUS_OK);
2717         h3 = io3.out.file.handle;
2718         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2719         CHECK_LEASE(&io3, "", true, LEASE1, 0);
2720
2721         /*
2722          * We send an ack without without being asked.
2723          */
2724         CHECK_NO_BREAK(tctx);
2725         lease_break_info = lease_break_info_tmp;
2726         ack.in.lease.lease_key =
2727                 lease_break_info.lease_break.current_lease.lease_key;
2728         ack.in.lease.lease_state =
2729                 lease_break_info.lease_break.new_lease_state;
2730         ZERO_STRUCT(lease_break_info);
2731         status = smb2_lease_break_ack(tree, &ack);
2732         CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
2733
2734         CHECK_NO_BREAK(tctx);
2735
2736 done:
2737         smb2_util_close(tree, h1);
2738         smb2_util_close(tree, h2);
2739         smb2_util_close(tree, h3);
2740
2741         smb2_util_unlink(tree, fname);
2742         talloc_free(mem_ctx);
2743         return ret;
2744 }
2745
2746 static bool test_lease_breaking6(struct torture_context *tctx,
2747                                  struct smb2_tree *tree)
2748 {
2749         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2750         struct smb2_create io1 = {};
2751         struct smb2_create io2 = {};
2752         struct smb2_lease ls1 = {};
2753         struct smb2_handle h1a = {};
2754         struct smb2_handle h1b = {};
2755         struct smb2_handle h2 = {};
2756         struct smb2_request *req2 = NULL;
2757         struct smb2_lease_break_ack ack = {};
2758         const char *fname = "lease_breaking6.dat";
2759         bool ret = true;
2760         NTSTATUS status;
2761         uint32_t caps;
2762
2763         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2764         if (!(caps & SMB2_CAP_LEASING)) {
2765                 torture_skip(tctx, "leases are not supported");
2766         }
2767
2768         smb2_util_unlink(tree, fname);
2769
2770         tree->session->transport->lease.handler = torture_lease_handler;
2771         tree->session->transport->lease.private_data = tree;
2772         tree->session->transport->oplock.handler = torture_oplock_handler;
2773         tree->session->transport->oplock.private_data = tree;
2774
2775         /*
2776          * we defer acking the lease break.
2777          */
2778         ZERO_STRUCT(lease_break_info);
2779         lease_break_info.lease_skip_ack = true;
2780
2781         smb2_lease_create_share(&io1, &ls1, false, fname,
2782                                 smb2_util_share_access("RWD"),
2783                                 LEASE1,
2784                                 smb2_util_lease_state("RWH"));
2785         status = smb2_create(tree, mem_ctx, &io1);
2786         CHECK_STATUS(status, NT_STATUS_OK);
2787         h1a = io1.out.file.handle;
2788         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2789         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2790
2791         /*
2792          * a conflicting open is blocked until we ack the
2793          * lease break
2794          */
2795         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2796         req2 = smb2_create_send(tree, &io2);
2797         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2798
2799         /*
2800          * we got the lease break, but defer the ack.
2801          */
2802         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2803
2804         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2805
2806         ack.in.lease.lease_key =
2807                 lease_break_info.lease_break.current_lease.lease_key;
2808         ZERO_STRUCT(lease_break_info);
2809
2810         /*
2811          * a open using the same lease key is still works,
2812          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2813          */
2814         status = smb2_create(tree, mem_ctx, &io1);
2815         CHECK_STATUS(status, NT_STATUS_OK);
2816         h1b = io1.out.file.handle;
2817         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2818         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2819         smb2_util_close(tree, h1b);
2820
2821         CHECK_NO_BREAK(tctx);
2822
2823         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2824
2825         /*
2826          * We are asked to break to "RH", but we are allowed to
2827          * break to any of "RH", "R" or NONE.
2828          */
2829         ack.in.lease.lease_state = SMB2_LEASE_NONE;
2830         status = smb2_lease_break_ack(tree, &ack);
2831         CHECK_STATUS(status, NT_STATUS_OK);
2832         CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2833
2834         torture_assert(tctx, req2->cancel.can_cancel,
2835                        "req2 can_cancel");
2836
2837         status = smb2_create_recv(req2, tctx, &io2);
2838         CHECK_STATUS(status, NT_STATUS_OK);
2839         h2 = io2.out.file.handle;
2840         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2841         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2842
2843         CHECK_NO_BREAK(tctx);
2844 done:
2845         smb2_util_close(tree, h1a);
2846         smb2_util_close(tree, h1b);
2847         smb2_util_close(tree, h2);
2848         smb2_util_unlink(tree, fname);
2849         talloc_free(mem_ctx);
2850         return ret;
2851 }
2852
2853 static bool test_lease_lock1(struct torture_context *tctx,
2854                              struct smb2_tree *tree1a,
2855                              struct smb2_tree *tree2)
2856 {
2857         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2858         struct smb2_create io1 = {};
2859         struct smb2_create io2 = {};
2860         struct smb2_create io3 = {};
2861         struct smb2_lease ls1 = {};
2862         struct smb2_lease ls2 = {};
2863         struct smb2_lease ls3 = {};
2864         struct smb2_handle h1 = {};
2865         struct smb2_handle h2 = {};
2866         struct smb2_handle h3 = {};
2867         struct smb2_lock lck;
2868         struct smb2_lock_element el[1];
2869         const char *fname = "locktest.dat";
2870         bool ret = true;
2871         NTSTATUS status;
2872         uint32_t caps;
2873         struct smbcli_options options1;
2874         struct smb2_tree *tree1b = NULL;
2875
2876         options1 = tree1a->session->transport->options;
2877
2878         caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
2879         if (!(caps & SMB2_CAP_LEASING)) {
2880                 torture_skip(tctx, "leases are not supported");
2881         }
2882
2883         /* Set up handlers. */
2884         tree2->session->transport->lease.handler = torture_lease_handler;
2885         tree2->session->transport->lease.private_data = tree2;
2886         tree2->session->transport->oplock.handler = torture_oplock_handler;
2887         tree2->session->transport->oplock.private_data = tree2;
2888
2889         tree1a->session->transport->lease.handler = torture_lease_handler;
2890         tree1a->session->transport->lease.private_data = tree1a;
2891         tree1a->session->transport->oplock.handler = torture_oplock_handler;
2892         tree1a->session->transport->oplock.private_data = tree1a;
2893
2894         /* create a new connection (same client_guid) */
2895         if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
2896                 torture_warning(tctx, "couldn't reconnect, bailing\n");
2897                 ret = false;
2898                 goto done;
2899         }
2900
2901         tree1b->session->transport->lease.handler = torture_lease_handler;
2902         tree1b->session->transport->lease.private_data = tree1b;
2903         tree1b->session->transport->oplock.handler = torture_oplock_handler;
2904         tree1b->session->transport->oplock.private_data = tree1b;
2905
2906         smb2_util_unlink(tree1a, fname);
2907
2908         ZERO_STRUCT(lease_break_info);
2909         ZERO_STRUCT(lck);
2910
2911         /* Open a handle on tree1a. */
2912         smb2_lease_create_share(&io1, &ls1, false, fname,
2913                                 smb2_util_share_access("RWD"),
2914                                 LEASE1,
2915                                 smb2_util_lease_state("RWH"));
2916         status = smb2_create(tree1a, mem_ctx, &io1);
2917         CHECK_STATUS(status, NT_STATUS_OK);
2918         h1 = io1.out.file.handle;
2919         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2920         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2921
2922         /* Open a second handle on tree1b. */
2923         smb2_lease_create_share(&io2, &ls2, false, fname,
2924                                 smb2_util_share_access("RWD"),
2925                                 LEASE2,
2926                                 smb2_util_lease_state("RWH"));
2927         status = smb2_create(tree1b, mem_ctx, &io2);
2928         CHECK_STATUS(status, NT_STATUS_OK);
2929         h2 = io2.out.file.handle;
2930         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2931         CHECK_LEASE(&io2, "RH", true, LEASE2, 0);
2932         /* And LEASE1 got broken to RH. */
2933         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2934         ZERO_STRUCT(lease_break_info);
2935
2936         /* Now open a lease on a different client guid. */
2937         smb2_lease_create_share(&io3, &ls3, false, fname,
2938                                 smb2_util_share_access("RWD"),
2939                                 LEASE3,
2940                                 smb2_util_lease_state("RWH"));
2941         status = smb2_create(tree2, mem_ctx, &io3);
2942         CHECK_STATUS(status, NT_STATUS_OK);
2943         h3 = io3.out.file.handle;
2944         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2945         CHECK_LEASE(&io3, "RH", true, LEASE3, 0);
2946         /* Doesn't break. */
2947         CHECK_NO_BREAK(tctx);
2948
2949         lck.in.locks            = el;
2950         /*
2951          * Try and get get an exclusive byte
2952          * range lock on H1 (LEASE1).
2953          */
2954
2955         lck.in.lock_count       = 1;
2956         lck.in.lock_sequence    = 1;
2957         lck.in.file.handle      = h1;
2958         el[0].offset            = 0;
2959         el[0].length            = 1;
2960         el[0].reserved          = 0;
2961         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
2962         status = smb2_lock(tree1a, &lck);
2963         CHECK_STATUS(status, NT_STATUS_OK);
2964
2965         /* LEASE2 and LEASE3 should get broken to NONE. */
2966         torture_wait_for_lease_break(tctx);
2967         torture_wait_for_lease_break(tctx);
2968         torture_wait_for_lease_break(tctx);
2969         torture_wait_for_lease_break(tctx);
2970
2971         CHECK_VAL(lease_break_info.failures, 0);                      \
2972         CHECK_VAL(lease_break_info.count, 2);                         \
2973
2974         /* Get state of the H1 (LEASE1) */
2975         smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state(""));
2976         status = smb2_create(tree1a, mem_ctx, &io1);
2977         CHECK_STATUS(status, NT_STATUS_OK);
2978         /* Should still be RH. */
2979         CHECK_LEASE(&io1, "RH", true, LEASE1, 0);
2980         smb2_util_close(tree1a, io1.out.file.handle);
2981
2982         /* Get state of the H2 (LEASE2) */
2983         smb2_lease_create(&io2, &ls2, false, fname, LEASE2, smb2_util_lease_state(""));
2984         status = smb2_create(tree1b, mem_ctx, &io2);
2985         CHECK_STATUS(status, NT_STATUS_OK);
2986         CHECK_LEASE(&io2, "", true, LEASE2, 0);
2987         smb2_util_close(tree1b, io2.out.file.handle);
2988
2989         /* Get state of the H3 (LEASE3) */
2990         smb2_lease_create(&io3, &ls3, false, fname, LEASE3, smb2_util_lease_state(""));
2991         status = smb2_create(tree2, mem_ctx, &io3);
2992         CHECK_STATUS(status, NT_STATUS_OK);
2993         CHECK_LEASE(&io3, "", true, LEASE3, 0);
2994         smb2_util_close(tree2, io3.out.file.handle);
2995
2996         ZERO_STRUCT(lease_break_info);
2997
2998         /*
2999          * Try and get get an exclusive byte
3000          * range lock on H3 (LEASE3).
3001          */
3002         lck.in.lock_count       = 1;
3003         lck.in.lock_sequence    = 2;
3004         lck.in.file.handle      = h3;
3005         el[0].offset            = 100;
3006         el[0].length            = 1;
3007         el[0].reserved          = 0;
3008         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
3009         status = smb2_lock(tree2, &lck);
3010         CHECK_STATUS(status, NT_STATUS_OK);
3011         /* LEASE1 got broken to NONE. */
3012         CHECK_BREAK_INFO("RH", "", LEASE1);
3013         ZERO_STRUCT(lease_break_info);
3014
3015 done:
3016         smb2_util_close(tree1a, h1);
3017         smb2_util_close(tree1b, h2);
3018         smb2_util_close(tree2, h3);
3019
3020         smb2_util_unlink(tree1a, fname);
3021         talloc_free(mem_ctx);
3022         return ret;
3023 }
3024
3025 static bool test_lease_complex1(struct torture_context *tctx,
3026                                 struct smb2_tree *tree1a)
3027 {
3028         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3029         struct smb2_create io1;
3030         struct smb2_create io2;
3031         struct smb2_lease ls1;
3032         struct smb2_lease ls2;
3033         struct smb2_handle h = {{0}};
3034         struct smb2_handle h2 = {{0}};
3035         struct smb2_handle h3 = {{0}};
3036         struct smb2_write w;
3037         NTSTATUS status;
3038         const char *fname = "lease_complex1.dat";
3039         bool ret = true;
3040         uint32_t caps;
3041         struct smb2_tree *tree1b = NULL;
3042         struct smbcli_options options1;
3043
3044         options1 = tree1a->session->transport->options;
3045
3046         caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
3047         if (!(caps & SMB2_CAP_LEASING)) {
3048                 torture_skip(tctx, "leases are not supported");
3049         }
3050
3051         tree1a->session->transport->lease.handler = torture_lease_handler;
3052         tree1a->session->transport->lease.private_data = tree1a;
3053         tree1a->session->transport->oplock.handler = torture_oplock_handler;
3054         tree1a->session->transport->oplock.private_data = tree1a;
3055
3056         /* create a new connection (same client_guid) */
3057         if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
3058                 torture_warning(tctx, "couldn't reconnect, bailing\n");
3059                 ret = false;
3060                 goto done;
3061         }
3062
3063         tree1b->session->transport->lease.handler = torture_lease_handler;
3064         tree1b->session->transport->lease.private_data = tree1b;
3065         tree1b->session->transport->oplock.handler = torture_oplock_handler;
3066         tree1b->session->transport->oplock.private_data = tree1b;
3067
3068         smb2_util_unlink(tree1a, fname);
3069
3070         ZERO_STRUCT(lease_break_info);
3071
3072         /* Grab R lease over connection 1a */
3073         smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state("R"));
3074         status = smb2_create(tree1a, mem_ctx, &io1);
3075         CHECK_STATUS(status, NT_STATUS_OK);
3076         h = io1.out.file.handle;
3077         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3078         CHECK_LEASE(&io1, "R", true, LEASE1, 0);
3079
3080         /* Upgrade to RWH over connection 1b */
3081         ls1.lease_state = smb2_util_lease_state("RWH");
3082         status = smb2_create(tree1b, mem_ctx, &io1);
3083         CHECK_STATUS(status, NT_STATUS_OK);
3084         h2 = io1.out.file.handle;
3085         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3086         CHECK_LEASE(&io1, "RHW", true, LEASE1, 0);
3087
3088         /* close over connection 1b */
3089         status = smb2_util_close(tree1b, h2);
3090         CHECK_STATUS(status, NT_STATUS_OK);
3091
3092         /* Contend with LEASE2. */
3093         smb2_lease_create(&io2, &ls2, false, fname, LEASE2, smb2_util_lease_state("R"));
3094         status = smb2_create(tree1b, mem_ctx, &io2);
3095         CHECK_STATUS(status, NT_STATUS_OK);
3096         h3 = io2.out.file.handle;
3097         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3098         CHECK_LEASE(&io2, "R", true, LEASE2, 0);
3099
3100         /* Verify that we were only sent one break. */
3101         CHECK_BREAK_INFO("RHW", "RH", LEASE1);
3102
3103         /* again RH over connection 1b doesn't change the epoch */
3104         ls1.lease_state = smb2_util_lease_state("RH");
3105         status = smb2_create(tree1b, mem_ctx, &io1);
3106         CHECK_STATUS(status, NT_STATUS_OK);
3107         h2 = io1.out.file.handle;
3108         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3109         CHECK_LEASE(&io1, "RH", true, LEASE1, 0);
3110
3111         /* close over connection 1b */
3112         status = smb2_util_close(tree1b, h2);
3113         CHECK_STATUS(status, NT_STATUS_OK);
3114
3115         ZERO_STRUCT(lease_break_info);
3116
3117         ZERO_STRUCT(w);
3118         w.in.file.handle = h;
3119         w.in.offset      = 0;
3120         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
3121         memset(w.in.data.data, 'o', w.in.data.length);
3122         status = smb2_write(tree1a, &w);
3123         CHECK_STATUS(status, NT_STATUS_OK);
3124
3125         ls2.lease_epoch += 1;
3126         CHECK_BREAK_INFO("R", "", LEASE2);
3127
3128         ZERO_STRUCT(lease_break_info);
3129
3130         ZERO_STRUCT(w);
3131         w.in.file.handle = h3;
3132         w.in.offset      = 0;
3133         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
3134         memset(w.in.data.data, 'o', w.in.data.length);
3135         status = smb2_write(tree1b, &w);
3136         CHECK_STATUS(status, NT_STATUS_OK);
3137
3138         ls1.lease_epoch += 1;
3139         CHECK_BREAK_INFO("RH", "", LEASE1);
3140
3141  done:
3142         smb2_util_close(tree1a, h);
3143         smb2_util_close(tree1b, h2);
3144         smb2_util_close(tree1b, h3);
3145
3146         smb2_util_unlink(tree1a, fname);
3147
3148         talloc_free(mem_ctx);
3149
3150         return ret;
3151 }
3152
3153 static bool test_lease_v2_complex1(struct torture_context *tctx,
3154                                    struct smb2_tree *tree1a)
3155 {
3156         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3157         struct smb2_create io1;
3158         struct smb2_create io2;
3159         struct smb2_lease ls1;
3160         struct smb2_lease ls2;
3161         struct smb2_handle h = {{0}};
3162         struct smb2_handle h2 = {{0}};
3163         struct smb2_handle h3 = {{0}};
3164         struct smb2_write w;
3165         NTSTATUS status;
3166         const char *fname = "lease_v2_complex1.dat";
3167         bool ret = true;
3168         uint32_t caps;
3169         enum protocol_types protocol;
3170         struct smb2_tree *tree1b = NULL;
3171         struct smbcli_options options1;
3172
3173         options1 = tree1a->session->transport->options;
3174
3175         caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
3176         if (!(caps & SMB2_CAP_LEASING)) {
3177                 torture_skip(tctx, "leases are not supported");
3178         }
3179
3180         protocol = smbXcli_conn_protocol(tree1a->session->transport->conn);
3181         if (protocol < PROTOCOL_SMB3_00) {
3182                 torture_skip(tctx, "v2 leases are not supported");
3183         }
3184
3185         tree1a->session->transport->lease.handler = torture_lease_handler;
3186         tree1a->session->transport->lease.private_data = tree1a;
3187         tree1a->session->transport->oplock.handler = torture_oplock_handler;
3188         tree1a->session->transport->oplock.private_data = tree1a;
3189
3190         /* create a new connection (same client_guid) */
3191         if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
3192                 torture_warning(tctx, "couldn't reconnect, bailing\n");
3193                 ret = false;
3194                 goto done;
3195         }
3196
3197         tree1b->session->transport->lease.handler = torture_lease_handler;
3198         tree1b->session->transport->lease.private_data = tree1b;
3199         tree1b->session->transport->oplock.handler = torture_oplock_handler;
3200         tree1b->session->transport->oplock.private_data = tree1b;
3201
3202         smb2_util_unlink(tree1a, fname);
3203
3204         ZERO_STRUCT(lease_break_info);
3205
3206         /* Grab R lease over connection 1a */
3207         smb2_lease_v2_create(&io1, &ls1, false, fname, LEASE1, NULL,
3208                              smb2_util_lease_state("R"), 0x4711);
3209         status = smb2_create(tree1a, mem_ctx, &io1);
3210         CHECK_STATUS(status, NT_STATUS_OK);
3211         h = io1.out.file.handle;
3212         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3213         ls1.lease_epoch += 1;
3214         CHECK_LEASE_V2(&io1, "R", true, LEASE1,
3215                        0, 0, ls1.lease_epoch);
3216
3217         /* Upgrade to RWH over connection 1b */
3218         ls1.lease_state = smb2_util_lease_state("RWH");
3219         status = smb2_create(tree1b, mem_ctx, &io1);
3220         CHECK_STATUS(status, NT_STATUS_OK);
3221         h2 = io1.out.file.handle;
3222         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3223         ls1.lease_epoch += 1;
3224         CHECK_LEASE_V2(&io1, "RHW", true, LEASE1,
3225                        0, 0, ls1.lease_epoch);
3226
3227         /* close over connection 1b */
3228         status = smb2_util_close(tree1b, h2);
3229         CHECK_STATUS(status, NT_STATUS_OK);
3230
3231         /* Contend with LEASE2. */
3232         smb2_lease_v2_create(&io2, &ls2, false, fname, LEASE2, NULL,
3233                              smb2_util_lease_state("R"), 0x11);
3234         status = smb2_create(tree1b, mem_ctx, &io2);
3235         CHECK_STATUS(status, NT_STATUS_OK);
3236         h3 = io2.out.file.handle;
3237         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3238         ls2.lease_epoch += 1;
3239         CHECK_LEASE_V2(&io2, "R", true, LEASE2,
3240                        0, 0, ls2.lease_epoch);
3241
3242         /* Verify that we were only sent one break. */
3243         ls1.lease_epoch += 1;
3244         CHECK_BREAK_INFO_V2(tree1a->session->transport,
3245                             "RHW", "RH", LEASE1, ls1.lease_epoch);
3246
3247         /* again RH over connection 1b doesn't change the epoch */
3248         ls1.lease_state = smb2_util_lease_state("RH");
3249         status = smb2_create(tree1b, mem_ctx, &io1);
3250         CHECK_STATUS(status, NT_STATUS_OK);
3251         h2 = io1.out.file.handle;
3252         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3253         CHECK_LEASE_V2(&io1, "RH", true, LEASE1,
3254                        0, 0, ls1.lease_epoch);
3255
3256         /* close over connection 1b */
3257         status = smb2_util_close(tree1b, h2);
3258         CHECK_STATUS(status, NT_STATUS_OK);
3259
3260         ZERO_STRUCT(lease_break_info);
3261
3262         ZERO_STRUCT(w);
3263         w.in.file.handle = h;
3264         w.in.offset      = 0;
3265         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
3266         memset(w.in.data.data, 'o', w.in.data.length);
3267         status = smb2_write(tree1a, &w);
3268         CHECK_STATUS(status, NT_STATUS_OK);
3269
3270         ls2.lease_epoch += 1;
3271         CHECK_BREAK_INFO_V2(tree1a->session->transport,
3272                             "R", "", LEASE2, ls2.lease_epoch);
3273
3274         ZERO_STRUCT(lease_break_info);
3275
3276         ZERO_STRUCT(w);
3277         w.in.file.handle = h3;
3278         w.in.offset      = 0;
3279         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
3280         memset(w.in.data.data, 'o', w.in.data.length);
3281         status = smb2_write(tree1b, &w);
3282         CHECK_STATUS(status, NT_STATUS_OK);
3283
3284         ls1.lease_epoch += 1;
3285         CHECK_BREAK_INFO_V2(tree1a->session->transport,
3286                             "RH", "", LEASE1, ls1.lease_epoch);
3287
3288  done:
3289         smb2_util_close(tree1a, h);
3290         smb2_util_close(tree1b, h2);
3291         smb2_util_close(tree1b, h3);
3292
3293         smb2_util_unlink(tree1a, fname);
3294
3295         talloc_free(mem_ctx);
3296
3297         return ret;
3298 }
3299
3300 static bool test_lease_v2_complex2(struct torture_context *tctx,
3301                                    struct smb2_tree *tree1a)
3302 {
3303         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3304         struct smb2_create io1;
3305         struct smb2_create io2;
3306         struct smb2_lease ls1;
3307         struct smb2_lease ls2;
3308         struct smb2_handle h = {{0}};
3309         struct smb2_handle h2 = {{0}};
3310         struct smb2_request *req2 = NULL;
3311         struct smb2_lease_break_ack ack = {};
3312         NTSTATUS status;
3313         const char *fname = "lease_v2_complex2.dat";
3314         bool ret = true;
3315         uint32_t caps;
3316         enum protocol_types protocol;
3317         struct smb2_tree *tree1b = NULL;
3318         struct smbcli_options options1;
3319
3320         options1 = tree1a->session->transport->options;
3321
3322         caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
3323         if (!(caps & SMB2_CAP_LEASING)) {
3324                 torture_skip(tctx, "leases are not supported");
3325         }
3326
3327         protocol = smbXcli_conn_protocol(tree1a->session->transport->conn);
3328         if (protocol < PROTOCOL_SMB3_00) {
3329                 torture_skip(tctx, "v2 leases are not supported");
3330         }
3331
3332         tree1a->session->transport->lease.handler = torture_lease_handler;
3333         tree1a->session->transport->lease.private_data = tree1a;
3334         tree1a->session->transport->oplock.handler = torture_oplock_handler;
3335         tree1a->session->transport->oplock.private_data = tree1a;
3336
3337         /* create a new connection (same client_guid) */
3338         if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
3339                 torture_warning(tctx, "couldn't reconnect, bailing\n");
3340                 ret = false;
3341                 goto done;
3342         }
3343
3344         tree1b->session->transport->lease.handler = torture_lease_handler;
3345         tree1b->session->transport->lease.private_data = tree1b;
3346         tree1b->session->transport->oplock.handler = torture_oplock_handler;
3347         tree1b->session->transport->oplock.private_data = tree1b;
3348
3349         smb2_util_unlink(tree1a, fname);
3350
3351         ZERO_STRUCT(lease_break_info);
3352
3353         /* Grab RWH lease over connection 1a */
3354         smb2_lease_v2_create(&io1, &ls1, false, fname, LEASE1, NULL,
3355                              smb2_util_lease_state("RWH"), 0x4711);
3356         status = smb2_create(tree1a, mem_ctx, &io1);
3357         CHECK_STATUS(status, NT_STATUS_OK);
3358         h = io1.out.file.handle;
3359         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3360         ls1.lease_epoch += 1;
3361         CHECK_LEASE_V2(&io1, "RWH", true, LEASE1,
3362                        0, 0, ls1.lease_epoch);
3363
3364         /*
3365          * we defer acking the lease break.
3366          */
3367         ZERO_STRUCT(lease_break_info);
3368         lease_break_info.lease_skip_ack = true;
3369
3370         /* Ask for RWH on connection 1b, different lease. */
3371         smb2_lease_v2_create(&io2, &ls2, false, fname, LEASE2, NULL,
3372                              smb2_util_lease_state("RWH"), 0x11);
3373         req2 = smb2_create_send(tree1b, &io2);
3374         torture_assert(tctx, req2 != NULL, "smb2_create_send");
3375
3376         ls1.lease_epoch += 1;
3377
3378         CHECK_BREAK_INFO_V2(tree1a->session->transport,
3379                             "RWH", "RH", LEASE1, ls1.lease_epoch);
3380
3381         /* Send the break ACK on tree1b. */
3382         ack.in.lease.lease_key =
3383                 lease_break_info.lease_break.current_lease.lease_key;
3384         ack.in.lease.lease_state = SMB2_LEASE_HANDLE|SMB2_LEASE_READ;
3385
3386         status = smb2_lease_break_ack(tree1b, &ack);
3387         CHECK_STATUS(status, NT_STATUS_OK);
3388         CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
3389
3390         ZERO_STRUCT(lease_break_info);
3391
3392         status = smb2_create_recv(req2, tctx, &io2);
3393         CHECK_STATUS(status, NT_STATUS_OK);
3394         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3395         CHECK_LEASE_V2(&io2, "RH", true, LEASE2,
3396                        0, 0, ls2.lease_epoch+1);
3397         h2 = io2.out.file.handle;
3398
3399  done:
3400         smb2_util_close(tree1a, h);
3401         smb2_util_close(tree1b, h2);
3402
3403         smb2_util_unlink(tree1a, fname);
3404
3405         talloc_free(mem_ctx);
3406
3407         return ret;
3408 }
3409
3410
3411 static bool test_lease_timeout(struct torture_context *tctx,
3412                                struct smb2_tree *tree)
3413 {
3414         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3415         struct smb2_create io;
3416         struct smb2_lease ls1;
3417         struct smb2_lease ls2;
3418         struct smb2_handle h = {{0}};
3419         struct smb2_handle hnew = {{0}};
3420         struct smb2_handle h1b = {{0}};
3421         NTSTATUS status;
3422         const char *fname = "lease_timeout.dat";
3423         bool ret = true;
3424         struct smb2_lease_break_ack ack = {};
3425         struct smb2_request *req2 = NULL;
3426         struct smb2_write w;
3427         uint32_t caps;
3428
3429         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
3430         if (!(caps & SMB2_CAP_LEASING)) {
3431                 torture_skip(tctx, "leases are not supported");
3432         }
3433
3434         smb2_util_unlink(tree, fname);
3435
3436         /* Grab a RWH lease. */
3437         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3438         status = smb2_create(tree, mem_ctx, &io);
3439         CHECK_STATUS(status, NT_STATUS_OK);
3440         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3441         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3442         h = io.out.file.handle;
3443
3444         tree->session->transport->lease.handler = torture_lease_handler;
3445         tree->session->transport->lease.private_data = tree;
3446         tree->session->transport->oplock.handler = torture_oplock_handler;
3447         tree->session->transport->oplock.private_data = tree;
3448
3449         /*
3450          * Just don't ack the lease break.
3451          */
3452         ZERO_STRUCT(lease_break_info);
3453         lease_break_info.lease_skip_ack = true;
3454
3455         /* Break with a RWH request. */
3456         smb2_lease_create(&io, &ls2, false, fname, LEASE2, smb2_util_lease_state("RWH"));
3457         req2 = smb2_create_send(tree, &io);
3458         torture_assert(tctx, req2 != NULL, "smb2_create_send");
3459         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
3460
3461         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
3462
3463         /* Copy the break request. */
3464         ack.in.lease.lease_key =
3465                 lease_break_info.lease_break.current_lease.lease_key;
3466         ack.in.lease.lease_state =
3467                 lease_break_info.lease_break.new_lease_state;
3468
3469         /* Now wait for the timeout and get the reply. */
3470         status = smb2_create_recv(req2, tctx, &io);
3471         CHECK_STATUS(status, NT_STATUS_OK);
3472         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3473         CHECK_LEASE(&io, "RH", true, LEASE2, 0);
3474         hnew = io.out.file.handle;
3475
3476         /* Ack the break after the timeout... */
3477         status = smb2_lease_break_ack(tree, &ack);
3478         CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
3479
3480         /* Get state of the original handle. */
3481         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state(""));
3482         status = smb2_create(tree, mem_ctx, &io);
3483         CHECK_STATUS(status, NT_STATUS_OK);
3484         CHECK_LEASE(&io, "", true, LEASE1, 0);
3485         smb2_util_close(tree, io.out.file.handle);
3486
3487         /* Write on the original handle and make sure it's still valid. */
3488         ZERO_STRUCT(lease_break_info);
3489         ZERO_STRUCT(w);
3490         w.in.file.handle = h;
3491         w.in.offset      = 0;
3492         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
3493         memset(w.in.data.data, '1', w.in.data.length);
3494         status = smb2_write(tree, &w);
3495         CHECK_STATUS(status, NT_STATUS_OK);
3496
3497         /* Causes new handle to break to NONE. */
3498         CHECK_BREAK_INFO("RH", "", LEASE2);
3499
3500         /* Write on the new handle. */
3501         ZERO_STRUCT(lease_break_info);
3502         ZERO_STRUCT(w);
3503         w.in.file.handle = hnew;
3504         w.in.offset      = 0;
3505         w.in.data        = data_blob_talloc(mem_ctx, NULL, 1024);
3506         memset(w.in.data.data, '2', w.in.data.length);
3507         status = smb2_write(tree, &w);
3508         CHECK_STATUS(status, NT_STATUS_OK);
3509         /* No break - original handle was already NONE. */
3510         CHECK_NO_BREAK(tctx);
3511         smb2_util_close(tree, hnew);
3512
3513         /* Upgrade to R on LEASE1. */
3514         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("R"));
3515         status = smb2_create(tree, mem_ctx, &io);
3516         CHECK_STATUS(status, NT_STATUS_OK);
3517         CHECK_LEASE(&io, "R", true, LEASE1, 0);
3518         h1b = io.out.file.handle;
3519         smb2_util_close(tree, h1b);
3520
3521         /* Upgrade to RWH on LEASE1. */
3522         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3523         status = smb2_create(tree, mem_ctx, &io);
3524         CHECK_STATUS(status, NT_STATUS_OK);
3525         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3526         h1b = io.out.file.handle;
3527         smb2_util_close(tree, h1b);
3528
3529  done:
3530         smb2_util_close(tree, h);
3531         smb2_util_close(tree, hnew);
3532         smb2_util_close(tree, h1b);
3533
3534         smb2_util_unlink(tree, fname);
3535
3536         talloc_free(mem_ctx);
3537
3538         return ret;
3539 }
3540
3541 static bool test_lease_v2_rename(struct torture_context *tctx,
3542                                  struct smb2_tree *tree)
3543 {
3544         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3545         struct smb2_create io;
3546         struct smb2_lease ls1;
3547         struct smb2_lease ls2;
3548         struct smb2_handle h = {{0}};
3549         struct smb2_handle h1 = {{0}};
3550         struct smb2_handle h2 = {{0}};
3551         union smb_setfileinfo sinfo;
3552         const char *fname = "lease_v2_rename_src.dat";
3553         const char *fname_dst = "lease_v2_rename_dst.dat";
3554         bool ret = true;
3555         NTSTATUS status;
3556         uint32_t caps;
3557         enum protocol_types protocol;
3558
3559         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
3560         if (!(caps & SMB2_CAP_LEASING)) {
3561                 torture_skip(tctx, "leases are not supported");
3562         }
3563
3564         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
3565         if (protocol < PROTOCOL_SMB3_00) {
3566                 torture_skip(tctx, "v2 leases are not supported");
3567         }
3568
3569         smb2_util_unlink(tree, fname);
3570         smb2_util_unlink(tree, fname_dst);
3571
3572         tree->session->transport->lease.handler = torture_lease_handler;
3573         tree->session->transport->lease.private_data = tree;
3574         tree->session->transport->oplock.handler = torture_oplock_handler;
3575         tree->session->transport->oplock.private_data = tree;
3576
3577         ZERO_STRUCT(lease_break_info);
3578
3579         ZERO_STRUCT(io);
3580         smb2_lease_v2_create_share(&io, &ls1, false, fname,
3581                                    smb2_util_share_access("RWD"),
3582                                    LEASE1, NULL,
3583                                    smb2_util_lease_state("RHW"),
3584                                    0x4711);
3585         status = smb2_create(tree, mem_ctx, &io);
3586         CHECK_STATUS(status, NT_STATUS_OK);
3587         h = io.out.file.handle;
3588         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3589         ls1.lease_epoch += 1;
3590         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch);
3591
3592         /* Now rename - what happens ? */
3593         ZERO_STRUCT(sinfo);
3594         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3595         sinfo.rename_information.in.file.handle = h;
3596         sinfo.rename_information.in.overwrite = true;
3597         sinfo.rename_information.in.new_name = fname_dst;
3598         status = smb2_setinfo_file(tree, &sinfo);
3599         CHECK_STATUS(status, NT_STATUS_OK);
3600
3601         /* No lease break. */
3602         CHECK_NO_BREAK(tctx);
3603
3604         /* Check we can open another handle on the new name. */
3605         smb2_lease_v2_create_share(&io, &ls1, false, fname_dst,
3606                                    smb2_util_share_access("RWD"),
3607                                    LEASE1, NULL,
3608                                    smb2_util_lease_state(""),
3609                                    ls1.lease_epoch);
3610         status = smb2_create(tree, mem_ctx, &io);
3611         CHECK_STATUS(status, NT_STATUS_OK);
3612         h1 = io.out.file.handle;
3613         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3614         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch);
3615         smb2_util_close(tree, h1);
3616
3617         /* Try another lease key. */
3618         smb2_lease_v2_create_share(&io, &ls2, false, fname_dst,
3619                                    smb2_util_share_access("RWD"),
3620                                    LEASE2, NULL,
3621                                    smb2_util_lease_state("RWH"),
3622                                    0x44);
3623         status = smb2_create(tree, mem_ctx, &io);
3624         CHECK_STATUS(status, NT_STATUS_OK);
3625         h2 = io.out.file.handle;
3626         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3627         ls2.lease_epoch += 1;
3628         CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch );
3629         CHECK_BREAK_INFO_V2(tree->session->transport,
3630                             "RWH", "RH", LEASE1, ls1.lease_epoch + 1);
3631         ls1.lease_epoch += 1;
3632         ZERO_STRUCT(lease_break_info);
3633
3634         /* Now rename back. */
3635         ZERO_STRUCT(sinfo);
3636         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3637         sinfo.rename_information.in.file.handle = h;
3638         sinfo.rename_information.in.overwrite = true;
3639         sinfo.rename_information.in.new_name = fname;
3640         status = smb2_setinfo_file(tree, &sinfo);
3641         CHECK_STATUS(status, NT_STATUS_OK);
3642
3643         /* Breaks to R on LEASE2. */
3644         CHECK_BREAK_INFO_V2(tree->session->transport,
3645                             "RH", "R", LEASE2, ls2.lease_epoch + 1);
3646         ls2.lease_epoch += 1;
3647
3648         /* Check we can open another handle on the current name. */
3649         smb2_lease_v2_create_share(&io, &ls1, false, fname,
3650                                    smb2_util_share_access("RWD"),
3651                                    LEASE1, NULL,
3652                                    smb2_util_lease_state(""),
3653                                    ls1.lease_epoch);
3654         status = smb2_create(tree, mem_ctx, &io);
3655         CHECK_STATUS(status, NT_STATUS_OK);
3656         h1 = io.out.file.handle;
3657         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3658         CHECK_LEASE_V2(&io, "RH", true, LEASE1, 0, 0, ls1.lease_epoch);
3659         smb2_util_close(tree, h1);
3660
3661 done:
3662
3663         smb2_util_close(tree, h);
3664         smb2_util_close(tree, h1);
3665         smb2_util_close(tree, h2);
3666
3667         smb2_util_unlink(tree, fname);
3668         smb2_util_unlink(tree, fname_dst);
3669
3670         smb2_util_unlink(tree, fname);
3671         talloc_free(mem_ctx);
3672         return ret;
3673 }
3674
3675
3676 static bool test_lease_dynamic_share(struct torture_context *tctx,
3677                                    struct smb2_tree *tree1a)
3678 {
3679         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3680         struct smb2_create io;
3681         struct smb2_lease ls1;
3682         struct smb2_handle h, h1, h2;
3683         struct smb2_write w;
3684         NTSTATUS status;
3685         const char *fname = "dynamic_path.dat";
3686         bool ret = true;
3687         uint32_t caps;
3688         struct smb2_tree *tree_2_1 = NULL;
3689         struct smb2_tree *tree_3_0 = NULL;
3690         struct smbcli_options options2_1;
3691         struct smbcli_options options3_0;
3692         const char *orig_share = NULL;
3693
3694         if (!TARGET_IS_SAMBA3(tctx)) {
3695                 torture_skip(tctx, "dynamic shares are not supported");
3696                 return true;
3697         }
3698
3699         options2_1 = tree1a->session->transport->options;
3700         options3_0 = tree1a->session->transport->options;
3701
3702         caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
3703         if (!(caps & SMB2_CAP_LEASING)) {
3704                 torture_skip(tctx, "leases are not supported");
3705         }
3706
3707         /*
3708          * Save off original share name and change it to dynamic_share.
3709          * This must have been pre-created with a dynamic path containing
3710          * %R.
3711          */
3712
3713         orig_share = lpcfg_parm_string(tctx->lp_ctx, NULL, "torture", "share");
3714         orig_share = talloc_strdup(tctx->lp_ctx, orig_share);
3715         if (orig_share == NULL) {
3716                 torture_result(tctx, TORTURE_FAIL, __location__ "no memory\n");
3717                 ret = false;
3718                 goto done;
3719         }
3720         lpcfg_set_cmdline(tctx->lp_ctx, "torture:share", "dynamic_share");
3721
3722         /* Set max protocol to SMB2.1 */
3723         options2_1.max_protocol = PROTOCOL_SMB2_10;
3724         /* create a new connection (same client_guid) */
3725         if (!torture_smb2_connection_ext(tctx, 0, &options2_1, &tree_2_1)) {
3726                 torture_result(tctx,  TORTURE_FAIL,
3727                         __location__ "couldn't reconnect "
3728                         "max protocol 2.1, bailing\n");
3729                 ret = false;
3730                 goto done;
3731         }
3732
3733         tree_2_1->session->transport->lease.handler = torture_lease_handler;
3734         tree_2_1->session->transport->lease.private_data = tree_2_1;
3735         tree_2_1->session->transport->oplock.handler = torture_oplock_handler;
3736         tree_2_1->session->transport->oplock.private_data = tree_2_1;
3737
3738         smb2_util_unlink(tree_2_1, fname);
3739
3740         /* Set max protocol to SMB3.0 */
3741         options3_0.max_protocol = PROTOCOL_SMB3_00;
3742         /* create a new connection (same client_guid) */
3743         if (!torture_smb2_connection_ext(tctx, 0, &options3_0, &tree_3_0)) {
3744                 torture_result(tctx,  TORTURE_FAIL,
3745                         __location__ "couldn't reconnect "
3746                         "max protocol 3.0, bailing\n");
3747                 ret = false;
3748                 goto done;
3749         }
3750
3751         tree_3_0->session->transport->lease.handler = torture_lease_handler;
3752         tree_3_0->session->transport->lease.private_data = tree_3_0;
3753         tree_3_0->session->transport->oplock.handler = torture_oplock_handler;
3754         tree_3_0->session->transport->oplock.private_data = tree_3_0;
3755
3756         smb2_util_unlink(tree_3_0, fname);
3757
3758         ZERO_STRUCT(lease_break_info);
3759
3760         /* Get RWH lease over connection 2_1 */
3761         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3762         status = smb2_create(tree_2_1, mem_ctx, &io);
3763         CHECK_STATUS(status, NT_STATUS_OK);
3764         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3765         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3766         h = io.out.file.handle;
3767
3768         /* Write some data into it. */
3769         w.in.file.handle = h;
3770         w.in.offset      = 0;
3771         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
3772         memset(w.in.data.data, '1', w.in.data.length);
3773         status = smb2_write(tree_2_1, &w);
3774         CHECK_STATUS(status, NT_STATUS_OK);
3775
3776         /* Open the same name over connection 3_0. */
3777         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3778         status = smb2_create(tree_3_0, mem_ctx, &io);
3779         CHECK_STATUS(status, NT_STATUS_OK);
3780         h1 = io.out.file.handle;
3781         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3782
3783         /* h1 should have replied with NONE. */
3784         CHECK_LEASE(&io, "", true, LEASE1, 0);
3785
3786         /* We should have broken h to NONE. */
3787         CHECK_BREAK_INFO("RWH", "", LEASE1);
3788
3789         /* Try to upgrade to RWH over connection 2_1 */
3790         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3791         status = smb2_create(tree_2_1, mem_ctx, &io);
3792         CHECK_STATUS(status, NT_STATUS_OK);
3793         h2 = io.out.file.handle;
3794         CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
3795         CHECK_VAL(io.out.size, 4096);
3796         CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
3797         /* Should have been denied. */
3798         CHECK_LEASE(&io, "", true, LEASE1, 0);
3799         smb2_util_close(tree_2_1, h2);
3800
3801         /* Try to upgrade to RWH over connection 3_0 */
3802         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3803         status = smb2_create(tree_3_0, mem_ctx, &io);
3804         CHECK_STATUS(status, NT_STATUS_OK);
3805         h2 = io.out.file.handle;
3806         CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
3807         CHECK_VAL(io.out.size, 0);
3808         CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
3809         /* Should have been denied. */
3810         CHECK_LEASE(&io, "", true, LEASE1, 0);
3811         smb2_util_close(tree_3_0, h2);
3812
3813         /* Write some data into it. */
3814         w.in.file.handle = h1;
3815         w.in.offset      = 0;
3816         w.in.data        = data_blob_talloc(mem_ctx, NULL, 1024);
3817         memset(w.in.data.data, '2', w.in.data.length);
3818         status = smb2_write(tree_3_0, &w);
3819         CHECK_STATUS(status, NT_STATUS_OK);
3820
3821         /* Close everything.. */
3822         smb2_util_close(tree_2_1, h);
3823         smb2_util_close(tree_3_0, h1);
3824
3825         /* And ensure we can get a lease ! */
3826         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3827         status = smb2_create(tree_2_1, mem_ctx, &io);
3828         CHECK_STATUS(status, NT_STATUS_OK);
3829         CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
3830         CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
3831         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3832         h = io.out.file.handle;
3833         /* And the file is the right size. */
3834         CHECK_VAL(io.out.size, 4096);                           \
3835         /* Close it. */
3836         smb2_util_close(tree_2_1, h);
3837
3838         /* And ensure we can get a lease ! */
3839         smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH"));
3840         status = smb2_create(tree_3_0, mem_ctx, &io);
3841         CHECK_STATUS(status, NT_STATUS_OK);
3842         CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
3843         CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
3844         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
3845         h = io.out.file.handle;
3846         /* And the file is the right size. */
3847         CHECK_VAL(io.out.size, 1024);                           \
3848         /* Close it. */
3849         smb2_util_close(tree_3_0, h);
3850
3851  done:
3852
3853         if (tree_2_1 != NULL) {
3854                 smb2_util_close(tree_2_1, h);
3855                 smb2_util_unlink(tree_2_1, fname);
3856         }
3857         if (tree_3_0 != NULL) {
3858                 smb2_util_close(tree_3_0, h1);
3859                 smb2_util_close(tree_3_0, h2);
3860
3861                 smb2_util_unlink(tree_3_0, fname);
3862         }
3863
3864         /* Set sharename back. */
3865         lpcfg_set_cmdline(tctx->lp_ctx, "torture:share", orig_share);
3866
3867         talloc_free(mem_ctx);
3868
3869         return ret;
3870 }
3871
3872 /*
3873  * Test identifies a bug where the Samba server will not trigger a lease break
3874  * for a handle caching lease held by a client when the underlying file is
3875  * deleted.
3876  * Test:
3877  *      Connect session2.
3878  *      open file in session1
3879  *              session1 should have RWH lease.
3880  *      open file in session2
3881  *              lease break sent to session1 to downgrade lease to RH
3882  *      close file in session 2
3883  *      unlink file in session 2
3884  *              lease break sent to session1 to downgrade lease to R
3885  *      Cleanup
3886  */
3887 static bool test_lease_unlink(struct torture_context *tctx,
3888                               struct smb2_tree *tree1)
3889 {
3890         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3891         NTSTATUS status;
3892         bool ret = true;
3893         struct smbcli_options transport2_options;
3894         struct smb2_tree *tree2 = NULL;
3895         struct smb2_transport *transport1 = tree1->session->transport;
3896         struct smb2_transport *transport2;
3897         struct smb2_handle h1 = {{ 0 }};
3898         struct smb2_handle h2 = {{ 0 }};
3899         const char *fname = "lease_unlink.dat";
3900         uint32_t caps;
3901         struct smb2_create io1;
3902         struct smb2_create io2;
3903         struct smb2_lease ls1;
3904         struct smb2_lease ls2;
3905
3906         caps = smb2cli_conn_server_capabilities(
3907                         tree1->session->transport->conn);
3908         if (!(caps & SMB2_CAP_LEASING)) {
3909                 torture_skip(tctx, "leases are not supported");
3910         }
3911
3912         /* Connect 2nd connection */
3913         transport2_options = transport1->options;
3914         transport2_options.client_guid = GUID_random();
3915         if (!torture_smb2_connection_ext(tctx, 0, &transport2_options, &tree2)) {
3916                 torture_warning(tctx, "couldn't reconnect, bailing\n");
3917                 return false;
3918         }
3919         transport2 = tree2->session->transport;
3920
3921         /* Set lease handlers */
3922         transport1->lease.handler = torture_lease_handler;
3923         transport1->lease.private_data = tree1;
3924         transport2->lease.handler = torture_lease_handler;
3925         transport2->lease.private_data = tree2;
3926
3927
3928         smb2_lease_create(&io1, &ls1, false, fname, LEASE1,
3929                                 smb2_util_lease_state("RHW"));
3930         smb2_lease_create(&io2, &ls2, false, fname, LEASE2,
3931                                 smb2_util_lease_state("RHW"));
3932
3933         smb2_util_unlink(tree1, fname);
3934
3935         torture_comment(tctx, "Client opens fname with session 1\n");
3936         torture_reset_lease_break_info(tctx, &lease_break_info);
3937         status = smb2_create(tree1, mem_ctx, &io1);
3938         CHECK_STATUS(status, NT_STATUS_OK);
3939         h1 = io1.out.file.handle;
3940         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3941         CHECK_LEASE(&io1, "RHW", true, LEASE1, 0);
3942         CHECK_VAL(lease_break_info.count, 0);
3943
3944         torture_comment(tctx, "Client opens fname with session 2\n");
3945         torture_reset_lease_break_info(tctx, &lease_break_info);
3946         status = smb2_create(tree2, mem_ctx, &io2);
3947         CHECK_STATUS(status, NT_STATUS_OK);
3948         h2 = io2.out.file.handle;
3949         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3950         CHECK_LEASE(&io2, "RH", true, LEASE2, 0);
3951         CHECK_VAL(lease_break_info.count, 1);
3952         CHECK_BREAK_INFO("RHW", "RH", LEASE1);
3953
3954         torture_comment(tctx,
3955                 "Client closes and then unlinks fname with session 2\n");
3956         torture_reset_lease_break_info(tctx, &lease_break_info);
3957         smb2_util_close(tree2, h2);
3958         smb2_util_unlink(tree2, fname);
3959         CHECK_VAL(lease_break_info.count, 1);
3960         CHECK_BREAK_INFO("RH", "R", LEASE1);
3961
3962 done:
3963         smb2_util_close(tree1, h1);
3964         smb2_util_close(tree2, h2);
3965         smb2_util_unlink(tree1, fname);
3966
3967         return ret;
3968 }
3969
3970 struct torture_suite *torture_smb2_lease_init(TALLOC_CTX *ctx)
3971 {
3972         struct torture_suite *suite =
3973             torture_suite_create(ctx, "lease");
3974
3975         torture_suite_add_1smb2_test(suite, "request", test_lease_request);
3976         torture_suite_add_1smb2_test(suite, "break_twice",
3977                                      test_lease_break_twice);
3978         torture_suite_add_1smb2_test(suite, "nobreakself",
3979                                      test_lease_nobreakself);
3980         torture_suite_add_1smb2_test(suite, "statopen", test_lease_statopen);
3981         torture_suite_add_1smb2_test(suite, "statopen2", test_lease_statopen2);
3982         torture_suite_add_1smb2_test(suite, "statopen3", test_lease_statopen3);
3983         torture_suite_add_1smb2_test(suite, "upgrade", test_lease_upgrade);
3984         torture_suite_add_1smb2_test(suite, "upgrade2", test_lease_upgrade2);
3985         torture_suite_add_1smb2_test(suite, "upgrade3", test_lease_upgrade3);
3986         torture_suite_add_1smb2_test(suite, "break", test_lease_break);
3987         torture_suite_add_1smb2_test(suite, "oplock", test_lease_oplock);
3988         torture_suite_add_1smb2_test(suite, "multibreak", test_lease_multibreak);
3989         torture_suite_add_1smb2_test(suite, "breaking1", test_lease_breaking1);
3990         torture_suite_add_1smb2_test(suite, "breaking2", test_lease_breaking2);
3991         torture_suite_add_1smb2_test(suite, "breaking3", test_lease_breaking3);
3992         torture_suite_add_1smb2_test(suite, "v2_breaking3", test_lease_v2_breaking3);
3993         torture_suite_add_1smb2_test(suite, "breaking4", test_lease_breaking4);
3994         torture_suite_add_1smb2_test(suite, "breaking5", test_lease_breaking5);
3995         torture_suite_add_1smb2_test(suite, "breaking6", test_lease_breaking6);
3996         torture_suite_add_2smb2_test(suite, "lock1", test_lease_lock1);
3997         torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1);
3998         torture_suite_add_1smb2_test(suite, "v2_request_parent",
3999                                      test_lease_v2_request_parent);
4000         torture_suite_add_1smb2_test(suite, "v2_request", test_lease_v2_request);
4001         torture_suite_add_1smb2_test(suite, "v2_epoch1", test_lease_v2_epoch1);
4002         torture_suite_add_1smb2_test(suite, "v2_epoch2", test_lease_v2_epoch2);
4003         torture_suite_add_1smb2_test(suite, "v2_epoch3", test_lease_v2_epoch3);
4004         torture_suite_add_1smb2_test(suite, "v2_complex1", test_lease_v2_complex1);
4005         torture_suite_add_1smb2_test(suite, "v2_complex2", test_lease_v2_complex2);
4006         torture_suite_add_1smb2_test(suite, "v2_rename", test_lease_v2_rename);
4007         torture_suite_add_1smb2_test(suite, "dynamic_share", test_lease_dynamic_share);
4008         torture_suite_add_1smb2_test(suite, "timeout", test_lease_timeout);
4009         torture_suite_add_1smb2_test(suite, "unlink", test_lease_unlink);
4010
4011         suite->description = talloc_strdup(suite, "SMB2-LEASE tests");
4012
4013         return suite;
4014 }