s4-torture: add test for lease break after file unlink
[nivanova/samba-autobuild/.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.alloc_size, 0);                   \
53                 CHECK_VAL((__io)->out.size, 0);                         \
54                 CHECK_VAL((__io)->out.file_attr, (__attribute));        \
55                 CHECK_VAL((__io)->out.reserved2, 0);                    \
56         } while(0)
57
58 #define CHECK_LEASE(__io, __state, __oplevel, __key, __flags)           \
59         do {                                                            \
60                 CHECK_VAL((__io)->out.lease_response.lease_version, 1); \
61                 if (__oplevel) {                                        \
62                         CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \
63                         CHECK_VAL((__io)->out.lease_response.lease_key.data[0], (__key)); \
64                         CHECK_VAL((__io)->out.lease_response.lease_key.data[1], ~(__key)); \
65                         CHECK_VAL((__io)->out.lease_response.lease_state, smb2_util_lease_state(__state)); \
66                 } else {                                                \
67                         CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); \
68                         CHECK_VAL((__io)->out.lease_response.lease_key.data[0], 0); \
69                         CHECK_VAL((__io)->out.lease_response.lease_key.data[1], 0); \
70                         CHECK_VAL((__io)->out.lease_response.lease_state, 0); \
71                 }                                                       \
72                                                                         \
73                 CHECK_VAL((__io)->out.lease_response.lease_flags, (__flags));   \
74                 CHECK_VAL((__io)->out.lease_response.lease_duration, 0); \
75                 CHECK_VAL((__io)->out.lease_response.lease_epoch, 0); \
76         } while(0)
77
78 #define CHECK_LEASE_V2(__io, __state, __oplevel, __key, __flags, __parent, __epoch) \
79         do {                                                            \
80                 CHECK_VAL((__io)->out.lease_response_v2.lease_version, 2); \
81                 if (__oplevel) {                                        \
82                         CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \
83                         CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], (__key)); \
84                         CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[1], ~(__key)); \
85                         CHECK_VAL((__io)->out.lease_response_v2.lease_state, smb2_util_lease_state(__state)); \
86                 } else {                                                \
87                         CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); \
88                         CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], 0); \
89                         CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[1], 0); \
90                         CHECK_VAL((__io)->out.lease_response_v2.lease_state, 0); \
91                 }                                                       \
92                                                                         \
93                 CHECK_VAL((__io)->out.lease_response_v2.lease_flags, __flags); \
94                 if (__flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET) { \
95                         CHECK_VAL((__io)->out.lease_response_v2.parent_lease_key.data[0], (__parent)); \
96                         CHECK_VAL((__io)->out.lease_response_v2.parent_lease_key.data[1], ~(__parent)); \
97                 } \
98                 CHECK_VAL((__io)->out.lease_response_v2.lease_duration, 0); \
99                 CHECK_VAL((__io)->out.lease_response_v2.lease_epoch, (__epoch)); \
100         } while(0)
101
102 static const uint64_t LEASE1 = 0xBADC0FFEE0DDF00Dull;
103 static const uint64_t LEASE2 = 0xDEADBEEFFEEDBEADull;
104 static const uint64_t LEASE3 = 0xDAD0FFEDD00DF00Dull;
105 static const uint64_t LEASE4 = 0xBAD0FFEDD00DF00Dull;
106
107 #define NREQUEST_RESULTS 8
108 static const char *request_results[NREQUEST_RESULTS][2] = {
109         { "", "" },
110         { "R", "R" },
111         { "H", "" },
112         { "W", "" },
113         { "RH", "RH" },
114         { "RW", "RW" },
115         { "HW", "" },
116         { "RHW", "RHW" },
117 };
118
119 static bool test_lease_request(struct torture_context *tctx,
120                                struct smb2_tree *tree)
121 {
122         TALLOC_CTX *mem_ctx = talloc_new(tctx);
123         struct smb2_create io;
124         struct smb2_lease ls;
125         struct smb2_handle h1 = {{0}};
126         struct smb2_handle h2 = {{0}};
127         NTSTATUS status;
128         const char *fname = "lease_request.dat";
129         const char *fname2 = "lease_request.2.dat";
130         const char *sname = "lease_request.dat:stream";
131         const char *dname = "lease_request.dir";
132         bool ret = true;
133         int i;
134         uint32_t caps;
135
136         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
137         if (!(caps & SMB2_CAP_LEASING)) {
138                 torture_skip(tctx, "leases are not supported");
139         }
140
141         smb2_util_unlink(tree, fname);
142         smb2_util_unlink(tree, fname2);
143         smb2_util_rmdir(tree, dname);
144
145         /* Win7 is happy to grant RHW leases on files. */
146         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
147         status = smb2_create(tree, mem_ctx, &io);
148         CHECK_STATUS(status, NT_STATUS_OK);
149         h1 = io.out.file.handle;
150         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
151         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
152
153         /* But will reject leases on directories. */
154         if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
155                 smb2_lease_create(&io, &ls, true, dname, LEASE2, smb2_util_lease_state("RHW"));
156                 status = smb2_create(tree, mem_ctx, &io);
157                 CHECK_STATUS(status, NT_STATUS_OK);
158                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY);
159                 CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
160                 smb2_util_close(tree, io.out.file.handle);
161         }
162
163         /* Also rejects multiple files leased under the same key. */
164         smb2_lease_create(&io, &ls, true, fname2, LEASE1, smb2_util_lease_state("RHW"));
165         status = smb2_create(tree, mem_ctx, &io);
166         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
167
168         /* And grants leases on streams (with separate leasekey). */
169         smb2_lease_create(&io, &ls, false, sname, LEASE2, smb2_util_lease_state("RHW"));
170         status = smb2_create(tree, mem_ctx, &io);
171         h2 = io.out.file.handle;
172         CHECK_STATUS(status, NT_STATUS_OK);
173         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
174         CHECK_LEASE(&io, "RHW", true, LEASE2, 0);
175         smb2_util_close(tree, h2);
176
177         smb2_util_close(tree, h1);
178
179         /* Now see what combos are actually granted. */
180         for (i = 0; i < NREQUEST_RESULTS; i++) {
181                 torture_comment(tctx, "Requesting lease type %s(%x),"
182                     " expecting %s(%x)\n",
183                     request_results[i][0], smb2_util_lease_state(request_results[i][0]),
184                     request_results[i][1], smb2_util_lease_state(request_results[i][1]));
185                 smb2_lease_create(&io, &ls, false, fname, LEASE1,
186                     smb2_util_lease_state(request_results[i][0]));
187                 status = smb2_create(tree, mem_ctx, &io);
188                 h2 = io.out.file.handle;
189                 CHECK_STATUS(status, NT_STATUS_OK);
190                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
191                 CHECK_LEASE(&io, request_results[i][1], true, LEASE1, 0);
192                 smb2_util_close(tree, io.out.file.handle);
193         }
194
195  done:
196         smb2_util_close(tree, h1);
197         smb2_util_close(tree, h2);
198
199         smb2_util_unlink(tree, fname);
200         smb2_util_unlink(tree, fname2);
201         smb2_util_rmdir(tree, dname);
202
203         talloc_free(mem_ctx);
204
205         return ret;
206 }
207
208 static bool test_lease_upgrade(struct torture_context *tctx,
209                                struct smb2_tree *tree)
210 {
211         TALLOC_CTX *mem_ctx = talloc_new(tctx);
212         struct smb2_create io;
213         struct smb2_lease ls;
214         struct smb2_handle h = {{0}};
215         struct smb2_handle hnew = {{0}};
216         NTSTATUS status;
217         const char *fname = "lease_upgrade.dat";
218         bool ret = true;
219         uint32_t caps;
220
221         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
222         if (!(caps & SMB2_CAP_LEASING)) {
223                 torture_skip(tctx, "leases are not supported");
224         }
225
226         smb2_util_unlink(tree, fname);
227
228         /* Grab a RH lease. */
229         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
230         status = smb2_create(tree, mem_ctx, &io);
231         CHECK_STATUS(status, NT_STATUS_OK);
232         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
233         CHECK_LEASE(&io, "RH", true, LEASE1, 0);
234         h = io.out.file.handle;
235
236         /* Upgrades (sidegrades?) to RW leave us with an RH. */
237         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RW"));
238         status = smb2_create(tree, mem_ctx, &io);
239         CHECK_STATUS(status, NT_STATUS_OK);
240         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
241         CHECK_LEASE(&io, "RH", true, LEASE1, 0);
242         hnew = io.out.file.handle;
243
244         smb2_util_close(tree, hnew);
245
246         /* Upgrade to RHW lease. */
247         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
248         status = smb2_create(tree, mem_ctx, &io);
249         CHECK_STATUS(status, NT_STATUS_OK);
250         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
251         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
252         hnew = io.out.file.handle;
253
254         smb2_util_close(tree, h);
255         h = hnew;
256
257         /* Attempt to downgrade - original lease state is maintained. */
258         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
259         status = smb2_create(tree, mem_ctx, &io);
260         CHECK_STATUS(status, NT_STATUS_OK);
261         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
262         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
263         hnew = io.out.file.handle;
264
265         smb2_util_close(tree, hnew);
266
267  done:
268         smb2_util_close(tree, h);
269         smb2_util_close(tree, hnew);
270
271         smb2_util_unlink(tree, fname);
272
273         talloc_free(mem_ctx);
274
275         return ret;
276 }
277
278 /**
279  * upgrade2 test.
280  * full matrix of lease upgrade combinations
281  * (non-contended case)
282  *
283  * The summary of the behaviour is this:
284  * -------------------------------------
285  * An uncontended lease upgrade results in a change
286  * if and only if the requested lease state is
287  * - valid, and
288  * - strictly a superset of the lease state already held.
289  *
290  * In that case the resulting lease state is the one
291  * requested in the upgrade.
292  */
293 struct lease_upgrade2_test {
294         const char *initial;
295         const char *upgrade_to;
296         const char *expected;
297 };
298
299 #define NUM_LEASE_TYPES 5
300 #define NUM_UPGRADE_TESTS ( NUM_LEASE_TYPES * NUM_LEASE_TYPES )
301 struct lease_upgrade2_test lease_upgrade2_tests[NUM_UPGRADE_TESTS] = {
302         { "", "", "" },
303         { "", "R", "R" },
304         { "", "RH", "RH" },
305         { "", "RW", "RW" },
306         { "", "RWH", "RWH" },
307
308         { "R", "", "R" },
309         { "R", "R", "R" },
310         { "R", "RH", "RH" },
311         { "R", "RW", "RW" },
312         { "R", "RWH", "RWH" },
313
314         { "RH", "", "RH" },
315         { "RH", "R", "RH" },
316         { "RH", "RH", "RH" },
317         { "RH", "RW", "RH" },
318         { "RH", "RWH", "RWH" },
319
320         { "RW", "", "RW" },
321         { "RW", "R", "RW" },
322         { "RW", "RH", "RW" },
323         { "RW", "RW", "RW" },
324         { "RW", "RWH", "RWH" },
325
326         { "RWH", "", "RWH" },
327         { "RWH", "R", "RWH" },
328         { "RWH", "RH", "RWH" },
329         { "RWH", "RW", "RWH" },
330         { "RWH", "RWH", "RWH" },
331 };
332
333 static bool test_lease_upgrade2(struct torture_context *tctx,
334                                 struct smb2_tree *tree)
335 {
336         TALLOC_CTX *mem_ctx = talloc_new(tctx);
337         struct smb2_handle h, hnew;
338         NTSTATUS status;
339         struct smb2_create io;
340         struct smb2_lease ls;
341         const char *fname = "lease_upgrade2.dat";
342         bool ret = true;
343         int i;
344         uint32_t caps;
345
346         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
347         if (!(caps & SMB2_CAP_LEASING)) {
348                 torture_skip(tctx, "leases are not supported");
349         }
350
351         for (i = 0; i < NUM_UPGRADE_TESTS; i++) {
352                 struct lease_upgrade2_test t = lease_upgrade2_tests[i];
353
354                 smb2_util_unlink(tree, fname);
355
356                 /* Grab a lease. */
357                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.initial));
358                 status = smb2_create(tree, mem_ctx, &io);
359                 CHECK_STATUS(status, NT_STATUS_OK);
360                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
361                 CHECK_LEASE(&io, t.initial, true, LEASE1, 0);
362                 h = io.out.file.handle;
363
364                 /* Upgrade. */
365                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
366                 status = smb2_create(tree, mem_ctx, &io);
367                 CHECK_STATUS(status, NT_STATUS_OK);
368                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
369                 CHECK_LEASE(&io, t.expected, true, LEASE1, 0);
370                 hnew = io.out.file.handle;
371
372                 smb2_util_close(tree, hnew);
373                 smb2_util_close(tree, h);
374         }
375
376  done:
377         smb2_util_close(tree, h);
378         smb2_util_close(tree, hnew);
379
380         smb2_util_unlink(tree, fname);
381
382         talloc_free(mem_ctx);
383
384         return ret;
385 }
386
387
388 /**
389  * upgrade3:
390  * full matrix of lease upgrade combinations
391  * (contended case)
392  *
393  * We start with 2 leases, and check how one can
394  * be upgraded
395  *
396  * The summary of the behaviour is this:
397  * -------------------------------------
398  *
399  * If we have two leases (lease1 and lease2) on the same file,
400  * then attempt to upgrade lease1 results in a change if and only
401  * if the requested lease state:
402  * - is valid,
403  * - is strictly a superset of lease1, and
404  * - can held together with lease2.
405  *
406  * In that case, the resuling lease state of the upgraded lease1
407  * is the state requested in the upgrade. lease2 is not broken
408  * and remains unchanged.
409  *
410  * Note that this contrasts the case of directly opening with
411  * an initial requested lease state, in which case you get that
412  * portion of the requested state that can be shared with the
413  * already existing leases (or the states that they get broken to).
414  */
415 struct lease_upgrade3_test {
416         const char *held1;
417         const char *held2;
418         const char *upgrade_to;
419         const char *upgraded_to;
420 };
421
422 #define NUM_UPGRADE3_TESTS ( 20 )
423 struct lease_upgrade3_test lease_upgrade3_tests[NUM_UPGRADE3_TESTS] = {
424         {"R", "R", "", "R" },
425         {"R", "R", "R", "R" },
426         {"R", "R", "RW", "R" },
427         {"R", "R", "RH", "RH" },
428         {"R", "R", "RHW", "R" },
429
430         {"R", "RH", "", "R" },
431         {"R", "RH", "R", "R" },
432         {"R", "RH", "RW", "R" },
433         {"R", "RH", "RH", "RH" },
434         {"R", "RH", "RHW", "R" },
435
436         {"RH", "R", "", "RH" },
437         {"RH", "R", "R", "RH" },
438         {"RH", "R", "RW", "RH" },
439         {"RH", "R", "RH", "RH" },
440         {"RH", "R", "RHW", "RH" },
441
442         {"RH", "RH", "", "RH" },
443         {"RH", "RH", "R", "RH" },
444         {"RH", "RH", "RW", "RH" },
445         {"RH", "RH", "RH", "RH" },
446         {"RH", "RH", "RHW", "RH" },
447 };
448
449 static bool test_lease_upgrade3(struct torture_context *tctx,
450                                 struct smb2_tree *tree)
451 {
452         TALLOC_CTX *mem_ctx = talloc_new(tctx);
453         struct smb2_handle h, h2, hnew;
454         NTSTATUS status;
455         struct smb2_create io;
456         struct smb2_lease ls;
457         const char *fname = "lease_upgrade3.dat";
458         bool ret = true;
459         int i;
460         uint32_t caps;
461
462         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
463         if (!(caps & SMB2_CAP_LEASING)) {
464                 torture_skip(tctx, "leases are not supported");
465         }
466
467         tree->session->transport->lease.handler = torture_lease_handler;
468         tree->session->transport->lease.private_data = tree;
469
470         smb2_util_unlink(tree, fname);
471
472         for (i = 0; i < NUM_UPGRADE3_TESTS; i++) {
473                 struct lease_upgrade3_test t = lease_upgrade3_tests[i];
474
475                 smb2_util_unlink(tree, fname);
476
477                 ZERO_STRUCT(lease_break_info);
478
479                 /* grab first lease */
480                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.held1));
481                 status = smb2_create(tree, mem_ctx, &io);
482                 CHECK_STATUS(status, NT_STATUS_OK);
483                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
484                 CHECK_LEASE(&io, t.held1, true, LEASE1, 0);
485                 h = io.out.file.handle;
486
487                 /* grab second lease */
488                 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(t.held2));
489                 status = smb2_create(tree, mem_ctx, &io);
490                 CHECK_STATUS(status, NT_STATUS_OK);
491                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
492                 CHECK_LEASE(&io, t.held2, true, LEASE2, 0);
493                 h2 = io.out.file.handle;
494
495                 /* no break has happened */
496                 CHECK_VAL(lease_break_info.count, 0);
497                 CHECK_VAL(lease_break_info.failures, 0);
498
499                 /* try to upgrade lease1 */
500                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
501                 status = smb2_create(tree, mem_ctx, &io);
502                 CHECK_STATUS(status, NT_STATUS_OK);
503                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
504                 CHECK_LEASE(&io, t.upgraded_to, true, LEASE1, 0);
505                 hnew = io.out.file.handle;
506
507                 /* no break has happened */
508                 CHECK_VAL(lease_break_info.count, 0);
509                 CHECK_VAL(lease_break_info.failures, 0);
510
511                 smb2_util_close(tree, hnew);
512                 smb2_util_close(tree, h);
513                 smb2_util_close(tree, h2);
514         }
515
516  done:
517         smb2_util_close(tree, h);
518         smb2_util_close(tree, hnew);
519         smb2_util_close(tree, h2);
520
521         smb2_util_unlink(tree, fname);
522
523         talloc_free(mem_ctx);
524
525         return ret;
526 }
527
528
529
530 /*
531   break_results should be read as "held lease, new lease, hold broken to, new
532   grant", i.e. { "RH", "RW", "RH", "R" } means that if key1 holds RH and key2
533   tries for RW, key1 will be broken to RH (in this case, not broken at all)
534   and key2 will be granted R.
535
536   Note: break_results only includes things that Win7 will actually grant (see
537   request_results above).
538  */
539 #define NBREAK_RESULTS 16
540 static const char *break_results[NBREAK_RESULTS][4] = {
541         {"R",   "R",    "R",    "R"},
542         {"R",   "RH",   "R",    "RH"},
543         {"R",   "RW",   "R",    "R"},
544         {"R",   "RHW",  "R",    "RH"},
545
546         {"RH",  "R",    "RH",   "R"},
547         {"RH",  "RH",   "RH",   "RH"},
548         {"RH",  "RW",   "RH",   "R"},
549         {"RH",  "RHW",  "RH",   "RH"},
550
551         {"RW",  "R",    "R",    "R"},
552         {"RW",  "RH",   "R",    "RH"},
553         {"RW",  "RW",   "R",    "R"},
554         {"RW",  "RHW",  "R",    "RH"},
555
556         {"RHW", "R",    "RH",   "R"},
557         {"RHW", "RH",   "RH",   "RH"},
558         {"RHW", "RW",   "RH",   "R"},
559         {"RHW", "RHW",  "RH",   "RH"},
560 };
561
562 static bool test_lease_break(struct torture_context *tctx,
563                                struct smb2_tree *tree)
564 {
565         TALLOC_CTX *mem_ctx = talloc_new(tctx);
566         struct smb2_create io;
567         struct smb2_lease ls;
568         struct smb2_handle h, h2, h3;
569         NTSTATUS status;
570         const char *fname = "lease_break.dat";
571         bool ret = true;
572         int i;
573         uint32_t caps;
574
575         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
576         if (!(caps & SMB2_CAP_LEASING)) {
577                 torture_skip(tctx, "leases are not supported");
578         }
579
580         tree->session->transport->lease.handler = torture_lease_handler;
581         tree->session->transport->lease.private_data = tree;
582
583         smb2_util_unlink(tree, fname);
584
585         for (i = 0; i < NBREAK_RESULTS; i++) {
586                 const char *held = break_results[i][0];
587                 const char *contend = break_results[i][1];
588                 const char *brokento = break_results[i][2];
589                 const char *granted = break_results[i][3];
590                 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
591                     "expecting break to %s(%x) and grant of %s(%x)\n",
592                     held, smb2_util_lease_state(held), contend, smb2_util_lease_state(contend),
593                     brokento, smb2_util_lease_state(brokento), granted, smb2_util_lease_state(granted));
594
595                 ZERO_STRUCT(lease_break_info);
596
597                 /* Grab lease. */
598                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(held));
599                 status = smb2_create(tree, mem_ctx, &io);
600                 CHECK_STATUS(status, NT_STATUS_OK);
601                 h = io.out.file.handle;
602                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
603                 CHECK_LEASE(&io, held, true, LEASE1, 0);
604
605                 /* Possibly contend lease. */
606                 smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(contend));
607                 status = smb2_create(tree, mem_ctx, &io);
608                 CHECK_STATUS(status, NT_STATUS_OK);
609                 h2 = io.out.file.handle;
610                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
611                 CHECK_LEASE(&io, granted, true, LEASE2, 0);
612
613                 if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) {
614                         CHECK_BREAK_INFO(held, brokento, LEASE1);
615                 } else {
616                         CHECK_NO_BREAK(tctx);
617                 }
618
619                 ZERO_STRUCT(lease_break_info);
620
621                 /*
622                   Now verify that an attempt to upgrade LEASE1 results in no
623                   break and no change in LEASE1.
624                  */
625                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
626                 status = smb2_create(tree, mem_ctx, &io);
627                 CHECK_STATUS(status, NT_STATUS_OK);
628                 h3 = io.out.file.handle;
629                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
630                 CHECK_LEASE(&io, brokento, true, LEASE1, 0);
631                 CHECK_VAL(lease_break_info.count, 0);
632                 CHECK_VAL(lease_break_info.failures, 0);
633
634                 smb2_util_close(tree, h);
635                 smb2_util_close(tree, h2);
636                 smb2_util_close(tree, h3);
637
638                 status = smb2_util_unlink(tree, fname);
639                 CHECK_STATUS(status, NT_STATUS_OK);
640         }
641
642  done:
643         smb2_util_close(tree, h);
644         smb2_util_close(tree, h2);
645
646         smb2_util_unlink(tree, fname);
647
648         talloc_free(mem_ctx);
649
650         return ret;
651 }
652
653 static bool test_lease_nobreakself(struct torture_context *tctx,
654                                    struct smb2_tree *tree)
655 {
656         TALLOC_CTX *mem_ctx = talloc_new(tctx);
657         struct smb2_create io;
658         struct smb2_lease ls;
659         struct smb2_handle h1 = {{0}};
660         struct smb2_handle h2 = {{0}};
661         NTSTATUS status;
662         const char *fname = "lease_nobreakself.dat";
663         bool ret = true;
664         uint32_t caps;
665         char c = 0;
666
667         caps = smb2cli_conn_server_capabilities(
668                 tree->session->transport->conn);
669         if (!(caps & SMB2_CAP_LEASING)) {
670                 torture_skip(tctx, "leases are not supported");
671         }
672
673         smb2_util_unlink(tree, fname);
674
675         /* Win7 is happy to grant RHW leases on files. */
676         smb2_lease_create(&io, &ls, false, fname, LEASE1,
677                           smb2_util_lease_state("R"));
678         status = smb2_create(tree, mem_ctx, &io);
679         CHECK_STATUS(status, NT_STATUS_OK);
680         h1 = io.out.file.handle;
681         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
682         CHECK_LEASE(&io, "R", true, LEASE1, 0);
683
684         smb2_lease_create(&io, &ls, false, fname, LEASE2,
685                           smb2_util_lease_state("R"));
686         status = smb2_create(tree, mem_ctx, &io);
687         CHECK_STATUS(status, NT_STATUS_OK);
688         h2 = io.out.file.handle;
689         CHECK_LEASE(&io, "R", true, LEASE2, 0);
690
691         ZERO_STRUCT(lease_break_info);
692
693         tree->session->transport->lease.handler = torture_lease_handler;
694         tree->session->transport->lease.private_data = tree;
695
696         /* Make sure we don't break ourselves on write */
697
698         status = smb2_util_write(tree, h1, &c, 0, 1);
699         CHECK_STATUS(status, NT_STATUS_OK);
700         CHECK_BREAK_INFO("R", "", LEASE2);
701
702         /* Try the other way round. First, upgrade LEASE2 to R again */
703
704         smb2_lease_create(&io, &ls, false, fname, LEASE2,
705                           smb2_util_lease_state("R"));
706         status = smb2_create(tree, mem_ctx, &io);
707         CHECK_STATUS(status, NT_STATUS_OK);
708         CHECK_LEASE(&io, "R", true, LEASE2, 0);
709         smb2_util_close(tree, io.out.file.handle);
710
711         /* Now break LEASE1 via h2 */
712
713         ZERO_STRUCT(lease_break_info);
714         status = smb2_util_write(tree, h2, &c, 0, 1);
715         CHECK_STATUS(status, NT_STATUS_OK);
716         CHECK_BREAK_INFO("R", "", LEASE1);
717
718         /* .. and break LEASE2 via h1 */
719
720         ZERO_STRUCT(lease_break_info);
721         status = smb2_util_write(tree, h1, &c, 0, 1);
722         CHECK_STATUS(status, NT_STATUS_OK);
723         CHECK_BREAK_INFO("R", "", LEASE2);
724
725 done:
726         smb2_util_close(tree, h2);
727         smb2_util_close(tree, h1);
728         smb2_util_unlink(tree, fname);
729         talloc_free(mem_ctx);
730         return ret;
731 }
732
733 static bool test_lease_statopen(struct torture_context *tctx,
734                                    struct smb2_tree *tree)
735 {
736         TALLOC_CTX *mem_ctx = talloc_new(tctx);
737         struct smb2_create io;
738         struct smb2_lease ls;
739         struct smb2_handle h1 = {{0}};
740         struct smb2_handle h2 = {{0}};
741         NTSTATUS status;
742         const char *fname = "lease_statopen.dat";
743         bool ret = true;
744         uint32_t caps;
745
746         caps = smb2cli_conn_server_capabilities(
747                 tree->session->transport->conn);
748         if (!(caps & SMB2_CAP_LEASING)) {
749                 torture_skip(tctx, "leases are not supported");
750         }
751
752         smb2_util_unlink(tree, fname);
753
754         /* Create file. */
755         smb2_lease_create(&io, &ls, false, fname, LEASE1,
756                           smb2_util_lease_state("RWH"));
757         status = smb2_create(tree, mem_ctx, &io);
758         CHECK_STATUS(status, NT_STATUS_OK);
759         h1 = io.out.file.handle;
760         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
761         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
762         smb2_util_close(tree, h1);
763
764         /* Stat open file with RWH lease. */
765         smb2_lease_create_share(&io, &ls, false, fname, 0, LEASE1,
766                           smb2_util_lease_state("RWH"));
767         io.in.desired_access = FILE_READ_ATTRIBUTES;
768         status = smb2_create(tree, mem_ctx, &io);
769         CHECK_STATUS(status, NT_STATUS_OK);
770         h2 = io.out.file.handle;
771         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
772
773         ZERO_STRUCT(lease_break_info);
774
775         tree->session->transport->lease.handler = torture_lease_handler;
776         tree->session->transport->lease.private_data = tree;
777
778         /* Ensure non-stat open doesn't break and gets same lease
779            state as existing stat open. */
780         smb2_lease_create(&io, &ls, false, fname, LEASE1,
781                           smb2_util_lease_state(""));
782         status = smb2_create(tree, mem_ctx, &io);
783         CHECK_STATUS(status, NT_STATUS_OK);
784         h1 = io.out.file.handle;
785         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
786         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
787
788         CHECK_NO_BREAK(tctx);
789         smb2_util_close(tree, h1);
790
791         /* Open with conflicting lease. stat open should break down to RH */
792         smb2_lease_create(&io, &ls, false, fname, LEASE2,
793                           smb2_util_lease_state("RWH"));
794         status = smb2_create(tree, mem_ctx, &io);
795         CHECK_STATUS(status, NT_STATUS_OK);
796         h1 = io.out.file.handle;
797         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
798         CHECK_LEASE(&io, "RH", true, LEASE2, 0);
799
800         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
801
802 done:
803         smb2_util_close(tree, h2);
804         smb2_util_close(tree, h1);
805         smb2_util_unlink(tree, fname);
806         talloc_free(mem_ctx);
807         return ret;
808 }
809
810 static bool test_lease_statopen2(struct torture_context *tctx,
811                                  struct smb2_tree *tree)
812 {
813         TALLOC_CTX *mem_ctx = talloc_new(tctx);
814         struct smb2_create io;
815         struct smb2_lease ls;
816         struct smb2_handle h1 = {{0}};
817         struct smb2_handle h2 = {{0}};
818         struct smb2_handle h3 = {{0}};
819         NTSTATUS status;
820         const char *fname = "lease_statopen2.dat";
821         bool ret = true;
822         uint32_t caps;
823
824         caps = smb2cli_conn_server_capabilities(
825                 tree->session->transport->conn);
826         if (!(caps & SMB2_CAP_LEASING)) {
827                 torture_skip(tctx, "leases are not supported");
828         }
829
830         smb2_util_unlink(tree, fname);
831         ZERO_STRUCT(lease_break_info);
832         tree->session->transport->lease.handler = torture_lease_handler;
833         tree->session->transport->lease.private_data = tree;
834
835         status = torture_smb2_testfile(tree, fname, &h1);
836         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
837                                         "smb2_create failed\n");
838         smb2_util_close(tree, h1);
839         ZERO_STRUCT(h1);
840
841         /* Open file with RWH lease. */
842         smb2_lease_create_share(&io, &ls, false, fname,
843                                 smb2_util_share_access("RWD"),
844                                 LEASE1,
845                                 smb2_util_lease_state("RWH"));
846         io.in.desired_access = SEC_FILE_WRITE_DATA;
847         status = smb2_create(tree, mem_ctx, &io);
848         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
849                                         "smb2_create failed\n");
850         h1 = io.out.file.handle;
851         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
852
853         /* Stat open */
854         ZERO_STRUCT(io);
855         io.in.desired_access = FILE_READ_ATTRIBUTES;
856         io.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
857         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
858         io.in.create_disposition = NTCREATEX_DISP_OPEN;
859         io.in.fname = fname;
860         status = smb2_create(tree, mem_ctx, &io);
861         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
862                                         "smb2_create failed\n");
863         h2 = io.out.file.handle;
864
865         /* Open file with RWH lease. */
866         smb2_lease_create_share(&io, &ls, false, fname,
867                                 smb2_util_share_access("RWD"),
868                                 LEASE1,
869                                 smb2_util_lease_state("RWH"));
870         io.in.desired_access = SEC_FILE_WRITE_DATA;
871         status = smb2_create(tree, mem_ctx, &io);
872         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
873                                         "smb2_create failed\n");
874         h3 = io.out.file.handle;
875         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
876
877 done:
878         if (!smb2_util_handle_empty(h3)) {
879                 smb2_util_close(tree, h3);
880         }
881         if (!smb2_util_handle_empty(h2)) {
882                 smb2_util_close(tree, h2);
883         }
884         if (!smb2_util_handle_empty(h1)) {
885                 smb2_util_close(tree, h1);
886         }
887         smb2_util_unlink(tree, fname);
888         talloc_free(mem_ctx);
889         return ret;
890 }
891
892 static bool test_lease_statopen3(struct torture_context *tctx,
893                                  struct smb2_tree *tree)
894 {
895         TALLOC_CTX *mem_ctx = talloc_new(tctx);
896         struct smb2_create io;
897         struct smb2_lease ls;
898         struct smb2_handle h1 = {{0}};
899         struct smb2_handle h2 = {{0}};
900         NTSTATUS status;
901         const char *fname = "lease_statopen3.dat";
902         bool ret = true;
903         uint32_t caps;
904
905         caps = smb2cli_conn_server_capabilities(
906                 tree->session->transport->conn);
907         if (!(caps & SMB2_CAP_LEASING)) {
908                 torture_skip(tctx, "leases are not supported");
909         }
910
911         smb2_util_unlink(tree, fname);
912         ZERO_STRUCT(lease_break_info);
913         tree->session->transport->lease.handler = torture_lease_handler;
914         tree->session->transport->lease.private_data = tree;
915
916         status = torture_smb2_testfile(tree, fname, &h1);
917         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
918                                         "smb2_create failed\n");
919         smb2_util_close(tree, h1);
920         ZERO_STRUCT(h1);
921
922         /* Stat open */
923         ZERO_STRUCT(io);
924         io.in.desired_access = FILE_READ_ATTRIBUTES;
925         io.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
926         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
927         io.in.create_disposition = NTCREATEX_DISP_OPEN;
928         io.in.fname = fname;
929         status = smb2_create(tree, mem_ctx, &io);
930         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
931                                         "smb2_create failed\n");
932         h1 = io.out.file.handle;
933
934         /* Open file with RWH lease. */
935         smb2_lease_create_share(&io, &ls, false, fname,
936                                 smb2_util_share_access("RWD"),
937                                 LEASE1,
938                                 smb2_util_lease_state("RWH"));
939         io.in.desired_access = SEC_FILE_WRITE_DATA;
940         status = smb2_create(tree, mem_ctx, &io);
941         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
942                                         "smb2_create failed\n");
943         h2 = io.out.file.handle;
944         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
945
946 done:
947         if (!smb2_util_handle_empty(h1)) {
948                 smb2_util_close(tree, h1);
949         }
950         if (!smb2_util_handle_empty(h2)) {
951                 smb2_util_close(tree, h2);
952         }
953         smb2_util_unlink(tree, fname);
954         talloc_free(mem_ctx);
955         return ret;
956 }
957
958 static void torture_oplock_break_callback(struct smb2_request *req)
959 {
960         NTSTATUS status;
961         struct smb2_break br;
962
963         ZERO_STRUCT(br);
964         status = smb2_break_recv(req, &br);
965         if (!NT_STATUS_IS_OK(status))
966                 lease_break_info.oplock_failures++;
967
968         return;
969 }
970
971 /* a oplock break request handler */
972 static bool torture_oplock_handler(struct smb2_transport *transport,
973                                    const struct smb2_handle *handle,
974                                    uint8_t level, void *private_data)
975 {
976         struct smb2_tree *tree = private_data;
977         struct smb2_request *req;
978         struct smb2_break br;
979
980         lease_break_info.oplock_handle = *handle;
981         lease_break_info.oplock_level   = level;
982         lease_break_info.oplock_count++;
983
984         ZERO_STRUCT(br);
985         br.in.file.handle = *handle;
986         br.in.oplock_level = level;
987
988         if (lease_break_info.held_oplock_level > SMB2_OPLOCK_LEVEL_II) {
989                 req = smb2_break_send(tree, &br);
990                 req->async.fn = torture_oplock_break_callback;
991                 req->async.private_data = NULL;
992         }
993         lease_break_info.held_oplock_level = level;
994
995         return true;
996 }
997
998 #define NOPLOCK_RESULTS 12
999 static const char *oplock_results[NOPLOCK_RESULTS][4] = {
1000         {"R",   "s",    "R",    "s"},
1001         {"R",   "x",    "R",    "s"},
1002         {"R",   "b",    "R",    "s"},
1003
1004         {"RH",  "s",    "RH",   ""},
1005         {"RH",  "x",    "RH",   ""},
1006         {"RH",  "b",    "RH",   ""},
1007
1008         {"RW",  "s",    "R",    "s"},
1009         {"RW",  "x",    "R",    "s"},
1010         {"RW",  "b",    "R",    "s"},
1011
1012         {"RHW", "s",    "RH",   ""},
1013         {"RHW", "x",    "RH",   ""},
1014         {"RHW", "b",    "RH",   ""},
1015 };
1016
1017 static const char *oplock_results_2[NOPLOCK_RESULTS][4] = {
1018         {"s",   "R",    "s",    "R"},
1019         {"s",   "RH",   "s",    "R"},
1020         {"s",   "RW",   "s",    "R"},
1021         {"s",   "RHW",  "s",    "R"},
1022
1023         {"x",   "R",    "s",    "R"},
1024         {"x",   "RH",   "s",    "R"},
1025         {"x",   "RW",   "s",    "R"},
1026         {"x",   "RHW",  "s",    "R"},
1027
1028         {"b",   "R",    "s",    "R"},
1029         {"b",   "RH",   "s",    "R"},
1030         {"b",   "RW",   "s",    "R"},
1031         {"b",   "RHW",  "s",    "R"},
1032 };
1033
1034 static bool test_lease_oplock(struct torture_context *tctx,
1035                               struct smb2_tree *tree)
1036 {
1037         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1038         struct smb2_create io;
1039         struct smb2_lease ls;
1040         struct smb2_handle h, h2;
1041         NTSTATUS status;
1042         const char *fname = "lease_oplock.dat";
1043         bool ret = true;
1044         int i;
1045         uint32_t caps;
1046
1047         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1048         if (!(caps & SMB2_CAP_LEASING)) {
1049                 torture_skip(tctx, "leases are not supported");
1050         }
1051
1052         tree->session->transport->lease.handler = torture_lease_handler;
1053         tree->session->transport->lease.private_data = tree;
1054         tree->session->transport->oplock.handler = torture_oplock_handler;
1055         tree->session->transport->oplock.private_data = tree;
1056
1057         smb2_util_unlink(tree, fname);
1058
1059         for (i = 0; i < NOPLOCK_RESULTS; i++) {
1060                 const char *held = oplock_results[i][0];
1061                 const char *contend = oplock_results[i][1];
1062                 const char *brokento = oplock_results[i][2];
1063                 const char *granted = oplock_results[i][3];
1064                 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
1065                     "expecting break to %s(%x) and grant of %s(%x)\n",
1066                     held, smb2_util_lease_state(held), contend, smb2_util_oplock_level(contend),
1067                     brokento, smb2_util_lease_state(brokento), granted, smb2_util_oplock_level(granted));
1068
1069                 ZERO_STRUCT(lease_break_info);
1070
1071                 /* Grab lease. */
1072                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(held));
1073                 status = smb2_create(tree, mem_ctx, &io);
1074                 CHECK_STATUS(status, NT_STATUS_OK);
1075                 h = io.out.file.handle;
1076                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1077                 CHECK_LEASE(&io, held, true, LEASE1, 0);
1078
1079                 /* Does an oplock contend the lease? */
1080                 smb2_oplock_create(&io, fname, smb2_util_oplock_level(contend));
1081                 status = smb2_create(tree, mem_ctx, &io);
1082                 CHECK_STATUS(status, NT_STATUS_OK);
1083                 h2 = io.out.file.handle;
1084                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1085                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(granted));
1086                 lease_break_info.held_oplock_level = io.out.oplock_level;
1087
1088                 if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) {
1089                         CHECK_BREAK_INFO(held, brokento, LEASE1);
1090                 } else {
1091                         CHECK_NO_BREAK(tctx);
1092                 }
1093
1094                 smb2_util_close(tree, h);
1095                 smb2_util_close(tree, h2);
1096
1097                 status = smb2_util_unlink(tree, fname);
1098                 CHECK_STATUS(status, NT_STATUS_OK);
1099         }
1100
1101         for (i = 0; i < NOPLOCK_RESULTS; i++) {
1102                 const char *held = oplock_results_2[i][0];
1103                 const char *contend = oplock_results_2[i][1];
1104                 const char *brokento = oplock_results_2[i][2];
1105                 const char *granted = oplock_results_2[i][3];
1106                 torture_comment(tctx, "Hold %s(%x), requesting %s(%x), "
1107                     "expecting break to %s(%x) and grant of %s(%x)\n",
1108                     held, smb2_util_oplock_level(held), contend, smb2_util_lease_state(contend),
1109                     brokento, smb2_util_oplock_level(brokento), granted, smb2_util_lease_state(granted));
1110
1111                 ZERO_STRUCT(lease_break_info);
1112
1113                 /* Grab an oplock. */
1114                 smb2_oplock_create(&io, fname, smb2_util_oplock_level(held));
1115                 status = smb2_create(tree, mem_ctx, &io);
1116                 CHECK_STATUS(status, NT_STATUS_OK);
1117                 h = io.out.file.handle;
1118                 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1119                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(held));
1120                 lease_break_info.held_oplock_level = io.out.oplock_level;
1121
1122                 /* Grab lease. */
1123                 smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(contend));
1124                 status = smb2_create(tree, mem_ctx, &io);
1125                 CHECK_STATUS(status, NT_STATUS_OK);
1126                 h2 = io.out.file.handle;
1127                 CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1128                 CHECK_LEASE(&io, granted, true, LEASE1, 0);
1129
1130                 if (smb2_util_oplock_level(held) != smb2_util_oplock_level(brokento)) {
1131                         CHECK_OPLOCK_BREAK(brokento);
1132                 } else {
1133                         CHECK_NO_BREAK(tctx);
1134                 }
1135
1136                 smb2_util_close(tree, h);
1137                 smb2_util_close(tree, h2);
1138
1139                 status = smb2_util_unlink(tree, fname);
1140                 CHECK_STATUS(status, NT_STATUS_OK);
1141         }
1142
1143  done:
1144         smb2_util_close(tree, h);
1145         smb2_util_close(tree, h2);
1146
1147         smb2_util_unlink(tree, fname);
1148
1149         talloc_free(mem_ctx);
1150
1151         return ret;
1152 }
1153
1154 static bool test_lease_multibreak(struct torture_context *tctx,
1155                                   struct smb2_tree *tree)
1156 {
1157         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1158         struct smb2_create io;
1159         struct smb2_lease ls;
1160         struct smb2_handle h = {{0}};
1161         struct smb2_handle h2 = {{0}};
1162         struct smb2_handle h3 = {{0}};
1163         struct smb2_write w;
1164         NTSTATUS status;
1165         const char *fname = "lease_multibreak.dat";
1166         bool ret = true;
1167         uint32_t caps;
1168
1169         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1170         if (!(caps & SMB2_CAP_LEASING)) {
1171                 torture_skip(tctx, "leases are not supported");
1172         }
1173
1174         tree->session->transport->lease.handler = torture_lease_handler;
1175         tree->session->transport->lease.private_data = tree;
1176         tree->session->transport->oplock.handler = torture_oplock_handler;
1177         tree->session->transport->oplock.private_data = tree;
1178
1179         smb2_util_unlink(tree, fname);
1180
1181         ZERO_STRUCT(lease_break_info);
1182
1183         /* Grab lease, upgrade to RHW .. */
1184         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RH"));
1185         status = smb2_create(tree, mem_ctx, &io);
1186         CHECK_STATUS(status, NT_STATUS_OK);
1187         h = io.out.file.handle;
1188         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1189         CHECK_LEASE(&io, "RH", true, LEASE1, 0);
1190
1191         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW"));
1192         status = smb2_create(tree, mem_ctx, &io);
1193         CHECK_STATUS(status, NT_STATUS_OK);
1194         h2 = io.out.file.handle;
1195         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1196         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
1197
1198         /* Contend with LEASE2. */
1199         smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state("RHW"));
1200         status = smb2_create(tree, mem_ctx, &io);
1201         CHECK_STATUS(status, NT_STATUS_OK);
1202         h3 = io.out.file.handle;
1203         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1204         CHECK_LEASE(&io, "RH", true, LEASE2, 0);
1205
1206         /* Verify that we were only sent one break. */
1207         CHECK_BREAK_INFO("RHW", "RH", LEASE1);
1208
1209         /* Drop LEASE1 / LEASE2 */
1210         status = smb2_util_close(tree, h);
1211         CHECK_STATUS(status, NT_STATUS_OK);
1212         status = smb2_util_close(tree, h2);
1213         CHECK_STATUS(status, NT_STATUS_OK);
1214         status = smb2_util_close(tree, h3);
1215         CHECK_STATUS(status, NT_STATUS_OK);
1216
1217         ZERO_STRUCT(lease_break_info);
1218
1219         /* Grab an R lease. */
1220         smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("R"));
1221         status = smb2_create(tree, mem_ctx, &io);
1222         CHECK_STATUS(status, NT_STATUS_OK);
1223         h = io.out.file.handle;
1224         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1225         CHECK_LEASE(&io, "R", true, LEASE1, 0);
1226
1227         /* Grab a level-II oplock. */
1228         smb2_oplock_create(&io, fname, smb2_util_oplock_level("s"));
1229         status = smb2_create(tree, mem_ctx, &io);
1230         CHECK_STATUS(status, NT_STATUS_OK);
1231         h2 = io.out.file.handle;
1232         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1233         CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
1234         lease_break_info.held_oplock_level = io.out.oplock_level;
1235
1236         /* Verify no breaks. */
1237         CHECK_NO_BREAK(tctx);
1238
1239         /* Open for truncate, force a break. */
1240         smb2_generic_create(&io, NULL, false, fname,
1241             NTCREATEX_DISP_OVERWRITE_IF, smb2_util_oplock_level(""), 0, 0);
1242         status = smb2_create(tree, mem_ctx, &io);
1243         CHECK_STATUS(status, NT_STATUS_OK);
1244         h3 = io.out.file.handle;
1245         CHECK_CREATED(&io, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
1246         CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(""));
1247         lease_break_info.held_oplock_level = io.out.oplock_level;
1248
1249         /* Sleep, use a write to clear the recv queue. */
1250         smb_msleep(250);
1251         ZERO_STRUCT(w);
1252         w.in.file.handle = h3;
1253         w.in.offset      = 0;
1254         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
1255         memset(w.in.data.data, 'o', w.in.data.length);
1256         status = smb2_write(tree, &w);
1257         CHECK_STATUS(status, NT_STATUS_OK);
1258
1259         /* Verify one oplock break, one lease break. */
1260         CHECK_OPLOCK_BREAK("");
1261         CHECK_BREAK_INFO("R", "", LEASE1);
1262
1263  done:
1264         smb2_util_close(tree, h);
1265         smb2_util_close(tree, h2);
1266         smb2_util_close(tree, h3);
1267
1268         smb2_util_unlink(tree, fname);
1269
1270         talloc_free(mem_ctx);
1271
1272         return ret;
1273 }
1274
1275 static bool test_lease_v2_request_parent(struct torture_context *tctx,
1276                                          struct smb2_tree *tree)
1277 {
1278         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1279         struct smb2_create io;
1280         struct smb2_lease ls;
1281         struct smb2_handle h1 = {{0}};
1282         uint64_t parent = LEASE2;
1283         NTSTATUS status;
1284         const char *fname = "lease_v2_request_parent.dat";
1285         bool ret = true;
1286         uint32_t caps;
1287         enum protocol_types protocol;
1288
1289         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1290         if (!(caps & SMB2_CAP_LEASING)) {
1291                 torture_skip(tctx, "leases are not supported");
1292         }
1293         if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
1294                 torture_skip(tctx, "directory leases are not supported");
1295         }
1296
1297         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1298         if (protocol < PROTOCOL_SMB3_00) {
1299                 torture_skip(tctx, "v2 leases are not supported");
1300         }
1301
1302         smb2_util_unlink(tree, fname);
1303
1304         ZERO_STRUCT(lease_break_info);
1305
1306         ZERO_STRUCT(io);
1307         smb2_lease_v2_create_share(&io, &ls, false, fname,
1308                                    smb2_util_share_access("RWD"),
1309                                    LEASE1, &parent,
1310                                    smb2_util_lease_state("RHW"),
1311                                    0x11);
1312
1313         status = smb2_create(tree, mem_ctx, &io);
1314         CHECK_STATUS(status, NT_STATUS_OK);
1315         h1 = io.out.file.handle;
1316         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1317         CHECK_LEASE_V2(&io, "RHW", true, LEASE1,
1318                        SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2,
1319                        ls.lease_epoch + 1);
1320
1321  done:
1322         smb2_util_close(tree, h1);
1323         smb2_util_unlink(tree, fname);
1324
1325         talloc_free(mem_ctx);
1326
1327         return ret;
1328 }
1329
1330 static bool test_lease_break_twice(struct torture_context *tctx,
1331                                    struct smb2_tree *tree)
1332 {
1333         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1334         struct smb2_create io;
1335         struct smb2_lease ls1;
1336         struct smb2_lease ls2;
1337         struct smb2_handle h1 = {{0}};
1338         NTSTATUS status;
1339         const char *fname = "lease_break_twice.dat";
1340         bool ret = true;
1341         uint32_t caps;
1342         enum protocol_types protocol;
1343
1344         caps = smb2cli_conn_server_capabilities(
1345                 tree->session->transport->conn);
1346         if (!(caps & SMB2_CAP_LEASING)) {
1347                 torture_skip(tctx, "leases are not supported");
1348         }
1349
1350         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1351         if (protocol < PROTOCOL_SMB3_00) {
1352                 torture_skip(tctx, "v2 leases are not supported");
1353         }
1354
1355         smb2_util_unlink(tree, fname);
1356
1357         ZERO_STRUCT(lease_break_info);
1358         ZERO_STRUCT(io);
1359
1360         smb2_lease_v2_create_share(
1361                 &io, &ls1, false, fname, smb2_util_share_access("RWD"),
1362                 LEASE1, NULL, smb2_util_lease_state("RWH"), 0x11);
1363
1364         status = smb2_create(tree, mem_ctx, &io);
1365         CHECK_STATUS(status, NT_STATUS_OK);
1366         h1 = io.out.file.handle;
1367         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1368         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch + 1);
1369
1370         tree->session->transport->lease.handler = torture_lease_handler;
1371         tree->session->transport->lease.private_data = tree;
1372
1373         ZERO_STRUCT(lease_break_info);
1374
1375         smb2_lease_v2_create_share(
1376                 &io, &ls2, false, fname, smb2_util_share_access("R"),
1377                 LEASE2, NULL, smb2_util_lease_state("RWH"), 0x22);
1378
1379         status = smb2_create(tree, mem_ctx, &io);
1380         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
1381         CHECK_BREAK_INFO_V2(tree->session->transport,
1382                             "RWH", "RW", LEASE1, ls1.lease_epoch + 2);
1383
1384         smb2_lease_v2_create_share(
1385                 &io, &ls2, false, fname, smb2_util_share_access("RWD"),
1386                 LEASE2, NULL, smb2_util_lease_state("RWH"), 0x22);
1387
1388         ZERO_STRUCT(lease_break_info);
1389
1390         status = smb2_create(tree, mem_ctx, &io);
1391         CHECK_STATUS(status, NT_STATUS_OK);
1392         CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch + 1);
1393         CHECK_BREAK_INFO_V2(tree->session->transport,
1394                             "RW", "R", LEASE1, ls1.lease_epoch + 3);
1395
1396 done:
1397         smb2_util_close(tree, h1);
1398         smb2_util_unlink(tree, fname);
1399         talloc_free(mem_ctx);
1400         return ret;
1401 }
1402
1403 static bool test_lease_v2_request(struct torture_context *tctx,
1404                                   struct smb2_tree *tree)
1405 {
1406         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1407         struct smb2_create io;
1408         struct smb2_lease ls1, ls2, ls2t, ls3, ls4;
1409         struct smb2_handle h1 = {{0}};
1410         struct smb2_handle h2 = {{0}};
1411         struct smb2_handle h3 = {{0}};
1412         struct smb2_handle h4 = {{0}};
1413         struct smb2_handle h5 = {{0}};
1414         struct smb2_write w;
1415         NTSTATUS status;
1416         const char *fname = "lease_v2_request.dat";
1417         const char *dname = "lease_v2_request.dir";
1418         const char *dnamefname = "lease_v2_request.dir\\lease.dat";
1419         const char *dnamefname2 = "lease_v2_request.dir\\lease2.dat";
1420         bool ret = true;
1421         uint32_t caps;
1422         enum protocol_types protocol;
1423
1424         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1425         if (!(caps & SMB2_CAP_LEASING)) {
1426                 torture_skip(tctx, "leases are not supported");
1427         }
1428         if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) {
1429                 torture_skip(tctx, "directory leases are not supported");
1430         }
1431
1432         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1433         if (protocol < PROTOCOL_SMB3_00) {
1434                 torture_skip(tctx, "v2 leases are not supported");
1435         }
1436
1437         smb2_util_unlink(tree, fname);
1438         smb2_deltree(tree, dname);
1439
1440         tree->session->transport->lease.handler = torture_lease_handler;
1441         tree->session->transport->lease.private_data = tree;
1442         tree->session->transport->oplock.handler = torture_oplock_handler;
1443         tree->session->transport->oplock.private_data = tree;
1444
1445         ZERO_STRUCT(lease_break_info);
1446
1447         ZERO_STRUCT(io);
1448         smb2_lease_v2_create_share(&io, &ls1, false, fname,
1449                                    smb2_util_share_access("RWD"),
1450                                    LEASE1, NULL,
1451                                    smb2_util_lease_state("RHW"),
1452                                    0x11);
1453
1454         status = smb2_create(tree, mem_ctx, &io);
1455         CHECK_STATUS(status, NT_STATUS_OK);
1456         h1 = io.out.file.handle;
1457         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1458         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch + 1);
1459
1460         ZERO_STRUCT(io);
1461         smb2_lease_v2_create_share(&io, &ls2, true, dname,
1462                                    smb2_util_share_access("RWD"),
1463                                    LEASE2, NULL,
1464                                    smb2_util_lease_state("RHW"),
1465                                    0x22);
1466         status = smb2_create(tree, mem_ctx, &io);
1467         CHECK_STATUS(status, NT_STATUS_OK);
1468         h2 = io.out.file.handle;
1469         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY);
1470         CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch + 1);
1471
1472         ZERO_STRUCT(io);
1473         smb2_lease_v2_create_share(&io, &ls3, false, dnamefname,
1474                                    smb2_util_share_access("RWD"),
1475                                    LEASE3, &LEASE2,
1476                                    smb2_util_lease_state("RHW"),
1477                                    0x33);
1478         status = smb2_create(tree, mem_ctx, &io);
1479         CHECK_STATUS(status, NT_STATUS_OK);
1480         h3 = io.out.file.handle;
1481         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1482         CHECK_LEASE_V2(&io, "RHW", true, LEASE3,
1483                        SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2,
1484                        ls3.lease_epoch + 1);
1485
1486         CHECK_NO_BREAK(tctx);
1487
1488         ZERO_STRUCT(io);
1489         smb2_lease_v2_create_share(&io, &ls4, false, dnamefname2,
1490                                    smb2_util_share_access("RWD"),
1491                                    LEASE4, NULL,
1492                                    smb2_util_lease_state("RHW"),
1493                                    0x44);
1494         status = smb2_create(tree, mem_ctx, &io);
1495         CHECK_STATUS(status, NT_STATUS_OK);
1496         h4 = io.out.file.handle;
1497         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1498         CHECK_LEASE_V2(&io, "RHW", true, LEASE4, 0, 0, ls4.lease_epoch + 1);
1499
1500         CHECK_BREAK_INFO_V2(tree->session->transport,
1501                             "RH", "", LEASE2, ls2.lease_epoch + 2);
1502
1503         ZERO_STRUCT(lease_break_info);
1504
1505         ZERO_STRUCT(io);
1506         smb2_lease_v2_create_share(&io, &ls2t, true, dname,
1507                                    smb2_util_share_access("RWD"),
1508                                    LEASE2, NULL,
1509                                    smb2_util_lease_state("RHW"),
1510                                    0x222);
1511         io.in.create_disposition = NTCREATEX_DISP_OPEN;
1512         status = smb2_create(tree, mem_ctx, &io);
1513         CHECK_STATUS(status, NT_STATUS_OK);
1514         h5 = io.out.file.handle;
1515         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_DIRECTORY);
1516         CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch+3);
1517         smb2_util_close(tree, h5);
1518
1519         ZERO_STRUCT(w);
1520         w.in.file.handle = h4;
1521         w.in.offset      = 0;
1522         w.in.data        = data_blob_talloc(mem_ctx, NULL, 4096);
1523         memset(w.in.data.data, 'o', w.in.data.length);
1524         status = smb2_write(tree, &w);
1525         CHECK_STATUS(status, NT_STATUS_OK);
1526
1527         /*
1528          * Wait 4 seconds in order to check if the write time
1529          * was updated (after 2 seconds).
1530          */
1531         smb_msleep(4000);
1532         CHECK_NO_BREAK(tctx);
1533
1534         /*
1535          * only the close on the modified file break the
1536          * directory lease.
1537          */
1538         smb2_util_close(tree, h4);
1539
1540         CHECK_BREAK_INFO_V2(tree->session->transport,
1541                             "RH", "", LEASE2, ls2.lease_epoch+4);
1542
1543  done:
1544         smb2_util_close(tree, h1);
1545         smb2_util_close(tree, h2);
1546         smb2_util_close(tree, h3);
1547         smb2_util_close(tree, h4);
1548         smb2_util_close(tree, h5);
1549
1550         smb2_util_unlink(tree, fname);
1551         smb2_deltree(tree, dname);
1552
1553         talloc_free(mem_ctx);
1554
1555         return ret;
1556 }
1557
1558 static bool test_lease_v2_epoch1(struct torture_context *tctx,
1559                                  struct smb2_tree *tree)
1560 {
1561         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1562         struct smb2_create io;
1563         struct smb2_lease ls;
1564         struct smb2_handle h;
1565         const char *fname = "lease_v2_epoch1.dat";
1566         bool ret = true;
1567         NTSTATUS status;
1568         uint32_t caps;
1569         enum protocol_types protocol;
1570
1571         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1572         if (!(caps & SMB2_CAP_LEASING)) {
1573                 torture_skip(tctx, "leases are not supported");
1574         }
1575
1576         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1577         if (protocol < PROTOCOL_SMB3_00) {
1578                 torture_skip(tctx, "v2 leases are not supported");
1579         }
1580
1581         smb2_util_unlink(tree, fname);
1582
1583         tree->session->transport->lease.handler = torture_lease_handler;
1584         tree->session->transport->lease.private_data = tree;
1585         tree->session->transport->oplock.handler = torture_oplock_handler;
1586         tree->session->transport->oplock.private_data = tree;
1587
1588         ZERO_STRUCT(lease_break_info);
1589
1590         ZERO_STRUCT(io);
1591         smb2_lease_v2_create_share(&io, &ls, false, fname,
1592                                    smb2_util_share_access("RWD"),
1593                                    LEASE1, NULL,
1594                                    smb2_util_lease_state("RHW"),
1595                                    0x4711);
1596         status = smb2_create(tree, mem_ctx, &io);
1597         CHECK_STATUS(status, NT_STATUS_OK);
1598         h = io.out.file.handle;
1599         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1600         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls.lease_epoch + 1);
1601         smb2_util_close(tree, h);
1602         smb2_util_unlink(tree, fname);
1603
1604         smb2_lease_v2_create_share(&io, &ls, false, fname,
1605                                    smb2_util_share_access("RWD"),
1606                                    LEASE1, NULL,
1607                                    smb2_util_lease_state("RHW"),
1608                                    0x11);
1609
1610         status = smb2_create(tree, mem_ctx, &io);
1611         CHECK_STATUS(status, NT_STATUS_OK);
1612         h = io.out.file.handle;
1613         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1614         CHECK_LEASE_V2(&io, "RWH", true, LEASE1, 0, 0, ls.lease_epoch + 1);
1615         smb2_util_close(tree, h);
1616
1617 done:
1618         smb2_util_unlink(tree, fname);
1619         talloc_free(mem_ctx);
1620         return ret;
1621 }
1622
1623 static bool test_lease_v2_epoch2(struct torture_context *tctx,
1624                                  struct smb2_tree *tree)
1625 {
1626         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1627         struct smb2_create io;
1628         struct smb2_lease ls1v2, ls1v2t, ls1v1;
1629         struct smb2_handle hv2 = {}, hv1 = {};
1630         const char *fname = "lease_v2_epoch2.dat";
1631         bool ret = true;
1632         NTSTATUS status;
1633         uint32_t caps;
1634         enum protocol_types protocol;
1635
1636         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1637         if (!(caps & SMB2_CAP_LEASING)) {
1638                 torture_skip(tctx, "leases are not supported");
1639         }
1640
1641         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1642         if (protocol < PROTOCOL_SMB3_00) {
1643                 torture_skip(tctx, "v2 leases are not supported");
1644         }
1645
1646         smb2_util_unlink(tree, fname);
1647
1648         tree->session->transport->lease.handler = torture_lease_handler;
1649         tree->session->transport->lease.private_data = tree;
1650         tree->session->transport->oplock.handler = torture_oplock_handler;
1651         tree->session->transport->oplock.private_data = tree;
1652
1653         ZERO_STRUCT(lease_break_info);
1654
1655         ZERO_STRUCT(io);
1656         smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1657                                    smb2_util_share_access("RWD"),
1658                                    LEASE1, NULL,
1659                                    smb2_util_lease_state("R"),
1660                                    0x4711);
1661         status = smb2_create(tree, mem_ctx, &io);
1662         CHECK_STATUS(status, NT_STATUS_OK);
1663         hv2 = io.out.file.handle;
1664         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1665         CHECK_LEASE_V2(&io, "R", true, LEASE1, 0, 0, ls1v2.lease_epoch + 1);
1666
1667         ZERO_STRUCT(io);
1668         smb2_lease_create_share(&io, &ls1v1, false, fname,
1669                                 smb2_util_share_access("RWD"),
1670                                 LEASE1,
1671                                 smb2_util_lease_state("RH"));
1672         status = smb2_create(tree, mem_ctx, &io);
1673         CHECK_STATUS(status, NT_STATUS_OK);
1674         hv1 = io.out.file.handle;
1675         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1676         CHECK_LEASE_V2(&io, "RH", true, LEASE1, 0, 0, ls1v2.lease_epoch + 2);
1677
1678         smb2_util_close(tree, hv2);
1679
1680         ZERO_STRUCT(io);
1681         smb2_lease_v2_create_share(&io, &ls1v2t, false, fname,
1682                                    smb2_util_share_access("RWD"),
1683                                    LEASE1, NULL,
1684                                    smb2_util_lease_state("RHW"),
1685                                    0x11);
1686         status = smb2_create(tree, mem_ctx, &io);
1687         CHECK_STATUS(status, NT_STATUS_OK);
1688         hv2 = io.out.file.handle;
1689         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1690         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1v2.lease_epoch + 3);
1691
1692         smb2_util_close(tree, hv2);
1693
1694         smb2_oplock_create(&io, fname, SMB2_OPLOCK_LEVEL_NONE);
1695         status = smb2_create(tree, mem_ctx, &io);
1696         CHECK_STATUS(status, NT_STATUS_OK);
1697         hv2 = io.out.file.handle;
1698         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1699         CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1700
1701         CHECK_BREAK_INFO_V2(tree->session->transport,
1702                             "RWH", "RH", LEASE1, ls1v2.lease_epoch + 4);
1703
1704         smb2_util_close(tree, hv2);
1705         smb2_util_close(tree, hv1);
1706
1707         ZERO_STRUCT(io);
1708         smb2_lease_create_share(&io, &ls1v1, false, fname,
1709                                 smb2_util_share_access("RWD"),
1710                                 LEASE1,
1711                                 smb2_util_lease_state("RHW"));
1712         status = smb2_create(tree, mem_ctx, &io);
1713         CHECK_STATUS(status, NT_STATUS_OK);
1714         hv1 = io.out.file.handle;
1715         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1716         CHECK_LEASE(&io, "RHW", true, LEASE1, 0);
1717
1718         smb2_util_close(tree, hv1);
1719
1720 done:
1721         smb2_util_close(tree, hv2);
1722         smb2_util_close(tree, hv1);
1723         smb2_util_unlink(tree, fname);
1724         talloc_free(mem_ctx);
1725         return ret;
1726 }
1727
1728 static bool test_lease_v2_epoch3(struct torture_context *tctx,
1729                                  struct smb2_tree *tree)
1730 {
1731         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1732         struct smb2_create io;
1733         struct smb2_lease ls1v1 = {}, ls1v1t = {},ls1v2 = {};
1734         struct smb2_handle hv1 = {}, hv2 = {};
1735         const char *fname = "lease_v2_epoch3.dat";
1736         bool ret = true;
1737         NTSTATUS status;
1738         uint32_t caps;
1739         enum protocol_types protocol;
1740
1741         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1742         if (!(caps & SMB2_CAP_LEASING)) {
1743                 torture_skip(tctx, "leases are not supported");
1744         }
1745
1746         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
1747         if (protocol < PROTOCOL_SMB3_00) {
1748                 torture_skip(tctx, "v2 leases are not supported");
1749         }
1750
1751         smb2_util_unlink(tree, fname);
1752
1753         tree->session->transport->lease.handler = torture_lease_handler;
1754         tree->session->transport->lease.private_data = tree;
1755         tree->session->transport->oplock.handler = torture_oplock_handler;
1756         tree->session->transport->oplock.private_data = tree;
1757
1758         ZERO_STRUCT(lease_break_info);
1759
1760         ZERO_STRUCT(io);
1761         smb2_lease_create_share(&io, &ls1v1, false, fname,
1762                                 smb2_util_share_access("RWD"),
1763                                 LEASE1,
1764                                 smb2_util_lease_state("R"));
1765         status = smb2_create(tree, mem_ctx, &io);
1766         CHECK_STATUS(status, NT_STATUS_OK);
1767         hv1 = io.out.file.handle;
1768         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1769         CHECK_LEASE(&io, "R", true, LEASE1, 0);
1770
1771         ZERO_STRUCT(io);
1772         smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1773                                    smb2_util_share_access("RWD"),
1774                                    LEASE1, NULL,
1775                                    smb2_util_lease_state("RW"),
1776                                    0x4711);
1777         status = smb2_create(tree, mem_ctx, &io);
1778         CHECK_STATUS(status, NT_STATUS_OK);
1779         hv2 = io.out.file.handle;
1780         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1781         CHECK_LEASE(&io, "RW", true, LEASE1, 0);
1782
1783         smb2_util_close(tree, hv1);
1784
1785         ZERO_STRUCT(io);
1786         smb2_lease_create_share(&io, &ls1v1t, false, fname,
1787                                 smb2_util_share_access("RWD"),
1788                                 LEASE1,
1789                                 smb2_util_lease_state("RWH"));
1790         status = smb2_create(tree, mem_ctx, &io);
1791         CHECK_STATUS(status, NT_STATUS_OK);
1792         hv1 = io.out.file.handle;
1793         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1794         CHECK_LEASE(&io, "RWH", true, LEASE1, 0);
1795
1796         smb2_util_close(tree, hv1);
1797
1798         smb2_oplock_create(&io, fname, SMB2_OPLOCK_LEVEL_NONE);
1799         status = smb2_create(tree, mem_ctx, &io);
1800         CHECK_STATUS(status, NT_STATUS_OK);
1801         hv1 = io.out.file.handle;
1802         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1803         CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1804
1805         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
1806
1807         smb2_util_close(tree, hv1);
1808         smb2_util_close(tree, hv2);
1809
1810         ZERO_STRUCT(io);
1811         smb2_lease_v2_create_share(&io, &ls1v2, false, fname,
1812                                    smb2_util_share_access("RWD"),
1813                                    LEASE1, NULL,
1814                                    smb2_util_lease_state("RWH"),
1815                                    0x4711);
1816         status = smb2_create(tree, mem_ctx, &io);
1817         CHECK_STATUS(status, NT_STATUS_OK);
1818         hv2 = io.out.file.handle;
1819         CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1820         CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1v2.lease_epoch + 1);
1821         smb2_util_close(tree, hv2);
1822
1823 done:
1824         smb2_util_close(tree, hv2);
1825         smb2_util_close(tree, hv1);
1826         smb2_util_unlink(tree, fname);
1827         talloc_free(mem_ctx);
1828         return ret;
1829 }
1830
1831 static bool test_lease_breaking1(struct torture_context *tctx,
1832                                  struct smb2_tree *tree)
1833 {
1834         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1835         struct smb2_create io1 = {};
1836         struct smb2_create io2 = {};
1837         struct smb2_lease ls1 = {};
1838         struct smb2_handle h1a = {};
1839         struct smb2_handle h1b = {};
1840         struct smb2_handle h2 = {};
1841         struct smb2_request *req2 = NULL;
1842         struct smb2_lease_break_ack ack = {};
1843         const char *fname = "lease_breaking1.dat";
1844         bool ret = true;
1845         NTSTATUS status;
1846         uint32_t caps;
1847
1848         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1849         if (!(caps & SMB2_CAP_LEASING)) {
1850                 torture_skip(tctx, "leases are not supported");
1851         }
1852
1853         smb2_util_unlink(tree, fname);
1854
1855         tree->session->transport->lease.handler = torture_lease_handler;
1856         tree->session->transport->lease.private_data = tree;
1857         tree->session->transport->oplock.handler = torture_oplock_handler;
1858         tree->session->transport->oplock.private_data = tree;
1859
1860         /*
1861          * we defer acking the lease break.
1862          */
1863         ZERO_STRUCT(lease_break_info);
1864         lease_break_info.lease_skip_ack = true;
1865
1866         smb2_lease_create_share(&io1, &ls1, false, fname,
1867                                 smb2_util_share_access("RWD"),
1868                                 LEASE1,
1869                                 smb2_util_lease_state("RWH"));
1870         status = smb2_create(tree, mem_ctx, &io1);
1871         CHECK_STATUS(status, NT_STATUS_OK);
1872         h1a = io1.out.file.handle;
1873         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1874         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
1875
1876         /*
1877          * a conflicting open is blocked until we ack the
1878          * lease break
1879          */
1880         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
1881         req2 = smb2_create_send(tree, &io2);
1882         torture_assert(tctx, req2 != NULL, "smb2_create_send");
1883
1884         /*
1885          * we got the lease break, but defer the ack.
1886          */
1887         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
1888
1889         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1890
1891         ack.in.lease.lease_key =
1892                 lease_break_info.lease_break.current_lease.lease_key;
1893         ack.in.lease.lease_state =
1894                 lease_break_info.lease_break.new_lease_state;
1895         ZERO_STRUCT(lease_break_info);
1896
1897         /*
1898          * a open using the same lease key is still works,
1899          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
1900          */
1901         status = smb2_create(tree, mem_ctx, &io1);
1902         CHECK_STATUS(status, NT_STATUS_OK);
1903         h1b = io1.out.file.handle;
1904         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1905         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
1906         smb2_util_close(tree, h1b);
1907
1908         CHECK_NO_BREAK(tctx);
1909
1910         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1911
1912         /*
1913          * We ack the lease break.
1914          */
1915         status = smb2_lease_break_ack(tree, &ack);
1916         CHECK_STATUS(status, NT_STATUS_OK);
1917         CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
1918
1919         torture_assert(tctx, req2->cancel.can_cancel,
1920                        "req2 can_cancel");
1921
1922         status = smb2_create_recv(req2, tctx, &io2);
1923         CHECK_STATUS(status, NT_STATUS_OK);
1924         h2 = io2.out.file.handle;
1925         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
1926         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
1927
1928         CHECK_NO_BREAK(tctx);
1929 done:
1930         smb2_util_close(tree, h1a);
1931         smb2_util_close(tree, h1b);
1932         smb2_util_close(tree, h2);
1933         smb2_util_unlink(tree, fname);
1934         talloc_free(mem_ctx);
1935         return ret;
1936 }
1937
1938 static bool test_lease_breaking2(struct torture_context *tctx,
1939                                  struct smb2_tree *tree)
1940 {
1941         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1942         struct smb2_create io1 = {};
1943         struct smb2_create io2 = {};
1944         struct smb2_lease ls1 = {};
1945         struct smb2_handle h1a = {};
1946         struct smb2_handle h1b = {};
1947         struct smb2_handle h2 = {};
1948         struct smb2_request *req2 = NULL;
1949         struct smb2_lease_break_ack ack = {};
1950         const char *fname = "lease_breaking2.dat";
1951         bool ret = true;
1952         NTSTATUS status;
1953         uint32_t caps;
1954
1955         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
1956         if (!(caps & SMB2_CAP_LEASING)) {
1957                 torture_skip(tctx, "leases are not supported");
1958         }
1959
1960         smb2_util_unlink(tree, fname);
1961
1962         tree->session->transport->lease.handler = torture_lease_handler;
1963         tree->session->transport->lease.private_data = tree;
1964         tree->session->transport->oplock.handler = torture_oplock_handler;
1965         tree->session->transport->oplock.private_data = tree;
1966
1967         /*
1968          * we defer acking the lease break.
1969          */
1970         ZERO_STRUCT(lease_break_info);
1971         lease_break_info.lease_skip_ack = true;
1972
1973         smb2_lease_create_share(&io1, &ls1, false, fname,
1974                                 smb2_util_share_access("RWD"),
1975                                 LEASE1,
1976                                 smb2_util_lease_state("RWH"));
1977         status = smb2_create(tree, mem_ctx, &io1);
1978         CHECK_STATUS(status, NT_STATUS_OK);
1979         h1a = io1.out.file.handle;
1980         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1981         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
1982
1983         /*
1984          * a conflicting open is blocked until we ack the
1985          * lease break
1986          */
1987         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
1988         io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
1989         req2 = smb2_create_send(tree, &io2);
1990         torture_assert(tctx, req2 != NULL, "smb2_create_send");
1991
1992         /*
1993          * we got the lease break, but defer the ack.
1994          */
1995         CHECK_BREAK_INFO("RWH", "", LEASE1);
1996
1997         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
1998
1999         ack.in.lease.lease_key =
2000                 lease_break_info.lease_break.current_lease.lease_key;
2001         ZERO_STRUCT(lease_break_info);
2002
2003         /*
2004          * a open using the same lease key is still works,
2005          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2006          */
2007         status = smb2_create(tree, mem_ctx, &io1);
2008         CHECK_STATUS(status, NT_STATUS_OK);
2009         h1b = io1.out.file.handle;
2010         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2011         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2012         smb2_util_close(tree, h1b);
2013
2014         CHECK_NO_BREAK(tctx);
2015
2016         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2017
2018         /*
2019          * We ack the lease break.
2020          */
2021         ack.in.lease.lease_state =
2022                 SMB2_LEASE_READ | SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE;
2023         status = smb2_lease_break_ack(tree, &ack);
2024         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2025
2026         ack.in.lease.lease_state =
2027                 SMB2_LEASE_READ | SMB2_LEASE_WRITE;
2028         status = smb2_lease_break_ack(tree, &ack);
2029         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2030
2031         ack.in.lease.lease_state =
2032                 SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE;
2033         status = smb2_lease_break_ack(tree, &ack);
2034         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2035
2036         ack.in.lease.lease_state =
2037                 SMB2_LEASE_READ | SMB2_LEASE_HANDLE;
2038         status = smb2_lease_break_ack(tree, &ack);
2039         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2040
2041         ack.in.lease.lease_state = SMB2_LEASE_WRITE;
2042         status = smb2_lease_break_ack(tree, &ack);
2043         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2044
2045         ack.in.lease.lease_state = SMB2_LEASE_HANDLE;
2046         status = smb2_lease_break_ack(tree, &ack);
2047         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2048
2049         ack.in.lease.lease_state = SMB2_LEASE_READ;
2050         status = smb2_lease_break_ack(tree, &ack);
2051         CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED);
2052
2053         /* Try again with the correct state this time. */
2054         ack.in.lease.lease_state = SMB2_LEASE_NONE;;
2055         status = smb2_lease_break_ack(tree, &ack);
2056         CHECK_STATUS(status, NT_STATUS_OK);
2057         CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2058
2059         status = smb2_lease_break_ack(tree, &ack);
2060         CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
2061
2062         torture_assert(tctx, req2->cancel.can_cancel,
2063                        "req2 can_cancel");
2064
2065         status = smb2_create_recv(req2, tctx, &io2);
2066         CHECK_STATUS(status, NT_STATUS_OK);
2067         h2 = io2.out.file.handle;
2068         CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2069         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2070
2071         CHECK_NO_BREAK(tctx);
2072
2073         /* Get state of the original handle. */
2074         smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state(""));
2075         status = smb2_create(tree, mem_ctx, &io1);
2076         CHECK_STATUS(status, NT_STATUS_OK);
2077         CHECK_LEASE(&io1, "", true, LEASE1, 0);
2078         smb2_util_close(tree, io1.out.file.handle);
2079
2080 done:
2081         smb2_util_close(tree, h1a);
2082         smb2_util_close(tree, h1b);
2083         smb2_util_close(tree, h2);
2084         smb2_util_unlink(tree, fname);
2085         talloc_free(mem_ctx);
2086         return ret;
2087 }
2088
2089 static bool test_lease_breaking3(struct torture_context *tctx,
2090                                  struct smb2_tree *tree)
2091 {
2092         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2093         struct smb2_create io1 = {};
2094         struct smb2_create io2 = {};
2095         struct smb2_create io3 = {};
2096         struct smb2_lease ls1 = {};
2097         struct smb2_handle h1a = {};
2098         struct smb2_handle h1b = {};
2099         struct smb2_handle h2 = {};
2100         struct smb2_handle h3 = {};
2101         struct smb2_request *req2 = NULL;
2102         struct smb2_request *req3 = NULL;
2103         struct lease_break_info lease_break_info_tmp = {};
2104         struct smb2_lease_break_ack ack = {};
2105         const char *fname = "lease_breaking3.dat";
2106         bool ret = true;
2107         NTSTATUS status;
2108         uint32_t caps;
2109
2110         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2111         if (!(caps & SMB2_CAP_LEASING)) {
2112                 torture_skip(tctx, "leases are not supported");
2113         }
2114
2115         smb2_util_unlink(tree, fname);
2116
2117         tree->session->transport->lease.handler = torture_lease_handler;
2118         tree->session->transport->lease.private_data = tree;
2119         tree->session->transport->oplock.handler = torture_oplock_handler;
2120         tree->session->transport->oplock.private_data = tree;
2121
2122         /*
2123          * we defer acking the lease break.
2124          */
2125         ZERO_STRUCT(lease_break_info);
2126         lease_break_info.lease_skip_ack = true;
2127
2128         smb2_lease_create_share(&io1, &ls1, false, fname,
2129                                 smb2_util_share_access("RWD"),
2130                                 LEASE1,
2131                                 smb2_util_lease_state("RWH"));
2132         status = smb2_create(tree, mem_ctx, &io1);
2133         CHECK_STATUS(status, NT_STATUS_OK);
2134         h1a = io1.out.file.handle;
2135         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2136         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2137
2138         /*
2139          * a conflicting open is blocked until we ack the
2140          * lease break
2141          */
2142         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2143         req2 = smb2_create_send(tree, &io2);
2144         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2145
2146         /*
2147          * we got the lease break, but defer the ack.
2148          */
2149         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2150
2151         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2152
2153         /*
2154          * a open using the same lease key is still works,
2155          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2156          */
2157         status = smb2_create(tree, mem_ctx, &io1);
2158         CHECK_STATUS(status, NT_STATUS_OK);
2159         h1b = io1.out.file.handle;
2160         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2161         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2162         smb2_util_close(tree, h1b);
2163
2164         /*
2165          * a conflicting open with NTCREATEX_DISP_OVERWRITE
2166          * doesn't trigger an immediate lease break to none.
2167          */
2168         lease_break_info_tmp = lease_break_info;
2169         ZERO_STRUCT(lease_break_info);
2170         smb2_oplock_create(&io3, fname, SMB2_OPLOCK_LEVEL_NONE);
2171         io3.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2172         req3 = smb2_create_send(tree, &io3);
2173         torture_assert(tctx, req3 != NULL, "smb2_create_send");
2174         CHECK_NO_BREAK(tctx);
2175         lease_break_info = lease_break_info_tmp;
2176
2177         torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2178
2179         ack.in.lease.lease_key =
2180                 lease_break_info.lease_break.current_lease.lease_key;
2181         ack.in.lease.lease_state =
2182                 lease_break_info.lease_break.new_lease_state;
2183         ZERO_STRUCT(lease_break_info);
2184
2185         /*
2186          * a open using the same lease key is still works,
2187          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2188          */
2189         status = smb2_create(tree, mem_ctx, &io1);
2190         CHECK_STATUS(status, NT_STATUS_OK);
2191         h1b = io1.out.file.handle;
2192         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2193         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2194         smb2_util_close(tree, h1b);
2195
2196         CHECK_NO_BREAK(tctx);
2197
2198         /*
2199          * We ack the lease break, but defer acking the next break (to "R")
2200          */
2201         lease_break_info.lease_skip_ack = true;
2202         status = smb2_lease_break_ack(tree, &ack);
2203         CHECK_STATUS(status, NT_STATUS_OK);
2204         CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
2205
2206         /*
2207          * We got an additional break downgrading to just "R"
2208          * while we defer the ack.
2209          */
2210         CHECK_BREAK_INFO("RH", "R", LEASE1);
2211
2212         ack.in.lease.lease_key =
2213                 lease_break_info.lease_break.current_lease.lease_key;
2214         ack.in.lease.lease_state =
2215                 lease_break_info.lease_break.new_lease_state;
2216         ZERO_STRUCT(lease_break_info);
2217
2218         /*
2219          * a open using the same lease key is still works,
2220          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2221          */
2222         status = smb2_create(tree, mem_ctx, &io1);
2223         CHECK_STATUS(status, NT_STATUS_OK);
2224         h1b = io1.out.file.handle;
2225         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2226         CHECK_LEASE(&io1, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2227         smb2_util_close(tree, h1b);
2228
2229         CHECK_NO_BREAK(tctx);
2230
2231         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2232         torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2233
2234         /*
2235          * We ack the downgrade to "R" and get an immediate break to none
2236          */
2237         status = smb2_lease_break_ack(tree, &ack);
2238         CHECK_STATUS(status, NT_STATUS_OK);
2239         CHECK_LEASE_BREAK_ACK(&ack, "R", LEASE1);
2240
2241         /*
2242          * We get the downgrade to none.
2243          */
2244         CHECK_BREAK_INFO("R", "", LEASE1);
2245
2246         torture_assert(tctx, req2->cancel.can_cancel,
2247                        "req2 can_cancel");
2248         torture_assert(tctx, req3->cancel.can_cancel,
2249                        "req3 can_cancel");
2250
2251         ZERO_STRUCT(lease_break_info);
2252
2253         status = smb2_create_recv(req2, tctx, &io2);
2254         CHECK_STATUS(status, NT_STATUS_OK);
2255         h2 = io2.out.file.handle;
2256         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2257         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2258
2259         status = smb2_create_recv(req3, tctx, &io3);
2260         CHECK_STATUS(status, NT_STATUS_OK);
2261         h3 = io3.out.file.handle;
2262         CHECK_CREATED(&io3, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2263         CHECK_VAL(io3.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2264
2265         CHECK_NO_BREAK(tctx);
2266 done:
2267         smb2_util_close(tree, h1a);
2268         smb2_util_close(tree, h1b);
2269         smb2_util_close(tree, h2);
2270         smb2_util_close(tree, h3);
2271
2272         smb2_util_unlink(tree, fname);
2273         talloc_free(mem_ctx);
2274         return ret;
2275 }
2276
2277 static bool test_lease_v2_breaking3(struct torture_context *tctx,
2278                                  struct smb2_tree *tree)
2279 {
2280         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2281         struct smb2_create io1 = {};
2282         struct smb2_create io2 = {};
2283         struct smb2_create io3 = {};
2284         struct smb2_lease ls1 = {};
2285         struct smb2_handle h1a = {};
2286         struct smb2_handle h1b = {};
2287         struct smb2_handle h2 = {};
2288         struct smb2_handle h3 = {};
2289         struct smb2_request *req2 = NULL;
2290         struct smb2_request *req3 = NULL;
2291         struct lease_break_info lease_break_info_tmp = {};
2292         struct smb2_lease_break_ack ack = {};
2293         const char *fname = "v2_lease_breaking3.dat";
2294         bool ret = true;
2295         NTSTATUS status;
2296         uint32_t caps;
2297         enum protocol_types protocol;
2298
2299         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2300         if (!(caps & SMB2_CAP_LEASING)) {
2301                 torture_skip(tctx, "leases are not supported");
2302         }
2303
2304         protocol = smbXcli_conn_protocol(tree->session->transport->conn);
2305         if (protocol < PROTOCOL_SMB3_00) {
2306                 torture_skip(tctx, "v2 leases are not supported");
2307         }
2308
2309         smb2_util_unlink(tree, fname);
2310
2311         tree->session->transport->lease.handler = torture_lease_handler;
2312         tree->session->transport->lease.private_data = tree;
2313         tree->session->transport->oplock.handler = torture_oplock_handler;
2314         tree->session->transport->oplock.private_data = tree;
2315
2316         /*
2317          * we defer acking the lease break.
2318          */
2319         ZERO_STRUCT(lease_break_info);
2320         lease_break_info.lease_skip_ack = true;
2321
2322         smb2_lease_v2_create_share(&io1, &ls1, false, fname,
2323                                    smb2_util_share_access("RWD"),
2324                                    LEASE1, NULL,
2325                                    smb2_util_lease_state("RHW"),
2326                                    0x11);
2327         status = smb2_create(tree, mem_ctx, &io1);
2328         CHECK_STATUS(status, NT_STATUS_OK);
2329         h1a = io1.out.file.handle;
2330         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2331         /* Epoch increases on open. */
2332         ls1.lease_epoch += 1;
2333         CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch);
2334
2335         /*
2336          * a conflicting open is blocked until we ack the
2337          * lease break
2338          */
2339         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2340         req2 = smb2_create_send(tree, &io2);
2341         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2342
2343         /*
2344          * we got the lease break, but defer the ack.
2345          */
2346         CHECK_BREAK_INFO_V2(tree->session->transport,
2347                             "RWH", "RH", LEASE1, ls1.lease_epoch + 1);
2348
2349         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2350
2351         /* On receiving a lease break, we must sync the new epoch. */
2352         ls1.lease_epoch = lease_break_info.lease_break.new_epoch;
2353
2354         /*
2355          * a open using the same lease key is still works,
2356          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2357          */
2358         status = smb2_create(tree, mem_ctx, &io1);
2359         CHECK_STATUS(status, NT_STATUS_OK);
2360         h1b = io1.out.file.handle;
2361         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2362         CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2363         smb2_util_close(tree, h1b);
2364
2365         /*
2366          * a conflicting open with NTCREATEX_DISP_OVERWRITE
2367          * doesn't trigger an immediate lease break to none.
2368          */
2369         lease_break_info_tmp = lease_break_info;
2370         ZERO_STRUCT(lease_break_info);
2371         smb2_oplock_create(&io3, fname, SMB2_OPLOCK_LEVEL_NONE);
2372         io3.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2373         req3 = smb2_create_send(tree, &io3);
2374         torture_assert(tctx, req3 != NULL, "smb2_create_send");
2375         CHECK_NO_BREAK(tctx);
2376         lease_break_info = lease_break_info_tmp;
2377
2378         torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2379
2380         ack.in.lease.lease_key =
2381                 lease_break_info.lease_break.current_lease.lease_key;
2382         ack.in.lease.lease_state =
2383                 lease_break_info.lease_break.new_lease_state;
2384         ZERO_STRUCT(lease_break_info);
2385
2386         /*
2387          * a open using the same lease key is still works,
2388          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2389          */
2390         status = smb2_create(tree, mem_ctx, &io1);
2391         CHECK_STATUS(status, NT_STATUS_OK);
2392         h1b = io1.out.file.handle;
2393         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2394         CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2395         smb2_util_close(tree, h1b);
2396
2397         CHECK_NO_BREAK(tctx);
2398
2399         /*
2400          * We ack the lease break, but defer acking the next break (to "R")
2401          */
2402         lease_break_info.lease_skip_ack = true;
2403         status = smb2_lease_break_ack(tree, &ack);
2404         CHECK_STATUS(status, NT_STATUS_OK);
2405         CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1);
2406
2407         /*
2408          * We got an additional break downgrading to just "R"
2409          * while we defer the ack.
2410          */
2411         CHECK_BREAK_INFO_V2(tree->session->transport,
2412                             "RH", "R", LEASE1, ls1.lease_epoch);
2413         /* On receiving a lease break, we must sync the new epoch. */
2414         ls1.lease_epoch = lease_break_info.lease_break.new_epoch;
2415
2416         ack.in.lease.lease_key =
2417                 lease_break_info.lease_break.current_lease.lease_key;
2418         ack.in.lease.lease_state =
2419                 lease_break_info.lease_break.new_lease_state;
2420         ZERO_STRUCT(lease_break_info);
2421
2422         /*
2423          * a open using the same lease key is still works,
2424          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2425          */
2426         status = smb2_create(tree, mem_ctx, &io1);
2427         CHECK_STATUS(status, NT_STATUS_OK);
2428         h1b = io1.out.file.handle;
2429         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2430         CHECK_LEASE_V2(&io1, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS, 0, ls1.lease_epoch);
2431         smb2_util_close(tree, h1b);
2432
2433         CHECK_NO_BREAK(tctx);
2434
2435         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2436         torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending");
2437
2438         /*
2439          * We ack the downgrade to "R" and get an immediate break to none
2440          */
2441         status = smb2_lease_break_ack(tree, &ack);
2442         CHECK_STATUS(status, NT_STATUS_OK);
2443         CHECK_LEASE_BREAK_ACK(&ack, "R", LEASE1);
2444
2445         /*
2446          * We get the downgrade to none.
2447          */
2448         CHECK_BREAK_INFO_V2(tree->session->transport,
2449                             "R", "", LEASE1, ls1.lease_epoch);
2450
2451         torture_assert(tctx, req2->cancel.can_cancel,
2452                        "req2 can_cancel");
2453         torture_assert(tctx, req3->cancel.can_cancel,
2454                        "req3 can_cancel");
2455
2456         ZERO_STRUCT(lease_break_info);
2457
2458         status = smb2_create_recv(req2, tctx, &io2);
2459         CHECK_STATUS(status, NT_STATUS_OK);
2460         h2 = io2.out.file.handle;
2461         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2462         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2463
2464         status = smb2_create_recv(req3, tctx, &io3);
2465         CHECK_STATUS(status, NT_STATUS_OK);
2466         h3 = io3.out.file.handle;
2467         CHECK_CREATED(&io3, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2468         CHECK_VAL(io3.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2469
2470         CHECK_NO_BREAK(tctx);
2471 done:
2472         smb2_util_close(tree, h1a);
2473         smb2_util_close(tree, h1b);
2474         smb2_util_close(tree, h2);
2475         smb2_util_close(tree, h3);
2476
2477         smb2_util_unlink(tree, fname);
2478         talloc_free(mem_ctx);
2479         return ret;
2480 }
2481
2482
2483 static bool test_lease_breaking4(struct torture_context *tctx,
2484                                  struct smb2_tree *tree)
2485 {
2486         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2487         struct smb2_create io1 = {};
2488         struct smb2_create io2 = {};
2489         struct smb2_create io3 = {};
2490         struct smb2_lease ls1 = {};
2491         struct smb2_lease ls1t = {};
2492         struct smb2_handle h1 = {};
2493         struct smb2_handle h2 = {};
2494         struct smb2_handle h3 = {};
2495         struct smb2_request *req2 = NULL;
2496         struct lease_break_info lease_break_info_tmp = {};
2497         struct smb2_lease_break_ack ack = {};
2498         const char *fname = "lease_breaking4.dat";
2499         bool ret = true;
2500         NTSTATUS status;
2501         uint32_t caps;
2502
2503         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2504         if (!(caps & SMB2_CAP_LEASING)) {
2505                 torture_skip(tctx, "leases are not supported");
2506         }
2507
2508         smb2_util_unlink(tree, fname);
2509
2510         tree->session->transport->lease.handler = torture_lease_handler;
2511         tree->session->transport->lease.private_data = tree;
2512         tree->session->transport->oplock.handler = torture_oplock_handler;
2513         tree->session->transport->oplock.private_data = tree;
2514
2515         /*
2516          * we defer acking the lease break.
2517          */
2518         ZERO_STRUCT(lease_break_info);
2519         lease_break_info.lease_skip_ack = true;
2520
2521         smb2_lease_create_share(&io1, &ls1, false, fname,
2522                                 smb2_util_share_access("RWD"),
2523                                 LEASE1,
2524                                 smb2_util_lease_state("RH"));
2525         status = smb2_create(tree, mem_ctx, &io1);
2526         CHECK_STATUS(status, NT_STATUS_OK);
2527         h1 = io1.out.file.handle;
2528         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2529         CHECK_LEASE(&io1, "RH", true, LEASE1, 0);
2530
2531         CHECK_NO_BREAK(tctx);
2532
2533         /*
2534          * a conflicting open is *not* blocked until we ack the
2535          * lease break
2536          */
2537         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2538         io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2539         req2 = smb2_create_send(tree, &io2);
2540         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2541
2542         /*
2543          * We got a break from RH to NONE, we're supported to ack
2544          * this downgrade
2545          */
2546         CHECK_BREAK_INFO("RH", "", LEASE1);
2547
2548         lease_break_info_tmp = lease_break_info;
2549         ZERO_STRUCT(lease_break_info);
2550         CHECK_NO_BREAK(tctx);
2551
2552         torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2553
2554         status = smb2_create_recv(req2, tctx, &io2);
2555         CHECK_STATUS(status, NT_STATUS_OK);
2556         h2 = io2.out.file.handle;
2557         CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2558         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2559         smb2_util_close(tree, h2);
2560
2561         CHECK_NO_BREAK(tctx);
2562
2563         /*
2564          * a conflicting open is *not* blocked until we ack the
2565          * lease break, even if the lease is in breaking state.
2566          */
2567         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2568         io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2569         req2 = smb2_create_send(tree, &io2);
2570         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2571
2572         CHECK_NO_BREAK(tctx);
2573
2574         torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2575
2576         status = smb2_create_recv(req2, tctx, &io2);
2577         CHECK_STATUS(status, NT_STATUS_OK);
2578         h2 = io2.out.file.handle;
2579         CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2580         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2581         smb2_util_close(tree, h2);
2582
2583         CHECK_NO_BREAK(tctx);
2584
2585         /*
2586          * We now ask the server about the current lease state
2587          * which should still be "RH", but with
2588          * SMB2_LEASE_FLAG_BREAK_IN_PROGRESS.
2589          */
2590         smb2_lease_create_share(&io3, &ls1t, false, fname,
2591                                 smb2_util_share_access("RWD"),
2592                                 LEASE1,
2593                                 smb2_util_lease_state(""));
2594         status = smb2_create(tree, mem_ctx, &io3);
2595         CHECK_STATUS(status, NT_STATUS_OK);
2596         h3 = io3.out.file.handle;
2597         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2598         CHECK_LEASE(&io3, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2599
2600         /*
2601          * We finally ack the lease break...
2602          */
2603         CHECK_NO_BREAK(tctx);
2604         lease_break_info = lease_break_info_tmp;
2605         ack.in.lease.lease_key =
2606                 lease_break_info.lease_break.current_lease.lease_key;
2607         ack.in.lease.lease_state =
2608                 lease_break_info.lease_break.new_lease_state;
2609         ZERO_STRUCT(lease_break_info);
2610         lease_break_info.lease_skip_ack = true;
2611
2612         status = smb2_lease_break_ack(tree, &ack);
2613         CHECK_STATUS(status, NT_STATUS_OK);
2614         CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2615
2616         CHECK_NO_BREAK(tctx);
2617
2618 done:
2619         smb2_util_close(tree, h1);
2620         smb2_util_close(tree, h2);
2621         smb2_util_close(tree, h3);
2622
2623         smb2_util_unlink(tree, fname);
2624         talloc_free(mem_ctx);
2625         return ret;
2626 }
2627
2628 static bool test_lease_breaking5(struct torture_context *tctx,
2629                                  struct smb2_tree *tree)
2630 {
2631         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2632         struct smb2_create io1 = {};
2633         struct smb2_create io2 = {};
2634         struct smb2_create io3 = {};
2635         struct smb2_lease ls1 = {};
2636         struct smb2_lease ls1t = {};
2637         struct smb2_handle h1 = {};
2638         struct smb2_handle h2 = {};
2639         struct smb2_handle h3 = {};
2640         struct smb2_request *req2 = NULL;
2641         struct lease_break_info lease_break_info_tmp = {};
2642         struct smb2_lease_break_ack ack = {};
2643         const char *fname = "lease_breaking5.dat";
2644         bool ret = true;
2645         NTSTATUS status;
2646         uint32_t caps;
2647
2648         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2649         if (!(caps & SMB2_CAP_LEASING)) {
2650                 torture_skip(tctx, "leases are not supported");
2651         }
2652
2653         smb2_util_unlink(tree, fname);
2654
2655         tree->session->transport->lease.handler = torture_lease_handler;
2656         tree->session->transport->lease.private_data = tree;
2657         tree->session->transport->oplock.handler = torture_oplock_handler;
2658         tree->session->transport->oplock.private_data = tree;
2659
2660         /*
2661          * we defer acking the lease break.
2662          */
2663         ZERO_STRUCT(lease_break_info);
2664         lease_break_info.lease_skip_ack = true;
2665
2666         smb2_lease_create_share(&io1, &ls1, false, fname,
2667                                 smb2_util_share_access("RWD"),
2668                                 LEASE1,
2669                                 smb2_util_lease_state("R"));
2670         status = smb2_create(tree, mem_ctx, &io1);
2671         CHECK_STATUS(status, NT_STATUS_OK);
2672         h1 = io1.out.file.handle;
2673         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2674         CHECK_LEASE(&io1, "R", true, LEASE1, 0);
2675
2676         CHECK_NO_BREAK(tctx);
2677
2678         /*
2679          * a conflicting open is *not* blocked until we ack the
2680          * lease break
2681          */
2682         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2683         io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
2684         req2 = smb2_create_send(tree, &io2);
2685         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2686
2687         /*
2688          * We got a break from RH to NONE, we're supported to ack
2689          * this downgrade
2690          */
2691         CHECK_BREAK_INFO("R", "", LEASE1);
2692
2693         lease_break_info_tmp = lease_break_info;
2694         ZERO_STRUCT(lease_break_info);
2695         CHECK_NO_BREAK(tctx);
2696
2697         torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done");
2698
2699         status = smb2_create_recv(req2, tctx, &io2);
2700         CHECK_STATUS(status, NT_STATUS_OK);
2701         h2 = io2.out.file.handle;
2702         CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE);
2703         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2704
2705         CHECK_NO_BREAK(tctx);
2706
2707         /*
2708          * We now ask the server about the current lease state
2709          * which should still be "RH", but with
2710          * SMB2_LEASE_FLAG_BREAK_IN_PROGRESS.
2711          */
2712         smb2_lease_create_share(&io3, &ls1t, false, fname,
2713                                 smb2_util_share_access("RWD"),
2714                                 LEASE1,
2715                                 smb2_util_lease_state(""));
2716         status = smb2_create(tree, mem_ctx, &io3);
2717         CHECK_STATUS(status, NT_STATUS_OK);
2718         h3 = io3.out.file.handle;
2719         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2720         CHECK_LEASE(&io3, "", true, LEASE1, 0);
2721
2722         /*
2723          * We send an ack without without being asked.
2724          */
2725         CHECK_NO_BREAK(tctx);
2726         lease_break_info = lease_break_info_tmp;
2727         ack.in.lease.lease_key =
2728                 lease_break_info.lease_break.current_lease.lease_key;
2729         ack.in.lease.lease_state =
2730                 lease_break_info.lease_break.new_lease_state;
2731         ZERO_STRUCT(lease_break_info);
2732         status = smb2_lease_break_ack(tree, &ack);
2733         CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
2734
2735         CHECK_NO_BREAK(tctx);
2736
2737 done:
2738         smb2_util_close(tree, h1);
2739         smb2_util_close(tree, h2);
2740         smb2_util_close(tree, h3);
2741
2742         smb2_util_unlink(tree, fname);
2743         talloc_free(mem_ctx);
2744         return ret;
2745 }
2746
2747 static bool test_lease_breaking6(struct torture_context *tctx,
2748                                  struct smb2_tree *tree)
2749 {
2750         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2751         struct smb2_create io1 = {};
2752         struct smb2_create io2 = {};
2753         struct smb2_lease ls1 = {};
2754         struct smb2_handle h1a = {};
2755         struct smb2_handle h1b = {};
2756         struct smb2_handle h2 = {};
2757         struct smb2_request *req2 = NULL;
2758         struct smb2_lease_break_ack ack = {};
2759         const char *fname = "lease_breaking6.dat";
2760         bool ret = true;
2761         NTSTATUS status;
2762         uint32_t caps;
2763
2764         caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
2765         if (!(caps & SMB2_CAP_LEASING)) {
2766                 torture_skip(tctx, "leases are not supported");
2767         }
2768
2769         smb2_util_unlink(tree, fname);
2770
2771         tree->session->transport->lease.handler = torture_lease_handler;
2772         tree->session->transport->lease.private_data = tree;
2773         tree->session->transport->oplock.handler = torture_oplock_handler;
2774         tree->session->transport->oplock.private_data = tree;
2775
2776         /*
2777          * we defer acking the lease break.
2778          */
2779         ZERO_STRUCT(lease_break_info);
2780         lease_break_info.lease_skip_ack = true;
2781
2782         smb2_lease_create_share(&io1, &ls1, false, fname,
2783                                 smb2_util_share_access("RWD"),
2784                                 LEASE1,
2785                                 smb2_util_lease_state("RWH"));
2786         status = smb2_create(tree, mem_ctx, &io1);
2787         CHECK_STATUS(status, NT_STATUS_OK);
2788         h1a = io1.out.file.handle;
2789         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2790         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2791
2792         /*
2793          * a conflicting open is blocked until we ack the
2794          * lease break
2795          */
2796         smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE);
2797         req2 = smb2_create_send(tree, &io2);
2798         torture_assert(tctx, req2 != NULL, "smb2_create_send");
2799
2800         /*
2801          * we got the lease break, but defer the ack.
2802          */
2803         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2804
2805         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2806
2807         ack.in.lease.lease_key =
2808                 lease_break_info.lease_break.current_lease.lease_key;
2809         ZERO_STRUCT(lease_break_info);
2810
2811         /*
2812          * a open using the same lease key is still works,
2813          * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS
2814          */
2815         status = smb2_create(tree, mem_ctx, &io1);
2816         CHECK_STATUS(status, NT_STATUS_OK);
2817         h1b = io1.out.file.handle;
2818         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2819         CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS);
2820         smb2_util_close(tree, h1b);
2821
2822         CHECK_NO_BREAK(tctx);
2823
2824         torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending");
2825
2826         /*
2827          * We are asked to break to "RH", but we are allowed to
2828          * break to any of "RH", "R" or NONE.
2829          */
2830         ack.in.lease.lease_state = SMB2_LEASE_NONE;
2831         status = smb2_lease_break_ack(tree, &ack);
2832         CHECK_STATUS(status, NT_STATUS_OK);
2833         CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1);
2834
2835         torture_assert(tctx, req2->cancel.can_cancel,
2836                        "req2 can_cancel");
2837
2838         status = smb2_create_recv(req2, tctx, &io2);
2839         CHECK_STATUS(status, NT_STATUS_OK);
2840         h2 = io2.out.file.handle;
2841         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2842         CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE);
2843
2844         CHECK_NO_BREAK(tctx);
2845 done:
2846         smb2_util_close(tree, h1a);
2847         smb2_util_close(tree, h1b);
2848         smb2_util_close(tree, h2);
2849         smb2_util_unlink(tree, fname);
2850         talloc_free(mem_ctx);
2851         return ret;
2852 }
2853
2854 static bool test_lease_lock1(struct torture_context *tctx,
2855                              struct smb2_tree *tree1a,
2856                              struct smb2_tree *tree2)
2857 {
2858         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2859         struct smb2_create io1 = {};
2860         struct smb2_create io2 = {};
2861         struct smb2_create io3 = {};
2862         struct smb2_lease ls1 = {};
2863         struct smb2_lease ls2 = {};
2864         struct smb2_lease ls3 = {};
2865         struct smb2_handle h1 = {};
2866         struct smb2_handle h2 = {};
2867         struct smb2_handle h3 = {};
2868         struct smb2_lock lck;
2869         struct smb2_lock_element el[1];
2870         const char *fname = "locktest.dat";
2871         bool ret = true;
2872         NTSTATUS status;
2873         uint32_t caps;
2874         struct smbcli_options options1;
2875         struct smb2_tree *tree1b = NULL;
2876
2877         options1 = tree1a->session->transport->options;
2878
2879         caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
2880         if (!(caps & SMB2_CAP_LEASING)) {
2881                 torture_skip(tctx, "leases are not supported");
2882         }
2883
2884         /* Set up handlers. */
2885         tree2->session->transport->lease.handler = torture_lease_handler;
2886         tree2->session->transport->lease.private_data = tree2;
2887         tree2->session->transport->oplock.handler = torture_oplock_handler;
2888         tree2->session->transport->oplock.private_data = tree2;
2889
2890         tree1a->session->transport->lease.handler = torture_lease_handler;
2891         tree1a->session->transport->lease.private_data = tree1a;
2892         tree1a->session->transport->oplock.handler = torture_oplock_handler;
2893         tree1a->session->transport->oplock.private_data = tree1a;
2894
2895         /* create a new connection (same client_guid) */
2896         if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
2897                 torture_warning(tctx, "couldn't reconnect, bailing\n");
2898                 ret = false;
2899                 goto done;
2900         }
2901
2902         tree1b->session->transport->lease.handler = torture_lease_handler;
2903         tree1b->session->transport->lease.private_data = tree1b;
2904         tree1b->session->transport->oplock.handler = torture_oplock_handler;
2905         tree1b->session->transport->oplock.private_data = tree1b;
2906
2907         smb2_util_unlink(tree1a, fname);
2908
2909         ZERO_STRUCT(lease_break_info);
2910         ZERO_STRUCT(lck);
2911
2912         /* Open a handle on tree1a. */
2913         smb2_lease_create_share(&io1, &ls1, false, fname,
2914                                 smb2_util_share_access("RWD"),
2915                                 LEASE1,
2916                                 smb2_util_lease_state("RWH"));
2917         status = smb2_create(tree1a, mem_ctx, &io1);
2918         CHECK_STATUS(status, NT_STATUS_OK);
2919         h1 = io1.out.file.handle;
2920         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
2921         CHECK_LEASE(&io1, "RWH", true, LEASE1, 0);
2922
2923         /* Open a second handle on tree1b. */
2924         smb2_lease_create_share(&io2, &ls2, false, fname,
2925                                 smb2_util_share_access("RWD"),
2926                                 LEASE2,
2927                                 smb2_util_lease_state("RWH"));
2928         status = smb2_create(tree1b, mem_ctx, &io2);
2929         CHECK_STATUS(status, NT_STATUS_OK);
2930         h2 = io2.out.file.handle;
2931         CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2932         CHECK_LEASE(&io2, "RH", true, LEASE2, 0);
2933         /* And LEASE1 got broken to RH. */
2934         CHECK_BREAK_INFO("RWH", "RH", LEASE1);
2935         ZERO_STRUCT(lease_break_info);
2936
2937         /* Now open a lease on a different client guid. */
2938         smb2_lease_create_share(&io3, &ls3, false, fname,
2939                                 smb2_util_share_access("RWD"),
2940                                 LEASE3,
2941                                 smb2_util_lease_state("RWH"));
2942         status = smb2_create(tree2, mem_ctx, &io3);
2943         CHECK_STATUS(status, NT_STATUS_OK);
2944         h3 = io3.out.file.handle;
2945         CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
2946         CHECK_LEASE(&io3, "RH", true, LEASE3, 0);
2947         /* Doesn't break. */
2948         CHECK_NO_BREAK(tctx);
2949
2950         lck.in.locks            = el;
2951         /*
2952          * Try and get get an exclusive byte
2953          * range lock on H1 (LEASE1).
2954          */
2955
2956         lck.in.lock_count       = 1;
2957         lck.in.lock_sequence    = 1;
2958         lck.in.file.handle      = h1;
2959         el[0].offset            = 0;
2960         el[0].length            = 1;
2961         el[0].reserved          = 0;
2962         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
2963         status = smb2_lock(tree1a, &lck);
2964         CHECK_STATUS(status, NT_STATUS_OK);
2965
2966         /* LEASE2 and LEASE3 should get broken to NONE. */
2967         torture_wait_for_lease_break(tctx);
2968         torture_wait_for_lease_break(tctx);
2969         torture_wait_for_lease_break(tctx);
2970         torture_wait_for_lease_break(tctx);
2971
2972         CHECK_VAL(lease_break_info.failures, 0);                      \
2973         CHECK_VAL(lease_break_info.count, 2);                         \
2974
2975         /* Get state of the H1 (LEASE1) */
2976         smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state(""));
2977         status = smb2_create(tree1a, mem_ctx, &io1);
2978         CHECK_STATUS(status, NT_STATUS_OK);
2979         /* Should still be RH. */
2980         CHECK_LEASE(&io1, "RH", true, LEASE1, 0);
2981         smb2_util_close(tree1a, io1.out.file.handle);
2982
2983         /* Get state of the H2 (LEASE2) */
2984         smb2_lease_create(&io2, &ls2, false, fname, LEASE2, smb2_util_lease_state(""));
2985         status = smb2_create(tree1b, mem_ctx, &io2);
2986         CHECK_STATUS(status, NT_STATUS_OK);
2987         CHECK_LEASE(&io2, "", true, LEASE2, 0);
2988         smb2_util_close(tree1b, io2.out.file.handle);
2989
2990         /* Get state of the H3 (LEASE3) */
2991         smb2_lease_create(&io3, &ls3, false, fname, LEASE3, smb2_util_lease_state(""));
2992         status = smb2_create(tree2, mem_ctx, &io3);
2993         CHECK_STATUS(status, NT_STATUS_OK);
2994         CHECK_LEASE(&io3, "", true, LEASE3, 0);
2995         smb2_util_close(tree2, io3.out.file.handle);
2996
2997         ZERO_STRUCT(lease_break_info);
2998
2999         /*
3000          * Try and get get an exclusive byte
3001          * range lock on H3 (LEASE3).
3002          */
3003         lck.in.lock_count       = 1;
3004         lck.in.lock_sequence    = 2;
3005         lck.in.file.handle      = h3;
3006         el[0].offset            = 100;
3007         el[0].length            = 1;
3008         el[0].reserved          = 0;
3009         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
3010         status = smb2_lock(tree2, &lck);
3011         CHECK_STATUS(status, NT_STATUS_OK);
3012         /* LEASE1 got broken to NONE. */
3013         CHECK_BREAK_INFO("RH", "", LEASE1);
3014         ZERO_STRUCT(lease_break_info);
3015
3016 done:
3017         smb2_util_close(tree1a, h1);
3018         smb2_util_close(tree1b, h2);
3019         smb2_util_close(tree2, h3);
3020
3021         smb2_util_unlink(tree1a, fname);
3022         talloc_free(mem_ctx);
3023         return ret;
3024 }
3025
3026 static bool test_lease_complex1(struct torture_context *tctx,
3027                                 struct smb2_tree *tree1a)
3028 {
3029         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3030         struct smb2_create io1;
3031         struct smb2_create io2;
3032         struct smb2_lease ls1;
3033         struct smb2_lease ls2;
3034         struct smb2_handle h = {{0}};
3035         struct smb2_handle h2 = {{0}};
3036         struct smb2_handle h3 = {{0}};
3037         struct smb2_write w;
3038         NTSTATUS status;
3039         const char *fname = "lease_complex1.dat";
3040         bool ret = true;
3041         uint32_t caps;
3042         struct smb2_tree *tree1b = NULL;
3043         struct smbcli_options options1;
3044
3045         options1 = tree1a->session->transport->options;
3046
3047         caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn);
3048         if (!(caps & SMB2_CAP_LEASING)) {
3049                 torture_skip(tctx, "leases are not supported");
3050         }
3051
3052         tree1a->session->transport->lease.handler = torture_lease_handler;
3053         tree1a->session->transport->lease.private_data = tree1a;
3054         tree1a->session->transport->oplock.handler = torture_oplock_handler;
3055         tree1a->session->transport->oplock.private_data = tree1a;
3056
3057         /* create a new connection (same client_guid) */
3058         if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) {
3059                 torture_warning(tctx, "couldn't reconnect, bailing\n");
3060                 ret = false;
3061                 goto done;
3062         }
3063
3064         tree1b->session->transport->lease.handler = torture_lease_handler;
3065         tree1b->session->transport->lease.private_data = tree1b;
3066         tree1b->session->transport->oplock.handler = torture_oplock_handler;
3067         tree1b->session->transport->oplock.private_data = tree1b;
3068
3069         smb2_util_unlink(tree1a, fname);
3070
3071         ZERO_STRUCT(lease_break_info);
3072
3073         /* Grab R lease over connection 1a */
3074         smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state("R"));
3075         status = smb2_create(tree1a, mem_ctx, &io1);
3076         CHECK_STATUS(status, NT_STATUS_OK);
3077         h = io1.out.file.handle;
3078         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
3079         CHECK_LEASE(&io1, "R", true, LEASE1, 0);
3080
3081         /* Upgrade to RWH over connection 1b */
3082         ls1.lease_state = smb2_util_lease_state("RWH");
3083         status = smb2_create(tree1b, mem_ctx, &io1);
3084         CHECK_STATUS(status, NT_STATUS_OK);
3085         h2 = io1.out.file.handle;
3086         CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
3087         CHECK_LEASE(&io1, "RHW", true, LEASE1, 0);
3088
3089         /* close over connection 1b */