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