LCOV - code coverage report
Current view: top level - source4/torture/smb2 - lease.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 44 2645 1.7 %
Date: 2024-06-13 04:01:37 Functions: 1 43 2.3 %

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

Generated by: LCOV version 1.13