LCOV - code coverage report
Current view: top level - source4/torture/smb2 - lease.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 2513 2855 88.0 %
Date: 2024-04-21 15:09:00 Functions: 43 43 100.0 %

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

Generated by: LCOV version 1.14