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