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