LCOV - code coverage report
Current view: top level - source4/torture/smb2 - replay.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 2343 2527 92.7 %
Date: 2021-08-25 13:27:56 Functions: 62 62 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    test suite for SMB2 replay
       5             : 
       6             :    Copyright (C) Anubhav Rakshit 2014
       7             :    Copyright (C) Stefan Metzmacher 2014
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.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 "../libcli/smb/smbXcli_base.h"
      29             : #include "lib/cmdline/cmdline.h"
      30             : #include "auth/credentials/credentials.h"
      31             : #include "libcli/security/security.h"
      32             : #include "libcli/resolve/resolve.h"
      33             : #include "lib/param/param.h"
      34             : #include "lib/events/events.h"
      35             : #include "oplock_break_handler.h"
      36             : #include "lease_break_handler.h"
      37             : 
      38             : #define CHECK_VAL(v, correct) do { \
      39             :         if ((v) != (correct)) { \
      40             :                 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
      41             :                                 __location__, #v, (int)v, (int)correct); \
      42             :                 ret = false; \
      43             :                 goto done; \
      44             :         }} while (0)
      45             : 
      46             : #define CHECK_STATUS(status, correct) do { \
      47             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      48             :                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
      49             :                        nt_errstr(status), nt_errstr(correct)); \
      50             :                 ret = false; \
      51             :                 goto done; \
      52             :         }} while (0)
      53             : 
      54             : #define CHECK_CREATED(__io, __created, __attribute)                     \
      55             :         do {                                                            \
      56             :                 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
      57             :                 CHECK_VAL((__io)->out.size, 0);                              \
      58             :                 CHECK_VAL((__io)->out.file_attr, (__attribute));     \
      59             :                 CHECK_VAL((__io)->out.reserved2, 0);                 \
      60             :         } while(0)
      61             : 
      62             : #define CHECK_HANDLE(__h1, __h2)                                        \
      63             :         do {                                                            \
      64             :                 CHECK_VAL((__h1)->data[0], (__h2)->data[0]);              \
      65             :                 CHECK_VAL((__h1)->data[1], (__h2)->data[1]);              \
      66             :         } while(0)
      67             : 
      68             : #define __IO_OUT_VAL(__io1, __io2, __m) \
      69             :         CHECK_VAL((__io1)->out.__m, (__io2)->out.__m)
      70             : 
      71             : #define CHECK_CREATE_OUT(__io1, __io2)                          \
      72             :         do {                                                    \
      73             :                 CHECK_HANDLE(&(__io1)->out.file.handle,          \
      74             :                              &(__io2)->out.file.handle); \
      75             :                 __IO_OUT_VAL(__io1, __io2, oplock_level);       \
      76             :                 __IO_OUT_VAL(__io1, __io2, create_action);      \
      77             :                 __IO_OUT_VAL(__io1, __io2, create_time);        \
      78             :                 __IO_OUT_VAL(__io1, __io2, access_time);        \
      79             :                 __IO_OUT_VAL(__io1, __io2, write_time);         \
      80             :                 __IO_OUT_VAL(__io1, __io2, change_time);        \
      81             :                 __IO_OUT_VAL(__io1, __io2, alloc_size);         \
      82             :                 __IO_OUT_VAL(__io1, __io2, size);               \
      83             :                 __IO_OUT_VAL(__io1, __io2, file_attr);          \
      84             :                 __IO_OUT_VAL(__io1, __io2, durable_open);       \
      85             :                 __IO_OUT_VAL(__io1, __io2, durable_open_v2);    \
      86             :                 __IO_OUT_VAL(__io1, __io2, persistent_open);    \
      87             :                 __IO_OUT_VAL(__io1, __io2, timeout);            \
      88             :                 __IO_OUT_VAL(__io1, __io2, blobs.num_blobs);    \
      89             :                 if ((__io1)->out.oplock_level == SMB2_OPLOCK_LEVEL_LEASE) { \
      90             :                         __IO_OUT_VAL(__io1, __io2, lease_response.lease_state);\
      91             :                         __IO_OUT_VAL(__io1, __io2, lease_response.lease_key.data[0]);\
      92             :                         __IO_OUT_VAL(__io1, __io2, lease_response.lease_key.data[1]);\
      93             :                 } \
      94             :         } while(0)
      95             : 
      96             : #define WAIT_FOR_ASYNC_RESPONSE(__tctx, __req) do { \
      97             :         torture_comment((__tctx), "Waiting for async response: %s\n", #__req); \
      98             :         while (!(__req)->cancel.can_cancel && (__req)->state <= SMB2_REQUEST_RECV) { \
      99             :                 if (tevent_loop_once((__tctx)->ev) != 0) { \
     100             :                         break; \
     101             :                 } \
     102             :         } \
     103             : } while(0)
     104             : 
     105             : #define BASEDIR "replaytestdir"
     106             : 
     107             : /**
     108             :  * Test what happens when SMB2_FLAGS_REPLAY_OPERATION is enabled for various
     109             :  * commands. We want to verify if the server returns an error code or not.
     110             :  */
     111           5 : static bool test_replay_commands(struct torture_context *tctx, struct smb2_tree *tree)
     112             : {
     113           5 :         bool ret = true;
     114             :         NTSTATUS status;
     115             :         struct smb2_handle h;
     116             :         uint8_t buf[200];
     117             :         struct smb2_read rd;
     118             :         union smb_setfileinfo sfinfo;
     119             :         union smb_fileinfo qfinfo;
     120             :         union smb_ioctl ioctl;
     121             :         struct smb2_lock lck;
     122             :         struct smb2_lock_element el[2];
     123             :         struct smb2_flush f;
     124           5 :         TALLOC_CTX *tmp_ctx = talloc_new(tree);
     125           5 :         const char *fname = BASEDIR "\\replay_commands.dat";
     126           5 :         struct smb2_transport *transport = tree->session->transport;
     127             : 
     128           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
     129           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
     130             :                                    "Replay tests\n");
     131             :         }
     132             : 
     133           4 :         torture_reset_break_info(tctx, &break_info);
     134           4 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
     135           4 :         tree->session->transport->oplock.private_data = tree;
     136             : 
     137           4 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
     138           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     139           4 :         smb2_util_close(tree, h);
     140             : 
     141           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
     142             : 
     143           4 :         torture_comment(tctx, "Try Commands with Replay Flags Enabled\n");
     144             : 
     145           4 :         torture_comment(tctx, "Trying create\n");
     146           4 :         status = torture_smb2_testfile(tree, fname, &h);
     147           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     148           4 :         CHECK_VAL(break_info.count, 0);
     149             :         /*
     150             :          * Wireshark shows that the response has SMB2_FLAGS_REPLAY_OPERATION
     151             :          * flags set. The server should ignore this flag.
     152             :          */
     153             : 
     154           4 :         torture_comment(tctx, "Trying write\n");
     155           4 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
     156           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     157             : 
     158           4 :         f = (struct smb2_flush) {
     159             :                 .in.file.handle = h
     160             :         };
     161           4 :         torture_comment(tctx, "Trying flush\n");
     162           4 :         status = smb2_flush(tree, &f);
     163           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     164             : 
     165           4 :         rd = (struct smb2_read) {
     166             :                 .in.file.handle = h,
     167             :                 .in.length = 10,
     168             :                 .in.offset = 0,
     169             :                 .in.min_count = 1
     170             :         };
     171           4 :         torture_comment(tctx, "Trying read\n");
     172           4 :         status = smb2_read(tree, tmp_ctx, &rd);
     173           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     174           4 :         CHECK_VAL(rd.out.data.length, 10);
     175             : 
     176           4 :         sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
     177           4 :         sfinfo.position_information.in.file.handle = h;
     178           4 :         sfinfo.position_information.in.position = 0x1000;
     179           4 :         torture_comment(tctx, "Trying setinfo\n");
     180           4 :         status = smb2_setinfo_file(tree, &sfinfo);
     181           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     182             : 
     183           4 :         qfinfo = (union smb_fileinfo) {
     184             :                 .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
     185             :                 .generic.in.file.handle = h
     186             :         };
     187           4 :         torture_comment(tctx, "Trying getinfo\n");
     188           4 :         status = smb2_getinfo_file(tree, tmp_ctx, &qfinfo);
     189           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     190           4 :         CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
     191             : 
     192           4 :         ioctl = (union smb_ioctl) {
     193             :                 .smb2.level = RAW_IOCTL_SMB2,
     194             :                 .smb2.in.file.handle = h,
     195             :                 .smb2.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID,
     196             :                 .smb2.in.max_output_response = 64,
     197             :                 .smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL
     198             :         };
     199           4 :         torture_comment(tctx, "Trying ioctl\n");
     200           4 :         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
     201           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     202             : 
     203           4 :         lck = (struct smb2_lock) {
     204             :                 .in.locks = el,
     205             :                 .in.lock_count = 0x0001,
     206             :                 .in.lock_sequence = 0x00000000,
     207             :                 .in.file.handle = h
     208             :         };
     209           4 :         el[0].reserved          = 0x00000000;
     210           4 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     211             :                 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     212             : 
     213           4 :         torture_comment(tctx, "Trying lock\n");
     214           4 :         el[0].offset            = 0x0000000000000000;
     215           4 :         el[0].length            = 0x0000000000000100;
     216           4 :         status = smb2_lock(tree, &lck);
     217           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     218             : 
     219           4 :         lck.in.file.handle      = h;
     220           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     221           4 :         status = smb2_lock(tree, &lck);
     222           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     223             : 
     224           4 :         CHECK_VAL(break_info.count, 0);
     225           8 : done:
     226           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     227           4 :         smb2_util_close(tree, h);
     228           4 :         smb2_deltree(tree, BASEDIR);
     229             : 
     230           4 :         talloc_free(tmp_ctx);
     231             : 
     232           4 :         return ret;
     233             : }
     234             : 
     235             : /**
     236             :  * Test replay detection without create GUID on single channel.
     237             :  * Regular creates can not be replayed.
     238             :  * The return code is unaffected of the REPLAY_OPERATION flag.
     239             :  */
     240           5 : static bool test_replay_regular(struct torture_context *tctx,
     241             :                                 struct smb2_tree *tree)
     242             : {
     243             :         NTSTATUS status;
     244           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
     245             :         struct smb2_handle _h;
     246           5 :         struct smb2_handle *h = NULL;
     247             :         struct smb2_create io;
     248           5 :         uint32_t perms = 0;
     249           5 :         bool ret = true;
     250           5 :         const char *fname = BASEDIR "\\replay_regular.dat";
     251           5 :         struct smb2_transport *transport = tree->session->transport;
     252             : 
     253           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
     254           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
     255             :                                    "replay tests\n");
     256             :         }
     257             : 
     258           4 :         torture_reset_break_info(tctx, &break_info);
     259           4 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
     260           4 :         tree->session->transport->oplock.private_data = tree;
     261             : 
     262           4 :         smb2_util_unlink(tree, fname);
     263           4 :         status = torture_smb2_testdir(tree, BASEDIR, &_h);
     264           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     265           4 :         smb2_util_close(tree, _h);
     266           4 :         CHECK_VAL(break_info.count, 0);
     267             : 
     268           4 :         torture_comment(tctx, "No replay detection for regular create\n");
     269             : 
     270           4 :         perms = SEC_STD_SYNCHRONIZE | SEC_STD_READ_CONTROL | SEC_STD_DELETE |
     271             :                 SEC_DIR_WRITE_ATTRIBUTE | SEC_DIR_READ_ATTRIBUTE |
     272             :                 SEC_DIR_WRITE_EA | SEC_FILE_APPEND_DATA |
     273             :                 SEC_FILE_WRITE_DATA;
     274             : 
     275           4 :         io = (struct smb2_create) {
     276             :                 .in.desired_access  = perms,
     277             :                 .in.file_attributes = 0,
     278             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
     279             :                 .in.share_access    = NTCREATEX_SHARE_ACCESS_DELETE,
     280             :                 .in.create_options  = 0x0,
     281             :                 .in.fname   = fname
     282             :         };
     283             : 
     284           4 :         status = smb2_create(tree, tctx, &io);
     285           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     286           4 :         CHECK_VAL(break_info.count, 0);
     287           4 :         _h = io.out.file.handle;
     288           4 :         h = &_h;
     289           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
     290             : 
     291           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
     292           4 :         status = smb2_create(tree, tctx, &io);
     293           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     294           4 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
     295           4 :         CHECK_VAL(break_info.count, 0);
     296             : 
     297           4 :         smb2_util_close(tree, *h);
     298           4 :         h = NULL;
     299           4 :         smb2_util_unlink(tree, fname);
     300             : 
     301             :         /*
     302             :          * Same experiment with different create disposition.
     303             :          */
     304           4 :         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     305           4 :         status = smb2_create(tree, tctx, &io);
     306           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     307           4 :         CHECK_VAL(break_info.count, 0);
     308           4 :         _h = io.out.file.handle;
     309           4 :         h = &_h;
     310           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
     311             : 
     312           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
     313           4 :         status = smb2_create(tree, tctx, &io);
     314           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     315           4 :         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
     316           4 :         CHECK_VAL(break_info.count, 0);
     317             : 
     318           4 :         smb2_util_close(tree, *h);
     319           4 :         h = NULL;
     320           4 :         smb2_util_unlink(tree, fname);
     321             : 
     322             :         /*
     323             :          * Now with more generous share mode.
     324             :          */
     325           4 :         io.in.share_access = smb2_util_share_access("RWD");
     326           4 :         status = smb2_create(tree, tctx, &io);
     327           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     328           4 :         CHECK_VAL(break_info.count, 0);
     329           4 :         _h = io.out.file.handle;
     330           4 :         h = &_h;
     331           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
     332             : 
     333           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
     334           4 :         status = smb2_create(tree, tctx, &io);
     335           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     336           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     337           4 :         CHECK_VAL(break_info.count, 0);
     338             : 
     339           8 : done:
     340           4 :         if (h != NULL) {
     341           4 :                 smb2_util_close(tree, *h);
     342             :         }
     343           4 :         smb2_deltree(tree, BASEDIR);
     344             : 
     345           4 :         talloc_free(tree);
     346           4 :         talloc_free(mem_ctx);
     347             : 
     348           4 :         return ret;
     349             : }
     350             : 
     351             : /**
     352             :  * Test Durability V2 Create Replay Detection on Single Channel.
     353             :  */
     354           5 : static bool test_replay_dhv2_oplock1(struct torture_context *tctx,
     355             :                                      struct smb2_tree *tree)
     356             : {
     357             :         NTSTATUS status;
     358           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
     359             :         struct smb2_handle _h;
     360           5 :         struct smb2_handle *h = NULL;
     361             :         struct smb2_create io, ref1;
     362           5 :         struct GUID create_guid = GUID_random();
     363           5 :         bool ret = true;
     364           5 :         const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat";
     365           5 :         struct smb2_transport *transport = tree->session->transport;
     366             :         uint32_t share_capabilities;
     367             :         bool share_is_so;
     368             : 
     369           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
     370           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
     371             :                                    "replay tests\n");
     372             :         }
     373             : 
     374           4 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
     375           4 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
     376             : 
     377           4 :         torture_reset_break_info(tctx, &break_info);
     378           4 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
     379           4 :         tree->session->transport->oplock.private_data = tree;
     380             : 
     381           4 :         torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
     382             :                               "Channel\n");
     383           4 :         smb2_util_unlink(tree, fname);
     384           4 :         status = torture_smb2_testdir(tree, BASEDIR, &_h);
     385           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     386           4 :         smb2_util_close(tree, _h);
     387           4 :         CHECK_VAL(break_info.count, 0);
     388             : 
     389           4 :         smb2_oplock_create_share(&io, fname,
     390             :                         smb2_util_share_access(""),
     391           4 :                         smb2_util_oplock_level("b"));
     392           4 :         io.in.durable_open = false;
     393           4 :         io.in.durable_open_v2 = true;
     394           4 :         io.in.persistent_open = false;
     395           4 :         io.in.create_guid = create_guid;
     396           4 :         io.in.timeout = UINT32_MAX;
     397             : 
     398           4 :         status = smb2_create(tree, mem_ctx, &io);
     399           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     400           4 :         ref1 = io;
     401           4 :         _h = io.out.file.handle;
     402           4 :         h = &_h;
     403           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
     404           4 :         CHECK_VAL(io.out.durable_open, false);
     405           4 :         if (share_is_so) {
     406           0 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
     407           0 :                 CHECK_VAL(io.out.durable_open_v2, false);
     408           0 :                 CHECK_VAL(io.out.timeout, 0);
     409             :         } else {
     410           4 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
     411           4 :                 CHECK_VAL(io.out.durable_open_v2, true);
     412           4 :                 CHECK_VAL(io.out.timeout, 300*1000);
     413             :         }
     414             : 
     415             :         /*
     416             :          * Replay Durable V2 Create on single channel
     417             :          */
     418           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
     419           4 :         status = smb2_create(tree, mem_ctx, &io);
     420           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     421           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     422           4 :         CHECK_CREATE_OUT(&io, &ref1);
     423           4 :         CHECK_VAL(break_info.count, 0);
     424             : 
     425           8 : done:
     426           4 :         if (h != NULL) {
     427           4 :                 smb2_util_close(tree, *h);
     428             :         }
     429           4 :         smb2_deltree(tree, BASEDIR);
     430             : 
     431           4 :         talloc_free(tree);
     432           4 :         talloc_free(mem_ctx);
     433             : 
     434           4 :         return ret;
     435             : }
     436             : 
     437             : /**
     438             :  * Test Durability V2 Create Replay Detection on Single Channel.
     439             :  * Hand in a different oplock level in the replay.
     440             :  * Server responds with the handed in oplock level and
     441             :  * corresponding durable status, but does not change the
     442             :  * oplock level or durable status of the opened file.
     443             :  */
     444           5 : static bool test_replay_dhv2_oplock2(struct torture_context *tctx,
     445             :                                       struct smb2_tree *tree)
     446             : {
     447             :         NTSTATUS status;
     448           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
     449             :         struct smb2_handle _h;
     450           5 :         struct smb2_handle *h = NULL;
     451             :         struct smb2_create io, ref1, ref2;
     452           5 :         struct GUID create_guid = GUID_random();
     453           5 :         bool ret = true;
     454           5 :         const char *fname = BASEDIR "\\replay_dhv2_oplock2.dat";
     455           5 :         struct smb2_transport *transport = tree->session->transport;
     456             :         uint32_t share_capabilities;
     457             :         bool share_is_so;
     458             : 
     459           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
     460           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
     461             :                                    "replay tests\n");
     462             :         }
     463             : 
     464           4 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
     465           4 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
     466             : 
     467           4 :         torture_reset_break_info(tctx, &break_info);
     468           4 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
     469           4 :         tree->session->transport->oplock.private_data = tree;
     470             : 
     471           4 :         torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
     472             :                               "Channel\n");
     473           4 :         smb2_util_unlink(tree, fname);
     474           4 :         status = torture_smb2_testdir(tree, BASEDIR, &_h);
     475           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     476           4 :         smb2_util_close(tree, _h);
     477           4 :         CHECK_VAL(break_info.count, 0);
     478             : 
     479           4 :         smb2_oplock_create_share(&io, fname,
     480             :                         smb2_util_share_access(""),
     481           4 :                         smb2_util_oplock_level("b"));
     482           4 :         io.in.durable_open = false;
     483           4 :         io.in.durable_open_v2 = true;
     484           4 :         io.in.persistent_open = false;
     485           4 :         io.in.create_guid = create_guid;
     486           4 :         io.in.timeout = UINT32_MAX;
     487             : 
     488           4 :         status = smb2_create(tree, mem_ctx, &io);
     489           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     490           4 :         ref1 = io;
     491           4 :         _h = io.out.file.handle;
     492           4 :         h = &_h;
     493           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
     494           4 :         CHECK_VAL(io.out.durable_open, false);
     495           4 :         if (share_is_so) {
     496           0 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
     497           0 :                 CHECK_VAL(io.out.durable_open_v2, false);
     498           0 :                 CHECK_VAL(io.out.timeout, 0);
     499             :         } else {
     500           4 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
     501           4 :                 CHECK_VAL(io.out.durable_open_v2, true);
     502           4 :                 CHECK_VAL(io.out.timeout, 300*1000);
     503             :         }
     504             : 
     505             :         /*
     506             :          * Replay durable v2 create on single channel:
     507             :          *
     508             :          * Replay the create with a different oplock (none).
     509             :          * The server replies with the requested oplock level
     510             :          * and also only replies with durable handle based
     511             :          * on whether it could have been granted based on
     512             :          * the requested oplock type.
     513             :          */
     514           4 :         smb2_oplock_create_share(&io, fname,
     515             :                         smb2_util_share_access(""),
     516           4 :                         smb2_util_oplock_level(""));
     517           4 :         io.in.durable_open = false;
     518           4 :         io.in.durable_open_v2 = true;
     519           4 :         io.in.persistent_open = false;
     520           4 :         io.in.create_guid = create_guid;
     521           4 :         io.in.timeout = UINT32_MAX;
     522             : 
     523             :         /*
     524             :          * Adapt the response to the exepected values
     525             :          */
     526           4 :         ref2 = ref1;
     527           4 :         ref2.out.oplock_level = smb2_util_oplock_level("");
     528           4 :         ref2.out.durable_open_v2 = false;
     529           4 :         ref2.out.timeout = 0;
     530           4 :         ref2.out.blobs.num_blobs = 0;
     531             : 
     532           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
     533           4 :         status = smb2_create(tree, mem_ctx, &io);
     534           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     535           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     536           4 :         CHECK_CREATE_OUT(&io, &ref2);
     537           4 :         CHECK_VAL(break_info.count, 0);
     538             : 
     539             :         /*
     540             :          * Prove that the open file still has a batch oplock
     541             :          * by breaking it with another open.
     542             :          */
     543           4 :         smb2_oplock_create_share(&io, fname,
     544             :                         smb2_util_share_access(""),
     545           4 :                         smb2_util_oplock_level("b"));
     546           4 :         io.in.durable_open = false;
     547           4 :         io.in.durable_open_v2 = true;
     548           4 :         io.in.persistent_open = false;
     549           4 :         io.in.create_guid = GUID_random();
     550           4 :         io.in.timeout = UINT32_MAX;
     551           4 :         status = smb2_create(tree, mem_ctx, &io);
     552           4 :         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
     553             : 
     554           4 :         if (!share_is_so) {
     555           4 :                 CHECK_VAL(break_info.count, 1);
     556           4 :                 CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle);
     557           4 :                 CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
     558           4 :                 torture_reset_break_info(tctx, &break_info);
     559             :         }
     560             : 
     561           4 : done:
     562           4 :         if (h != NULL) {
     563           4 :                 smb2_util_close(tree, *h);
     564             :         }
     565           4 :         smb2_deltree(tree, BASEDIR);
     566             : 
     567           4 :         talloc_free(tree);
     568           4 :         talloc_free(mem_ctx);
     569             : 
     570           4 :         return ret;
     571             : }
     572             : 
     573             : /**
     574             :  * Test Durability V2 Create Replay Detection on Single Channel.
     575             :  * Replay with a different share mode. The share mode of
     576             :  * the opened file is not changed by this.
     577             :  */
     578           5 : static bool test_replay_dhv2_oplock3(struct torture_context *tctx,
     579             :                                      struct smb2_tree *tree)
     580             : {
     581             :         NTSTATUS status;
     582           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
     583             :         struct smb2_handle _h;
     584           5 :         struct smb2_handle *h = NULL;
     585             :         struct smb2_create io, ref1;
     586           5 :         struct GUID create_guid = GUID_random();
     587           5 :         bool ret = true;
     588           5 :         const char *fname = BASEDIR "\\replay_dhv2_oplock3.dat";
     589           5 :         struct smb2_transport *transport = tree->session->transport;
     590             :         uint32_t share_capabilities;
     591             :         bool share_is_so;
     592             : 
     593           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
     594           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
     595             :                                    "replay tests\n");
     596             :         }
     597             : 
     598           4 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
     599           4 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
     600             : 
     601           4 :         torture_reset_break_info(tctx, &break_info);
     602           4 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
     603           4 :         tree->session->transport->oplock.private_data = tree;
     604             : 
     605           4 :         torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
     606             :                               "Channel\n");
     607           4 :         smb2_util_unlink(tree, fname);
     608           4 :         status = torture_smb2_testdir(tree, BASEDIR, &_h);
     609           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     610           4 :         smb2_util_close(tree, _h);
     611           4 :         CHECK_VAL(break_info.count, 0);
     612             : 
     613           4 :         smb2_oplock_create_share(&io, fname,
     614             :                         smb2_util_share_access(""),
     615           4 :                         smb2_util_oplock_level("b"));
     616           4 :         io.in.durable_open = false;
     617           4 :         io.in.durable_open_v2 = true;
     618           4 :         io.in.persistent_open = false;
     619           4 :         io.in.create_guid = create_guid;
     620           4 :         io.in.timeout = UINT32_MAX;
     621             : 
     622           4 :         status = smb2_create(tree, mem_ctx, &io);
     623           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     624           4 :         ref1 = io;
     625           4 :         _h = io.out.file.handle;
     626           4 :         h = &_h;
     627           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
     628           4 :         CHECK_VAL(io.out.durable_open, false);
     629           4 :         if (share_is_so) {
     630           0 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
     631           0 :                 CHECK_VAL(io.out.durable_open_v2, false);
     632           0 :                 CHECK_VAL(io.out.timeout, 0);
     633             :         } else {
     634           4 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
     635           4 :                 CHECK_VAL(io.out.durable_open_v2, true);
     636           4 :                 CHECK_VAL(io.out.timeout, 300*1000);
     637             :         }
     638             : 
     639             :         /*
     640             :          * Replay durable v2 create on single channel:
     641             :          *
     642             :          * Replay the create with a different share mode.
     643             :          * The server replies with the requested share
     644             :          * mode instead of that which is associated to
     645             :          * the handle.
     646             :          */
     647           4 :         smb2_oplock_create_share(&io, fname,
     648             :                         smb2_util_share_access("RWD"),
     649           4 :                         smb2_util_oplock_level("b"));
     650           4 :         io.in.durable_open = false;
     651           4 :         io.in.durable_open_v2 = true;
     652           4 :         io.in.persistent_open = false;
     653           4 :         io.in.create_guid = create_guid;
     654           4 :         io.in.timeout = UINT32_MAX;
     655             : 
     656           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
     657           4 :         status = smb2_create(tree, mem_ctx, &io);
     658           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     659           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     660           4 :         CHECK_CREATE_OUT(&io, &ref1);
     661           4 :         CHECK_VAL(break_info.count, 0);
     662             : 
     663             :         /*
     664             :          * In order to prove that the different share mode in the
     665             :          * replayed create had no effect on the open file handle,
     666             :          * show that a new create yields NT_STATUS_SHARING_VIOLATION.
     667             :          */
     668           4 :         smb2_oplock_create_share(&io, fname,
     669             :                         smb2_util_share_access(""),
     670           4 :                         smb2_util_oplock_level("b"));
     671           4 :         io.in.durable_open = false;
     672           4 :         io.in.durable_open_v2 = true;
     673           4 :         io.in.persistent_open = false;
     674           4 :         io.in.create_guid = GUID_random();
     675           4 :         io.in.timeout = UINT32_MAX;
     676           4 :         status = smb2_create(tree, mem_ctx, &io);
     677           4 :         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
     678             : 
     679           4 :         if (!share_is_so) {
     680           4 :                 CHECK_VAL(break_info.count, 1);
     681           4 :                 CHECK_HANDLE(&break_info.handle, &ref1.out.file.handle);
     682           4 :                 CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
     683           4 :                 torture_reset_break_info(tctx, &break_info);
     684             :         }
     685             : 
     686           4 : done:
     687           4 :         if (h != NULL) {
     688           4 :                 smb2_util_close(tree, *h);
     689             :         }
     690           4 :         smb2_deltree(tree, BASEDIR);
     691             : 
     692           4 :         talloc_free(tree);
     693           4 :         talloc_free(mem_ctx);
     694             : 
     695           4 :         return ret;
     696             : }
     697             : 
     698             : /**
     699             :  * Test Durability V2 Create Replay Detection on Single Channel.
     700             :  * Create with an oplock, and replay with a lease.
     701             :  */
     702           5 : static bool test_replay_dhv2_oplock_lease(struct torture_context *tctx,
     703             :                                           struct smb2_tree *tree)
     704             : {
     705             :         NTSTATUS status;
     706           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
     707             :         struct smb2_handle _h;
     708           5 :         struct smb2_handle *h = NULL;
     709             :         struct smb2_create io;
     710           5 :         struct GUID create_guid = GUID_random();
     711           5 :         bool ret = true;
     712           5 :         const char *fname = BASEDIR "\\replay_dhv2_oplock1.dat";
     713           5 :         struct smb2_transport *transport = tree->session->transport;
     714             :         uint32_t share_capabilities;
     715             :         bool share_is_so;
     716             :         uint32_t server_capabilities;
     717             :         struct smb2_lease ls;
     718             :         uint64_t lease_key;
     719             : 
     720           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
     721           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
     722             :                                    "replay tests\n");
     723             :         }
     724             : 
     725           4 :         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
     726           4 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
     727           2 :                 torture_skip(tctx, "leases are not supported");
     728             :         }
     729             : 
     730           2 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
     731           2 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
     732             : 
     733           2 :         torture_reset_break_info(tctx, &break_info);
     734           2 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
     735           2 :         tree->session->transport->oplock.private_data = tree;
     736             : 
     737           2 :         torture_comment(tctx, "Replay of DurableHandleReqV2 on Single "
     738             :                               "Channel\n");
     739           2 :         smb2_util_unlink(tree, fname);
     740           2 :         status = torture_smb2_testdir(tree, BASEDIR, &_h);
     741           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     742           2 :         smb2_util_close(tree, _h);
     743           2 :         CHECK_VAL(break_info.count, 0);
     744             : 
     745           2 :         smb2_oplock_create_share(&io, fname,
     746             :                         smb2_util_share_access(""),
     747           2 :                         smb2_util_oplock_level("b"));
     748           2 :         io.in.durable_open = false;
     749           2 :         io.in.durable_open_v2 = true;
     750           2 :         io.in.persistent_open = false;
     751           2 :         io.in.create_guid = create_guid;
     752           2 :         io.in.timeout = UINT32_MAX;
     753             : 
     754           2 :         status = smb2_create(tree, mem_ctx, &io);
     755           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     756           2 :         _h = io.out.file.handle;
     757           2 :         h = &_h;
     758           2 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
     759           2 :         CHECK_VAL(io.out.durable_open, false);
     760           2 :         if (share_is_so) {
     761           0 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
     762           0 :                 CHECK_VAL(io.out.durable_open_v2, false);
     763           0 :                 CHECK_VAL(io.out.timeout, 0);
     764             :         } else {
     765           2 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
     766           2 :                 CHECK_VAL(io.out.durable_open_v2, true);
     767           2 :                 CHECK_VAL(io.out.timeout, 300*1000);
     768             :         }
     769             : 
     770             :         /*
     771             :          * Replay Durable V2 Create on single channel
     772             :          * but replay it with a lease instead of an oplock.
     773             :          */
     774           2 :         lease_key = random();
     775           2 :         smb2_lease_create(&io, &ls, false /* dir */, fname,
     776             :                         lease_key, smb2_util_lease_state("RH"));
     777           2 :         io.in.durable_open = false;
     778           2 :         io.in.durable_open_v2 = true;
     779           2 :         io.in.persistent_open = false;
     780           2 :         io.in.create_guid = create_guid;
     781           2 :         io.in.timeout = UINT32_MAX;
     782             : 
     783           2 :         smb2cli_session_start_replay(tree->session->smbXcli);
     784           2 :         status = smb2_create(tree, mem_ctx, &io);
     785           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     786           2 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
     787             : 
     788           4 : done:
     789           2 :         if (h != NULL) {
     790           2 :                 smb2_util_close(tree, *h);
     791             :         }
     792           2 :         smb2_deltree(tree, BASEDIR);
     793             : 
     794           2 :         talloc_free(tree);
     795           2 :         talloc_free(mem_ctx);
     796             : 
     797           2 :         return ret;
     798             : }
     799             : 
     800             : 
     801             : /**
     802             :  * Test durability v2 create replay detection on single channel.
     803             :  * Variant with leases instead of oplocks:
     804             :  * - open a file with a rh lease
     805             :  * - upgrade to a rwh lease with a second create
     806             :  * - replay the first create.
     807             :  *   ==> it gets back the upgraded lease level
     808             :  */
     809           5 : static bool test_replay_dhv2_lease1(struct torture_context *tctx,
     810             :                                     struct smb2_tree *tree)
     811             : {
     812             :         NTSTATUS status;
     813           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
     814             :         struct smb2_handle _h1;
     815           5 :         struct smb2_handle *h1 = NULL;
     816             :         struct smb2_handle _h2;
     817           5 :         struct smb2_handle *h2 = NULL;
     818             :         struct smb2_create io1, io2, ref1;
     819           5 :         struct GUID create_guid = GUID_random();
     820           5 :         bool ret = true;
     821           5 :         const char *fname = BASEDIR "\\replay2_lease1.dat";
     822           5 :         struct smb2_transport *transport = tree->session->transport;
     823             :         uint32_t share_capabilities;
     824             :         bool share_is_so;
     825             :         uint32_t server_capabilities;
     826             :         struct smb2_lease ls1, ls2;
     827             :         uint64_t lease_key;
     828             : 
     829           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
     830           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
     831             :                                    "replay tests\n");
     832             :         }
     833             : 
     834           4 :         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
     835           4 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
     836           2 :                 torture_skip(tctx, "leases are not supported");
     837             :         }
     838             : 
     839           2 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
     840           2 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
     841             : 
     842           2 :         torture_reset_break_info(tctx, &break_info);
     843           2 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
     844           2 :         tree->session->transport->oplock.private_data = tree;
     845             : 
     846           2 :         torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
     847             :                               "on Single Channel\n");
     848           2 :         smb2_util_unlink(tree, fname);
     849           2 :         status = torture_smb2_testdir(tree, BASEDIR, &_h1);
     850           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     851           2 :         smb2_util_close(tree, _h1);
     852           2 :         CHECK_VAL(break_info.count, 0);
     853             : 
     854           2 :         lease_key = random();
     855             : 
     856           2 :         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
     857             :                         lease_key, smb2_util_lease_state("RH"));
     858           2 :         io1.in.durable_open = false;
     859           2 :         io1.in.durable_open_v2 = true;
     860           2 :         io1.in.persistent_open = false;
     861           2 :         io1.in.create_guid = create_guid;
     862           2 :         io1.in.timeout = UINT32_MAX;
     863             : 
     864           2 :         status = smb2_create(tree, mem_ctx, &io1);
     865           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     866           2 :         ref1 = io1;
     867           2 :         _h1 = io1.out.file.handle;
     868           2 :         h1 = &_h1;
     869           2 :         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
     870           2 :         CHECK_VAL(io1.out.durable_open, false);
     871           2 :         CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
     872           2 :         CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
     873           2 :         CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
     874           2 :         if (share_is_so) {
     875           0 :                 CHECK_VAL(io1.out.lease_response.lease_state,
     876             :                           smb2_util_lease_state("R"));
     877           0 :                 CHECK_VAL(io1.out.durable_open_v2, false);
     878           0 :                 CHECK_VAL(io1.out.timeout, 0);
     879             :         } else {
     880           2 :                 CHECK_VAL(io1.out.lease_response.lease_state,
     881             :                           smb2_util_lease_state("RH"));
     882           2 :                 CHECK_VAL(io1.out.durable_open_v2, true);
     883           2 :                 CHECK_VAL(io1.out.timeout, 300*1000);
     884             :         }
     885             : 
     886             :         /*
     887             :          * Upgrade the lease to RWH
     888             :          */
     889           2 :         smb2_lease_create(&io2, &ls2, false /* dir */, fname,
     890             :                         lease_key, smb2_util_lease_state("RHW"));
     891           2 :         io2.in.durable_open = false;
     892           2 :         io2.in.durable_open_v2 = true;
     893           2 :         io2.in.persistent_open = false;
     894           2 :         io2.in.create_guid = GUID_random(); /* new guid... */
     895           2 :         io2.in.timeout = UINT32_MAX;
     896             : 
     897           2 :         status = smb2_create(tree, mem_ctx, &io2);
     898           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     899           2 :         _h2 = io2.out.file.handle;
     900           2 :         h2 = &_h2;
     901             : 
     902             :         /*
     903             :          * Replay Durable V2 Create on single channel.
     904             :          * We get the io from open #1 but with the
     905             :          * upgraded lease.
     906             :          */
     907             : 
     908             :         /* adapt expected lease in response */
     909           2 :         if (!share_is_so) {
     910           2 :                 ref1.out.lease_response.lease_state =
     911           2 :                         smb2_util_lease_state("RHW");
     912             :         }
     913             : 
     914           2 :         smb2cli_session_start_replay(tree->session->smbXcli);
     915           2 :         status = smb2_create(tree, mem_ctx, &io1);
     916           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     917           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     918           2 :         CHECK_CREATE_OUT(&io1, &ref1);
     919           2 :         CHECK_VAL(break_info.count, 0);
     920             : 
     921           4 : done:
     922           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
     923             : 
     924           2 :         if (h1 != NULL) {
     925           2 :                 smb2_util_close(tree, *h1);
     926             :         }
     927           2 :         if (h2 != NULL) {
     928           2 :                 smb2_util_close(tree, *h2);
     929             :         }
     930           2 :         smb2_deltree(tree, BASEDIR);
     931             : 
     932           2 :         talloc_free(tree);
     933           2 :         talloc_free(mem_ctx);
     934             : 
     935           2 :         return ret;
     936             : }
     937             : 
     938             : /**
     939             :  * Test durability v2 create replay detection on single channel.
     940             :  * Variant with leases instead of oplocks, where the
     941             :  * replay does not specify the original lease level but
     942             :  * just a "R" lease. This still gives the upgraded lease
     943             :  * level in the reply.
     944             :  * - open a file with a rh lease
     945             :  * - upgrade to a rwh lease with a second create
     946             :  * - replay the first create.
     947             :  *   ==> it gets back the upgraded lease level
     948             :  */
     949           5 : static bool test_replay_dhv2_lease2(struct torture_context *tctx,
     950             :                                     struct smb2_tree *tree)
     951             : {
     952             :         NTSTATUS status;
     953           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
     954             :         struct smb2_handle _h1;
     955           5 :         struct smb2_handle *h1 = NULL;
     956             :         struct smb2_handle _h2;
     957           5 :         struct smb2_handle *h2 = NULL;
     958             :         struct smb2_create io1, io2, ref1;
     959           5 :         struct GUID create_guid = GUID_random();
     960           5 :         bool ret = true;
     961           5 :         const char *fname = BASEDIR "\\replay2_lease2.dat";
     962           5 :         struct smb2_transport *transport = tree->session->transport;
     963             :         uint32_t share_capabilities;
     964             :         bool share_is_so;
     965             :         uint32_t server_capabilities;
     966             :         struct smb2_lease ls1, ls2;
     967             :         uint64_t lease_key;
     968             : 
     969           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
     970           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
     971             :                                    "replay tests\n");
     972             :         }
     973             : 
     974           4 :         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
     975           4 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
     976           2 :                 torture_skip(tctx, "leases are not supported");
     977             :         }
     978             : 
     979           2 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
     980           2 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
     981             : 
     982           2 :         torture_reset_break_info(tctx, &break_info);
     983           2 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
     984           2 :         tree->session->transport->oplock.private_data = tree;
     985             : 
     986           2 :         torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
     987             :                               "on Single Channel\n");
     988           2 :         smb2_util_unlink(tree, fname);
     989           2 :         status = torture_smb2_testdir(tree, BASEDIR, &_h1);
     990           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     991           2 :         smb2_util_close(tree, _h1);
     992           2 :         CHECK_VAL(break_info.count, 0);
     993             : 
     994           2 :         lease_key = random();
     995             : 
     996           2 :         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
     997             :                         lease_key, smb2_util_lease_state("RH"));
     998           2 :         io1.in.durable_open = false;
     999           2 :         io1.in.durable_open_v2 = true;
    1000           2 :         io1.in.persistent_open = false;
    1001           2 :         io1.in.create_guid = create_guid;
    1002           2 :         io1.in.timeout = UINT32_MAX;
    1003             : 
    1004           2 :         status = smb2_create(tree, mem_ctx, &io1);
    1005           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1006           2 :         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    1007           2 :         CHECK_VAL(io1.out.durable_open, false);
    1008           2 :         CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
    1009           2 :         CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
    1010           2 :         CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
    1011           2 :         if (share_is_so) {
    1012           0 :                 CHECK_VAL(io1.out.lease_response.lease_state,
    1013             :                           smb2_util_lease_state("R"));
    1014           0 :                 CHECK_VAL(io1.out.durable_open_v2, false);
    1015           0 :                 CHECK_VAL(io1.out.timeout, 0);
    1016             :         } else {
    1017           2 :                 CHECK_VAL(io1.out.lease_response.lease_state,
    1018             :                           smb2_util_lease_state("RH"));
    1019           2 :                 CHECK_VAL(io1.out.durable_open_v2, true);
    1020           2 :                 CHECK_VAL(io1.out.timeout, 300*1000);
    1021             :         }
    1022           2 :         ref1 = io1;
    1023           2 :         _h1 = io1.out.file.handle;
    1024           2 :         h1 = &_h1;
    1025             : 
    1026             :         /*
    1027             :          * Upgrade the lease to RWH
    1028             :          */
    1029           2 :         smb2_lease_create(&io2, &ls2, false /* dir */, fname,
    1030             :                         lease_key, smb2_util_lease_state("RHW"));
    1031           2 :         io2.in.durable_open = false;
    1032           2 :         io2.in.durable_open_v2 = true;
    1033           2 :         io2.in.persistent_open = false;
    1034           2 :         io2.in.create_guid = GUID_random(); /* new guid... */
    1035           2 :         io2.in.timeout = UINT32_MAX;
    1036             : 
    1037           2 :         status = smb2_create(tree, mem_ctx, &io2);
    1038           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1039           2 :         _h2 = io2.out.file.handle;
    1040           2 :         h2 = &_h2;
    1041             : 
    1042             :         /*
    1043             :          * Replay Durable V2 Create on single channel.
    1044             :          * Changing the requested lease level to "R"
    1045             :          * does not change the response:
    1046             :          * We get the reply from open #1 but with the
    1047             :          * upgraded lease.
    1048             :          */
    1049             : 
    1050             :         /* adapt the expected response */
    1051           2 :         if (!share_is_so) {
    1052           2 :                 ref1.out.lease_response.lease_state =
    1053           2 :                                         smb2_util_lease_state("RHW");
    1054             :         }
    1055             : 
    1056           2 :         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
    1057             :                         lease_key, smb2_util_lease_state("R"));
    1058           2 :         io1.in.durable_open = false;
    1059           2 :         io1.in.durable_open_v2 = true;
    1060           2 :         io1.in.persistent_open = false;
    1061           2 :         io1.in.create_guid = create_guid;
    1062           2 :         io1.in.timeout = UINT32_MAX;
    1063             : 
    1064           2 :         smb2cli_session_start_replay(tree->session->smbXcli);
    1065           2 :         status = smb2_create(tree, mem_ctx, &io1);
    1066           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    1067           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1068           2 :         CHECK_CREATE_OUT(&io1, &ref1);
    1069           2 :         CHECK_VAL(break_info.count, 0);
    1070             : 
    1071           4 : done:
    1072           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    1073             : 
    1074           2 :         if (h1 != NULL) {
    1075           2 :                 smb2_util_close(tree, *h1);
    1076             :         }
    1077           2 :         if (h2 != NULL) {
    1078           2 :                 smb2_util_close(tree, *h2);
    1079             :         }
    1080           2 :         smb2_deltree(tree, BASEDIR);
    1081             : 
    1082           2 :         talloc_free(tree);
    1083           2 :         talloc_free(mem_ctx);
    1084             : 
    1085           2 :         return ret;
    1086             : }
    1087             : 
    1088             : /**
    1089             :  * Test durability v2 create replay detection on single channel.
    1090             :  * create with a lease, and replay with a different lease key
    1091             :  */
    1092           5 : static bool test_replay_dhv2_lease3(struct torture_context *tctx,
    1093             :                                     struct smb2_tree *tree)
    1094             : {
    1095             :         NTSTATUS status;
    1096           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    1097             :         struct smb2_handle _h1;
    1098           5 :         struct smb2_handle *h1 = NULL;
    1099             :         struct smb2_handle _h2;
    1100           5 :         struct smb2_handle *h2 = NULL;
    1101             :         struct smb2_create io1, io2;
    1102           5 :         struct GUID create_guid = GUID_random();
    1103           5 :         bool ret = true;
    1104           5 :         const char *fname = BASEDIR "\\replay2_lease2.dat";
    1105           5 :         struct smb2_transport *transport = tree->session->transport;
    1106             :         uint32_t share_capabilities;
    1107             :         bool share_is_so;
    1108             :         uint32_t server_capabilities;
    1109             :         struct smb2_lease ls1, ls2;
    1110             :         uint64_t lease_key;
    1111             : 
    1112           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
    1113           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    1114             :                                    "replay tests\n");
    1115             :         }
    1116             : 
    1117           4 :         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
    1118           4 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
    1119           2 :                 torture_skip(tctx, "leases are not supported");
    1120             :         }
    1121             : 
    1122           2 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
    1123           2 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    1124             : 
    1125           2 :         torture_reset_break_info(tctx, &break_info);
    1126           2 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
    1127           2 :         tree->session->transport->oplock.private_data = tree;
    1128             : 
    1129           2 :         torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
    1130             :                               "on Single Channel\n");
    1131           2 :         smb2_util_unlink(tree, fname);
    1132           2 :         status = torture_smb2_testdir(tree, BASEDIR, &_h1);
    1133           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1134           2 :         smb2_util_close(tree, _h1);
    1135           2 :         CHECK_VAL(break_info.count, 0);
    1136             : 
    1137           2 :         lease_key = random();
    1138             : 
    1139           2 :         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
    1140             :                         lease_key, smb2_util_lease_state("RH"));
    1141           2 :         io1.in.durable_open = false;
    1142           2 :         io1.in.durable_open_v2 = true;
    1143           2 :         io1.in.persistent_open = false;
    1144           2 :         io1.in.create_guid = create_guid;
    1145           2 :         io1.in.timeout = UINT32_MAX;
    1146             : 
    1147           2 :         status = smb2_create(tree, mem_ctx, &io1);
    1148           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1149           2 :         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    1150           2 :         CHECK_VAL(io1.out.durable_open, false);
    1151           2 :         CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
    1152           2 :         CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
    1153           2 :         CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
    1154           2 :         if (share_is_so) {
    1155           0 :                 CHECK_VAL(io1.out.lease_response.lease_state,
    1156             :                           smb2_util_lease_state("R"));
    1157           0 :                 CHECK_VAL(io1.out.durable_open_v2, false);
    1158           0 :                 CHECK_VAL(io1.out.timeout, 0);
    1159             :         } else {
    1160           2 :                 CHECK_VAL(io1.out.lease_response.lease_state,
    1161             :                           smb2_util_lease_state("RH"));
    1162           2 :                 CHECK_VAL(io1.out.durable_open_v2, true);
    1163           2 :                 CHECK_VAL(io1.out.timeout, 300*1000);
    1164             :         }
    1165           2 :         _h1 = io1.out.file.handle;
    1166           2 :         h1 = &_h1;
    1167             : 
    1168             :         /*
    1169             :          * Upgrade the lease to RWH
    1170             :          */
    1171           2 :         smb2_lease_create(&io2, &ls2, false /* dir */, fname,
    1172             :                         lease_key, smb2_util_lease_state("RHW"));
    1173           2 :         io2.in.durable_open = false;
    1174           2 :         io2.in.durable_open_v2 = true;
    1175           2 :         io2.in.persistent_open = false;
    1176           2 :         io2.in.create_guid = GUID_random(); /* new guid... */
    1177           2 :         io2.in.timeout = UINT32_MAX;
    1178             : 
    1179           2 :         status = smb2_create(tree, mem_ctx, &io2);
    1180           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1181           2 :         _h2 = io2.out.file.handle;
    1182           2 :         h2 = &_h2;
    1183             : 
    1184             :         /*
    1185             :          * Replay Durable V2 Create on single channel.
    1186             :          * use a different lease key.
    1187             :          */
    1188             : 
    1189           4 :         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
    1190           2 :                         random() /* lease key */,
    1191             :                         smb2_util_lease_state("RH"));
    1192           2 :         io1.in.durable_open = false;
    1193           2 :         io1.in.durable_open_v2 = true;
    1194           2 :         io1.in.persistent_open = false;
    1195           2 :         io1.in.create_guid = create_guid;
    1196           2 :         io1.in.timeout = UINT32_MAX;
    1197             : 
    1198           2 :         smb2cli_session_start_replay(tree->session->smbXcli);
    1199           2 :         status = smb2_create(tree, mem_ctx, &io1);
    1200           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    1201           2 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1202             : 
    1203           4 : done:
    1204           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    1205             : 
    1206           2 :         if (h1 != NULL) {
    1207           2 :                 smb2_util_close(tree, *h1);
    1208             :         }
    1209           2 :         if (h2 != NULL) {
    1210           2 :                 smb2_util_close(tree, *h2);
    1211             :         }
    1212           2 :         smb2_deltree(tree, BASEDIR);
    1213             : 
    1214           2 :         talloc_free(tree);
    1215           2 :         talloc_free(mem_ctx);
    1216             : 
    1217           2 :         return ret;
    1218             : }
    1219             : 
    1220             : /**
    1221             :  * Test durability v2 create replay detection on single channel.
    1222             :  * Do the original create with a lease, and do the replay
    1223             :  * with an oplock.
    1224             :  */
    1225           5 : static bool test_replay_dhv2_lease_oplock(struct torture_context *tctx,
    1226             :                                           struct smb2_tree *tree)
    1227             : {
    1228             :         NTSTATUS status;
    1229           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    1230             :         struct smb2_handle _h1;
    1231           5 :         struct smb2_handle *h1 = NULL;
    1232             :         struct smb2_handle _h2;
    1233           5 :         struct smb2_handle *h2 = NULL;
    1234             :         struct smb2_create io1, io2, ref1;
    1235           5 :         struct GUID create_guid = GUID_random();
    1236           5 :         bool ret = true;
    1237           5 :         const char *fname = BASEDIR "\\replay2_lease1.dat";
    1238           5 :         struct smb2_transport *transport = tree->session->transport;
    1239             :         uint32_t share_capabilities;
    1240             :         bool share_is_so;
    1241             :         uint32_t server_capabilities;
    1242             :         struct smb2_lease ls1, ls2;
    1243             :         uint64_t lease_key;
    1244             : 
    1245           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
    1246           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    1247             :                                    "replay tests\n");
    1248             :         }
    1249             : 
    1250           4 :         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
    1251           4 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
    1252           2 :                 torture_skip(tctx, "leases are not supported");
    1253             :         }
    1254             : 
    1255           2 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
    1256           2 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    1257             : 
    1258           2 :         torture_reset_break_info(tctx, &break_info);
    1259           2 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
    1260           2 :         tree->session->transport->oplock.private_data = tree;
    1261             : 
    1262           2 :         torture_comment(tctx, "Replay of DurableHandleReqV2 with Lease "
    1263             :                               "on Single Channel\n");
    1264           2 :         smb2_util_unlink(tree, fname);
    1265           2 :         status = torture_smb2_testdir(tree, BASEDIR, &_h1);
    1266           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1267           2 :         smb2_util_close(tree, _h1);
    1268           2 :         CHECK_VAL(break_info.count, 0);
    1269             : 
    1270           2 :         lease_key = random();
    1271             : 
    1272           2 :         smb2_lease_create(&io1, &ls1, false /* dir */, fname,
    1273             :                         lease_key, smb2_util_lease_state("RH"));
    1274           2 :         io1.in.durable_open = false;
    1275           2 :         io1.in.durable_open_v2 = true;
    1276           2 :         io1.in.persistent_open = false;
    1277           2 :         io1.in.create_guid = create_guid;
    1278           2 :         io1.in.timeout = UINT32_MAX;
    1279             : 
    1280           2 :         status = smb2_create(tree, mem_ctx, &io1);
    1281           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1282           2 :         ref1 = io1;
    1283           2 :         _h1 = io1.out.file.handle;
    1284           2 :         h1 = &_h1;
    1285           2 :         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    1286           2 :         CHECK_VAL(io1.out.durable_open, false);
    1287           2 :         CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
    1288           2 :         CHECK_VAL(io1.out.lease_response.lease_key.data[0], lease_key);
    1289           2 :         CHECK_VAL(io1.out.lease_response.lease_key.data[1], ~lease_key);
    1290           2 :         if (share_is_so) {
    1291           0 :                 CHECK_VAL(io1.out.lease_response.lease_state,
    1292             :                           smb2_util_lease_state("R"));
    1293           0 :                 CHECK_VAL(io1.out.durable_open_v2, false);
    1294           0 :                 CHECK_VAL(io1.out.timeout, 0);
    1295             :         } else {
    1296           2 :                 CHECK_VAL(io1.out.lease_response.lease_state,
    1297             :                           smb2_util_lease_state("RH"));
    1298           2 :                 CHECK_VAL(io1.out.durable_open_v2, true);
    1299           2 :                 CHECK_VAL(io1.out.timeout, 300*1000);
    1300             :         }
    1301             : 
    1302             :         /*
    1303             :          * Upgrade the lease to RWH
    1304             :          */
    1305           2 :         smb2_lease_create(&io2, &ls2, false /* dir */, fname,
    1306             :                         lease_key, smb2_util_lease_state("RHW"));
    1307           2 :         io2.in.durable_open = false;
    1308           2 :         io2.in.durable_open_v2 = true;
    1309           2 :         io2.in.persistent_open = false;
    1310           2 :         io2.in.create_guid = GUID_random(); /* new guid... */
    1311           2 :         io2.in.timeout = UINT32_MAX;
    1312             : 
    1313           2 :         status = smb2_create(tree, mem_ctx, &io2);
    1314           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1315           2 :         _h2 = io2.out.file.handle;
    1316           2 :         h2 = &_h2;
    1317             : 
    1318             :         /*
    1319             :          * Replay Durable V2 Create on single channel.
    1320             :          * We get the io from open #1 but with the
    1321             :          * upgraded lease.
    1322             :          */
    1323             : 
    1324           2 :         smb2_oplock_create_share(&io2, fname,
    1325             :                         smb2_util_share_access(""),
    1326           2 :                         smb2_util_oplock_level("b"));
    1327           2 :         io2.in.durable_open = false;
    1328           2 :         io2.in.durable_open_v2 = true;
    1329           2 :         io2.in.persistent_open = false;
    1330           2 :         io2.in.create_guid = create_guid;
    1331           2 :         io2.in.timeout = UINT32_MAX;
    1332             : 
    1333             :         /* adapt expected lease in response */
    1334           2 :         if (!share_is_so) {
    1335           2 :                 ref1.out.lease_response.lease_state =
    1336           2 :                         smb2_util_lease_state("RHW");
    1337             :         }
    1338             : 
    1339           2 :         smb2cli_session_start_replay(tree->session->smbXcli);
    1340           2 :         status = smb2_create(tree, mem_ctx, &io1);
    1341           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    1342           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1343           2 :         CHECK_CREATE_OUT(&io1, &ref1);
    1344           2 :         CHECK_VAL(break_info.count, 0);
    1345             : 
    1346           4 : done:
    1347           2 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    1348             : 
    1349           2 :         if (h1 != NULL) {
    1350           2 :                 smb2_util_close(tree, *h1);
    1351             :         }
    1352           2 :         if (h2 != NULL) {
    1353           2 :                 smb2_util_close(tree, *h2);
    1354             :         }
    1355           2 :         smb2_deltree(tree, BASEDIR);
    1356             : 
    1357           2 :         talloc_free(tree);
    1358           2 :         talloc_free(mem_ctx);
    1359             : 
    1360           2 :         return ret;
    1361             : }
    1362             : 
    1363             : /**
    1364             :  * This tests replay with a pending open on a single
    1365             :  * channel. It tests the case where the client2 open
    1366             :  * is deferred because it conflicts with a HANDLE lease,
    1367             :  * which is broken because the operation should otherwise
    1368             :  * return NT_STATUS_SHARING_VIOLATION.
    1369             :  *
    1370             :  * With a durablev2 request containing a create_guid:
    1371             :  * - client2_level = NONE:
    1372             :  *   but without asking for an oplock nor a lease.
    1373             :  * - client2_level = BATCH:
    1374             :  *   and asking for a batch oplock.
    1375             :  * - client2_level = LEASE
    1376             :  *   and asking for an RWH lease.
    1377             :  *
    1378             :  * While another client holds a batch oplock or
    1379             :  * RWH lease. (client1_level => LEASE or BATCH).
    1380             :  *
    1381             :  * There are two modes of this test one, with releaseing
    1382             :  * the oplock/lease of client1 via close or ack.
    1383             :  * (release_op SMB2_OP_CLOSE/SMB2_OP_BREAK).
    1384             :  *
    1385             :  * Windows doesn't detect replays in this case and
    1386             :  * always result in NT_STATUS_SHARING_VIOLATION.
    1387             :  *
    1388             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    1389             :  */
    1390          20 : static bool _test_dhv2_pending1_vs_violation(struct torture_context *tctx,
    1391             :                                              const char *testname,
    1392             :                                              struct smb2_tree *tree1,
    1393             :                                              uint8_t client1_level,
    1394             :                                              uint8_t release_op,
    1395             :                                              struct smb2_tree *tree2,
    1396             :                                              uint8_t client2_level,
    1397             :                                              NTSTATUS orig21_reject_status,
    1398             :                                              NTSTATUS replay22_reject_status,
    1399             :                                              NTSTATUS replay23_reject_status)
    1400             : {
    1401             :         NTSTATUS status;
    1402          20 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    1403             :         struct smb2_handle _h1;
    1404          20 :         struct smb2_handle *h1 = NULL;
    1405          20 :         struct smb2_handle *h2f = NULL;
    1406             :         struct smb2_handle _h21;
    1407          20 :         struct smb2_handle *h21 = NULL;
    1408             :         struct smb2_handle _h23;
    1409          20 :         struct smb2_handle *h23 = NULL;
    1410             :         struct smb2_handle _h24;
    1411          20 :         struct smb2_handle *h24 = NULL;
    1412             :         struct smb2_create io1, io21, io22, io23, io24;
    1413          20 :         struct GUID create_guid1 = GUID_random();
    1414          20 :         struct GUID create_guid2 = GUID_random();
    1415          20 :         struct smb2_request *req21 = NULL;
    1416          20 :         struct smb2_request *req22 = NULL;
    1417          20 :         bool ret = true;
    1418             :         char fname[256];
    1419          20 :         struct smb2_transport *transport1 = tree1->session->transport;
    1420             :         uint32_t server_capabilities;
    1421             :         uint32_t share_capabilities;
    1422             :         struct smb2_lease ls1;
    1423             :         uint64_t lease_key1;
    1424          20 :         uint16_t lease_epoch1 = 0;
    1425             :         struct smb2_break op_ack1;
    1426             :         struct smb2_lease_break_ack lb_ack1;
    1427             :         struct smb2_lease ls2;
    1428             :         uint64_t lease_key2;
    1429          20 :         uint16_t lease_epoch2 = 0;
    1430             :         bool share_is_so;
    1431          20 :         struct smb2_transport *transport2 = tree2->session->transport;
    1432          20 :         int request_timeout2 = transport2->options.request_timeout;
    1433          20 :         struct smb2_session *session2 = tree2->session;
    1434          20 :         const char *hold_name = NULL;
    1435             : 
    1436          20 :         switch (client1_level) {
    1437          20 :         case SMB2_OPLOCK_LEVEL_LEASE:
    1438          20 :                 hold_name = "RWH Lease";
    1439          20 :                 break;
    1440           0 :         case SMB2_OPLOCK_LEVEL_BATCH:
    1441           0 :                 hold_name = "BATCH Oplock";
    1442           0 :                 break;
    1443           0 :         default:
    1444           0 :                 smb_panic(__location__);
    1445             :                 break;
    1446             :         }
    1447             : 
    1448          20 :         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
    1449           4 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    1450             :                                    "replay tests\n");
    1451             :         }
    1452             : 
    1453          16 :         server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
    1454          16 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
    1455           8 :                 if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
    1456           0 :                     client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1457           8 :                         torture_skip(tctx, "leases are not supported");
    1458             :                 }
    1459             :         }
    1460             : 
    1461           8 :         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
    1462           8 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    1463           8 :         if (share_is_so) {
    1464           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
    1465             :                              "%s not supported on SCALEOUT share",
    1466             :                              hold_name));
    1467             :         }
    1468             : 
    1469             :         /* Add some random component to the file name. */
    1470           8 :         snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
    1471             :                  BASEDIR, testname, generate_random_str(tctx, 8));
    1472             : 
    1473           8 :         torture_reset_break_info(tctx, &break_info);
    1474           8 :         break_info.oplock_skip_ack = true;
    1475           8 :         ZERO_STRUCT(op_ack1);
    1476           8 :         torture_reset_lease_break_info(tctx, &lease_break_info);
    1477           8 :         lease_break_info.lease_skip_ack = true;
    1478           8 :         ZERO_STRUCT(lb_ack1);
    1479           8 :         transport1->oplock.handler = torture_oplock_ack_handler;
    1480           8 :         transport1->oplock.private_data = tree1;
    1481           8 :         transport1->lease.handler = torture_lease_handler;
    1482           8 :         transport1->lease.private_data = tree1;
    1483           8 :         smb2_keepalive(transport1);
    1484           8 :         transport2->oplock.handler = torture_oplock_ack_handler;
    1485           8 :         transport2->oplock.private_data = tree2;
    1486           8 :         transport2->lease.handler = torture_lease_handler;
    1487           8 :         transport2->lease.private_data = tree2;
    1488           8 :         smb2_keepalive(transport2);
    1489             : 
    1490           8 :         smb2_util_unlink(tree1, fname);
    1491           8 :         status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
    1492           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    1493           8 :         smb2_util_close(tree1, _h1);
    1494           8 :         CHECK_VAL(break_info.count, 0);
    1495             : 
    1496           8 :         lease_key1 = random();
    1497           8 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1498           8 :                 smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
    1499           8 :                         lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
    1500             :         } else {
    1501           0 :                 smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
    1502             :         }
    1503           8 :         io1.in.share_access = 0;
    1504           8 :         io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1505           8 :         io1.in.durable_open = false;
    1506           8 :         io1.in.durable_open_v2 = true;
    1507           8 :         io1.in.persistent_open = false;
    1508           8 :         io1.in.create_guid = create_guid1;
    1509           8 :         io1.in.timeout = UINT32_MAX;
    1510             : 
    1511           8 :         status = smb2_create(tree1, mem_ctx, &io1);
    1512           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    1513           8 :         _h1 = io1.out.file.handle;
    1514           8 :         h1 = &_h1;
    1515           8 :         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    1516           8 :         CHECK_VAL(io1.out.durable_open, false);
    1517           8 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1518           8 :                 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
    1519           8 :                 CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
    1520           8 :                 CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
    1521           8 :                 CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
    1522           8 :                 CHECK_VAL(io1.out.lease_response_v2.lease_state,
    1523             :                           smb2_util_lease_state("RWH"));
    1524             :         } else {
    1525           0 :                 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    1526             :         }
    1527           8 :         CHECK_VAL(io1.out.durable_open_v2, true);
    1528           8 :         CHECK_VAL(io1.out.timeout, 300*1000);
    1529             : 
    1530           8 :         lease_key2 = random();
    1531           8 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1532           0 :                 smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
    1533           0 :                         lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
    1534             :         } else {
    1535           8 :                 smb2_oplock_create(&io21, fname, client2_level);
    1536             :         }
    1537           8 :         io21.in.share_access = 0;
    1538           8 :         io21.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1539           8 :         io21.in.desired_access = SEC_RIGHTS_FILE_READ;
    1540           8 :         io21.in.durable_open = false;
    1541           8 :         io21.in.durable_open_v2 = true;
    1542           8 :         io21.in.persistent_open = false;
    1543           8 :         io21.in.create_guid = create_guid2;
    1544           8 :         io21.in.timeout = UINT32_MAX;
    1545           8 :         io24 = io23 = io22 = io21;
    1546             : 
    1547           8 :         req21 = smb2_create_send(tree2, &io21);
    1548           8 :         torture_assert(tctx, req21 != NULL, "req21");
    1549             : 
    1550           8 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1551           8 :                 const struct smb2_lease_break *lb =
    1552             :                         &lease_break_info.lease_break;
    1553           8 :                 const struct smb2_lease *l = &lb->current_lease;
    1554           8 :                 const struct smb2_lease_key *k = &l->lease_key;
    1555             : 
    1556           8 :                 torture_wait_for_lease_break(tctx);
    1557           8 :                 CHECK_VAL(break_info.count, 0);
    1558           8 :                 CHECK_VAL(lease_break_info.count, 1);
    1559             : 
    1560           8 :                 torture_assert(tctx,
    1561             :                         lease_break_info.lease_transport == transport1,
    1562             :                         "expect lease break on transport1\n");
    1563           8 :                 CHECK_VAL(k->data[0], lease_key1);
    1564           8 :                 CHECK_VAL(k->data[1], ~lease_key1);
    1565             :                 /*
    1566             :                  * With share none the handle lease
    1567             :                  * is broken.
    1568             :                  */
    1569           8 :                 CHECK_VAL(lb->new_lease_state,
    1570             :                           smb2_util_lease_state("RW"));
    1571           8 :                 CHECK_VAL(lb->break_flags,
    1572             :                           SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
    1573           8 :                 CHECK_VAL(lb->new_epoch, lease_epoch1+1);
    1574           8 :                 lease_epoch1 += 1;
    1575             : 
    1576           8 :                 lb_ack1.in.lease.lease_key = lb->current_lease.lease_key;
    1577           8 :                 lb_ack1.in.lease.lease_state = lb->new_lease_state;
    1578             :         } else {
    1579           0 :                 torture_wait_for_oplock_break(tctx);
    1580           0 :                 CHECK_VAL(break_info.count, 1);
    1581           0 :                 CHECK_VAL(lease_break_info.count, 0);
    1582             : 
    1583           0 :                 torture_assert(tctx,
    1584             :                         break_info.received_transport == transport1,
    1585             :                         "expect oplock break on transport1\n");
    1586           0 :                 CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
    1587           0 :                 CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
    1588           0 :                 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    1589             : 
    1590           0 :                 op_ack1.in = break_info.br.in;
    1591             :         }
    1592             : 
    1593           8 :         torture_reset_break_info(tctx, &break_info);
    1594           8 :         break_info.oplock_skip_ack = true;
    1595           8 :         torture_reset_lease_break_info(tctx, &lease_break_info);
    1596           8 :         lease_break_info.lease_skip_ack = true;
    1597             : 
    1598           8 :         WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
    1599             : 
    1600           8 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1601           8 :                 torture_wait_for_lease_break(tctx);
    1602             :         } else {
    1603           0 :                 torture_wait_for_oplock_break(tctx);
    1604             :         }
    1605           8 :         CHECK_VAL(break_info.count, 0);
    1606           8 :         CHECK_VAL(lease_break_info.count, 0);
    1607             : 
    1608           8 :         if (NT_STATUS_EQUAL(replay22_reject_status, NT_STATUS_SHARING_VIOLATION)) {
    1609             :                 /*
    1610             :                  * The server is broken and doesn't
    1611             :                  * detect a replay, so we start an async
    1612             :                  * request and send a lease break ack
    1613             :                  * after 5 seconds in order to avoid
    1614             :                  * the 35 second delay.
    1615             :                  */
    1616           4 :                 torture_comment(tctx, "Starting ASYNC Replay req22 expecting %s\n",
    1617             :                                 nt_errstr(replay22_reject_status));
    1618           4 :                 smb2cli_session_start_replay(session2->smbXcli);
    1619           4 :                 transport2->options.request_timeout = 15;
    1620           4 :                 req22 = smb2_create_send(tree2, &io22);
    1621           4 :                 torture_assert(tctx, req22 != NULL, "req22");
    1622           4 :                 transport2->options.request_timeout = request_timeout2;
    1623           4 :                 smb2cli_session_stop_replay(session2->smbXcli);
    1624             : 
    1625           4 :                 WAIT_FOR_ASYNC_RESPONSE(tctx, req22);
    1626             :         } else {
    1627           4 :                 torture_comment(tctx, "SYNC Replay io22 expecting %s\n",
    1628             :                                 nt_errstr(replay22_reject_status));
    1629           4 :                 smb2cli_session_start_replay(session2->smbXcli);
    1630           4 :                 transport2->options.request_timeout = 5;
    1631           4 :                 status = smb2_create(tree2, tctx, &io22);
    1632           4 :                 CHECK_STATUS(status, replay22_reject_status);
    1633           4 :                 transport2->options.request_timeout = request_timeout2;
    1634           4 :                 smb2cli_session_stop_replay(session2->smbXcli);
    1635             :         }
    1636             : 
    1637             :         /*
    1638             :          * We don't expect any action for 35 seconds
    1639             :          *
    1640             :          * But we sleep just 5 seconds before we
    1641             :          * ack the break.
    1642             :          */
    1643           8 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1644           8 :                 torture_wait_for_lease_break(tctx);
    1645           8 :                 torture_wait_for_lease_break(tctx);
    1646           8 :                 torture_wait_for_lease_break(tctx);
    1647           8 :                 torture_wait_for_lease_break(tctx);
    1648           8 :                 torture_wait_for_lease_break(tctx);
    1649           8 :                 CHECK_VAL(break_info.count, 0);
    1650           8 :                 CHECK_VAL(lease_break_info.count, 0);
    1651             : 
    1652           8 :                 if (release_op == SMB2_OP_CLOSE) {
    1653           4 :                         torture_comment(tctx, "Closing h1\n");
    1654           4 :                         smb2_util_close(tree1, _h1);
    1655           4 :                         h1 = NULL;
    1656             :                 } else {
    1657           4 :                         torture_comment(tctx, "Acking lease_key1\n");
    1658           4 :                         status = smb2_lease_break_ack(tree1, &lb_ack1);
    1659           4 :                         CHECK_STATUS(status, NT_STATUS_OK);
    1660           4 :                         CHECK_VAL(lb_ack1.out.lease.lease_flags, 0);
    1661           4 :                         CHECK_VAL(lb_ack1.out.lease.lease_state, lb_ack1.in.lease.lease_state);
    1662           4 :                         CHECK_VAL(lb_ack1.out.lease.lease_key.data[0], lease_key1);
    1663           4 :                         CHECK_VAL(lb_ack1.out.lease.lease_key.data[1], ~lease_key1);
    1664           4 :                         CHECK_VAL(lb_ack1.out.lease.lease_duration, 0);
    1665             :                 }
    1666             :         } else {
    1667           0 :                 torture_wait_for_oplock_break(tctx);
    1668           0 :                 torture_wait_for_oplock_break(tctx);
    1669           0 :                 torture_wait_for_oplock_break(tctx);
    1670           0 :                 torture_wait_for_oplock_break(tctx);
    1671           0 :                 torture_wait_for_oplock_break(tctx);
    1672           0 :                 CHECK_VAL(break_info.count, 0);
    1673           0 :                 CHECK_VAL(lease_break_info.count, 0);
    1674             : 
    1675           0 :                 if (release_op == SMB2_OP_CLOSE) {
    1676           0 :                         torture_comment(tctx, "Closing h1\n");
    1677           0 :                         smb2_util_close(tree1, _h1);
    1678           0 :                         h1 = NULL;
    1679             :                 } else {
    1680           0 :                         torture_comment(tctx, "Acking break h1\n");
    1681           0 :                         status = smb2_break(tree1, &op_ack1);
    1682           0 :                         CHECK_STATUS(status, NT_STATUS_OK);
    1683           0 :                         CHECK_VAL(op_ack1.out.oplock_level, op_ack1.in.oplock_level);
    1684             :                 }
    1685             :         }
    1686             : 
    1687           8 :         torture_comment(tctx, "Checking req21 expecting %s\n",
    1688             :                         nt_errstr(orig21_reject_status));
    1689           8 :         status = smb2_create_recv(req21, tctx, &io21);
    1690           8 :         CHECK_STATUS(status, orig21_reject_status);
    1691           8 :         if (NT_STATUS_IS_OK(orig21_reject_status)) {
    1692           4 :                 _h21 = io21.out.file.handle;
    1693           4 :                 h21 = &_h21;
    1694           4 :                 if (h2f == NULL) {
    1695           4 :                         h2f = h21;
    1696             :                 }
    1697           4 :                 CHECK_VAL(h21->data[0], h2f->data[0]);
    1698           4 :                 CHECK_VAL(h21->data[1], h2f->data[1]);
    1699           4 :                 CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
    1700           4 :                 CHECK_VAL(io21.out.oplock_level, client2_level);
    1701           4 :                 CHECK_VAL(io21.out.durable_open, false);
    1702           4 :                 if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1703           0 :                         CHECK_VAL(io21.out.lease_response_v2.lease_key.data[0], lease_key2);
    1704           0 :                         CHECK_VAL(io21.out.lease_response_v2.lease_key.data[1], ~lease_key2);
    1705           0 :                         CHECK_VAL(io21.out.lease_response_v2.lease_epoch, lease_epoch2);
    1706           0 :                         CHECK_VAL(io21.out.lease_response_v2.lease_state,
    1707             :                                   smb2_util_lease_state("RHW"));
    1708           0 :                         CHECK_VAL(io21.out.durable_open_v2, true);
    1709           0 :                         CHECK_VAL(io21.out.timeout, 300*1000);
    1710           4 :                 } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
    1711           0 :                         CHECK_VAL(io21.out.durable_open_v2, true);
    1712           0 :                         CHECK_VAL(io21.out.timeout, 300*1000);
    1713             :                 } else {
    1714           4 :                         CHECK_VAL(io21.out.durable_open_v2, false);
    1715             :                 }
    1716             :         }
    1717             : 
    1718           8 :         if (NT_STATUS_EQUAL(replay22_reject_status, NT_STATUS_SHARING_VIOLATION)) {
    1719           4 :                 torture_comment(tctx, "Checking req22 expecting %s\n",
    1720             :                                 nt_errstr(replay22_reject_status));
    1721           4 :                 status = smb2_create_recv(req22, tctx, &io22);
    1722           4 :                 CHECK_STATUS(status, replay22_reject_status);
    1723             :         }
    1724             : 
    1725           4 :         torture_comment(tctx, "SYNC Replay io23 expecting %s\n",
    1726             :                         nt_errstr(replay23_reject_status));
    1727           4 :         smb2cli_session_start_replay(session2->smbXcli);
    1728           4 :         transport2->options.request_timeout = 5;
    1729           4 :         status = smb2_create(tree2, tctx, &io23);
    1730           4 :         transport2->options.request_timeout = request_timeout2;
    1731           4 :         CHECK_STATUS(status, replay23_reject_status);
    1732           4 :         smb2cli_session_stop_replay(session2->smbXcli);
    1733           4 :         if (NT_STATUS_IS_OK(replay23_reject_status)) {
    1734           2 :                 _h23 = io23.out.file.handle;
    1735           2 :                 h23 = &_h23;
    1736           2 :                 if (h2f == NULL) {
    1737           0 :                         h2f = h23;
    1738             :                 }
    1739           2 :                 CHECK_VAL(h23->data[0], h2f->data[0]);
    1740           2 :                 CHECK_VAL(h23->data[1], h2f->data[1]);
    1741           2 :                 CHECK_CREATED(&io23, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
    1742           2 :                 CHECK_VAL(io23.out.oplock_level, client2_level);
    1743           2 :                 CHECK_VAL(io23.out.durable_open, false);
    1744           2 :                 if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1745           0 :                         CHECK_VAL(io23.out.lease_response_v2.lease_key.data[0], lease_key2);
    1746           0 :                         CHECK_VAL(io23.out.lease_response_v2.lease_key.data[1], ~lease_key2);
    1747           0 :                         CHECK_VAL(io23.out.lease_response_v2.lease_epoch, lease_epoch2);
    1748           0 :                         CHECK_VAL(io23.out.lease_response_v2.lease_state,
    1749             :                                   smb2_util_lease_state("RHW"));
    1750           0 :                         CHECK_VAL(io23.out.durable_open_v2, true);
    1751           0 :                         CHECK_VAL(io23.out.timeout, 300*1000);
    1752           2 :                 } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
    1753           0 :                         CHECK_VAL(io23.out.durable_open_v2, true);
    1754           0 :                         CHECK_VAL(io23.out.timeout, 300*1000);
    1755             :                 } else {
    1756           2 :                         CHECK_VAL(io23.out.durable_open_v2, false);
    1757             :                 }
    1758             :         }
    1759             : 
    1760           4 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1761           4 :                 torture_wait_for_lease_break(tctx);
    1762             :         } else {
    1763           0 :                 torture_wait_for_oplock_break(tctx);
    1764             :         }
    1765           4 :         CHECK_VAL(break_info.count, 0);
    1766           4 :         CHECK_VAL(lease_break_info.count, 0);
    1767             : 
    1768           4 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1769           4 :                 torture_wait_for_lease_break(tctx);
    1770             :         } else {
    1771           0 :                 torture_wait_for_oplock_break(tctx);
    1772             :         }
    1773           4 :         CHECK_VAL(break_info.count, 0);
    1774           4 :         CHECK_VAL(lease_break_info.count, 0);
    1775             : 
    1776           4 :         if (h1 != NULL) {
    1777           2 :                 torture_comment(tctx, "Closing h1\n");
    1778           2 :                 smb2_util_close(tree1, _h1);
    1779           2 :                 h1 = NULL;
    1780             :         }
    1781             : 
    1782           4 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1783           4 :                 torture_wait_for_lease_break(tctx);
    1784             :         } else {
    1785           0 :                 torture_wait_for_oplock_break(tctx);
    1786             :         }
    1787           4 :         CHECK_VAL(break_info.count, 0);
    1788           4 :         CHECK_VAL(lease_break_info.count, 0);
    1789             : 
    1790           4 :         torture_comment(tctx, "SYNC Replay io24 expecting %s\n",
    1791           4 :                         nt_errstr(NT_STATUS_OK));
    1792           4 :         smb2cli_session_start_replay(session2->smbXcli);
    1793           4 :         transport2->options.request_timeout = 5;
    1794           4 :         status = smb2_create(tree2, tctx, &io24);
    1795           4 :         transport2->options.request_timeout = request_timeout2;
    1796           4 :         smb2cli_session_stop_replay(session2->smbXcli);
    1797           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1798           4 :         _h24 = io24.out.file.handle;
    1799           4 :         h24 = &_h24;
    1800           4 :         if (h2f == NULL) {
    1801           2 :                 h2f = h24;
    1802             :         }
    1803           4 :         CHECK_VAL(h24->data[0], h2f->data[0]);
    1804           4 :         CHECK_VAL(h24->data[1], h2f->data[1]);
    1805           4 :         CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
    1806           4 :         CHECK_VAL(io24.out.oplock_level, client2_level);
    1807           4 :         CHECK_VAL(io24.out.durable_open, false);
    1808           4 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1809           0 :                 CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
    1810           0 :                 CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
    1811           0 :                 CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
    1812           0 :                 CHECK_VAL(io24.out.lease_response_v2.lease_state,
    1813             :                           smb2_util_lease_state("RHW"));
    1814           0 :                 CHECK_VAL(io24.out.durable_open_v2, true);
    1815           0 :                 CHECK_VAL(io24.out.timeout, 300*1000);
    1816           4 :         } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
    1817           0 :                 CHECK_VAL(io24.out.durable_open_v2, true);
    1818           0 :                 CHECK_VAL(io24.out.timeout, 300*1000);
    1819             :         } else {
    1820           4 :                 CHECK_VAL(io24.out.durable_open_v2, false);
    1821             :         }
    1822             : 
    1823           4 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1824           4 :                 torture_wait_for_lease_break(tctx);
    1825             :         } else {
    1826           0 :                 torture_wait_for_oplock_break(tctx);
    1827             :         }
    1828           4 :         CHECK_VAL(break_info.count, 0);
    1829           4 :         CHECK_VAL(lease_break_info.count, 0);
    1830           4 :         status = smb2_util_close(tree2, *h24);
    1831           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1832           4 :         h24 = NULL;
    1833             : 
    1834           4 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    1835           4 :                 torture_wait_for_lease_break(tctx);
    1836             :         } else {
    1837           0 :                 torture_wait_for_oplock_break(tctx);
    1838             :         }
    1839           4 :         CHECK_VAL(break_info.count, 0);
    1840           4 :         CHECK_VAL(lease_break_info.count, 0);
    1841             : 
    1842          12 : done:
    1843             : 
    1844           8 :         smbXcli_conn_disconnect(transport2->conn, NT_STATUS_LOCAL_DISCONNECT);
    1845             : 
    1846           8 :         if (h1 != NULL) {
    1847           2 :                 smb2_util_close(tree1, *h1);
    1848             :         }
    1849             : 
    1850           8 :         smb2_deltree(tree1, BASEDIR);
    1851             : 
    1852           8 :         TALLOC_FREE(tree1);
    1853           8 :         talloc_free(mem_ctx);
    1854             : 
    1855           8 :         return ret;
    1856             : }
    1857             : 
    1858             : /*
    1859             :  * This tests replay with a pending open on a single
    1860             :  * channel. It tests the case where the client2 open
    1861             :  * is deferred because it conflicts with a HANDLE lease,
    1862             :  * which is broken because the operation should otherwise
    1863             :  * return NT_STATUS_SHARING_VIOLATION.
    1864             :  *
    1865             :  * With a durablev2 request containing a create_guid,
    1866             :  * but without asking for an oplock nor a lease.
    1867             :  *
    1868             :  * While another client holds an RWH lease,
    1869             :  * which is released by a close.
    1870             :  *
    1871             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    1872             :  *
    1873             :  * This expects the sane reject status of
    1874             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    1875             :  *
    1876             :  * It won't pass against Windows as it returns
    1877             :  * NT_STATUS_SHARING_VIOLATION to the replay (after
    1878             :  * 35 seconds), and this tests reports NT_STATUS_IO_TIMEOUT,
    1879             :  * as it expectes a NT_STATUS_FILE_NOT_AVAILABLE within 5 seconds.
    1880             :  * see test_dhv2_pending1n_vs_violation_lease_close_windows().
    1881             :  */
    1882           5 : static bool test_dhv2_pending1n_vs_violation_lease_close_sane(struct torture_context *tctx,
    1883             :                                                               struct smb2_tree *tree1,
    1884             :                                                               struct smb2_tree *tree2)
    1885             : {
    1886           5 :         return _test_dhv2_pending1_vs_violation(tctx, __func__,
    1887             :                                                 tree1,
    1888             :                                                 SMB2_OPLOCK_LEVEL_LEASE,
    1889             :                                                 SMB2_OP_CLOSE,
    1890             :                                                 tree2,
    1891             :                                                 SMB2_OPLOCK_LEVEL_NONE,
    1892           5 :                                                 NT_STATUS_OK,
    1893           5 :                                                 NT_STATUS_FILE_NOT_AVAILABLE,
    1894           5 :                                                 NT_STATUS_OK);
    1895             : }
    1896             : 
    1897             : /*
    1898             :  * This tests replay with a pending open on a single
    1899             :  * channel. It tests the case where the client2 open
    1900             :  * is deferred because it conflicts with a HANDLE lease,
    1901             :  * which is broken because the operation should otherwise
    1902             :  * return NT_STATUS_SHARING_VIOLATION.
    1903             :  *
    1904             :  * With a durablev2 request containing a create_guid,
    1905             :  * but without asking for an oplock nor a lease.
    1906             :  *
    1907             :  * While another client holds an RWH lease,
    1908             :  * which is released by a close.
    1909             :  *
    1910             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    1911             :  *
    1912             :  * This expects the strange behavior of ignoring the
    1913             :  * replay, which is returned done by Windows Servers.
    1914             :  *
    1915             :  * It won't pass against Samba as it returns
    1916             :  * NT_STATUS_FILE_NOT_AVAILABLE
    1917             :  * see test_dhv2_pending1n_vs_violation_lease_close_sane().
    1918             :  */
    1919           5 : static bool test_dhv2_pending1n_vs_violation_lease_close_windows(struct torture_context *tctx,
    1920             :                                                                  struct smb2_tree *tree1,
    1921             :                                                                  struct smb2_tree *tree2)
    1922             : {
    1923           5 :         return _test_dhv2_pending1_vs_violation(tctx, __func__,
    1924             :                                                 tree1,
    1925             :                                                 SMB2_OPLOCK_LEVEL_LEASE,
    1926             :                                                 SMB2_OP_CLOSE,
    1927             :                                                 tree2,
    1928             :                                                 SMB2_OPLOCK_LEVEL_NONE,
    1929           5 :                                                 NT_STATUS_OK,
    1930           5 :                                                 NT_STATUS_SHARING_VIOLATION,
    1931           5 :                                                 NT_STATUS_OK);
    1932             : }
    1933             : 
    1934             : /*
    1935             :  * This tests replay with a pending open on a single
    1936             :  * channel. It tests the case where the client2 open
    1937             :  * is deferred because it conflicts with a HANDLE lease,
    1938             :  * which is broken because the operation should otherwise
    1939             :  * return NT_STATUS_SHARING_VIOLATION.
    1940             :  *
    1941             :  * With a durablev2 request containing a create_guid,
    1942             :  * but without asking for an oplock nor a lease.
    1943             :  *
    1944             :  * While another client holds an RWH lease,
    1945             :  * which is released by a lease break ack.
    1946             :  *
    1947             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    1948             :  *
    1949             :  * This expects the sane reject status of
    1950             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    1951             :  *
    1952             :  * It won't pass against Windows as it returns
    1953             :  * NT_STATUS_SHARING_VIOLATION to the replay (after
    1954             :  * 35 seconds), and this tests reports NT_STATUS_IO_TIMEOUT,
    1955             :  * as it expectes a NT_STATUS_FILE_NOT_AVAILABLE within 5 seconds.
    1956             :  * see test_dhv2_pending1n_vs_violation_lease_ack_windows().
    1957             :  */
    1958           5 : static bool test_dhv2_pending1n_vs_violation_lease_ack_sane(struct torture_context *tctx,
    1959             :                                                             struct smb2_tree *tree1,
    1960             :                                                             struct smb2_tree *tree2)
    1961             : {
    1962           5 :         return _test_dhv2_pending1_vs_violation(tctx, __func__,
    1963             :                                                 tree1,
    1964             :                                                 SMB2_OPLOCK_LEVEL_LEASE,
    1965             :                                                 SMB2_OP_BREAK,
    1966             :                                                 tree2,
    1967             :                                                 SMB2_OPLOCK_LEVEL_NONE,
    1968           5 :                                                 NT_STATUS_SHARING_VIOLATION,
    1969           5 :                                                 NT_STATUS_FILE_NOT_AVAILABLE,
    1970           5 :                                                 NT_STATUS_SHARING_VIOLATION);
    1971             : }
    1972             : 
    1973             : /*
    1974             :  * This tests replay with a pending open on a single
    1975             :  * channel. It tests the case where the client2 open
    1976             :  * is deferred because it conflicts with a HANDLE lease,
    1977             :  * which is broken because the operation should otherwise
    1978             :  * return NT_STATUS_SHARING_VIOLATION.
    1979             :  *
    1980             :  * With a durablev2 request containing a create_guid,
    1981             :  * but without asking for an oplock nor a lease.
    1982             :  *
    1983             :  * While another client holds an RWH lease,
    1984             :  * which is released by a close.
    1985             :  *
    1986             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    1987             :  *
    1988             :  * This expects the strange behavior of ignoring the
    1989             :  * replay, which is returned done by Windows Servers.
    1990             :  *
    1991             :  * It won't pass against Samba as it returns
    1992             :  * NT_STATUS_FILE_NOT_AVAILABLE
    1993             :  * see test_dhv2_pending1n_vs_violation_lease_ack_sane().
    1994             :  */
    1995           5 : static bool test_dhv2_pending1n_vs_violation_lease_ack_windows(struct torture_context *tctx,
    1996             :                                                                struct smb2_tree *tree1,
    1997             :                                                                struct smb2_tree *tree2)
    1998             : {
    1999           5 :         return _test_dhv2_pending1_vs_violation(tctx, __func__,
    2000             :                                                 tree1,
    2001             :                                                 SMB2_OPLOCK_LEVEL_LEASE,
    2002             :                                                 SMB2_OP_BREAK,
    2003             :                                                 tree2,
    2004             :                                                 SMB2_OPLOCK_LEVEL_NONE,
    2005           5 :                                                 NT_STATUS_SHARING_VIOLATION,
    2006           5 :                                                 NT_STATUS_SHARING_VIOLATION,
    2007           5 :                                                 NT_STATUS_SHARING_VIOLATION);
    2008             : }
    2009             : 
    2010             : /**
    2011             :  * This tests replay with a pending open on a single
    2012             :  * channel.
    2013             :  *
    2014             :  * With a durablev2 request containing a create_guid and
    2015             :  * a share_access of READ/WRITE/DELETE:
    2016             :  * - client2_level = NONE:
    2017             :  *   but without asking for an oplock nor a lease.
    2018             :  * - client2_level = BATCH:
    2019             :  *   and asking for a batch oplock.
    2020             :  * - client2_level = LEASE
    2021             :  *   and asking for an RWH lease.
    2022             :  *
    2023             :  * While another client holds a batch oplock or
    2024             :  * RWH lease. (client1_level => LEASE or BATCH).
    2025             :  * And allows share_access of READ/WRITE/DELETE.
    2026             :  *
    2027             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2028             :  */
    2029          60 : static bool _test_dhv2_pending1_vs_hold(struct torture_context *tctx,
    2030             :                                         const char *testname,
    2031             :                                         uint8_t client1_level,
    2032             :                                         uint8_t client2_level,
    2033             :                                         NTSTATUS reject_status,
    2034             :                                         struct smb2_tree *tree1,
    2035             :                                         struct smb2_tree *tree2)
    2036             : {
    2037             :         NTSTATUS status;
    2038          60 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2039             :         struct smb2_handle _h1;
    2040          60 :         struct smb2_handle *h1 = NULL;
    2041             :         struct smb2_handle _h21;
    2042          60 :         struct smb2_handle *h21 = NULL;
    2043             :         struct smb2_handle _h24;
    2044          60 :         struct smb2_handle *h24 = NULL;
    2045             :         struct smb2_create io1, io21, io22, io23, io24;
    2046          60 :         struct GUID create_guid1 = GUID_random();
    2047          60 :         struct GUID create_guid2 = GUID_random();
    2048          60 :         struct smb2_request *req21 = NULL;
    2049          60 :         bool ret = true;
    2050             :         char fname[256];
    2051          60 :         struct smb2_transport *transport1 = tree1->session->transport;
    2052             :         uint32_t server_capabilities;
    2053             :         uint32_t share_capabilities;
    2054             :         struct smb2_lease ls1;
    2055             :         uint64_t lease_key1;
    2056          60 :         uint16_t lease_epoch1 = 0;
    2057             :         struct smb2_lease ls2;
    2058             :         uint64_t lease_key2;
    2059          60 :         uint16_t lease_epoch2 = 0;
    2060             :         bool share_is_so;
    2061          60 :         struct smb2_transport *transport2 = tree2->session->transport;
    2062          60 :         int request_timeout2 = transport2->options.request_timeout;
    2063          60 :         struct smb2_session *session2 = tree2->session;
    2064          60 :         const char *hold_name = NULL;
    2065             : 
    2066          60 :         switch (client1_level) {
    2067          30 :         case SMB2_OPLOCK_LEVEL_LEASE:
    2068          30 :                 hold_name = "RWH Lease";
    2069          30 :                 break;
    2070          30 :         case SMB2_OPLOCK_LEVEL_BATCH:
    2071          30 :                 hold_name = "BATCH Oplock";
    2072          30 :                 break;
    2073           0 :         default:
    2074           0 :                 smb_panic(__location__);
    2075             :                 break;
    2076             :         }
    2077             : 
    2078          60 :         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
    2079          12 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    2080             :                                    "replay tests\n");
    2081             :         }
    2082             : 
    2083          48 :         server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
    2084          48 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
    2085          24 :                 if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
    2086           0 :                     client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2087          16 :                         torture_skip(tctx, "leases are not supported");
    2088             :                 }
    2089             :         }
    2090             : 
    2091          32 :         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
    2092          32 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    2093          32 :         if (share_is_so) {
    2094           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
    2095             :                              "%s not supported on SCALEOUT share",
    2096             :                              hold_name));
    2097             :         }
    2098             : 
    2099             :         /* Add some random component to the file name. */
    2100          32 :         snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
    2101             :                  BASEDIR, testname, generate_random_str(tctx, 8));
    2102             : 
    2103          32 :         torture_reset_break_info(tctx, &break_info);
    2104          32 :         break_info.oplock_skip_ack = true;
    2105          32 :         torture_reset_lease_break_info(tctx, &lease_break_info);
    2106          32 :         lease_break_info.lease_skip_ack = true;
    2107          32 :         transport1->oplock.handler = torture_oplock_ack_handler;
    2108          32 :         transport1->oplock.private_data = tree1;
    2109          32 :         transport1->lease.handler = torture_lease_handler;
    2110          32 :         transport1->lease.private_data = tree1;
    2111          32 :         smb2_keepalive(transport1);
    2112          32 :         transport2->oplock.handler = torture_oplock_ack_handler;
    2113          32 :         transport2->oplock.private_data = tree2;
    2114          32 :         transport2->lease.handler = torture_lease_handler;
    2115          32 :         transport2->lease.private_data = tree2;
    2116          32 :         smb2_keepalive(transport2);
    2117             : 
    2118          32 :         smb2_util_unlink(tree1, fname);
    2119          32 :         status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
    2120          32 :         CHECK_STATUS(status, NT_STATUS_OK);
    2121          32 :         smb2_util_close(tree1, _h1);
    2122          32 :         CHECK_VAL(break_info.count, 0);
    2123             : 
    2124          32 :         lease_key1 = random();
    2125          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2126          12 :                 smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
    2127          12 :                         lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
    2128             :         } else {
    2129          20 :                 smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
    2130             :         }
    2131          32 :         io1.in.share_access = smb2_util_share_access("RWD");
    2132          32 :         io1.in.durable_open = false;
    2133          32 :         io1.in.durable_open_v2 = true;
    2134          32 :         io1.in.persistent_open = false;
    2135          32 :         io1.in.create_guid = create_guid1;
    2136          32 :         io1.in.timeout = UINT32_MAX;
    2137             : 
    2138          32 :         status = smb2_create(tree1, mem_ctx, &io1);
    2139          32 :         CHECK_STATUS(status, NT_STATUS_OK);
    2140          32 :         _h1 = io1.out.file.handle;
    2141          32 :         h1 = &_h1;
    2142          32 :         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    2143          32 :         CHECK_VAL(io1.out.durable_open, false);
    2144          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2145          12 :                 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
    2146          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
    2147          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
    2148          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
    2149          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_state,
    2150             :                           smb2_util_lease_state("RHW"));
    2151             :         } else {
    2152          20 :                 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2153             :         }
    2154          32 :         CHECK_VAL(io1.out.durable_open_v2, true);
    2155          32 :         CHECK_VAL(io1.out.timeout, 300*1000);
    2156             : 
    2157          32 :         lease_key2 = random();
    2158          32 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2159           8 :                 smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
    2160           8 :                         lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
    2161             :         } else {
    2162          24 :                 smb2_oplock_create(&io21, fname, client2_level);
    2163             :         }
    2164          32 :         io21.in.share_access = smb2_util_share_access("RWD");
    2165          32 :         io21.in.durable_open = false;
    2166          32 :         io21.in.durable_open_v2 = true;
    2167          32 :         io21.in.persistent_open = false;
    2168          32 :         io21.in.create_guid = create_guid2;
    2169          32 :         io21.in.timeout = UINT32_MAX;
    2170          32 :         io24 = io23 = io22 = io21;
    2171             : 
    2172          32 :         req21 = smb2_create_send(tree2, &io21);
    2173          32 :         torture_assert(tctx, req21 != NULL, "req21");
    2174             : 
    2175          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2176          12 :                 const struct smb2_lease_break *lb =
    2177             :                         &lease_break_info.lease_break;
    2178          12 :                 const struct smb2_lease *l = &lb->current_lease;
    2179          12 :                 const struct smb2_lease_key *k = &l->lease_key;
    2180             : 
    2181          12 :                 torture_wait_for_lease_break(tctx);
    2182          12 :                 CHECK_VAL(break_info.count, 0);
    2183          12 :                 CHECK_VAL(lease_break_info.count, 1);
    2184             : 
    2185          12 :                 torture_assert(tctx,
    2186             :                         lease_break_info.lease_transport == transport1,
    2187             :                         "expect lease break on transport1\n");
    2188          12 :                 CHECK_VAL(k->data[0], lease_key1);
    2189          12 :                 CHECK_VAL(k->data[1], ~lease_key1);
    2190          12 :                 CHECK_VAL(lb->new_lease_state,
    2191             :                           smb2_util_lease_state("RH"));
    2192          12 :                 CHECK_VAL(lb->break_flags,
    2193             :                           SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
    2194          12 :                 CHECK_VAL(lb->new_epoch, lease_epoch1+1);
    2195          12 :                 lease_epoch1 += 1;
    2196             :         } else {
    2197          20 :                 torture_wait_for_oplock_break(tctx);
    2198          20 :                 CHECK_VAL(break_info.count, 1);
    2199          20 :                 CHECK_VAL(lease_break_info.count, 0);
    2200             : 
    2201          20 :                 torture_assert(tctx,
    2202             :                         break_info.received_transport == transport1,
    2203             :                         "expect oplock break on transport1\n");
    2204          20 :                 CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
    2205          20 :                 CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
    2206          20 :                 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    2207             :         }
    2208             : 
    2209          32 :         torture_reset_break_info(tctx, &break_info);
    2210          32 :         break_info.oplock_skip_ack = true;
    2211          32 :         torture_reset_lease_break_info(tctx, &lease_break_info);
    2212          32 :         lease_break_info.lease_skip_ack = true;
    2213             : 
    2214          32 :         WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
    2215             : 
    2216          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2217          12 :                 torture_wait_for_lease_break(tctx);
    2218             :         } else {
    2219          20 :                 torture_wait_for_oplock_break(tctx);
    2220             :         }
    2221          32 :         CHECK_VAL(break_info.count, 0);
    2222          32 :         CHECK_VAL(lease_break_info.count, 0);
    2223             : 
    2224          32 :         smb2cli_session_start_replay(session2->smbXcli);
    2225          32 :         transport2->options.request_timeout = 5;
    2226          32 :         status = smb2_create(tree2, tctx, &io22);
    2227          32 :         transport2->options.request_timeout = request_timeout2;
    2228          32 :         CHECK_STATUS(status, reject_status);
    2229          16 :         smb2cli_session_stop_replay(session2->smbXcli);
    2230             : 
    2231          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2232           6 :                 torture_wait_for_lease_break(tctx);
    2233             :         } else {
    2234          10 :                 torture_wait_for_oplock_break(tctx);
    2235             :         }
    2236          16 :         CHECK_VAL(break_info.count, 0);
    2237          16 :         CHECK_VAL(lease_break_info.count, 0);
    2238             : 
    2239          16 :         smb2cli_session_start_replay(session2->smbXcli);
    2240          16 :         transport2->options.request_timeout = 5;
    2241          16 :         status = smb2_create(tree2, tctx, &io23);
    2242          16 :         transport2->options.request_timeout = request_timeout2;
    2243          16 :         CHECK_STATUS(status, reject_status);
    2244          16 :         smb2cli_session_stop_replay(session2->smbXcli);
    2245             : 
    2246          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2247           6 :                 torture_wait_for_lease_break(tctx);
    2248             :         } else {
    2249          10 :                 torture_wait_for_oplock_break(tctx);
    2250             :         }
    2251          16 :         CHECK_VAL(break_info.count, 0);
    2252          16 :         CHECK_VAL(lease_break_info.count, 0);
    2253             : 
    2254          16 :         smb2_util_close(tree1, _h1);
    2255          16 :         h1 = NULL;
    2256             : 
    2257          16 :         status = smb2_create_recv(req21, tctx, &io21);
    2258          16 :         CHECK_STATUS(status, NT_STATUS_OK);
    2259          16 :         _h21 = io21.out.file.handle;
    2260          16 :         h21 = &_h21;
    2261          16 :         CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
    2262          16 :         CHECK_VAL(io21.out.oplock_level, client2_level);
    2263          16 :         CHECK_VAL(io21.out.durable_open, false);
    2264          16 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2265           4 :                 CHECK_VAL(io21.out.lease_response_v2.lease_key.data[0], lease_key2);
    2266           4 :                 CHECK_VAL(io21.out.lease_response_v2.lease_key.data[1], ~lease_key2);
    2267           4 :                 CHECK_VAL(io21.out.lease_response_v2.lease_epoch, lease_epoch2);
    2268           4 :                 CHECK_VAL(io21.out.lease_response_v2.lease_state,
    2269             :                           smb2_util_lease_state("RHW"));
    2270           4 :                 CHECK_VAL(io21.out.durable_open_v2, true);
    2271           4 :                 CHECK_VAL(io21.out.timeout, 300*1000);
    2272          12 :         } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
    2273           6 :                 CHECK_VAL(io21.out.durable_open_v2, true);
    2274           6 :                 CHECK_VAL(io21.out.timeout, 300*1000);
    2275             :         } else {
    2276           6 :                 CHECK_VAL(io21.out.durable_open_v2, false);
    2277             :         }
    2278             : 
    2279          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2280           6 :                 torture_wait_for_lease_break(tctx);
    2281             :         } else {
    2282          10 :                 torture_wait_for_oplock_break(tctx);
    2283             :         }
    2284          16 :         CHECK_VAL(break_info.count, 0);
    2285          16 :         CHECK_VAL(lease_break_info.count, 0);
    2286             : 
    2287          16 :         smb2cli_session_start_replay(session2->smbXcli);
    2288          16 :         status = smb2_create(tree2, tctx, &io24);
    2289          16 :         smb2cli_session_stop_replay(session2->smbXcli);
    2290          16 :         CHECK_STATUS(status, NT_STATUS_OK);
    2291          16 :         _h24 = io24.out.file.handle;
    2292          16 :         h24 = &_h24;
    2293          16 :         CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
    2294          16 :         CHECK_VAL(h24->data[0], h21->data[0]);
    2295          16 :         CHECK_VAL(h24->data[1], h21->data[1]);
    2296          16 :         CHECK_VAL(io24.out.oplock_level, client2_level);
    2297          16 :         CHECK_VAL(io24.out.durable_open, false);
    2298          16 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2299           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
    2300           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
    2301           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
    2302           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_state,
    2303             :                           smb2_util_lease_state("RHW"));
    2304           4 :                 CHECK_VAL(io24.out.durable_open_v2, true);
    2305           4 :                 CHECK_VAL(io24.out.timeout, 300*1000);
    2306          12 :         } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
    2307           6 :                 CHECK_VAL(io24.out.durable_open_v2, true);
    2308           6 :                 CHECK_VAL(io24.out.timeout, 300*1000);
    2309             :         } else {
    2310           6 :                 CHECK_VAL(io24.out.durable_open_v2, false);
    2311             :         }
    2312             : 
    2313          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2314           6 :                 torture_wait_for_lease_break(tctx);
    2315             :         } else {
    2316          10 :                 torture_wait_for_oplock_break(tctx);
    2317             :         }
    2318          16 :         CHECK_VAL(break_info.count, 0);
    2319          16 :         CHECK_VAL(lease_break_info.count, 0);
    2320          16 :         status = smb2_util_close(tree2, *h24);
    2321          16 :         CHECK_STATUS(status, NT_STATUS_OK);
    2322          16 :         h24 = NULL;
    2323             : 
    2324          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2325           6 :                 torture_wait_for_lease_break(tctx);
    2326             :         } else {
    2327          10 :                 torture_wait_for_oplock_break(tctx);
    2328             :         }
    2329          16 :         CHECK_VAL(break_info.count, 0);
    2330          16 :         CHECK_VAL(lease_break_info.count, 0);
    2331             : 
    2332          48 : done:
    2333             : 
    2334          32 :         smbXcli_conn_disconnect(transport2->conn, NT_STATUS_LOCAL_DISCONNECT);
    2335             : 
    2336          32 :         if (h1 != NULL) {
    2337          16 :                 smb2_util_close(tree1, *h1);
    2338             :         }
    2339             : 
    2340          32 :         smb2_deltree(tree1, BASEDIR);
    2341             : 
    2342          32 :         TALLOC_FREE(tree1);
    2343          32 :         talloc_free(mem_ctx);
    2344             : 
    2345          32 :         return ret;
    2346             : }
    2347             : 
    2348             : /**
    2349             :  * This tests replay with a pending open on a single
    2350             :  * channel.
    2351             :  *
    2352             :  * With a durablev2 request containing a create_guid,
    2353             :  * a share_access of READ/WRITE/DELETE,
    2354             :  * but without asking for an oplock nor a lease.
    2355             :  *
    2356             :  * While another client holds a batch oplock.
    2357             :  * And allows share_access of READ/WRITE/DELETE.
    2358             :  *
    2359             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2360             :  *
    2361             :  * This expects the sane reject status of
    2362             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    2363             :  *
    2364             :  * It won't pass against Windows as it returns
    2365             :  * NT_STATUS_ACCESS_DENIED see
    2366             :  * test_dhv2_pending1n_vs_oplock_windows().
    2367             :  */
    2368           5 : static bool test_dhv2_pending1n_vs_oplock_sane(struct torture_context *tctx,
    2369             :                                                struct smb2_tree *tree1,
    2370             :                                                struct smb2_tree *tree2)
    2371             : {
    2372           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2373             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2374             :                                            SMB2_OPLOCK_LEVEL_NONE,
    2375           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    2376             :                                            tree1, tree2);
    2377             : }
    2378             : 
    2379             : /**
    2380             :  * This tests replay with a pending open on a single
    2381             :  * channel.
    2382             :  *
    2383             :  * With a durablev2 request containing a create_guid,
    2384             :  * a share_access of READ/WRITE/DELETE,
    2385             :  * but without asking for an oplock nor a lease.
    2386             :  *
    2387             :  * While another client holds a batch oplock.
    2388             :  * And allows share_access of READ/WRITE/DELETE.
    2389             :  *
    2390             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2391             :  *
    2392             :  * This expects the strange reject status of
    2393             :  * NT_STATUS_ACCESS_DENIED, which is returned
    2394             :  * by Windows Servers.
    2395             :  *
    2396             :  * It won't pass against Samba as it returns
    2397             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    2398             :  * test_dhv2_pending1n_vs_oplock_sane.
    2399             :  */
    2400           5 : static bool test_dhv2_pending1n_vs_oplock_windows(struct torture_context *tctx,
    2401             :                                                   struct smb2_tree *tree1,
    2402             :                                                   struct smb2_tree *tree2)
    2403             : {
    2404           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2405             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2406             :                                            SMB2_OPLOCK_LEVEL_NONE,
    2407           5 :                                            NT_STATUS_ACCESS_DENIED,
    2408             :                                            tree1, tree2);
    2409             : }
    2410             : 
    2411             : /**
    2412             :  * This tests replay with a pending open on a single
    2413             :  * channel.
    2414             :  *
    2415             :  * With a durablev2 request containing a create_guid,
    2416             :  * a share_access of READ/WRITE/DELETE,
    2417             :  * but without asking for an oplock nor a lease.
    2418             :  *
    2419             :  * While another client holds an RWH lease.
    2420             :  * And allows share_access of READ/WRITE/DELETE.
    2421             :  *
    2422             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2423             :  *
    2424             :  * This expects the sane reject status of
    2425             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    2426             :  *
    2427             :  * It won't pass against Windows as it returns
    2428             :  * NT_STATUS_ACCESS_DENIED see
    2429             :  * test_dhv2_pending1n_vs_lease_windows().
    2430             :  */
    2431           5 : static bool test_dhv2_pending1n_vs_lease_sane(struct torture_context *tctx,
    2432             :                                               struct smb2_tree *tree1,
    2433             :                                               struct smb2_tree *tree2)
    2434             : {
    2435           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2436             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2437             :                                            SMB2_OPLOCK_LEVEL_NONE,
    2438           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    2439             :                                            tree1, tree2);
    2440             : }
    2441             : 
    2442             : /**
    2443             :  * This tests replay with a pending open on a single
    2444             :  * channel.
    2445             :  *
    2446             :  * With a durablev2 request containing a create_guid,
    2447             :  * a share_access of READ/WRITE/DELETE,
    2448             :  * but without asking for an oplock nor a lease.
    2449             :  *
    2450             :  * While another client holds an RWH lease.
    2451             :  * And allows share_access of READ/WRITE/DELETE.
    2452             :  *
    2453             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2454             :  *
    2455             :  * This expects the strange reject status of
    2456             :  * NT_STATUS_ACCESS_DENIED, which is returned
    2457             :  * by Windows Servers.
    2458             :  *
    2459             :  * It won't pass against Samba as it returns
    2460             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    2461             :  * test_dhv2_pending1n_vs_lease_sane.
    2462             :  */
    2463           5 : static bool test_dhv2_pending1n_vs_lease_windows(struct torture_context *tctx,
    2464             :                                                  struct smb2_tree *tree1,
    2465             :                                                  struct smb2_tree *tree2)
    2466             : {
    2467           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2468             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2469             :                                            SMB2_OPLOCK_LEVEL_NONE,
    2470           5 :                                            NT_STATUS_ACCESS_DENIED,
    2471             :                                            tree1, tree2);
    2472             : }
    2473             : 
    2474             : /**
    2475             :  * This tests replay with a pending open on a single
    2476             :  * channel.
    2477             :  *
    2478             :  * With a durablev2 request containing a create_guid,
    2479             :  * a share_access of READ/WRITE/DELETE,
    2480             :  * and asking for a v2 lease.
    2481             :  *
    2482             :  * While another client holds a batch oplock.
    2483             :  * And allows share_access of READ/WRITE/DELETE.
    2484             :  *
    2485             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2486             :  *
    2487             :  * This expects the sane reject status of
    2488             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    2489             :  *
    2490             :  * It won't pass against Windows as it returns
    2491             :  * NT_STATUS_ACCESS_DENIED see
    2492             :  * test_dhv2_pending1l_vs_oplock_windows().
    2493             :  */
    2494           5 : static bool test_dhv2_pending1l_vs_oplock_sane(struct torture_context *tctx,
    2495             :                                                struct smb2_tree *tree1,
    2496             :                                                struct smb2_tree *tree2)
    2497             : {
    2498           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2499             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2500             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2501           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    2502             :                                            tree1, tree2);
    2503             : }
    2504             : 
    2505             : /**
    2506             :  * This tests replay with a pending open on a single
    2507             :  * channel.
    2508             :  *
    2509             :  * With a durablev2 request containing a create_guid,
    2510             :  * a share_access of READ/WRITE/DELETE,
    2511             :  * and asking for a v2 lease.
    2512             :  *
    2513             :  * While another client holds a batch oplock.
    2514             :  * And allows share_access of READ/WRITE/DELETE.
    2515             :  *
    2516             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2517             :  *
    2518             :  * This expects the strange reject status of
    2519             :  * NT_STATUS_ACCESS_DENIED, which is returned
    2520             :  * by Windows Servers.
    2521             :  *
    2522             :  * It won't pass against Samba as it returns
    2523             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    2524             :  * test_dhv2_pending1l_vs_oplock_sane.
    2525             :  */
    2526           5 : static bool test_dhv2_pending1l_vs_oplock_windows(struct torture_context *tctx,
    2527             :                                                   struct smb2_tree *tree1,
    2528             :                                                   struct smb2_tree *tree2)
    2529             : {
    2530           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2531             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2532             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2533           5 :                                            NT_STATUS_ACCESS_DENIED,
    2534             :                                            tree1, tree2);
    2535             : }
    2536             : 
    2537             : /**
    2538             :  * This tests replay with a pending open on a single
    2539             :  * channel.
    2540             :  *
    2541             :  * With a durablev2 request containing a create_guid,
    2542             :  * a share_access of READ/WRITE/DELETE,
    2543             :  * and asking for a v2 lease.
    2544             :  *
    2545             :  * While another client holds an RWH lease.
    2546             :  * And allows share_access of READ/WRITE/DELETE.
    2547             :  *
    2548             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2549             :  *
    2550             :  * This expects the sane reject status of
    2551             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    2552             :  *
    2553             :  * It won't pass against Windows as it returns
    2554             :  * NT_STATUS_ACCESS_DENIED see
    2555             :  * test_dhv2_pending1l_vs_lease_windows().
    2556             :  */
    2557           5 : static bool test_dhv2_pending1l_vs_lease_sane(struct torture_context *tctx,
    2558             :                                               struct smb2_tree *tree1,
    2559             :                                               struct smb2_tree *tree2)
    2560             : {
    2561           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2562             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2563             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2564           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    2565             :                                            tree1, tree2);
    2566             : }
    2567             : 
    2568             : /**
    2569             :  * This tests replay with a pending open on a single
    2570             :  * channel.
    2571             :  *
    2572             :  * With a durablev2 request containing a create_guid,
    2573             :  * a share_access of READ/WRITE/DELETE,
    2574             :  * and asking for a v2 lease.
    2575             :  *
    2576             :  * While another client holds an RWH lease.
    2577             :  * And allows share_access of READ/WRITE/DELETE.
    2578             :  *
    2579             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2580             :  *
    2581             :  * This expects the strange reject status of
    2582             :  * NT_STATUS_ACCESS_DENIED, which is returned
    2583             :  * by Windows Servers.
    2584             :  *
    2585             :  * It won't pass against Samba as it returns
    2586             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    2587             :  * test_dhv2_pending1l_vs_lease_sane.
    2588             :  */
    2589           5 : static bool test_dhv2_pending1l_vs_lease_windows(struct torture_context *tctx,
    2590             :                                                  struct smb2_tree *tree1,
    2591             :                                                  struct smb2_tree *tree2)
    2592             : {
    2593           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2594             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2595             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2596           5 :                                            NT_STATUS_ACCESS_DENIED,
    2597             :                                            tree1, tree2);
    2598             : }
    2599             : 
    2600             : /**
    2601             :  * This tests replay with a pending open on a single
    2602             :  * channel.
    2603             :  *
    2604             :  * With a durablev2 request containing a create_guid,
    2605             :  * a share_access of READ/WRITE/DELETE,
    2606             :  * and asking for a batch oplock.
    2607             :  *
    2608             :  * While another client holds a batch oplock.
    2609             :  * And allows share_access of READ/WRITE/DELETE.
    2610             :  *
    2611             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2612             :  *
    2613             :  * This expects the sane reject status of
    2614             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    2615             :  *
    2616             :  * It won't pass against Windows as it returns
    2617             :  * NT_STATUS_ACCESS_DENIED see
    2618             :  * test_dhv2_pending1o_vs_oplock_windows().
    2619             :  */
    2620           5 : static bool test_dhv2_pending1o_vs_oplock_sane(struct torture_context *tctx,
    2621             :                                               struct smb2_tree *tree1,
    2622             :                                               struct smb2_tree *tree2)
    2623             : {
    2624           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2625             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2626             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2627           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    2628             :                                            tree1, tree2);
    2629             : }
    2630             : 
    2631             : /**
    2632             :  * This tests replay with a pending open on a single
    2633             :  * channel.
    2634             :  *
    2635             :  * With a durablev2 request containing a create_guid,
    2636             :  * a share_access of READ/WRITE/DELETE,
    2637             :  * and asking for a batch oplock.
    2638             :  *
    2639             :  * While another client holds a batch oplock.
    2640             :  * And allows share_access of READ/WRITE/DELETE.
    2641             :  *
    2642             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2643             :  *
    2644             :  * This expects the strange reject status of
    2645             :  * NT_STATUS_ACCESS_DENIED, which is returned
    2646             :  * by Windows Servers.
    2647             :  *
    2648             :  * It won't pass against Samba as it returns
    2649             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    2650             :  * test_dhv2_pending1o_vs_oplock_sane.
    2651             :  */
    2652           5 : static bool test_dhv2_pending1o_vs_oplock_windows(struct torture_context *tctx,
    2653             :                                                   struct smb2_tree *tree1,
    2654             :                                                   struct smb2_tree *tree2)
    2655             : {
    2656           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2657             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2658             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2659           5 :                                            NT_STATUS_ACCESS_DENIED,
    2660             :                                            tree1, tree2);
    2661             : }
    2662             : 
    2663             : /**
    2664             :  * This tests replay with a pending open on a single
    2665             :  * channel.
    2666             :  *
    2667             :  * With a durablev2 request containing a create_guid,
    2668             :  * a share_access of READ/WRITE/DELETE,
    2669             :  * and asking for a batch oplock.
    2670             :  *
    2671             :  * While another client holds an RWH lease.
    2672             :  * And allows share_access of READ/WRITE/DELETE.
    2673             :  *
    2674             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2675             :  *
    2676             :  * This expects the sane reject status of
    2677             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    2678             :  *
    2679             :  * It won't pass against Windows as it returns
    2680             :  * NT_STATUS_ACCESS_DENIED see
    2681             :  * test_dhv2_pending1o_vs_lease_windows().
    2682             :  */
    2683           5 : static bool test_dhv2_pending1o_vs_lease_sane(struct torture_context *tctx,
    2684             :                                               struct smb2_tree *tree1,
    2685             :                                               struct smb2_tree *tree2_1)
    2686             : {
    2687           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2688             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2689             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2690           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    2691             :                                            tree1, tree2_1);
    2692             : }
    2693             : 
    2694             : /**
    2695             :  * This tests replay with a pending open on a single
    2696             :  * channel.
    2697             :  *
    2698             :  * With a durablev2 request containing a create_guid,
    2699             :  * a share_access of READ/WRITE/DELETE,
    2700             :  * and asking for a batch oplock.
    2701             :  *
    2702             :  * While another client holds an RWH lease.
    2703             :  * And allows share_access of READ/WRITE/DELETE.
    2704             :  *
    2705             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2706             :  *
    2707             :  * This expects the strange reject status of
    2708             :  * NT_STATUS_ACCESS_DENIED, which is returned
    2709             :  * by Windows Servers.
    2710             :  *
    2711             :  * It won't pass against Samba as it returns
    2712             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    2713             :  * test_dhv2_pending1o_vs_lease_sane.
    2714             :  */
    2715           5 : static bool test_dhv2_pending1o_vs_lease_windows(struct torture_context *tctx,
    2716             :                                                  struct smb2_tree *tree1,
    2717             :                                                  struct smb2_tree *tree2)
    2718             : {
    2719           5 :         return _test_dhv2_pending1_vs_hold(tctx, __func__,
    2720             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    2721             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    2722           5 :                                            NT_STATUS_ACCESS_DENIED,
    2723             :                                            tree1, tree2);
    2724             : }
    2725             : 
    2726             : /**
    2727             :  * This tests replay with a pending open with 4 channels
    2728             :  * and closed transports on the client and server side.
    2729             :  *
    2730             :  * With a durablev2 request containing a create_guid and
    2731             :  * a share_access of READ/WRITE/DELETE:
    2732             :  * - client2_level = NONE:
    2733             :  *   but without asking for an oplock nor a lease.
    2734             :  * - client2_level = BATCH:
    2735             :  *   and asking for a batch oplock.
    2736             :  * - client2_level = LEASE
    2737             :  *   and asking for an RWH lease.
    2738             :  *
    2739             :  * While another client holds a batch oplock or
    2740             :  * RWH lease. (client1_level => LEASE or BATCH).
    2741             :  * And allows share_access of READ/WRITE/DELETE.
    2742             :  *
    2743             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    2744             :  */
    2745          60 : static bool _test_dhv2_pending2_vs_hold(struct torture_context *tctx,
    2746             :                                         const char *testname,
    2747             :                                         uint8_t client1_level,
    2748             :                                         uint8_t client2_level,
    2749             :                                         NTSTATUS reject_status,
    2750             :                                         struct smb2_tree *tree1,
    2751             :                                         struct smb2_tree *tree2_1)
    2752             : {
    2753          60 :         const char *host = torture_setting_string(tctx, "host", NULL);
    2754          60 :         const char *share = torture_setting_string(tctx, "share", NULL);
    2755          60 :         struct cli_credentials *credentials = samba_cmdline_get_creds();
    2756             :         NTSTATUS status;
    2757          60 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2758             :         struct smb2_handle _h1;
    2759          60 :         struct smb2_handle *h1 = NULL;
    2760             :         struct smb2_handle _h24;
    2761          60 :         struct smb2_handle *h24 = NULL;
    2762             :         struct smb2_create io1, io21, io22, io23, io24;
    2763          60 :         struct GUID create_guid1 = GUID_random();
    2764          60 :         struct GUID create_guid2 = GUID_random();
    2765          60 :         struct smb2_request *req21 = NULL;
    2766          60 :         bool ret = true;
    2767             :         char fname[256];
    2768          60 :         struct smb2_transport *transport1 = tree1->session->transport;
    2769             :         uint32_t server_capabilities;
    2770             :         uint32_t share_capabilities;
    2771             :         struct smb2_lease ls1;
    2772             :         uint64_t lease_key1;
    2773          60 :         uint16_t lease_epoch1 = 0;
    2774             :         struct smb2_lease ls2;
    2775             :         uint64_t lease_key2;
    2776          60 :         uint16_t lease_epoch2 = 0;
    2777             :         bool share_is_so;
    2778          60 :         struct smb2_transport *transport2_1 = tree2_1->session->transport;
    2779          60 :         int request_timeout2 = transport2_1->options.request_timeout;
    2780             :         struct smbcli_options options2x;
    2781          60 :         struct smb2_tree *tree2_2 = NULL;
    2782          60 :         struct smb2_tree *tree2_3 = NULL;
    2783          60 :         struct smb2_tree *tree2_4 = NULL;
    2784          60 :         struct smb2_transport *transport2_2 = NULL;
    2785          60 :         struct smb2_transport *transport2_3 = NULL;
    2786          60 :         struct smb2_transport *transport2_4 = NULL;
    2787          60 :         struct smb2_session *session2_1 = tree2_1->session;
    2788          60 :         struct smb2_session *session2_2 = NULL;
    2789          60 :         struct smb2_session *session2_3 = NULL;
    2790          60 :         struct smb2_session *session2_4 = NULL;
    2791          60 :         uint16_t csn2 = 1;
    2792          60 :         const char *hold_name = NULL;
    2793             : 
    2794          60 :         switch (client1_level) {
    2795          30 :         case SMB2_OPLOCK_LEVEL_LEASE:
    2796          30 :                 hold_name = "RWH Lease";
    2797          30 :                 break;
    2798          30 :         case SMB2_OPLOCK_LEVEL_BATCH:
    2799          30 :                 hold_name = "BATCH Oplock";
    2800          30 :                 break;
    2801           0 :         default:
    2802           0 :                 smb_panic(__location__);
    2803             :                 break;
    2804             :         }
    2805             : 
    2806          60 :         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
    2807          12 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    2808             :                                    "replay tests\n");
    2809             :         }
    2810             : 
    2811          48 :         server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
    2812          48 :         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
    2813           0 :                 torture_skip(tctx, "MULTI_CHANNEL are not supported");
    2814             :         }
    2815          48 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
    2816          24 :                 if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
    2817           0 :                     client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2818          16 :                         torture_skip(tctx, "leases are not supported");
    2819             :                 }
    2820             :         }
    2821             : 
    2822          32 :         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
    2823          32 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    2824          32 :         if (share_is_so) {
    2825           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
    2826             :                              "%s not supported on SCALEOUT share",
    2827             :                              hold_name));
    2828             :         }
    2829             : 
    2830             :         /* Add some random component to the file name. */
    2831          32 :         snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
    2832             :                  BASEDIR, testname, generate_random_str(tctx, 8));
    2833             : 
    2834          32 :         options2x = transport2_1->options;
    2835          32 :         options2x.only_negprot = true;
    2836             : 
    2837          32 :         status = smb2_connect(tctx,
    2838             :                               host,
    2839             :                               lpcfg_smb_ports(tctx->lp_ctx),
    2840             :                               share,
    2841             :                               lpcfg_resolve_context(tctx->lp_ctx),
    2842             :                               credentials,
    2843             :                               &tree2_2,
    2844             :                               tctx->ev,
    2845             :                               &options2x,
    2846             :                               lpcfg_socket_options(tctx->lp_ctx),
    2847             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
    2848             :                               );
    2849          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2850             :                                         "smb2_connect failed");
    2851          32 :         transport2_2 = tree2_2->session->transport;
    2852             : 
    2853          32 :         session2_2 = smb2_session_channel(transport2_2,
    2854             :                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
    2855             :                                           tctx,
    2856             :                                           session2_1);
    2857          32 :         torture_assert(tctx, session2_2 != NULL, "smb2_session_channel failed");
    2858             : 
    2859          32 :         status = smb2_session_setup_spnego(session2_2,
    2860             :                                            credentials,
    2861             :                                            0 /* previous_session_id */);
    2862          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2863             :                                         "smb2_session_setup_spnego failed");
    2864          32 :         tree2_2->smbXcli = tree2_1->smbXcli;
    2865          32 :         tree2_2->session = session2_2;
    2866             : 
    2867          32 :         status = smb2_connect(tctx,
    2868             :                               host,
    2869             :                               lpcfg_smb_ports(tctx->lp_ctx),
    2870             :                               share,
    2871             :                               lpcfg_resolve_context(tctx->lp_ctx),
    2872             :                               credentials,
    2873             :                               &tree2_3,
    2874             :                               tctx->ev,
    2875             :                               &options2x,
    2876             :                               lpcfg_socket_options(tctx->lp_ctx),
    2877             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
    2878             :                               );
    2879          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2880             :                                         "smb2_connect failed");
    2881          32 :         transport2_3 = tree2_3->session->transport;
    2882             : 
    2883          32 :         session2_3 = smb2_session_channel(transport2_3,
    2884             :                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
    2885             :                                           tctx,
    2886             :                                           session2_1);
    2887          32 :         torture_assert(tctx, session2_3 != NULL, "smb2_session_channel failed");
    2888             : 
    2889          32 :         status = smb2_session_setup_spnego(session2_3,
    2890             :                                            credentials,
    2891             :                                            0 /* previous_session_id */);
    2892          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2893             :                                         "smb2_session_setup_spnego failed");
    2894          32 :         tree2_3->smbXcli = tree2_1->smbXcli;
    2895          32 :         tree2_3->session = session2_3;
    2896             : 
    2897          32 :         status = smb2_connect(tctx,
    2898             :                               host,
    2899             :                               lpcfg_smb_ports(tctx->lp_ctx),
    2900             :                               share,
    2901             :                               lpcfg_resolve_context(tctx->lp_ctx),
    2902             :                               credentials,
    2903             :                               &tree2_4,
    2904             :                               tctx->ev,
    2905             :                               &options2x,
    2906             :                               lpcfg_socket_options(tctx->lp_ctx),
    2907             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
    2908             :                               );
    2909          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2910             :                                         "smb2_connect failed");
    2911          32 :         transport2_4 = tree2_4->session->transport;
    2912             : 
    2913          32 :         session2_4 = smb2_session_channel(transport2_4,
    2914             :                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
    2915             :                                           tctx,
    2916             :                                           session2_1);
    2917          32 :         torture_assert(tctx, session2_4 != NULL, "smb2_session_channel failed");
    2918             : 
    2919          32 :         status = smb2_session_setup_spnego(session2_4,
    2920             :                                            credentials,
    2921             :                                            0 /* previous_session_id */);
    2922          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2923             :                                         "smb2_session_setup_spnego failed");
    2924          32 :         tree2_4->smbXcli = tree2_1->smbXcli;
    2925          32 :         tree2_4->session = session2_4;
    2926             : 
    2927          32 :         smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
    2928             : 
    2929          32 :         torture_reset_break_info(tctx, &break_info);
    2930          32 :         break_info.oplock_skip_ack = true;
    2931          32 :         torture_reset_lease_break_info(tctx, &lease_break_info);
    2932          32 :         lease_break_info.lease_skip_ack = true;
    2933          32 :         transport1->oplock.handler = torture_oplock_ack_handler;
    2934          32 :         transport1->oplock.private_data = tree1;
    2935          32 :         transport1->lease.handler = torture_lease_handler;
    2936          32 :         transport1->lease.private_data = tree1;
    2937          32 :         smb2_keepalive(transport1);
    2938          32 :         transport2_1->oplock.handler = torture_oplock_ack_handler;
    2939          32 :         transport2_1->oplock.private_data = tree2_1;
    2940          32 :         transport2_1->lease.handler = torture_lease_handler;
    2941          32 :         transport2_1->lease.private_data = tree2_1;
    2942          32 :         smb2_keepalive(transport2_1);
    2943          32 :         transport2_2->oplock.handler = torture_oplock_ack_handler;
    2944          32 :         transport2_2->oplock.private_data = tree2_2;
    2945          32 :         transport2_2->lease.handler = torture_lease_handler;
    2946          32 :         transport2_2->lease.private_data = tree2_2;
    2947          32 :         smb2_keepalive(transport2_2);
    2948          32 :         transport2_3->oplock.handler = torture_oplock_ack_handler;
    2949          32 :         transport2_3->oplock.private_data = tree2_3;
    2950          32 :         transport2_3->lease.handler = torture_lease_handler;
    2951          32 :         transport2_3->lease.private_data = tree2_3;
    2952          32 :         smb2_keepalive(transport2_3);
    2953          32 :         transport2_4->oplock.handler = torture_oplock_ack_handler;
    2954          32 :         transport2_4->oplock.private_data = tree2_4;
    2955          32 :         transport2_4->lease.handler = torture_lease_handler;
    2956          32 :         transport2_4->lease.private_data = tree2_4;
    2957          32 :         smb2_keepalive(transport2_4);
    2958             : 
    2959          32 :         smb2_util_unlink(tree1, fname);
    2960          32 :         status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
    2961          32 :         CHECK_STATUS(status, NT_STATUS_OK);
    2962          32 :         smb2_util_close(tree1, _h1);
    2963          32 :         CHECK_VAL(break_info.count, 0);
    2964             : 
    2965          32 :         lease_key1 = random();
    2966          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2967          12 :                 smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
    2968          12 :                         lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
    2969             :         } else {
    2970          20 :                 smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
    2971             :         }
    2972          32 :         io1.in.durable_open = false;
    2973          32 :         io1.in.durable_open_v2 = true;
    2974          32 :         io1.in.persistent_open = false;
    2975          32 :         io1.in.create_guid = create_guid1;
    2976          32 :         io1.in.timeout = UINT32_MAX;
    2977             : 
    2978          32 :         status = smb2_create(tree1, mem_ctx, &io1);
    2979          32 :         CHECK_STATUS(status, NT_STATUS_OK);
    2980          32 :         _h1 = io1.out.file.handle;
    2981          32 :         h1 = &_h1;
    2982          32 :         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    2983          32 :         CHECK_VAL(io1.out.durable_open, false);
    2984          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2985          12 :                 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
    2986          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
    2987          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
    2988          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
    2989          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_state,
    2990             :                           smb2_util_lease_state("RHW"));
    2991             :         } else {
    2992          20 :                 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    2993             :         }
    2994          32 :         CHECK_VAL(io1.out.durable_open_v2, true);
    2995          32 :         CHECK_VAL(io1.out.timeout, 300*1000);
    2996             : 
    2997          32 :         lease_key2 = random();
    2998          32 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    2999           8 :                 smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
    3000           8 :                         lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
    3001             :         } else {
    3002          24 :                 smb2_oplock_create(&io21, fname, client2_level);
    3003             :         }
    3004          32 :         io21.in.durable_open = false;
    3005          32 :         io21.in.durable_open_v2 = true;
    3006          32 :         io21.in.persistent_open = false;
    3007          32 :         io21.in.create_guid = create_guid2;
    3008          32 :         io21.in.timeout = UINT32_MAX;
    3009          32 :         io24 = io23 = io22 = io21;
    3010             : 
    3011          32 :         req21 = smb2_create_send(tree2_1, &io21);
    3012          32 :         torture_assert(tctx, req21 != NULL, "req21");
    3013             : 
    3014          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3015          12 :                 const struct smb2_lease_break *lb =
    3016             :                         &lease_break_info.lease_break;
    3017          12 :                 const struct smb2_lease *l = &lb->current_lease;
    3018          12 :                 const struct smb2_lease_key *k = &l->lease_key;
    3019             : 
    3020          12 :                 torture_wait_for_lease_break(tctx);
    3021          12 :                 CHECK_VAL(break_info.count, 0);
    3022          12 :                 CHECK_VAL(lease_break_info.count, 1);
    3023             : 
    3024          12 :                 torture_assert(tctx,
    3025             :                         lease_break_info.lease_transport == transport1,
    3026             :                         "expect lease break on transport1\n");
    3027          12 :                 CHECK_VAL(k->data[0], lease_key1);
    3028          12 :                 CHECK_VAL(k->data[1], ~lease_key1);
    3029          12 :                 CHECK_VAL(lb->new_lease_state,
    3030             :                           smb2_util_lease_state("RH"));
    3031          12 :                 CHECK_VAL(lb->break_flags,
    3032             :                           SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
    3033          12 :                 CHECK_VAL(lb->new_epoch, lease_epoch1+1);
    3034          12 :                 lease_epoch1 += 1;
    3035             :         } else {
    3036          20 :                 torture_wait_for_oplock_break(tctx);
    3037          20 :                 CHECK_VAL(break_info.count, 1);
    3038          20 :                 CHECK_VAL(lease_break_info.count, 0);
    3039             : 
    3040          20 :                 torture_assert(tctx,
    3041             :                         break_info.received_transport == transport1,
    3042             :                         "expect oplock break on transport1\n");
    3043          20 :                 CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
    3044          20 :                 CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
    3045          20 :                 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    3046             :         }
    3047             : 
    3048          32 :         torture_reset_break_info(tctx, &break_info);
    3049          32 :         break_info.oplock_skip_ack = true;
    3050          32 :         torture_reset_lease_break_info(tctx, &lease_break_info);
    3051          32 :         lease_break_info.lease_skip_ack = true;
    3052             : 
    3053          32 :         WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
    3054             : 
    3055          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3056          12 :                 torture_wait_for_lease_break(tctx);
    3057             :         } else {
    3058          20 :                 torture_wait_for_oplock_break(tctx);
    3059             :         }
    3060          32 :         CHECK_VAL(break_info.count, 0);
    3061          32 :         CHECK_VAL(lease_break_info.count, 0);
    3062             : 
    3063          32 :         smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
    3064          32 :         smb2cli_session_reset_channel_sequence(session2_1->smbXcli, csn2++);
    3065             : 
    3066          32 :         smb2cli_session_start_replay(session2_2->smbXcli);
    3067          32 :         transport2_2->options.request_timeout = 5;
    3068          32 :         status = smb2_create(tree2_2, tctx, &io22);
    3069          32 :         transport2_2->options.request_timeout = request_timeout2;
    3070          32 :         CHECK_STATUS(status, reject_status);
    3071          16 :         smb2cli_session_stop_replay(session2_2->smbXcli);
    3072             : 
    3073          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3074           6 :                 torture_wait_for_lease_break(tctx);
    3075             :         } else {
    3076          10 :                 torture_wait_for_oplock_break(tctx);
    3077             :         }
    3078          16 :         CHECK_VAL(break_info.count, 0);
    3079          16 :         CHECK_VAL(lease_break_info.count, 0);
    3080             : 
    3081          16 :         smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
    3082          16 :         smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
    3083             : 
    3084          16 :         smb2cli_session_start_replay(session2_3->smbXcli);
    3085          16 :         transport2_3->options.request_timeout = 5;
    3086          16 :         status = smb2_create(tree2_3, tctx, &io23);
    3087          16 :         transport2_3->options.request_timeout = request_timeout2;
    3088          16 :         CHECK_STATUS(status, reject_status);
    3089          16 :         smb2cli_session_stop_replay(session2_3->smbXcli);
    3090             : 
    3091          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3092           6 :                 torture_wait_for_lease_break(tctx);
    3093             :         } else {
    3094          10 :                 torture_wait_for_oplock_break(tctx);
    3095             :         }
    3096          16 :         CHECK_VAL(break_info.count, 0);
    3097          16 :         CHECK_VAL(lease_break_info.count, 0);
    3098             : 
    3099          16 :         smb2_util_close(tree1, _h1);
    3100          16 :         h1 = NULL;
    3101             : 
    3102          16 :         status = smb2_create_recv(req21, tctx, &io21);
    3103          16 :         CHECK_STATUS(status, NT_STATUS_LOCAL_DISCONNECT);
    3104             : 
    3105          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3106           6 :                 torture_wait_for_lease_break(tctx);
    3107             :         } else {
    3108          10 :                 torture_wait_for_oplock_break(tctx);
    3109             :         }
    3110          16 :         CHECK_VAL(break_info.count, 0);
    3111          16 :         CHECK_VAL(lease_break_info.count, 0);
    3112             : 
    3113          16 :         smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
    3114          16 :         smb2cli_session_reset_channel_sequence(session2_3->smbXcli, csn2++);
    3115             : 
    3116          16 :         smb2cli_session_start_replay(session2_4->smbXcli);
    3117          16 :         status = smb2_create(tree2_4, tctx, &io24);
    3118          16 :         smb2cli_session_stop_replay(session2_4->smbXcli);
    3119          16 :         CHECK_STATUS(status, NT_STATUS_OK);
    3120          16 :         _h24 = io24.out.file.handle;
    3121          16 :         h24 = &_h24;
    3122          16 :         CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
    3123          16 :         CHECK_VAL(io24.out.oplock_level, client2_level);
    3124          16 :         CHECK_VAL(io24.out.durable_open, false);
    3125          16 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3126           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
    3127           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
    3128           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
    3129           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_state,
    3130             :                           smb2_util_lease_state("RHW"));
    3131           4 :                 CHECK_VAL(io24.out.durable_open_v2, true);
    3132           4 :                 CHECK_VAL(io24.out.timeout, 300*1000);
    3133          12 :         } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
    3134           6 :                 CHECK_VAL(io24.out.durable_open_v2, true);
    3135           6 :                 CHECK_VAL(io24.out.timeout, 300*1000);
    3136             :         } else {
    3137           6 :                 CHECK_VAL(io24.out.durable_open_v2, false);
    3138             :         }
    3139             : 
    3140          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3141           6 :                 torture_wait_for_lease_break(tctx);
    3142             :         } else {
    3143          10 :                 torture_wait_for_oplock_break(tctx);
    3144             :         }
    3145          16 :         CHECK_VAL(break_info.count, 0);
    3146          16 :         CHECK_VAL(lease_break_info.count, 0);
    3147          16 :         status = smb2_util_close(tree2_4, *h24);
    3148          16 :         CHECK_STATUS(status, NT_STATUS_OK);
    3149          16 :         h24 = NULL;
    3150             : 
    3151          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3152           6 :                 torture_wait_for_lease_break(tctx);
    3153             :         } else {
    3154          10 :                 torture_wait_for_oplock_break(tctx);
    3155             :         }
    3156          16 :         CHECK_VAL(break_info.count, 0);
    3157          16 :         CHECK_VAL(lease_break_info.count, 0);
    3158             : 
    3159          48 : done:
    3160             : 
    3161          32 :         smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
    3162          32 :         smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
    3163          32 :         smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
    3164          32 :         smbXcli_conn_disconnect(transport2_4->conn, NT_STATUS_LOCAL_DISCONNECT);
    3165             : 
    3166          32 :         if (h1 != NULL) {
    3167          16 :                 smb2_util_close(tree1, *h1);
    3168             :         }
    3169             : 
    3170          32 :         smb2_deltree(tree1, BASEDIR);
    3171             : 
    3172          32 :         TALLOC_FREE(tree1);
    3173          32 :         talloc_free(mem_ctx);
    3174             : 
    3175          32 :         return ret;
    3176             : }
    3177             : 
    3178             : /**
    3179             :  * This tests replay with a pending open with 4 channels
    3180             :  * and closed transports on the client and server side.
    3181             :  *
    3182             :  * With a durablev2 request containing a create_guid,
    3183             :  * a share_access of READ/WRITE/DELETE,
    3184             :  * but without asking for an oplock nor a lease.
    3185             :  *
    3186             :  * While another client holds an RWH lease.
    3187             :  * And allows share_access of READ/WRITE/DELETE.
    3188             :  *
    3189             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3190             :  *
    3191             :  * This expects the sane reject status of
    3192             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    3193             :  *
    3194             :  * It won't pass against Windows as it returns
    3195             :  * NT_STATUS_ACCESS_DENIED see
    3196             :  * test_dhv2_pending2n_vs_lease_windows().
    3197             :  */
    3198           5 : static bool test_dhv2_pending2n_vs_lease_sane(struct torture_context *tctx,
    3199             :                                               struct smb2_tree *tree1,
    3200             :                                               struct smb2_tree *tree2_1)
    3201             : {
    3202           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3203             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3204             :                                            SMB2_OPLOCK_LEVEL_NONE,
    3205           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    3206             :                                            tree1, tree2_1);
    3207             : }
    3208             : 
    3209             : /**
    3210             :  * This tests replay with a pending open with 4 channels
    3211             :  * and closed transports on the client and server side.
    3212             :  *
    3213             :  * With a durablev2 request containing a create_guid,
    3214             :  * a share_access of READ/WRITE/DELETE,
    3215             :  * but without asking for an oplock nor a lease.
    3216             :  *
    3217             :  * While another client holds an RWH lease.
    3218             :  * And allows share_access of READ/WRITE/DELETE.
    3219             :  *
    3220             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3221             :  *
    3222             :  * This expects the strange reject status of
    3223             :  * NT_STATUS_ACCESS_DENIED, which is returned
    3224             :  * by Windows Servers.
    3225             :  *
    3226             :  * It won't pass against Samba as it returns
    3227             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    3228             :  * test_dhv2_pending2n_vs_lease_sane().
    3229             :  */
    3230           5 : static bool test_dhv2_pending2n_vs_lease_windows(struct torture_context *tctx,
    3231             :                                                  struct smb2_tree *tree1,
    3232             :                                                  struct smb2_tree *tree2_1)
    3233             : {
    3234           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3235             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3236             :                                            SMB2_OPLOCK_LEVEL_NONE,
    3237           5 :                                            NT_STATUS_ACCESS_DENIED,
    3238             :                                            tree1, tree2_1);
    3239             : }
    3240             : 
    3241             : /**
    3242             :  * This tests replay with a pending open with 4 channels
    3243             :  * and closed transports on the client and server side.
    3244             :  *
    3245             :  * With a durablev2 request containing a create_guid,
    3246             :  * a share_access of READ/WRITE/DELETE,
    3247             :  * but without asking for an oplock nor a lease.
    3248             :  *
    3249             :  * While another client holds a batch oplock.
    3250             :  * And allows share_access of READ/WRITE/DELETE.
    3251             :  *
    3252             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3253             :  *
    3254             :  * This expects the sane reject status of
    3255             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    3256             :  *
    3257             :  * It won't pass against Windows as it returns
    3258             :  * NT_STATUS_ACCESS_DENIED see
    3259             :  * test_dhv2_pending2n_vs_oplock_windows().
    3260             :  */
    3261           5 : static bool test_dhv2_pending2n_vs_oplock_sane(struct torture_context *tctx,
    3262             :                                                struct smb2_tree *tree1,
    3263             :                                                struct smb2_tree *tree2_1)
    3264             : {
    3265           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3266             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3267             :                                            SMB2_OPLOCK_LEVEL_NONE,
    3268           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    3269             :                                            tree1, tree2_1);
    3270             : }
    3271             : 
    3272             : /**
    3273             :  * This tests replay with a pending open with 4 channels
    3274             :  * and closed transports on the client and server side.
    3275             :  *
    3276             :  * With a durablev2 request containing a create_guid,
    3277             :  * a share_access of READ/WRITE/DELETE,
    3278             :  * but without asking for an oplock nor a lease.
    3279             :  *
    3280             :  * While another client holds a batch oplock.
    3281             :  * And allows share_access of READ/WRITE/DELETE.
    3282             :  *
    3283             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3284             :  *
    3285             :  * This expects the strange reject status of
    3286             :  * NT_STATUS_ACCESS_DENIED, which is returned
    3287             :  * by Windows Servers.
    3288             :  *
    3289             :  * It won't pass against Samba as it returns
    3290             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    3291             :  * test_dhv2_pending2n_vs_oplock_sane().
    3292             :  */
    3293           5 : static bool test_dhv2_pending2n_vs_oplock_windows(struct torture_context *tctx,
    3294             :                                                   struct smb2_tree *tree1,
    3295             :                                                   struct smb2_tree *tree2_1)
    3296             : {
    3297           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3298             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3299             :                                            SMB2_OPLOCK_LEVEL_NONE,
    3300           5 :                                            NT_STATUS_ACCESS_DENIED,
    3301             :                                            tree1, tree2_1);
    3302             : }
    3303             : 
    3304             : /**
    3305             :  * This tests replay with a pending open with 4 channels
    3306             :  * and closed transports on the client and server side.
    3307             :  *
    3308             :  * With a durablev2 request containing a create_guid,
    3309             :  * a share_access of READ/WRITE/DELETE,
    3310             :  * and asking for a v2 lease.
    3311             :  *
    3312             :  * While another client holds a batch oplock.
    3313             :  * And allows share_access of READ/WRITE/DELETE.
    3314             :  *
    3315             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3316             :  *
    3317             :  * This expects the sane reject status of
    3318             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    3319             :  *
    3320             :  * It won't pass against Windows as it returns
    3321             :  * NT_STATUS_ACCESS_DENIED see
    3322             :  * test_dhv2_pending2l_vs_oplock_windows().
    3323             :  */
    3324           5 : static bool test_dhv2_pending2l_vs_oplock_sane(struct torture_context *tctx,
    3325             :                                                struct smb2_tree *tree1,
    3326             :                                                struct smb2_tree *tree2_1)
    3327             : {
    3328           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3329             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3330             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3331           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    3332             :                                            tree1, tree2_1);
    3333             : }
    3334             : 
    3335             : /**
    3336             :  * This tests replay with a pending open with 4 channels
    3337             :  * and closed transports on the client and server side.
    3338             :  *
    3339             :  * With a durablev2 request containing a create_guid,
    3340             :  * a share_access of READ/WRITE/DELETE,
    3341             :  * and asking for a v2 lease.
    3342             :  *
    3343             :  * While another client holds a batch oplock.
    3344             :  * And allows share_access of READ/WRITE/DELETE.
    3345             :  *
    3346             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3347             :  *
    3348             :  * This expects the strange reject status of
    3349             :  * NT_STATUS_ACCESS_DENIED, which is returned
    3350             :  * by Windows Servers.
    3351             :  *
    3352             :  * It won't pass against Samba as it returns
    3353             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    3354             :  * test_dhv2_pending2l_vs_oplock_sane().
    3355             :  */
    3356           5 : static bool test_dhv2_pending2l_vs_oplock_windows(struct torture_context *tctx,
    3357             :                                                   struct smb2_tree *tree1,
    3358             :                                                   struct smb2_tree *tree2_1)
    3359             : {
    3360           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3361             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3362             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3363           5 :                                            NT_STATUS_ACCESS_DENIED,
    3364             :                                            tree1, tree2_1);
    3365             : }
    3366             : 
    3367             : /**
    3368             :  * This tests replay with a pending open with 4 channels
    3369             :  * and closed transports on the client and server side.
    3370             :  *
    3371             :  * With a durablev2 request containing a create_guid,
    3372             :  * a share_access of READ/WRITE/DELETE,
    3373             :  * and asking for a v2 lease.
    3374             :  *
    3375             :  * While another client holds an RWH lease.
    3376             :  * And allows share_access of READ/WRITE/DELETE.
    3377             :  *
    3378             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3379             :  *
    3380             :  * This expects the sane reject status of
    3381             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    3382             :  *
    3383             :  * It won't pass against Windows as it returns
    3384             :  * NT_STATUS_ACCESS_DENIED see
    3385             :  * test_dhv2_pending2l_vs_oplock_windows().
    3386             :  */
    3387           5 : static bool test_dhv2_pending2l_vs_lease_sane(struct torture_context *tctx,
    3388             :                                               struct smb2_tree *tree1,
    3389             :                                               struct smb2_tree *tree2_1)
    3390             : {
    3391           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3392             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3393             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3394           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    3395             :                                            tree1, tree2_1);
    3396             : }
    3397             : 
    3398             : /**
    3399             :  * This tests replay with a pending open with 4 channels
    3400             :  * and closed transports on the client and server side.
    3401             :  *
    3402             :  * With a durablev2 request containing a create_guid,
    3403             :  * a share_access of READ/WRITE/DELETE,
    3404             :  * and asking for a v2 lease.
    3405             :  *
    3406             :  * While another client holds an RWH lease.
    3407             :  * And allows share_access of READ/WRITE/DELETE.
    3408             :  *
    3409             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3410             :  *
    3411             :  * This expects the strange reject status of
    3412             :  * NT_STATUS_ACCESS_DENIED, which is returned
    3413             :  * by Windows Servers.
    3414             :  *
    3415             :  * It won't pass against Samba as it returns
    3416             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    3417             :  * test_dhv2_pending2l_vs_oplock_sane().
    3418             :  */
    3419           5 : static bool test_dhv2_pending2l_vs_lease_windows(struct torture_context *tctx,
    3420             :                                                  struct smb2_tree *tree1,
    3421             :                                                  struct smb2_tree *tree2_1)
    3422             : {
    3423           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3424             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3425             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3426           5 :                                            NT_STATUS_ACCESS_DENIED,
    3427             :                                            tree1, tree2_1);
    3428             : }
    3429             : 
    3430             : /**
    3431             :  * This tests replay with a pending open with 4 channels
    3432             :  * and closed transports on the client and server side.
    3433             :  *
    3434             :  * With a durablev2 request containing a create_guid,
    3435             :  * a share_access of READ/WRITE/DELETE,
    3436             :  * and asking for a batch oplock
    3437             :  *
    3438             :  * While another client holds a batch oplock.
    3439             :  * And allows share_access of READ/WRITE/DELETE.
    3440             :  *
    3441             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3442             :  *
    3443             :  * This expects the sane reject status of
    3444             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    3445             :  *
    3446             :  * It won't pass against Windows as it returns
    3447             :  * NT_STATUS_ACCESS_DENIED see
    3448             :  * test_dhv2_pending2o_vs_oplock_windows().
    3449             :  */
    3450           5 : static bool test_dhv2_pending2o_vs_oplock_sane(struct torture_context *tctx,
    3451             :                                                struct smb2_tree *tree1,
    3452             :                                                struct smb2_tree *tree2_1)
    3453             : {
    3454           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3455             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3456             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3457           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    3458             :                                            tree1, tree2_1);
    3459             : }
    3460             : 
    3461             : /**
    3462             :  * This tests replay with a pending open with 4 channels
    3463             :  * and closed transports on the client and server side.
    3464             :  *
    3465             :  * With a durablev2 request containing a create_guid,
    3466             :  * a share_access of READ/WRITE/DELETE,
    3467             :  * and asking for a batch oplock.
    3468             :  *
    3469             :  * While another client holds a batch oplock.
    3470             :  * And allows share_access of READ/WRITE/DELETE.
    3471             :  *
    3472             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3473             :  *
    3474             :  * This expects the strange reject status of
    3475             :  * NT_STATUS_ACCESS_DENIED, which is returned
    3476             :  * by Windows Servers.
    3477             :  *
    3478             :  * It won't pass against Samba as it returns
    3479             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    3480             :  * test_dhv2_pending2o_vs_oplock_sane().
    3481             :  */
    3482           5 : static bool test_dhv2_pending2o_vs_oplock_windows(struct torture_context *tctx,
    3483             :                                                   struct smb2_tree *tree1,
    3484             :                                                   struct smb2_tree *tree2_1)
    3485             : {
    3486           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3487             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3488             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3489           5 :                                            NT_STATUS_ACCESS_DENIED,
    3490             :                                            tree1, tree2_1);
    3491             : }
    3492             : 
    3493             : /**
    3494             :  * This tests replay with a pending open with 4 channels
    3495             :  * and closed transports on the client and server side.
    3496             :  *
    3497             :  * With a durablev2 request containing a create_guid,
    3498             :  * a share_access of READ/WRITE/DELETE,
    3499             :  * and asking for a batch oplock
    3500             :  *
    3501             :  * While another client holds an RWH lease.
    3502             :  * And allows share_access of READ/WRITE/DELETE.
    3503             :  *
    3504             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3505             :  *
    3506             :  * This expects the sane reject status of
    3507             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    3508             :  *
    3509             :  * It won't pass against Windows as it returns
    3510             :  * NT_STATUS_ACCESS_DENIED see
    3511             :  * test_dhv2_pending2o_vs_lease_windows().
    3512             :  */
    3513           5 : static bool test_dhv2_pending2o_vs_lease_sane(struct torture_context *tctx,
    3514             :                                               struct smb2_tree *tree1,
    3515             :                                               struct smb2_tree *tree2_1)
    3516             : {
    3517           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3518             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3519             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3520           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    3521             :                                            tree1, tree2_1);
    3522             : }
    3523             : 
    3524             : /**
    3525             :  * This tests replay with a pending open with 4 channels
    3526             :  * and closed transports on the client and server side.
    3527             :  *
    3528             :  * With a durablev2 request containing a create_guid,
    3529             :  * a share_access of READ/WRITE/DELETE,
    3530             :  * and asking for a batch oplock.
    3531             :  *
    3532             :  * While another client holds an RWH lease.
    3533             :  * And allows share_access of READ/WRITE/DELETE.
    3534             :  *
    3535             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3536             :  *
    3537             :  * This expects the strange reject status of
    3538             :  * NT_STATUS_ACCESS_DENIED, which is returned
    3539             :  * by Windows Servers.
    3540             :  *
    3541             :  * It won't pass against Samba as it returns
    3542             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    3543             :  * test_dhv2_pending2o_vs_lease_sane().
    3544             :  */
    3545           5 : static bool test_dhv2_pending2o_vs_lease_windows(struct torture_context *tctx,
    3546             :                                                  struct smb2_tree *tree1,
    3547             :                                                  struct smb2_tree *tree2_1)
    3548             : {
    3549           5 :         return _test_dhv2_pending2_vs_hold(tctx, __func__,
    3550             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    3551             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    3552           5 :                                            NT_STATUS_ACCESS_DENIED,
    3553             :                                            tree1, tree2_1);
    3554             : }
    3555             : 
    3556             : /**
    3557             :  * This tests replay with a pending open with 4 channels
    3558             :  * and blocked transports on the client side.
    3559             :  *
    3560             :  * With a durablev2 request containing a create_guid and
    3561             :  * a share_access of READ/WRITE/DELETE:
    3562             :  * - client2_level = NONE:
    3563             :  *   but without asking for an oplock nor a lease.
    3564             :  * - client2_level = BATCH:
    3565             :  *   and asking for a batch oplock.
    3566             :  * - client2_level = LEASE
    3567             :  *   and asking for an RWH lease.
    3568             :  *
    3569             :  * While another client holds a batch oplock or
    3570             :  * RWH lease. (client1_level => LEASE or BATCH).
    3571             :  * And allows share_access of READ/WRITE/DELETE.
    3572             :  *
    3573             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    3574             :  */
    3575          60 : static bool _test_dhv2_pending3_vs_hold(struct torture_context *tctx,
    3576             :                                         const char *testname,
    3577             :                                         uint8_t client1_level,
    3578             :                                         uint8_t client2_level,
    3579             :                                         NTSTATUS reject_status,
    3580             :                                         struct smb2_tree *tree1,
    3581             :                                         struct smb2_tree *tree2_1)
    3582             : {
    3583          60 :         const char *host = torture_setting_string(tctx, "host", NULL);
    3584          60 :         const char *share = torture_setting_string(tctx, "share", NULL);
    3585          60 :         struct cli_credentials *credentials = samba_cmdline_get_creds();
    3586             :         NTSTATUS status;
    3587          60 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    3588             :         struct smb2_handle _h1;
    3589          60 :         struct smb2_handle *h1 = NULL;
    3590             :         struct smb2_handle _h21;
    3591          60 :         struct smb2_handle *h21 = NULL;
    3592             :         struct smb2_handle _h24;
    3593          60 :         struct smb2_handle *h24 = NULL;
    3594             :         struct smb2_create io1, io21, io22, io23, io24;
    3595          60 :         struct GUID create_guid1 = GUID_random();
    3596          60 :         struct GUID create_guid2 = GUID_random();
    3597          60 :         struct smb2_request *req21 = NULL;
    3598          60 :         bool ret = true;
    3599             :         char fname[256];
    3600          60 :         struct smb2_transport *transport1 = tree1->session->transport;
    3601             :         uint32_t server_capabilities;
    3602             :         uint32_t share_capabilities;
    3603             :         struct smb2_lease ls1;
    3604             :         uint64_t lease_key1;
    3605          60 :         uint16_t lease_epoch1 = 0;
    3606             :         struct smb2_lease ls2;
    3607             :         uint64_t lease_key2;
    3608          60 :         uint16_t lease_epoch2 = 0;
    3609             :         bool share_is_so;
    3610          60 :         struct smb2_transport *transport2_1 = tree2_1->session->transport;
    3611          60 :         int request_timeout2 = transport2_1->options.request_timeout;
    3612             :         struct smbcli_options options2x;
    3613          60 :         struct smb2_tree *tree2_2 = NULL;
    3614          60 :         struct smb2_tree *tree2_3 = NULL;
    3615          60 :         struct smb2_tree *tree2_4 = NULL;
    3616          60 :         struct smb2_transport *transport2_2 = NULL;
    3617          60 :         struct smb2_transport *transport2_3 = NULL;
    3618          60 :         struct smb2_transport *transport2_4 = NULL;
    3619          60 :         struct smb2_session *session2_1 = tree2_1->session;
    3620          60 :         struct smb2_session *session2_2 = NULL;
    3621          60 :         struct smb2_session *session2_3 = NULL;
    3622          60 :         struct smb2_session *session2_4 = NULL;
    3623          60 :         bool block_setup = false;
    3624          60 :         bool blocked2_1 = false;
    3625          60 :         bool blocked2_2 = false;
    3626          60 :         bool blocked2_3 = false;
    3627          60 :         uint16_t csn2 = 1;
    3628          60 :         const char *hold_name = NULL;
    3629             : 
    3630          60 :         switch (client1_level) {
    3631          30 :         case SMB2_OPLOCK_LEVEL_LEASE:
    3632          30 :                 hold_name = "RWH Lease";
    3633          30 :                 break;
    3634          30 :         case SMB2_OPLOCK_LEVEL_BATCH:
    3635          30 :                 hold_name = "BATCH Oplock";
    3636          30 :                 break;
    3637           0 :         default:
    3638           0 :                 smb_panic(__location__);
    3639             :                 break;
    3640             :         }
    3641             : 
    3642          60 :         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
    3643          12 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    3644             :                                    "replay tests\n");
    3645             :         }
    3646             : 
    3647          48 :         server_capabilities = smb2cli_conn_server_capabilities(transport1->conn);
    3648          48 :         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
    3649           0 :                 torture_skip(tctx, "MULTI_CHANNEL are not supported");
    3650             :         }
    3651          48 :         if (!(server_capabilities & SMB2_CAP_LEASING)) {
    3652          24 :                 if (client1_level == SMB2_OPLOCK_LEVEL_LEASE ||
    3653           0 :                     client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3654          16 :                         torture_skip(tctx, "leases are not supported");
    3655             :                 }
    3656             :         }
    3657             : 
    3658          32 :         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
    3659          32 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    3660          32 :         if (share_is_so) {
    3661           0 :                 torture_skip(tctx, talloc_asprintf(tctx,
    3662             :                              "%s not supported on SCALEOUT share",
    3663             :                              hold_name));
    3664             :         }
    3665             : 
    3666             :         /* Add some random component to the file name. */
    3667          32 :         snprintf(fname, sizeof(fname), "%s\\%s_%s.dat",
    3668             :                  BASEDIR, testname, generate_random_str(tctx, 8));
    3669             : 
    3670          32 :         options2x = transport2_1->options;
    3671          32 :         options2x.only_negprot = true;
    3672             : 
    3673          32 :         status = smb2_connect(tctx,
    3674             :                               host,
    3675             :                               lpcfg_smb_ports(tctx->lp_ctx),
    3676             :                               share,
    3677             :                               lpcfg_resolve_context(tctx->lp_ctx),
    3678             :                               credentials,
    3679             :                               &tree2_2,
    3680             :                               tctx->ev,
    3681             :                               &options2x,
    3682             :                               lpcfg_socket_options(tctx->lp_ctx),
    3683             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
    3684             :                               );
    3685          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3686             :                                         "smb2_connect failed");
    3687          32 :         transport2_2 = tree2_2->session->transport;
    3688             : 
    3689          32 :         session2_2 = smb2_session_channel(transport2_2,
    3690             :                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
    3691             :                                           tctx,
    3692             :                                           session2_1);
    3693          32 :         torture_assert(tctx, session2_2 != NULL, "smb2_session_channel failed");
    3694             : 
    3695          32 :         status = smb2_session_setup_spnego(session2_2,
    3696             :                                            credentials,
    3697             :                                            0 /* previous_session_id */);
    3698          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3699             :                                         "smb2_session_setup_spnego failed");
    3700          32 :         tree2_2->smbXcli = tree2_1->smbXcli;
    3701          32 :         tree2_2->session = session2_2;
    3702             : 
    3703          32 :         status = smb2_connect(tctx,
    3704             :                               host,
    3705             :                               lpcfg_smb_ports(tctx->lp_ctx),
    3706             :                               share,
    3707             :                               lpcfg_resolve_context(tctx->lp_ctx),
    3708             :                               credentials,
    3709             :                               &tree2_3,
    3710             :                               tctx->ev,
    3711             :                               &options2x,
    3712             :                               lpcfg_socket_options(tctx->lp_ctx),
    3713             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
    3714             :                               );
    3715          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3716             :                                         "smb2_connect failed");
    3717          32 :         transport2_3 = tree2_3->session->transport;
    3718             : 
    3719          32 :         session2_3 = smb2_session_channel(transport2_3,
    3720             :                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
    3721             :                                           tctx,
    3722             :                                           session2_1);
    3723          32 :         torture_assert(tctx, session2_3 != NULL, "smb2_session_channel failed");
    3724             : 
    3725          32 :         status = smb2_session_setup_spnego(session2_3,
    3726             :                                            credentials,
    3727             :                                            0 /* previous_session_id */);
    3728          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3729             :                                         "smb2_session_setup_spnego failed");
    3730          32 :         tree2_3->smbXcli = tree2_1->smbXcli;
    3731          32 :         tree2_3->session = session2_3;
    3732             : 
    3733          32 :         status = smb2_connect(tctx,
    3734             :                               host,
    3735             :                               lpcfg_smb_ports(tctx->lp_ctx),
    3736             :                               share,
    3737             :                               lpcfg_resolve_context(tctx->lp_ctx),
    3738             :                               credentials,
    3739             :                               &tree2_4,
    3740             :                               tctx->ev,
    3741             :                               &options2x,
    3742             :                               lpcfg_socket_options(tctx->lp_ctx),
    3743             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx)
    3744             :                               );
    3745          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3746             :                                         "smb2_connect failed");
    3747          32 :         transport2_4 = tree2_4->session->transport;
    3748             : 
    3749          32 :         session2_4 = smb2_session_channel(transport2_4,
    3750             :                                           lpcfg_gensec_settings(tctx, tctx->lp_ctx),
    3751             :                                           tctx,
    3752             :                                           session2_1);
    3753          32 :         torture_assert(tctx, session2_4 != NULL, "smb2_session_channel failed");
    3754             : 
    3755          32 :         status = smb2_session_setup_spnego(session2_4,
    3756             :                                            credentials,
    3757             :                                            0 /* previous_session_id */);
    3758          32 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3759             :                                         "smb2_session_setup_spnego failed");
    3760          32 :         tree2_4->smbXcli = tree2_1->smbXcli;
    3761          32 :         tree2_4->session = session2_4;
    3762             : 
    3763          32 :         smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
    3764             : 
    3765          32 :         torture_reset_break_info(tctx, &break_info);
    3766          32 :         break_info.oplock_skip_ack = true;
    3767          32 :         torture_reset_lease_break_info(tctx, &lease_break_info);
    3768          32 :         lease_break_info.lease_skip_ack = true;
    3769          32 :         transport1->oplock.handler = torture_oplock_ack_handler;
    3770          32 :         transport1->oplock.private_data = tree1;
    3771          32 :         transport1->lease.handler = torture_lease_handler;
    3772          32 :         transport1->lease.private_data = tree1;
    3773          32 :         smb2_keepalive(transport1);
    3774          32 :         transport2_1->oplock.handler = torture_oplock_ack_handler;
    3775          32 :         transport2_1->oplock.private_data = tree2_1;
    3776          32 :         transport2_1->lease.handler = torture_lease_handler;
    3777          32 :         transport2_1->lease.private_data = tree2_1;
    3778          32 :         smb2_keepalive(transport2_1);
    3779          32 :         transport2_2->oplock.handler = torture_oplock_ack_handler;
    3780          32 :         transport2_2->oplock.private_data = tree2_2;
    3781          32 :         transport2_2->lease.handler = torture_lease_handler;
    3782          32 :         transport2_2->lease.private_data = tree2_2;
    3783          32 :         smb2_keepalive(transport2_2);
    3784          32 :         transport2_3->oplock.handler = torture_oplock_ack_handler;
    3785          32 :         transport2_3->oplock.private_data = tree2_3;
    3786          32 :         transport2_3->lease.handler = torture_lease_handler;
    3787          32 :         transport2_3->lease.private_data = tree2_3;
    3788          32 :         smb2_keepalive(transport2_3);
    3789          32 :         transport2_4->oplock.handler = torture_oplock_ack_handler;
    3790          32 :         transport2_4->oplock.private_data = tree2_4;
    3791          32 :         transport2_4->lease.handler = torture_lease_handler;
    3792          32 :         transport2_4->lease.private_data = tree2_4;
    3793          32 :         smb2_keepalive(transport2_4);
    3794             : 
    3795          32 :         smb2_util_unlink(tree1, fname);
    3796          32 :         status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
    3797          32 :         CHECK_STATUS(status, NT_STATUS_OK);
    3798          32 :         smb2_util_close(tree1, _h1);
    3799          32 :         CHECK_VAL(break_info.count, 0);
    3800             : 
    3801          32 :         lease_key1 = random();
    3802          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3803          12 :                 smb2_lease_v2_create(&io1, &ls1, false /* dir */, fname,
    3804          12 :                         lease_key1, NULL, smb2_util_lease_state("RWH"), lease_epoch1++);
    3805             :         } else {
    3806          20 :                 smb2_oplock_create(&io1, fname, SMB2_OPLOCK_LEVEL_BATCH);
    3807             :         }
    3808          32 :         io1.in.durable_open = false;
    3809          32 :         io1.in.durable_open_v2 = true;
    3810          32 :         io1.in.persistent_open = false;
    3811          32 :         io1.in.create_guid = create_guid1;
    3812          32 :         io1.in.timeout = UINT32_MAX;
    3813             : 
    3814          32 :         status = smb2_create(tree1, mem_ctx, &io1);
    3815          32 :         CHECK_STATUS(status, NT_STATUS_OK);
    3816          32 :         _h1 = io1.out.file.handle;
    3817          32 :         h1 = &_h1;
    3818          32 :         CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    3819          32 :         CHECK_VAL(io1.out.durable_open, false);
    3820          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3821          12 :                 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
    3822          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_key.data[0], lease_key1);
    3823          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_key.data[1], ~lease_key1);
    3824          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_epoch, lease_epoch1);
    3825          12 :                 CHECK_VAL(io1.out.lease_response_v2.lease_state,
    3826             :                           smb2_util_lease_state("RHW"));
    3827             :         } else {
    3828          20 :                 CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
    3829             :         }
    3830          32 :         CHECK_VAL(io1.out.durable_open_v2, true);
    3831          32 :         CHECK_VAL(io1.out.timeout, 300*1000);
    3832             : 
    3833          32 :         lease_key2 = random();
    3834          32 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3835           8 :                 smb2_lease_v2_create(&io21, &ls2, false /* dir */, fname,
    3836           8 :                         lease_key2, NULL, smb2_util_lease_state("RWH"), lease_epoch2++);
    3837             :         } else {
    3838          24 :                 smb2_oplock_create(&io21, fname, client2_level);
    3839             :         }
    3840          32 :         io21.in.durable_open = false;
    3841          32 :         io21.in.durable_open_v2 = true;
    3842          32 :         io21.in.persistent_open = false;
    3843          32 :         io21.in.create_guid = create_guid2;
    3844          32 :         io21.in.timeout = UINT32_MAX;
    3845          32 :         io24 = io23 = io22 = io21;
    3846             : 
    3847          32 :         req21 = smb2_create_send(tree2_1, &io21);
    3848          32 :         torture_assert(tctx, req21 != NULL, "req21");
    3849             : 
    3850          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3851          12 :                 const struct smb2_lease_break *lb =
    3852             :                         &lease_break_info.lease_break;
    3853          12 :                 const struct smb2_lease *l = &lb->current_lease;
    3854          12 :                 const struct smb2_lease_key *k = &l->lease_key;
    3855             : 
    3856          12 :                 torture_wait_for_lease_break(tctx);
    3857          12 :                 CHECK_VAL(break_info.count, 0);
    3858          12 :                 CHECK_VAL(lease_break_info.count, 1);
    3859             : 
    3860          12 :                 torture_assert(tctx,
    3861             :                         lease_break_info.lease_transport == transport1,
    3862             :                         "expect lease break on transport1\n");
    3863          12 :                 CHECK_VAL(k->data[0], lease_key1);
    3864          12 :                 CHECK_VAL(k->data[1], ~lease_key1);
    3865          12 :                 CHECK_VAL(lb->new_lease_state,
    3866             :                           smb2_util_lease_state("RH"));
    3867          12 :                 CHECK_VAL(lb->break_flags,
    3868             :                           SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
    3869          12 :                 CHECK_VAL(lb->new_epoch, lease_epoch1+1);
    3870          12 :                 lease_epoch1 += 1;
    3871             :         } else {
    3872          20 :                 torture_wait_for_oplock_break(tctx);
    3873          20 :                 CHECK_VAL(break_info.count, 1);
    3874          20 :                 CHECK_VAL(lease_break_info.count, 0);
    3875             : 
    3876          20 :                 torture_assert(tctx,
    3877             :                         break_info.received_transport == transport1,
    3878             :                         "expect oplock break on transport1\n");
    3879          20 :                 CHECK_VAL(break_info.handle.data[0], _h1.data[0]);
    3880          20 :                 CHECK_VAL(break_info.handle.data[1], _h1.data[1]);
    3881          20 :                 CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
    3882             :         }
    3883             : 
    3884          32 :         torture_reset_break_info(tctx, &break_info);
    3885          32 :         break_info.oplock_skip_ack = true;
    3886          32 :         torture_reset_lease_break_info(tctx, &lease_break_info);
    3887          32 :         lease_break_info.lease_skip_ack = true;
    3888             : 
    3889          32 :         WAIT_FOR_ASYNC_RESPONSE(tctx, req21);
    3890             : 
    3891          32 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3892          12 :                 torture_wait_for_lease_break(tctx);
    3893             :         } else {
    3894          20 :                 torture_wait_for_oplock_break(tctx);
    3895             :         }
    3896          32 :         CHECK_VAL(break_info.count, 0);
    3897          32 :         CHECK_VAL(lease_break_info.count, 0);
    3898             : 
    3899          32 :         block_setup = test_setup_blocked_transports(tctx);
    3900          32 :         torture_assert(tctx, block_setup, "test_setup_blocked_transports");
    3901             : 
    3902          32 :         blocked2_1 = _test_block_smb2_transport(tctx, transport2_1, "transport2_1");
    3903          32 :         torture_assert_goto(tctx, blocked2_1, ret, done, "we could not block tcp transport");
    3904          32 :         smb2cli_session_reset_channel_sequence(session2_1->smbXcli, csn2++);
    3905             : 
    3906          32 :         smb2cli_session_start_replay(session2_2->smbXcli);
    3907          32 :         transport2_2->options.request_timeout = 5;
    3908          32 :         status = smb2_create(tree2_2, tctx, &io22);
    3909          32 :         transport2_2->options.request_timeout = request_timeout2;
    3910          32 :         CHECK_STATUS(status, reject_status);
    3911          16 :         smb2cli_session_stop_replay(session2_2->smbXcli);
    3912             : 
    3913          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3914           6 :                 torture_wait_for_lease_break(tctx);
    3915             :         } else {
    3916          10 :                 torture_wait_for_oplock_break(tctx);
    3917             :         }
    3918          16 :         CHECK_VAL(break_info.count, 0);
    3919          16 :         CHECK_VAL(lease_break_info.count, 0);
    3920             : 
    3921          16 :         blocked2_2 = _test_block_smb2_transport(tctx, transport2_2, "transport2_2");
    3922          16 :         torture_assert_goto(tctx, blocked2_2, ret, done, "we could not block tcp transport");
    3923          16 :         smb2cli_session_reset_channel_sequence(session2_2->smbXcli, csn2++);
    3924             : 
    3925          16 :         smb2cli_session_start_replay(session2_3->smbXcli);
    3926          16 :         transport2_3->options.request_timeout = 5;
    3927          16 :         status = smb2_create(tree2_3, tctx, &io23);
    3928          16 :         transport2_3->options.request_timeout = request_timeout2;
    3929          16 :         CHECK_STATUS(status, reject_status);
    3930          16 :         smb2cli_session_stop_replay(session2_3->smbXcli);
    3931             : 
    3932          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3933           6 :                 torture_wait_for_lease_break(tctx);
    3934             :         } else {
    3935          10 :                 torture_wait_for_oplock_break(tctx);
    3936             :         }
    3937          16 :         CHECK_VAL(break_info.count, 0);
    3938          16 :         CHECK_VAL(lease_break_info.count, 0);
    3939             : 
    3940          16 :         smb2_util_close(tree1, _h1);
    3941          16 :         h1 = NULL;
    3942             : 
    3943          16 :         status = smb2_create_recv(req21, tctx, &io21);
    3944          16 :         CHECK_STATUS(status, NT_STATUS_OK);
    3945          16 :         _h21 = io21.out.file.handle;
    3946          16 :         h21 = &_h21;
    3947          16 :         CHECK_CREATED(&io21, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
    3948          16 :         CHECK_VAL(io21.out.oplock_level, client2_level);
    3949          16 :         CHECK_VAL(io21.out.durable_open, false);
    3950          16 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3951           4 :                 CHECK_VAL(io21.out.lease_response_v2.lease_key.data[0], lease_key2);
    3952           4 :                 CHECK_VAL(io21.out.lease_response_v2.lease_key.data[1], ~lease_key2);
    3953           4 :                 CHECK_VAL(io21.out.lease_response_v2.lease_epoch, lease_epoch2);
    3954           4 :                 CHECK_VAL(io21.out.lease_response_v2.lease_state,
    3955             :                           smb2_util_lease_state("RHW"));
    3956           4 :                 CHECK_VAL(io21.out.durable_open_v2, true);
    3957           4 :                 CHECK_VAL(io21.out.timeout, 300*1000);
    3958          12 :         } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
    3959           6 :                 CHECK_VAL(io21.out.durable_open_v2, true);
    3960           6 :                 CHECK_VAL(io21.out.timeout, 300*1000);
    3961             :         } else {
    3962           6 :                 CHECK_VAL(io21.out.durable_open_v2, false);
    3963             :         }
    3964             : 
    3965          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3966           6 :                 torture_wait_for_lease_break(tctx);
    3967             :         } else {
    3968          10 :                 torture_wait_for_oplock_break(tctx);
    3969             :         }
    3970          16 :         CHECK_VAL(break_info.count, 0);
    3971          16 :         CHECK_VAL(lease_break_info.count, 0);
    3972             : 
    3973          16 :         blocked2_3 = _test_block_smb2_transport(tctx, transport2_3, "transport2_3");
    3974          16 :         torture_assert_goto(tctx, blocked2_3, ret, done, "we could not block tcp transport");
    3975          16 :         smb2cli_session_reset_channel_sequence(session2_3->smbXcli, csn2++);
    3976             : 
    3977          16 :         smb2cli_session_start_replay(session2_4->smbXcli);
    3978          16 :         status = smb2_create(tree2_4, tctx, &io24);
    3979          16 :         smb2cli_session_stop_replay(session2_4->smbXcli);
    3980          16 :         CHECK_STATUS(status, NT_STATUS_OK);
    3981          16 :         _h24 = io24.out.file.handle;
    3982          16 :         h24 = &_h24;
    3983          16 :         CHECK_CREATED(&io24, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
    3984          16 :         CHECK_VAL(h24->data[0], h21->data[0]);
    3985          16 :         CHECK_VAL(h24->data[1], h21->data[1]);
    3986          16 :         if (client2_level == SMB2_OPLOCK_LEVEL_LEASE) {
    3987           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_key.data[0], lease_key2);
    3988           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_key.data[1], ~lease_key2);
    3989           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_epoch, lease_epoch2);
    3990           4 :                 CHECK_VAL(io24.out.lease_response_v2.lease_state,
    3991             :                           smb2_util_lease_state("RHW"));
    3992           4 :                 CHECK_VAL(io24.out.durable_open_v2, true);
    3993           4 :                 CHECK_VAL(io24.out.timeout, 300*1000);
    3994          12 :         } else if (client2_level == SMB2_OPLOCK_LEVEL_BATCH) {
    3995           6 :                 CHECK_VAL(io24.out.durable_open_v2, true);
    3996           6 :                 CHECK_VAL(io24.out.timeout, 300*1000);
    3997             :         } else {
    3998           6 :                 CHECK_VAL(io24.out.durable_open_v2, false);
    3999             :         }
    4000             : 
    4001          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    4002           6 :                 torture_wait_for_lease_break(tctx);
    4003             :         } else {
    4004          10 :                 torture_wait_for_oplock_break(tctx);
    4005             :         }
    4006          16 :         CHECK_VAL(break_info.count, 0);
    4007          16 :         CHECK_VAL(lease_break_info.count, 0);
    4008          16 :         status = smb2_util_close(tree2_4, *h24);
    4009          16 :         CHECK_STATUS(status, NT_STATUS_OK);
    4010          16 :         h24 = NULL;
    4011             : 
    4012          16 :         if (client1_level == SMB2_OPLOCK_LEVEL_LEASE) {
    4013           6 :                 torture_wait_for_lease_break(tctx);
    4014             :         } else {
    4015          10 :                 torture_wait_for_oplock_break(tctx);
    4016             :         }
    4017          16 :         CHECK_VAL(break_info.count, 0);
    4018          16 :         CHECK_VAL(lease_break_info.count, 0);
    4019             : 
    4020          48 : done:
    4021             : 
    4022          32 :         if (blocked2_3) {
    4023          16 :                 _test_unblock_smb2_transport(tctx, transport2_3, "transport2_3");
    4024             :         }
    4025          32 :         if (blocked2_2) {
    4026          16 :                 _test_unblock_smb2_transport(tctx, transport2_2, "transport2_2");
    4027             :         }
    4028          32 :         if (blocked2_1) {
    4029          32 :                 _test_unblock_smb2_transport(tctx, transport2_1, "transport2_1");
    4030             :         }
    4031          32 :         if (block_setup) {
    4032          32 :                 test_cleanup_blocked_transports(tctx);
    4033             :         }
    4034             : 
    4035          32 :         smbXcli_conn_disconnect(transport2_1->conn, NT_STATUS_LOCAL_DISCONNECT);
    4036          32 :         smbXcli_conn_disconnect(transport2_2->conn, NT_STATUS_LOCAL_DISCONNECT);
    4037          32 :         smbXcli_conn_disconnect(transport2_3->conn, NT_STATUS_LOCAL_DISCONNECT);
    4038          32 :         smbXcli_conn_disconnect(transport2_4->conn, NT_STATUS_LOCAL_DISCONNECT);
    4039             : 
    4040          32 :         if (h1 != NULL) {
    4041          16 :                 smb2_util_close(tree1, *h1);
    4042             :         }
    4043             : 
    4044          32 :         smb2_deltree(tree1, BASEDIR);
    4045             : 
    4046          32 :         TALLOC_FREE(tree1);
    4047          32 :         talloc_free(mem_ctx);
    4048             : 
    4049          32 :         return ret;
    4050             : }
    4051             : 
    4052             : /**
    4053             :  * This tests replay with a pending open with 4 channels
    4054             :  * and blocked transports on the client side.
    4055             :  *
    4056             :  * With a durablev2 request containing a create_guid,
    4057             :  * a share_access of READ/WRITE/DELETE,
    4058             :  * but without asking for an oplock nor a lease.
    4059             :  *
    4060             :  * While another client holds an RWH lease.
    4061             :  * And allows share_access of READ/WRITE/DELETE.
    4062             :  *
    4063             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4064             :  *
    4065             :  * This expects the sane reject status of
    4066             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    4067             :  *
    4068             :  * It won't pass against Windows as it returns
    4069             :  * NT_STATUS_ACCESS_DENIED see
    4070             :  * test_dhv2_pending3n_vs_lease_windows().
    4071             :  */
    4072           5 : static bool test_dhv2_pending3n_vs_lease_sane(struct torture_context *tctx,
    4073             :                                               struct smb2_tree *tree1,
    4074             :                                               struct smb2_tree *tree2_1)
    4075             : {
    4076           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4077             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4078             :                                            SMB2_OPLOCK_LEVEL_NONE,
    4079           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    4080             :                                            tree1, tree2_1);
    4081             : }
    4082             : 
    4083             : /**
    4084             :  * This tests replay with a pending open with 4 channels
    4085             :  * and blocked transports on the client side.
    4086             :  *
    4087             :  * With a durablev2 request containing a create_guid,
    4088             :  * a share_access of READ/WRITE/DELETE,
    4089             :  * but without asking for an oplock nor a lease.
    4090             :  *
    4091             :  * While another client holds an RWH lease.
    4092             :  * And allows share_access of READ/WRITE/DELETE.
    4093             :  *
    4094             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4095             :  *
    4096             :  * This expects the strange reject status of
    4097             :  * NT_STATUS_ACCESS_DENIED, which is returned
    4098             :  * by Windows Servers.
    4099             :  *
    4100             :  * It won't pass against Samba as it returns
    4101             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    4102             :  * test_dhv2_pending3n_vs_lease_sane.
    4103             :  */
    4104           5 : static bool test_dhv2_pending3n_vs_lease_windows(struct torture_context *tctx,
    4105             :                                                  struct smb2_tree *tree1,
    4106             :                                                  struct smb2_tree *tree2_1)
    4107             : {
    4108           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4109             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4110             :                                            SMB2_OPLOCK_LEVEL_NONE,
    4111           5 :                                            NT_STATUS_ACCESS_DENIED,
    4112             :                                            tree1, tree2_1);
    4113             : }
    4114             : 
    4115             : /**
    4116             :  * This tests replay with a pending open with 4 channels
    4117             :  * and blocked transports on the client side.
    4118             :  *
    4119             :  * With a durablev2 request containing a create_guid,
    4120             :  * a share_access of READ/WRITE/DELETE,
    4121             :  * but without asking for an oplock nor a lease.
    4122             :  *
    4123             :  * While another client holds a batch oplock.
    4124             :  * And allows share_access of READ/WRITE/DELETE.
    4125             :  *
    4126             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4127             :  *
    4128             :  * This expects the sane reject status of
    4129             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    4130             :  *
    4131             :  * It won't pass against Windows as it returns
    4132             :  * NT_STATUS_ACCESS_DENIED see
    4133             :  * test_dhv2_pending3n_vs_oplock_windows().
    4134             :  */
    4135           5 : static bool test_dhv2_pending3n_vs_oplock_sane(struct torture_context *tctx,
    4136             :                                                struct smb2_tree *tree1,
    4137             :                                                struct smb2_tree *tree2_1)
    4138             : {
    4139           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4140             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4141             :                                            SMB2_OPLOCK_LEVEL_NONE,
    4142           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    4143             :                                            tree1, tree2_1);
    4144             : }
    4145             : 
    4146             : /**
    4147             :  * This tests replay with a pending open with 4 channels
    4148             :  * and blocked transports on the client side.
    4149             :  *
    4150             :  * With a durablev2 request containing a create_guid,
    4151             :  * a share_access of READ/WRITE/DELETE,
    4152             :  * but without asking for an oplock nor a lease.
    4153             :  *
    4154             :  * While another client holds a batch oplock.
    4155             :  * And allows share_access of READ/WRITE/DELETE.
    4156             :  *
    4157             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4158             :  *
    4159             :  * This expects the strange reject status of
    4160             :  * NT_STATUS_ACCESS_DENIED, which is returned
    4161             :  * by Windows Servers.
    4162             :  *
    4163             :  * It won't pass against Samba as it returns
    4164             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    4165             :  * test_dhv2_pending3n_vs_oplock_sane.
    4166             :  */
    4167           5 : static bool test_dhv2_pending3n_vs_oplock_windows(struct torture_context *tctx,
    4168             :                                                   struct smb2_tree *tree1,
    4169             :                                                   struct smb2_tree *tree2_1)
    4170             : {
    4171           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4172             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4173             :                                            SMB2_OPLOCK_LEVEL_NONE,
    4174           5 :                                            NT_STATUS_ACCESS_DENIED,
    4175             :                                            tree1, tree2_1);
    4176             : }
    4177             : 
    4178             : /**
    4179             :  * This tests replay with a pending open with 4 channels
    4180             :  * and blocked transports on the client side.
    4181             :  *
    4182             :  * With a durablev2 request containing a create_guid,
    4183             :  * a share_access of READ/WRITE/DELETE,
    4184             :  * and asking for a v2 lease.
    4185             :  *
    4186             :  * While another client holds a batch oplock.
    4187             :  * And allows share_access of READ/WRITE/DELETE.
    4188             :  *
    4189             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4190             :  *
    4191             :  * This expects the sane reject status of
    4192             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    4193             :  *
    4194             :  * It won't pass against Windows as it returns
    4195             :  * NT_STATUS_ACCESS_DENIED see
    4196             :  * test_dhv2_pending3l_vs_oplock_windows().
    4197             :  */
    4198           5 : static bool test_dhv2_pending3l_vs_oplock_sane(struct torture_context *tctx,
    4199             :                                                struct smb2_tree *tree1,
    4200             :                                                struct smb2_tree *tree2_1)
    4201             : {
    4202           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4203             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4204             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4205           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    4206             :                                            tree1, tree2_1);
    4207             : }
    4208             : 
    4209             : /**
    4210             :  * This tests replay with a pending open with 4 channels
    4211             :  * and blocked transports on the client side.
    4212             :  *
    4213             :  * With a durablev2 request containing a create_guid,
    4214             :  * a share_access of READ/WRITE/DELETE,
    4215             :  * and asking for a v2 lease.
    4216             :  *
    4217             :  * While another client holds a batch oplock.
    4218             :  * And allows share_access of READ/WRITE/DELETE.
    4219             :  *
    4220             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4221             :  *
    4222             :  * This expects the strange reject status of
    4223             :  * NT_STATUS_ACCESS_DENIED, which is returned
    4224             :  * by Windows Servers.
    4225             :  *
    4226             :  * It won't pass against Samba as it returns
    4227             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    4228             :  * test_dhv2_pending3l_vs_oplock_sane.
    4229             :  */
    4230           5 : static bool test_dhv2_pending3l_vs_oplock_windows(struct torture_context *tctx,
    4231             :                                                   struct smb2_tree *tree1,
    4232             :                                                   struct smb2_tree *tree2_1)
    4233             : {
    4234           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4235             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4236             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4237           5 :                                            NT_STATUS_ACCESS_DENIED,
    4238             :                                            tree1, tree2_1);
    4239             : }
    4240             : 
    4241             : /**
    4242             :  * This tests replay with a pending open with 4 channels
    4243             :  * and blocked transports on the client side.
    4244             :  *
    4245             :  * With a durablev2 request containing a create_guid,
    4246             :  * a share_access of READ/WRITE/DELETE,
    4247             :  * and asking for a v2 lease.
    4248             :  *
    4249             :  * While another client holds an RWH lease.
    4250             :  * And allows share_access of READ/WRITE/DELETE.
    4251             :  *
    4252             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4253             :  *
    4254             :  * This expects the sane reject status of
    4255             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    4256             :  *
    4257             :  * It won't pass against Windows as it returns
    4258             :  * NT_STATUS_ACCESS_DENIED see
    4259             :  * test_dhv2_pending3l_vs_lease_windows().
    4260             :  */
    4261           5 : static bool test_dhv2_pending3l_vs_lease_sane(struct torture_context *tctx,
    4262             :                                               struct smb2_tree *tree1,
    4263             :                                               struct smb2_tree *tree2_1)
    4264             : {
    4265           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4266             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4267             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4268           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    4269             :                                            tree1, tree2_1);
    4270             : }
    4271             : 
    4272             : /**
    4273             :  * This tests replay with a pending open with 4 channels
    4274             :  * and blocked transports on the client side.
    4275             :  *
    4276             :  * With a durablev2 request containing a create_guid,
    4277             :  * a share_access of READ/WRITE/DELETE,
    4278             :  * and asking for a v2 lease.
    4279             :  *
    4280             :  * While another client holds an RWH lease.
    4281             :  * And allows share_access of READ/WRITE/DELETE.
    4282             :  *
    4283             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4284             :  *
    4285             :  * This expects the strange reject status of
    4286             :  * NT_STATUS_ACCESS_DENIED, which is returned
    4287             :  * by Windows Servers.
    4288             :  *
    4289             :  * It won't pass against Samba as it returns
    4290             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    4291             :  * test_dhv2_pending3l_vs_lease_sane().
    4292             :  */
    4293           5 : static bool test_dhv2_pending3l_vs_lease_windows(struct torture_context *tctx,
    4294             :                                                  struct smb2_tree *tree1,
    4295             :                                                  struct smb2_tree *tree2_1)
    4296             : {
    4297           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4298             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4299             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4300           5 :                                            NT_STATUS_ACCESS_DENIED,
    4301             :                                            tree1, tree2_1);
    4302             : }
    4303             : 
    4304             : /**
    4305             :  * This tests replay with a pending open with 4 channels
    4306             :  * and blocked transports on the client side.
    4307             :  *
    4308             :  * With a durablev2 request containing a create_guid,
    4309             :  * a share_access of READ/WRITE/DELETE,
    4310             :  * and asking for a batch oplock.
    4311             :  *
    4312             :  * While another client holds a batch oplock.
    4313             :  * And allows share_access of READ/WRITE/DELETE.
    4314             :  *
    4315             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4316             :  *
    4317             :  * This expects the sane reject status of
    4318             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    4319             :  *
    4320             :  * It won't pass against Windows as it returns
    4321             :  * NT_STATUS_ACCESS_DENIED see
    4322             :  * test_dhv2_pending3o_vs_oplock_windows().
    4323             :  */
    4324           5 : static bool test_dhv2_pending3o_vs_oplock_sane(struct torture_context *tctx,
    4325             :                                                struct smb2_tree *tree1,
    4326             :                                                struct smb2_tree *tree2_1)
    4327             : {
    4328           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4329             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4330             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4331           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    4332             :                                            tree1, tree2_1);
    4333             : }
    4334             : 
    4335             : /**
    4336             :  * This tests replay with a pending open with 4 channels
    4337             :  * and blocked transports on the client side.
    4338             :  *
    4339             :  * With a durablev2 request containing a create_guid,
    4340             :  * a share_access of READ/WRITE/DELETE,
    4341             :  * and asking for a batch oplock.
    4342             :  *
    4343             :  * While another client holds a batch oplock.
    4344             :  * And allows share_access of READ/WRITE/DELETE.
    4345             :  *
    4346             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4347             :  *
    4348             :  * This expects the strange reject status of
    4349             :  * NT_STATUS_ACCESS_DENIED, which is returned
    4350             :  * by Windows Servers.
    4351             :  *
    4352             :  * It won't pass against Samba as it returns
    4353             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    4354             :  * test_dhv2_pending3o_vs_oplock_sane().
    4355             :  */
    4356           5 : static bool test_dhv2_pending3o_vs_oplock_windows(struct torture_context *tctx,
    4357             :                                                   struct smb2_tree *tree1,
    4358             :                                                   struct smb2_tree *tree2_1)
    4359             : {
    4360           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4361             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4362             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4363           5 :                                            NT_STATUS_ACCESS_DENIED,
    4364             :                                            tree1, tree2_1);
    4365             : }
    4366             : 
    4367             : /**
    4368             :  * This tests replay with a pending open with 4 channels
    4369             :  * and blocked transports on the client side.
    4370             :  *
    4371             :  * With a durablev2 request containing a create_guid,
    4372             :  * a share_access of READ/WRITE/DELETE,
    4373             :  * and asking for a batch oplock.
    4374             :  *
    4375             :  * While another client holds an RWH lease.
    4376             :  * And allows share_access of READ/WRITE/DELETE.
    4377             :  *
    4378             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4379             :  *
    4380             :  * This expects the sane reject status of
    4381             :  * NT_STATUS_FILE_NOT_AVAILABLE.
    4382             :  *
    4383             :  * It won't pass against Windows as it returns
    4384             :  * NT_STATUS_ACCESS_DENIED see
    4385             :  * test_dhv2_pending3o_vs_lease_windows().
    4386             :  */
    4387           5 : static bool test_dhv2_pending3o_vs_lease_sane(struct torture_context *tctx,
    4388             :                                               struct smb2_tree *tree1,
    4389             :                                               struct smb2_tree *tree2_1)
    4390             : {
    4391           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4392             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4393             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4394           5 :                                            NT_STATUS_FILE_NOT_AVAILABLE,
    4395             :                                            tree1, tree2_1);
    4396             : }
    4397             : 
    4398             : /**
    4399             :  * This tests replay with a pending open with 4 channels
    4400             :  * and blocked transports on the client side.
    4401             :  *
    4402             :  * With a durablev2 request containing a create_guid,
    4403             :  * a share_access of READ/WRITE/DELETE,
    4404             :  * and asking for a batch oplock.
    4405             :  *
    4406             :  * While another client holds an RWH lease.
    4407             :  * And allows share_access of READ/WRITE/DELETE.
    4408             :  *
    4409             :  * See https://bugzilla.samba.org/show_bug.cgi?id=14449
    4410             :  *
    4411             :  * This expects the strange reject status of
    4412             :  * NT_STATUS_ACCESS_DENIED, which is returned
    4413             :  * by Windows Servers.
    4414             :  *
    4415             :  * It won't pass against Samba as it returns
    4416             :  * NT_STATUS_FILE_NOT_AVAILABLE. see
    4417             :  * test_dhv2_pending3o_vs_lease_sane().
    4418             :  */
    4419           5 : static bool test_dhv2_pending3o_vs_lease_windows(struct torture_context *tctx,
    4420             :                                                  struct smb2_tree *tree1,
    4421             :                                                  struct smb2_tree *tree2_1)
    4422             : {
    4423           5 :         return _test_dhv2_pending3_vs_hold(tctx, __func__,
    4424             :                                            SMB2_OPLOCK_LEVEL_LEASE,
    4425             :                                            SMB2_OPLOCK_LEVEL_BATCH,
    4426           5 :                                            NT_STATUS_ACCESS_DENIED,
    4427             :                                            tree1, tree2_1);
    4428             : }
    4429             : 
    4430          24 : static bool test_channel_sequence_table(struct torture_context *tctx,
    4431             :                                         struct smb2_tree *tree,
    4432             :                                         bool do_replay,
    4433             :                                         uint16_t opcode)
    4434             : {
    4435          24 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    4436          24 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    4437             :         struct smb2_handle handle;
    4438          24 :         struct smb2_handle *phandle = NULL;
    4439             :         struct smb2_create io;
    4440          24 :         struct GUID create_guid = GUID_random();
    4441          24 :         bool ret = true;
    4442          24 :         const char *fname = BASEDIR "\\channel_sequence.dat";
    4443          24 :         uint16_t csn = 0;
    4444          24 :         uint16_t limit = UINT16_MAX - 0x7fff;
    4445             :         int i;
    4446             :         struct {
    4447             :                 uint16_t csn;
    4448             :                 bool csn_rand_low;
    4449             :                 bool csn_rand_high;
    4450             :                 NTSTATUS expected_status;
    4451          24 :         } tests[] = {
    4452             :                 {
    4453             :                         .csn                    = 0,
    4454             :                         .expected_status        = NT_STATUS_OK,
    4455             :                 },{
    4456             :                         .csn                    = 0x7fff + 1,
    4457             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4458             :                 },{
    4459             :                         .csn                    = 0x7fff + 2,
    4460             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4461             :                 },{
    4462             :                         .csn                    = -1,
    4463             :                         .csn_rand_high          = true,
    4464             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4465             :                 },{
    4466             :                         .csn                    = 0xffff,
    4467             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4468             :                 },{
    4469             :                         .csn                    = 0x7fff,
    4470             :                         .expected_status        = NT_STATUS_OK,
    4471             :                 },{
    4472             :                         .csn                    = 0x7ffe,
    4473             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4474             :                 },{
    4475             :                         .csn                    = 0,
    4476             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4477             :                 },{
    4478             :                         .csn                    = -1,
    4479             :                         .csn_rand_low           = true,
    4480             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4481             :                 },{
    4482             :                         .csn                    = 0x7fff + 1,
    4483             :                         .expected_status        = NT_STATUS_OK,
    4484             :                 },{
    4485             :                         .csn                    = 0xffff,
    4486             :                         .expected_status        = NT_STATUS_OK,
    4487             :                 },{
    4488             :                         .csn                    = 0,
    4489             :                         .expected_status        = NT_STATUS_OK,
    4490             :                 },{
    4491             :                         .csn                    = 1,
    4492             :                         .expected_status        = NT_STATUS_OK,
    4493             :                 },{
    4494             :                         .csn                    = 0,
    4495             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4496             :                 },{
    4497             :                         .csn                    = 1,
    4498             :                         .expected_status        = NT_STATUS_OK,
    4499             :                 },{
    4500             :                         .csn                    = 0xffff,
    4501             :                         .expected_status        = NT_STATUS_FILE_NOT_AVAILABLE,
    4502             :                 }
    4503             :         };
    4504             : 
    4505          24 :         smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
    4506             : 
    4507          24 :         csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli);
    4508          24 :         torture_comment(tctx, "Testing create with channel sequence number: 0x%04x\n", csn);
    4509             : 
    4510          24 :         smb2_oplock_create_share(&io, fname,
    4511             :                         smb2_util_share_access("RWD"),
    4512          24 :                         smb2_util_oplock_level("b"));
    4513          24 :         io.in.durable_open = false;
    4514          24 :         io.in.durable_open_v2 = true;
    4515          24 :         io.in.create_guid = create_guid;
    4516          24 :         io.in.timeout = UINT32_MAX;
    4517             : 
    4518          24 :         torture_assert_ntstatus_ok_goto(tctx,
    4519             :                 smb2_create(tree, mem_ctx, &io),
    4520             :                 ret, done, "failed to call smb2_create");
    4521             : 
    4522          24 :         handle = io.out.file.handle;
    4523          24 :         phandle = &handle;
    4524             : 
    4525         408 :         for (i=0; i <ARRAY_SIZE(tests); i++) {
    4526             : 
    4527         384 :                 const char *opstr = "";
    4528             :                 union smb_fileinfo qfinfo;
    4529             : 
    4530         384 :                 csn = tests[i].csn;
    4531             : 
    4532         384 :                 if (tests[i].csn_rand_low) {
    4533          24 :                         csn = rand() % limit;
    4534         360 :                 } else if (tests[i].csn_rand_high) {
    4535          24 :                         csn = rand() % limit + 0x7fff;
    4536             :                 }
    4537             : 
    4538         384 :                 switch (opcode) {
    4539         128 :                 case SMB2_OP_WRITE:
    4540         128 :                         opstr = "write";
    4541         128 :                         break;
    4542         128 :                 case SMB2_OP_IOCTL:
    4543         128 :                         opstr = "ioctl";
    4544         128 :                         break;
    4545         128 :                 case SMB2_OP_SETINFO:
    4546         128 :                         opstr = "setinfo";
    4547         128 :                         break;
    4548           0 :                 default:
    4549           0 :                         break;
    4550             :                 }
    4551             : 
    4552         384 :                 smb2cli_session_reset_channel_sequence(tree->session->smbXcli, csn);
    4553         384 :                 csn = smb2cli_session_current_channel_sequence(tree->session->smbXcli);
    4554             : 
    4555         384 :                 torture_comment(tctx, "Testing %s (replay: %s) with CSN 0x%04x, expecting: %s\n",
    4556             :                         opstr, do_replay ? "true" : "false", csn,
    4557             :                         nt_errstr(tests[i].expected_status));
    4558             : 
    4559         384 :                 if (do_replay) {
    4560         192 :                         smb2cli_session_start_replay(tree->session->smbXcli);
    4561             :                 }
    4562             : 
    4563         384 :                 switch (opcode) {
    4564         128 :                 case SMB2_OP_WRITE: {
    4565         128 :                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, 255);
    4566             : 
    4567         128 :                         generate_random_buffer(blob.data, blob.length);
    4568             : 
    4569         128 :                         status = smb2_util_write(tree, handle, blob.data, 0, blob.length);
    4570         128 :                         if (NT_STATUS_IS_OK(status)) {
    4571             :                                 struct smb2_read rd;
    4572             : 
    4573          56 :                                 rd = (struct smb2_read) {
    4574             :                                         .in.file.handle = handle,
    4575          56 :                                         .in.length = blob.length,
    4576             :                                         .in.offset = 0
    4577             :                                 };
    4578             : 
    4579          56 :                                 torture_assert_ntstatus_ok_goto(tctx,
    4580             :                                         smb2_read(tree, tree, &rd),
    4581             :                                         ret, done, "failed to read after write");
    4582             : 
    4583          56 :                                 torture_assert_data_blob_equal(tctx,
    4584             :                                         rd.out.data, blob,
    4585             :                                         "read/write mismatch");
    4586             :                         }
    4587         128 :                         break;
    4588             :                 }
    4589         128 :                 case SMB2_OP_IOCTL: {
    4590             :                         union smb_ioctl ioctl;
    4591         128 :                         ioctl = (union smb_ioctl) {
    4592             :                                 .smb2.level = RAW_IOCTL_SMB2,
    4593             :                                 .smb2.in.file.handle = handle,
    4594             :                                 .smb2.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID,
    4595             :                                 .smb2.in.max_output_response = 64,
    4596             :                                 .smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL
    4597             :                         };
    4598         128 :                         status = smb2_ioctl(tree, mem_ctx, &ioctl.smb2);
    4599         128 :                         break;
    4600             :                 }
    4601         128 :                 case SMB2_OP_SETINFO: {
    4602             :                         union smb_setfileinfo sfinfo;
    4603         128 :                         ZERO_STRUCT(sfinfo);
    4604         128 :                         sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
    4605         128 :                         sfinfo.generic.in.file.handle = handle;
    4606         128 :                         sfinfo.position_information.in.position = 0x1000;
    4607         128 :                         status = smb2_setinfo_file(tree, &sfinfo);
    4608         128 :                         break;
    4609             :                 }
    4610           0 :                 default:
    4611           0 :                         break;
    4612             :                 }
    4613             : 
    4614         384 :                 qfinfo = (union smb_fileinfo) {
    4615             :                         .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
    4616             :                         .generic.in.file.handle = handle
    4617             :                 };
    4618             : 
    4619         384 :                 torture_assert_ntstatus_ok_goto(tctx,
    4620             :                         smb2_getinfo_file(tree, mem_ctx, &qfinfo),
    4621             :                         ret, done, "failed to read after write");
    4622             : 
    4623         384 :                 if (do_replay) {
    4624         192 :                         smb2cli_session_stop_replay(tree->session->smbXcli);
    4625             :                 }
    4626             : 
    4627         384 :                 torture_assert_ntstatus_equal_goto(tctx,
    4628             :                         status, tests[i].expected_status,
    4629             :                         ret, done, "got unexpected failure code");
    4630             : 
    4631             :         }
    4632          24 : done:
    4633          24 :         if (phandle != NULL) {
    4634          24 :                 smb2_util_close(tree, *phandle);
    4635             :         }
    4636             : 
    4637          24 :         smb2_util_unlink(tree, fname);
    4638             : 
    4639          24 :         return ret;
    4640             : }
    4641             : 
    4642           5 : static bool test_channel_sequence(struct torture_context *tctx,
    4643             :                                   struct smb2_tree *tree)
    4644             : {
    4645           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    4646           5 :         bool ret = true;
    4647           5 :         const char *fname = BASEDIR "\\channel_sequence.dat";
    4648           5 :         struct smb2_transport *transport1 = tree->session->transport;
    4649             :         struct smb2_handle handle;
    4650           5 :         uint16_t opcodes[] = { SMB2_OP_WRITE, SMB2_OP_IOCTL, SMB2_OP_SETINFO };
    4651             :         int i;
    4652             : 
    4653           5 :         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
    4654           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    4655             :                                    "Replay tests\n");
    4656             :         }
    4657             : 
    4658           4 :         torture_comment(tctx, "Testing channel sequence numbers\n");
    4659             : 
    4660           4 :         smbXcli_conn_set_force_channel_sequence(transport1->conn, true);
    4661             : 
    4662           4 :         torture_assert_ntstatus_ok_goto(tctx,
    4663             :                 torture_smb2_testdir(tree, BASEDIR, &handle),
    4664             :                 ret, done, "failed to setup test directory");
    4665             : 
    4666           4 :         smb2_util_close(tree, handle);
    4667           4 :         smb2_util_unlink(tree, fname);
    4668             : 
    4669          16 :         for (i=0; i <ARRAY_SIZE(opcodes); i++) {
    4670          12 :                 torture_assert(tctx,
    4671             :                         test_channel_sequence_table(tctx, tree, false, opcodes[i]),
    4672             :                         "failed to test CSN without replay flag");
    4673          12 :                 torture_assert(tctx,
    4674             :                         test_channel_sequence_table(tctx, tree, true, opcodes[i]),
    4675             :                         "failed to test CSN with replay flag");
    4676             :         }
    4677             : 
    4678           4 : done:
    4679             : 
    4680           4 :         smb2_util_unlink(tree, fname);
    4681           4 :         smb2_deltree(tree, BASEDIR);
    4682             : 
    4683           4 :         talloc_free(tree);
    4684           4 :         talloc_free(mem_ctx);
    4685             : 
    4686           4 :         return ret;
    4687             : }
    4688             : 
    4689             : /**
    4690             :  * Test Durability V2 Create Replay Detection on Multi Channel
    4691             :  */
    4692           5 : static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1)
    4693             : {
    4694           5 :         const char *host = torture_setting_string(tctx, "host", NULL);
    4695           5 :         const char *share = torture_setting_string(tctx, "share", NULL);
    4696             :         NTSTATUS status;
    4697           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    4698             :         struct smb2_handle _h;
    4699           5 :         struct smb2_handle *h = NULL;
    4700             :         struct smb2_create io;
    4701           5 :         struct GUID create_guid = GUID_random();
    4702           5 :         bool ret = true;
    4703           5 :         const char *fname = BASEDIR "\\replay3.dat";
    4704           5 :         struct smb2_tree *tree2 = NULL;
    4705           5 :         struct smb2_transport *transport1 = tree1->session->transport;
    4706           5 :         struct smb2_transport *transport2 = NULL;
    4707           5 :         struct smb2_session *session1_1 = tree1->session;
    4708           5 :         struct smb2_session *session1_2 = NULL;
    4709             :         uint32_t share_capabilities;
    4710             :         bool share_is_so;
    4711             :         uint32_t server_capabilities;
    4712             : 
    4713           5 :         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
    4714           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    4715             :                                    "Replay tests\n");
    4716             :         }
    4717             : 
    4718           4 :         server_capabilities = smb2cli_conn_server_capabilities(
    4719           4 :                                         tree1->session->transport->conn);
    4720           4 :         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
    4721           0 :                 torture_skip(tctx,
    4722             :                              "Server does not support multi-channel.");
    4723             :         }
    4724             : 
    4725           4 :         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
    4726           4 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    4727             : 
    4728           4 :         torture_reset_break_info(tctx, &break_info);
    4729           4 :         transport1->oplock.handler = torture_oplock_ack_handler;
    4730           4 :         transport1->oplock.private_data = tree1;
    4731             : 
    4732           4 :         torture_comment(tctx, "Replay of DurableHandleReqV2 on Multi "
    4733             :                               "Channel\n");
    4734           4 :         status = torture_smb2_testdir(tree1, BASEDIR, &_h);
    4735           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4736           4 :         smb2_util_close(tree1, _h);
    4737           4 :         smb2_util_unlink(tree1, fname);
    4738           4 :         CHECK_VAL(break_info.count, 0);
    4739             : 
    4740             :         /*
    4741             :          * use the 1st channel, 1st session
    4742             :          */
    4743           4 :         smb2_oplock_create_share(&io, fname,
    4744             :                         smb2_util_share_access(""),
    4745           4 :                         smb2_util_oplock_level("b"));
    4746           4 :         io.in.durable_open = false;
    4747           4 :         io.in.durable_open_v2 = true;
    4748           4 :         io.in.persistent_open = false;
    4749           4 :         io.in.create_guid = create_guid;
    4750           4 :         io.in.timeout = UINT32_MAX;
    4751             : 
    4752           4 :         tree1->session = session1_1;
    4753           4 :         status = smb2_create(tree1, mem_ctx, &io);
    4754           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4755           4 :         _h = io.out.file.handle;
    4756           4 :         h = &_h;
    4757           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    4758           4 :         if (share_is_so) {
    4759           0 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
    4760           0 :                 CHECK_VAL(io.out.durable_open_v2, false);
    4761           0 :                 CHECK_VAL(io.out.timeout, 0);
    4762             :         } else {
    4763           4 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
    4764           4 :                 CHECK_VAL(io.out.durable_open_v2, true);
    4765           4 :                 CHECK_VAL(io.out.timeout, 300*1000);
    4766             :         }
    4767           4 :         CHECK_VAL(io.out.durable_open, false);
    4768           4 :         CHECK_VAL(break_info.count, 0);
    4769             : 
    4770           8 :         status = smb2_connect(tctx,
    4771             :                         host,
    4772             :                         lpcfg_smb_ports(tctx->lp_ctx),
    4773             :                         share,
    4774             :                         lpcfg_resolve_context(tctx->lp_ctx),
    4775             :                         samba_cmdline_get_creds(),
    4776             :                         &tree2,
    4777             :                         tctx->ev,
    4778           4 :                         &transport1->options,
    4779             :                         lpcfg_socket_options(tctx->lp_ctx),
    4780             :                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)
    4781             :                         );
    4782           4 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    4783             :                         "smb2_connect failed");
    4784           4 :         transport2 = tree2->session->transport;
    4785             : 
    4786           4 :         transport2->oplock.handler = torture_oplock_ack_handler;
    4787           4 :         transport2->oplock.private_data = tree2;
    4788             : 
    4789             :         /*
    4790             :          * Now bind the 1st session to 2nd transport channel
    4791             :          */
    4792           4 :         session1_2 = smb2_session_channel(transport2,
    4793             :                         lpcfg_gensec_settings(tctx, tctx->lp_ctx),
    4794             :                         tree2, session1_1);
    4795           4 :         torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
    4796             : 
    4797           4 :         status = smb2_session_setup_spnego(session1_2,
    4798             :                         samba_cmdline_get_creds(),
    4799             :                         0 /* previous_session_id */);
    4800           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4801             : 
    4802             :         /*
    4803             :          * use the 2nd channel, 1st session
    4804             :          */
    4805           4 :         tree1->session = session1_2;
    4806           4 :         smb2cli_session_start_replay(tree1->session->smbXcli);
    4807           4 :         status = smb2_create(tree1, mem_ctx, &io);
    4808           4 :         smb2cli_session_stop_replay(tree1->session->smbXcli);
    4809           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4810           4 :         _h = io.out.file.handle;
    4811           4 :         h = &_h;
    4812           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    4813           4 :         if (share_is_so) {
    4814           0 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
    4815           0 :                 CHECK_VAL(io.out.durable_open_v2, false);
    4816           0 :                 CHECK_VAL(io.out.timeout, 0);
    4817             :         } else {
    4818           4 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
    4819           4 :                 CHECK_VAL(io.out.durable_open_v2, true);
    4820           4 :                 CHECK_VAL(io.out.timeout, 300*1000);
    4821             :         }
    4822           4 :         CHECK_VAL(io.out.durable_open, false);
    4823           4 :         CHECK_VAL(break_info.count, 0);
    4824             : 
    4825           4 :         tree1->session = session1_1;
    4826           4 :         smb2_util_close(tree1, *h);
    4827           4 :         h = NULL;
    4828             : 
    4829           4 : done:
    4830           4 :         talloc_free(tree2);
    4831           4 :         tree1->session = session1_1;
    4832             : 
    4833           4 :         if (h != NULL) {
    4834           0 :                 smb2_util_close(tree1, *h);
    4835             :         }
    4836             : 
    4837           4 :         smb2_util_unlink(tree1, fname);
    4838           4 :         smb2_deltree(tree1, BASEDIR);
    4839             : 
    4840           4 :         talloc_free(tree1);
    4841           4 :         talloc_free(mem_ctx);
    4842             : 
    4843           4 :         return ret;
    4844             : }
    4845             : 
    4846             : /**
    4847             :  * Test Multichannel IO Ordering using ChannelSequence/Channel Epoch number
    4848             :  */
    4849           5 : static bool test_replay4(struct torture_context *tctx, struct smb2_tree *tree1)
    4850             : {
    4851           5 :         const char *host = torture_setting_string(tctx, "host", NULL);
    4852           5 :         const char *share = torture_setting_string(tctx, "share", NULL);
    4853             :         NTSTATUS status;
    4854           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    4855             :         struct smb2_handle _h1;
    4856           5 :         struct smb2_handle *h1 = NULL;
    4857             :         struct smb2_create io;
    4858           5 :         struct GUID create_guid = GUID_random();
    4859             :         uint8_t buf[64];
    4860             :         struct smb2_read rd;
    4861             :         union smb_setfileinfo sfinfo;
    4862           5 :         bool ret = true;
    4863           5 :         const char *fname = BASEDIR "\\replay4.dat";
    4864           5 :         struct smb2_tree *tree2 = NULL;
    4865           5 :         struct smb2_transport *transport1 = tree1->session->transport;
    4866           5 :         struct smb2_transport *transport2 = NULL;
    4867           5 :         struct smb2_session *session1_1 = tree1->session;
    4868           5 :         struct smb2_session *session1_2 = NULL;
    4869             :         uint16_t curr_cs;
    4870             :         uint32_t share_capabilities;
    4871             :         bool share_is_so;
    4872             :         uint32_t server_capabilities;
    4873             : 
    4874           5 :         if (smbXcli_conn_protocol(transport1->conn) < PROTOCOL_SMB3_00) {
    4875           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    4876             :                                    "Replay tests\n");
    4877             :         }
    4878             : 
    4879           4 :         server_capabilities = smb2cli_conn_server_capabilities(
    4880           4 :                                         tree1->session->transport->conn);
    4881           4 :         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
    4882           0 :                 torture_skip(tctx,
    4883             :                              "Server does not support multi-channel.");
    4884             :         }
    4885             : 
    4886           4 :         share_capabilities = smb2cli_tcon_capabilities(tree1->smbXcli);
    4887           4 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    4888             : 
    4889           4 :         torture_reset_break_info(tctx, &break_info);
    4890           4 :         transport1->oplock.handler = torture_oplock_ack_handler;
    4891           4 :         transport1->oplock.private_data = tree1;
    4892             : 
    4893           4 :         torture_comment(tctx, "IO Ordering for Multi Channel\n");
    4894           4 :         status = torture_smb2_testdir(tree1, BASEDIR, &_h1);
    4895           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4896           4 :         smb2_util_close(tree1, _h1);
    4897           4 :         smb2_util_unlink(tree1, fname);
    4898           4 :         CHECK_VAL(break_info.count, 0);
    4899             : 
    4900             :         /*
    4901             :          * use the 1st channel, 1st session
    4902             :          */
    4903             : 
    4904           4 :         smb2_oplock_create_share(&io, fname,
    4905             :                         smb2_util_share_access(""),
    4906           4 :                         smb2_util_oplock_level("b"));
    4907           4 :         io.in.durable_open = false;
    4908           4 :         io.in.durable_open_v2 = true;
    4909           4 :         io.in.persistent_open = false;
    4910           4 :         io.in.create_guid = create_guid;
    4911           4 :         io.in.timeout = UINT32_MAX;
    4912             : 
    4913           4 :         tree1->session = session1_1;
    4914           4 :         status = smb2_create(tree1, mem_ctx, &io);
    4915           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4916           4 :         _h1 = io.out.file.handle;
    4917           4 :         h1 = &_h1;
    4918           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    4919           4 :         if (share_is_so) {
    4920           0 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("s"));
    4921           0 :                 CHECK_VAL(io.out.durable_open_v2, false);
    4922           0 :                 CHECK_VAL(io.out.timeout, 0);
    4923             :         } else {
    4924           4 :                 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
    4925           4 :                 CHECK_VAL(io.out.durable_open_v2, true);
    4926           4 :                 CHECK_VAL(io.out.timeout, 300*1000);
    4927             :         }
    4928           4 :         CHECK_VAL(io.out.durable_open, false);
    4929           4 :         CHECK_VAL(break_info.count, 0);
    4930             : 
    4931           4 :         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
    4932           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4933             : 
    4934             :         /*
    4935             :          * Increment ChannelSequence so that server thinks that there's a
    4936             :          * Channel Failure
    4937             :          */
    4938           4 :         smb2cli_session_increment_channel_sequence(tree1->session->smbXcli);
    4939             : 
    4940             :         /*
    4941             :          * Perform a Read with incremented ChannelSequence
    4942             :          */
    4943           4 :         rd = (struct smb2_read) {
    4944           4 :                 .in.file.handle = *h1,
    4945             :                 .in.length = sizeof(buf),
    4946             :                 .in.offset = 0
    4947             :         };
    4948           4 :         status = smb2_read(tree1, tree1, &rd);
    4949           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4950             : 
    4951             :         /*
    4952             :          * Performing a Write with Stale ChannelSequence is not allowed by
    4953             :          * server
    4954             :          */
    4955           4 :         curr_cs = smb2cli_session_reset_channel_sequence(
    4956           4 :                                                 tree1->session->smbXcli, 0);
    4957           4 :         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
    4958           4 :         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
    4959             : 
    4960             :         /*
    4961             :          * Performing a Write Replay with Stale ChannelSequence is not allowed
    4962             :          * by server
    4963             :          */
    4964           4 :         smb2cli_session_start_replay(tree1->session->smbXcli);
    4965           4 :         smb2cli_session_reset_channel_sequence(tree1->session->smbXcli, 0);
    4966           4 :         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
    4967           4 :         smb2cli_session_stop_replay(tree1->session->smbXcli);
    4968           4 :         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
    4969             : 
    4970             :         /*
    4971             :          * Performing a SetInfo with stale ChannelSequence is not allowed by
    4972             :          * server
    4973             :          */
    4974           4 :         ZERO_STRUCT(sfinfo);
    4975           4 :         sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
    4976           4 :         sfinfo.generic.in.file.handle = *h1;
    4977           4 :         sfinfo.position_information.in.position = 0x1000;
    4978           4 :         status = smb2_setinfo_file(tree1, &sfinfo);
    4979           4 :         CHECK_STATUS(status, NT_STATUS_FILE_NOT_AVAILABLE);
    4980             : 
    4981             :         /*
    4982             :          * Performing a Read with stale ChannelSequence is allowed
    4983             :          */
    4984           4 :         rd = (struct smb2_read) {
    4985           4 :                 .in.file.handle = *h1,
    4986             :                 .in.length = ARRAY_SIZE(buf),
    4987             :                 .in.offset = 0
    4988             :         };
    4989           4 :         status = smb2_read(tree1, tree1, &rd);
    4990           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    4991             : 
    4992           8 :         status = smb2_connect(tctx,
    4993             :                         host,
    4994             :                         lpcfg_smb_ports(tctx->lp_ctx),
    4995             :                         share,
    4996             :                         lpcfg_resolve_context(tctx->lp_ctx),
    4997             :                         samba_cmdline_get_creds(),
    4998             :                         &tree2,
    4999             :                         tctx->ev,
    5000           4 :                         &transport1->options,
    5001             :                         lpcfg_socket_options(tctx->lp_ctx),
    5002             :                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)
    5003             :                         );
    5004           4 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    5005             :                         "smb2_connect failed");
    5006           4 :         transport2 = tree2->session->transport;
    5007             : 
    5008           4 :         transport2->oplock.handler = torture_oplock_ack_handler;
    5009           4 :         transport2->oplock.private_data = tree2;
    5010             : 
    5011             :         /*
    5012             :          * Now bind the 1st session to 2nd transport channel
    5013             :          */
    5014           4 :         session1_2 = smb2_session_channel(transport2,
    5015             :                         lpcfg_gensec_settings(tctx, tctx->lp_ctx),
    5016             :                         tree2, session1_1);
    5017           4 :         torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");
    5018             : 
    5019           4 :         status = smb2_session_setup_spnego(session1_2,
    5020             :                         samba_cmdline_get_creds(),
    5021             :                         0 /* previous_session_id */);
    5022           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5023             : 
    5024             :         /*
    5025             :          * use the 2nd channel, 1st session
    5026             :          */
    5027           4 :         tree1->session = session1_2;
    5028             : 
    5029             :         /*
    5030             :          * Write Replay with Correct ChannelSequence is allowed by the server
    5031             :          */
    5032           4 :         smb2cli_session_start_replay(tree1->session->smbXcli);
    5033           4 :         smb2cli_session_reset_channel_sequence(tree1->session->smbXcli,
    5034             :                                                curr_cs);
    5035           4 :         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
    5036           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5037           4 :         smb2cli_session_stop_replay(tree1->session->smbXcli);
    5038             : 
    5039             :         /*
    5040             :          * See what happens if we change the Buffer and perform a Write Replay.
    5041             :          * This is to show that Write Replay does not really care about the data
    5042             :          */
    5043           4 :         memset(buf, 'r', ARRAY_SIZE(buf));
    5044           4 :         smb2cli_session_start_replay(tree1->session->smbXcli);
    5045           4 :         status = smb2_util_write(tree1, *h1, buf, 0, ARRAY_SIZE(buf));
    5046           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5047           4 :         smb2cli_session_stop_replay(tree1->session->smbXcli);
    5048             : 
    5049             :         /*
    5050             :          * Read back from File to verify what was written
    5051             :          */
    5052           4 :         rd = (struct smb2_read) {
    5053           4 :                 .in.file.handle = *h1,
    5054             :                 .in.length = ARRAY_SIZE(buf),
    5055             :                 .in.offset = 0
    5056             :         };
    5057           4 :         status = smb2_read(tree1, tree1, &rd);
    5058           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5059             : 
    5060           8 :         if ((rd.out.data.length != ARRAY_SIZE(buf)) ||
    5061           4 :                         memcmp(rd.out.data.data, buf, ARRAY_SIZE(buf))) {
    5062           0 :                 torture_comment(tctx, "Write Replay Data Mismatch\n");
    5063             :         }
    5064             : 
    5065           4 :         tree1->session = session1_1;
    5066           4 :         smb2_util_close(tree1, *h1);
    5067           4 :         h1 = NULL;
    5068             : 
    5069           4 :         if (share_is_so) {
    5070           0 :                 CHECK_VAL(break_info.count, 1);
    5071             :         } else {
    5072           4 :                 CHECK_VAL(break_info.count, 0);
    5073             :         }
    5074           8 : done:
    5075           4 :         talloc_free(tree2);
    5076           4 :         tree1->session = session1_1;
    5077             : 
    5078           4 :         if (h1 != NULL) {
    5079           0 :                 smb2_util_close(tree1, *h1);
    5080             :         }
    5081             : 
    5082           4 :         smb2_util_unlink(tree1, fname);
    5083           4 :         smb2_deltree(tree1, BASEDIR);
    5084             : 
    5085           4 :         talloc_free(tree1);
    5086           4 :         talloc_free(mem_ctx);
    5087             : 
    5088           4 :         return ret;
    5089             : }
    5090             : 
    5091             : /**
    5092             :  * Test Durability V2 Persistent Create Replay on a Single Channel
    5093             :  */
    5094           5 : static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree)
    5095             : {
    5096             :         NTSTATUS status;
    5097           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    5098             :         struct smb2_handle _h;
    5099           5 :         struct smb2_handle *h = NULL;
    5100             :         struct smb2_create io;
    5101           5 :         struct GUID create_guid = GUID_random();
    5102           5 :         bool ret = true;
    5103             :         uint32_t share_capabilities;
    5104             :         bool share_is_ca;
    5105             :         bool share_is_so;
    5106             :         uint32_t server_capabilities;
    5107           5 :         const char *fname = BASEDIR "\\replay5.dat";
    5108           5 :         struct smb2_transport *transport = tree->session->transport;
    5109           5 :         struct smbcli_options options = tree->session->transport->options;
    5110           5 :         uint8_t expect_oplock = smb2_util_oplock_level("b");
    5111           5 :         NTSTATUS expect_status = NT_STATUS_DUPLICATE_OBJECTID;
    5112             : 
    5113           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
    5114           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    5115             :                                 "Replay tests\n");
    5116             :         }
    5117             : 
    5118           4 :         server_capabilities = smb2cli_conn_server_capabilities(
    5119           4 :                                         tree->session->transport->conn);
    5120           4 :         if (!(server_capabilities & SMB2_CAP_PERSISTENT_HANDLES)) {
    5121           4 :                 torture_skip(tctx,
    5122             :                              "Server does not support persistent handles.");
    5123             :         }
    5124             : 
    5125           0 :         share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
    5126             : 
    5127           0 :         share_is_ca = share_capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
    5128           0 :         if (!share_is_ca) {
    5129           0 :                 torture_skip(tctx, "Share is not continuously available.");
    5130             :         }
    5131             : 
    5132           0 :         share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
    5133           0 :         if (share_is_so) {
    5134           0 :                 expect_oplock = smb2_util_oplock_level("s");
    5135           0 :                 expect_status = NT_STATUS_FILE_NOT_AVAILABLE;
    5136             :         }
    5137             : 
    5138           0 :         torture_reset_break_info(tctx, &break_info);
    5139           0 :         transport->oplock.handler = torture_oplock_ack_handler;
    5140           0 :         transport->oplock.private_data = tree;
    5141             : 
    5142           0 :         torture_comment(tctx, "Replay of Persistent DurableHandleReqV2 on Single "
    5143             :                         "Channel\n");
    5144           0 :         status = torture_smb2_testdir(tree, BASEDIR, &_h);
    5145           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    5146           0 :         smb2_util_close(tree, _h);
    5147           0 :         smb2_util_unlink(tree, fname);
    5148           0 :         CHECK_VAL(break_info.count, 0);
    5149             : 
    5150           0 :         smb2_oplock_create_share(&io, fname,
    5151             :                         smb2_util_share_access("RWD"),
    5152           0 :                         smb2_util_oplock_level("b"));
    5153           0 :         io.in.durable_open = false;
    5154           0 :         io.in.durable_open_v2 = true;
    5155           0 :         io.in.persistent_open = true;
    5156           0 :         io.in.create_guid = create_guid;
    5157           0 :         io.in.timeout = UINT32_MAX;
    5158             : 
    5159           0 :         status = smb2_create(tree, mem_ctx, &io);
    5160           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    5161           0 :         _h = io.out.file.handle;
    5162           0 :         h = &_h;
    5163           0 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    5164           0 :         CHECK_VAL(io.out.oplock_level, expect_oplock);
    5165           0 :         CHECK_VAL(io.out.durable_open, false);
    5166           0 :         CHECK_VAL(io.out.durable_open_v2, true);
    5167           0 :         CHECK_VAL(io.out.persistent_open, true);
    5168           0 :         CHECK_VAL(io.out.timeout, 300*1000);
    5169           0 :         CHECK_VAL(break_info.count, 0);
    5170             : 
    5171             :         /* disconnect, leaving the durable open */
    5172           0 :         TALLOC_FREE(tree);
    5173             : 
    5174           0 :         if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) {
    5175           0 :                 torture_warning(tctx, "couldn't reconnect, bailing\n");
    5176           0 :                 ret = false;
    5177           0 :                 goto done;
    5178             :         }
    5179             : 
    5180             :         /* a re-open of a persistent handle causes an error */
    5181           0 :         status = smb2_create(tree, mem_ctx, &io);
    5182           0 :         CHECK_STATUS(status, expect_status);
    5183             : 
    5184             :         /* SMB2_FLAGS_REPLAY_OPERATION must be set to open the Persistent Handle */
    5185           0 :         smb2cli_session_start_replay(tree->session->smbXcli);
    5186           0 :         smb2cli_session_increment_channel_sequence(tree->session->smbXcli);
    5187           0 :         status = smb2_create(tree, mem_ctx, &io);
    5188           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    5189           0 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    5190           0 :         CHECK_VAL(io.out.durable_open, false);
    5191           0 :         CHECK_VAL(io.out.persistent_open, true);
    5192           0 :         CHECK_VAL(io.out.oplock_level, expect_oplock);
    5193           0 :         _h = io.out.file.handle;
    5194           0 :         h = &_h;
    5195             : 
    5196           0 :         smb2_util_close(tree, *h);
    5197           0 :         h = NULL;
    5198           0 : done:
    5199           0 :         if (h != NULL) {
    5200           0 :                 smb2_util_close(tree, *h);
    5201             :         }
    5202             : 
    5203           0 :         smb2_util_unlink(tree, fname);
    5204           0 :         smb2_deltree(tree, BASEDIR);
    5205             : 
    5206           0 :         talloc_free(tree);
    5207           0 :         talloc_free(mem_ctx);
    5208             : 
    5209           0 :         return ret;
    5210             : }
    5211             : 
    5212             : 
    5213             : /**
    5214             :  * Test Error Codes when a DurableHandleReqV2 with matching CreateGuid is
    5215             :  * re-sent with or without SMB2_FLAGS_REPLAY_OPERATION
    5216             :  */
    5217           5 : static bool test_replay6(struct torture_context *tctx, struct smb2_tree *tree)
    5218             : {
    5219             :         NTSTATUS status;
    5220           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    5221             :         struct smb2_handle _h;
    5222           5 :         struct smb2_handle *h = NULL;
    5223             :         struct smb2_create io, ref1;
    5224             :         union smb_fileinfo qfinfo;
    5225           5 :         struct GUID create_guid = GUID_random();
    5226           5 :         bool ret = true;
    5227           5 :         const char *fname = BASEDIR "\\replay6.dat";
    5228           5 :         struct smb2_transport *transport = tree->session->transport;
    5229             : 
    5230           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
    5231           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    5232             :                                    "replay tests\n");
    5233             :         }
    5234             : 
    5235           4 :         torture_reset_break_info(tctx, &break_info);
    5236           4 :         tree->session->transport->oplock.handler = torture_oplock_ack_handler;
    5237           4 :         tree->session->transport->oplock.private_data = tree;
    5238             : 
    5239           4 :         torture_comment(tctx, "Error Codes for DurableHandleReqV2 Replay\n");
    5240           4 :         smb2_util_unlink(tree, fname);
    5241           4 :         status = torture_smb2_testdir(tree, BASEDIR, &_h);
    5242           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5243           4 :         smb2_util_close(tree, _h);
    5244           4 :         torture_wait_for_oplock_break(tctx);
    5245           4 :         CHECK_VAL(break_info.count, 0);
    5246           4 :         torture_reset_break_info(tctx, &break_info);
    5247             : 
    5248           4 :         smb2_oplock_create_share(&io, fname,
    5249             :                         smb2_util_share_access("RWD"),
    5250           4 :                         smb2_util_oplock_level("b"));
    5251           4 :         io.in.durable_open = false;
    5252           4 :         io.in.durable_open_v2 = true;
    5253           4 :         io.in.persistent_open = false;
    5254           4 :         io.in.create_guid = create_guid;
    5255           4 :         io.in.timeout = UINT32_MAX;
    5256             : 
    5257           4 :         status = smb2_create(tree, mem_ctx, &io);
    5258           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5259           4 :         ref1 = io;
    5260           4 :         _h = io.out.file.handle;
    5261           4 :         h = &_h;
    5262           4 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    5263           4 :         CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
    5264           4 :         CHECK_VAL(io.out.durable_open, false);
    5265           4 :         CHECK_VAL(io.out.durable_open_v2, true);
    5266             : 
    5267           4 :         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    5268           4 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    5269           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
    5270           4 :         status = smb2_create(tree, mem_ctx, &io);
    5271           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    5272           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5273           4 :         CHECK_CREATE_OUT(&io, &ref1);
    5274           4 :         torture_wait_for_oplock_break(tctx);
    5275           4 :         CHECK_VAL(break_info.count, 0);
    5276           4 :         torture_reset_break_info(tctx, &break_info);
    5277             : 
    5278           4 :         qfinfo = (union smb_fileinfo) {
    5279             :                 .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
    5280           4 :                 .generic.in.file.handle = *h
    5281             :         };
    5282           4 :         torture_comment(tctx, "Trying getinfo\n");
    5283           4 :         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
    5284           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5285           4 :         CHECK_VAL(qfinfo.position_information.out.position, 0);
    5286             : 
    5287           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
    5288           4 :         status = smb2_create(tree, mem_ctx, &io);
    5289           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    5290           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5291           4 :         torture_assert_u64_not_equal_goto(tctx,
    5292             :                 io.out.file.handle.data[0],
    5293             :                 ref1.out.file.handle.data[0],
    5294             :                 ret, done, "data 0");
    5295           4 :         torture_assert_u64_not_equal_goto(tctx,
    5296             :                 io.out.file.handle.data[1],
    5297             :                 ref1.out.file.handle.data[1],
    5298             :                 ret, done, "data 1");
    5299           4 :         torture_wait_for_oplock_break(tctx);
    5300           4 :         CHECK_VAL(break_info.count, 1);
    5301           4 :         CHECK_VAL(break_info.level, smb2_util_oplock_level("s"));
    5302           4 :         torture_reset_break_info(tctx, &break_info);
    5303             : 
    5304             :         /*
    5305             :          * Resend the matching Durable V2 Create without
    5306             :          * SMB2_FLAGS_REPLAY_OPERATION. This triggers an oplock break and still
    5307             :          * gets NT_STATUS_DUPLICATE_OBJECTID
    5308             :          */
    5309           4 :         status = smb2_create(tree, mem_ctx, &io);
    5310           4 :         CHECK_STATUS(status, NT_STATUS_DUPLICATE_OBJECTID);
    5311           4 :         torture_wait_for_oplock_break(tctx);
    5312           4 :         CHECK_VAL(break_info.count, 0);
    5313           4 :         torture_reset_break_info(tctx, &break_info);
    5314             : 
    5315             :         /*
    5316             :          * According to MS-SMB2 3.3.5.9.10 if Durable V2 Create is replayed and
    5317             :          * FileAttributes or CreateDisposition do not match the earlier Create
    5318             :          * request the Server fails request with
    5319             :          * NT_STATUS_INVALID_PARAMETER. But through this test we see that server
    5320             :          * does not really care about changed FileAttributes or
    5321             :          * CreateDisposition.
    5322             :          */
    5323           4 :         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    5324           4 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    5325           4 :         smb2cli_session_start_replay(tree->session->smbXcli);
    5326           4 :         status = smb2_create(tree, mem_ctx, &io);
    5327           4 :         smb2cli_session_stop_replay(tree->session->smbXcli);
    5328           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5329           4 :         torture_assert_u64_not_equal_goto(tctx,
    5330             :                 io.out.file.handle.data[0],
    5331             :                 ref1.out.file.handle.data[0],
    5332             :                 ret, done, "data 0");
    5333           4 :         torture_assert_u64_not_equal_goto(tctx,
    5334             :                 io.out.file.handle.data[1],
    5335             :                 ref1.out.file.handle.data[1],
    5336             :                 ret, done, "data 1");
    5337           4 :         torture_wait_for_oplock_break(tctx);
    5338           4 :         CHECK_VAL(break_info.count, 0);
    5339             : 
    5340           8 : done:
    5341           4 :         if (h != NULL) {
    5342           4 :                 smb2_util_close(tree, *h);
    5343             :         }
    5344             : 
    5345           4 :         smb2_util_unlink(tree, fname);
    5346           4 :         smb2_deltree(tree, BASEDIR);
    5347             : 
    5348           4 :         talloc_free(tree);
    5349           4 :         talloc_free(mem_ctx);
    5350             : 
    5351           4 :         return ret;
    5352             : }
    5353             : 
    5354           5 : static bool test_replay7(struct torture_context *tctx, struct smb2_tree *tree)
    5355             : {
    5356           5 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    5357           5 :         struct smb2_transport *transport = tree->session->transport;
    5358             :         NTSTATUS status;
    5359             :         struct smb2_handle _dh;
    5360           5 :         struct smb2_handle *dh = NULL;
    5361             :         struct smb2_notify notify;
    5362             :         struct smb2_request *req;
    5363             :         union smb_fileinfo qfinfo;
    5364           5 :         bool ret = false;
    5365             : 
    5366           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
    5367           1 :                 torture_skip(tctx, "SMB 3.X Dialect family required for "
    5368             :                                    "replay tests\n");
    5369             :         }
    5370             : 
    5371           4 :         torture_comment(tctx, "Notify across increment/decrement of csn\n");
    5372             : 
    5373           4 :         smbXcli_conn_set_force_channel_sequence(transport->conn, true);
    5374             : 
    5375           4 :         status = torture_smb2_testdir(tree, BASEDIR, &_dh);
    5376           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5377           4 :         dh = &_dh;
    5378             : 
    5379           4 :         notify.in.recursive             = 0x0000;
    5380           4 :         notify.in.buffer_size   = 0xffff;
    5381           4 :         notify.in.file.handle   = _dh;
    5382           4 :         notify.in.completion_filter     = FILE_NOTIFY_CHANGE_FILE_NAME;
    5383           4 :         notify.in.unknown               = 0x00000000;
    5384             : 
    5385             :         /*
    5386             :          * This posts a long-running request with csn==0 to "dh". Now
    5387             :          * op->request_count==1 in smb2_server.c.
    5388             :          */
    5389           4 :         smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
    5390           4 :         req = smb2_notify_send(tree, &notify);
    5391             : 
    5392           4 :         qfinfo = (union smb_fileinfo) {
    5393             :                 .generic.level = RAW_FILEINFO_POSITION_INFORMATION,
    5394             :                 .generic.in.file.handle = _dh
    5395             :         };
    5396             : 
    5397             :         /*
    5398             :          * This sequence of 2 dummy requests moves
    5399             :          * op->request_count==1 to op->pre_request_count. The numbers
    5400             :          * used avoid int16 overflow.
    5401             :          */
    5402             : 
    5403           4 :         smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 30000);
    5404           4 :         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
    5405           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5406             : 
    5407           4 :         smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 60000);
    5408           4 :         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
    5409           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5410             : 
    5411             :         /*
    5412             :          * This final request turns the op->global->channel_sequence
    5413             :          * to the same as we had when sending the notify above. The
    5414             :          * notify's request count has in the meantime moved to
    5415             :          * op->pre_request_count.
    5416             :          */
    5417             : 
    5418           4 :         smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0);
    5419           4 :         status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
    5420           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5421             : 
    5422             :         /*
    5423             :          * At this point op->request_count==0.
    5424             :          *
    5425             :          * The next cancel makes us reply to the notify. Because the
    5426             :          * csn we currently use is the same as we used when sending
    5427             :          * the notify, smbd thinks it must decrement op->request_count
    5428             :          * and not op->pre_request_count.
    5429             :          */
    5430             : 
    5431           4 :         status = smb2_cancel(req);
    5432           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    5433             : 
    5434           4 :         status = smb2_notify_recv(req, mem_ctx, &notify);
    5435           4 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
    5436             : 
    5437           4 :         ret = true;
    5438             : 
    5439           4 : done:
    5440           4 :         if (dh != NULL) {
    5441           4 :                 smb2_util_close(tree, _dh);
    5442             :         }
    5443           4 :         smb2_deltree(tree, BASEDIR);
    5444           4 :         talloc_free(tree);
    5445           4 :         talloc_free(mem_ctx);
    5446             : 
    5447           4 :         return ret;
    5448             : }
    5449             : 
    5450        2353 : struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx)
    5451             : {
    5452        2353 :         struct torture_suite *suite =
    5453             :                 torture_suite_create(ctx, "replay");
    5454             : 
    5455        2353 :         torture_suite_add_1smb2_test(suite, "replay-commands", test_replay_commands);
    5456        2353 :         torture_suite_add_1smb2_test(suite, "replay-regular", test_replay_regular);
    5457        2353 :         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock1", test_replay_dhv2_oplock1);
    5458        2353 :         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock2", test_replay_dhv2_oplock2);
    5459        2353 :         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock3", test_replay_dhv2_oplock3);
    5460        2353 :         torture_suite_add_1smb2_test(suite, "replay-dhv2-oplock-lease", test_replay_dhv2_oplock_lease);
    5461        2353 :         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease1",  test_replay_dhv2_lease1);
    5462        2353 :         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease2",  test_replay_dhv2_lease2);
    5463        2353 :         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease3",  test_replay_dhv2_lease3);
    5464        2353 :         torture_suite_add_1smb2_test(suite, "replay-dhv2-lease-oplock",  test_replay_dhv2_lease_oplock);
    5465        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-close-sane", test_dhv2_pending1n_vs_violation_lease_close_sane);
    5466        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-ack-sane", test_dhv2_pending1n_vs_violation_lease_ack_sane);
    5467        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-close-windows", test_dhv2_pending1n_vs_violation_lease_close_windows);
    5468        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-violation-lease-ack-windows", test_dhv2_pending1n_vs_violation_lease_ack_windows);
    5469        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-oplock-sane", test_dhv2_pending1n_vs_oplock_sane);
    5470        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-oplock-windows", test_dhv2_pending1n_vs_oplock_windows);
    5471        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-lease-sane", test_dhv2_pending1n_vs_lease_sane);
    5472        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1n-vs-lease-windows",  test_dhv2_pending1n_vs_lease_windows);
    5473        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-oplock-sane", test_dhv2_pending1l_vs_oplock_sane);
    5474        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-oplock-windows", test_dhv2_pending1l_vs_oplock_windows);
    5475        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-lease-sane", test_dhv2_pending1l_vs_lease_sane);
    5476        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1l-vs-lease-windows", test_dhv2_pending1l_vs_lease_windows);
    5477        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-oplock-sane", test_dhv2_pending1o_vs_oplock_sane);
    5478        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-oplock-windows", test_dhv2_pending1o_vs_oplock_windows);
    5479        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-lease-sane", test_dhv2_pending1o_vs_lease_sane);
    5480        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending1o-vs-lease-windows", test_dhv2_pending1o_vs_lease_windows);
    5481        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-oplock-sane", test_dhv2_pending2n_vs_oplock_sane);
    5482        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-oplock-windows", test_dhv2_pending2n_vs_oplock_windows);
    5483        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-lease-sane", test_dhv2_pending2n_vs_lease_sane);
    5484        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2n-vs-lease-windows", test_dhv2_pending2n_vs_lease_windows);
    5485        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-oplock-sane", test_dhv2_pending2l_vs_oplock_sane);
    5486        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-oplock-windows", test_dhv2_pending2l_vs_oplock_windows);
    5487        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-lease-sane", test_dhv2_pending2l_vs_lease_sane);
    5488        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2l-vs-lease-windows", test_dhv2_pending2l_vs_lease_windows);
    5489        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-oplock-sane", test_dhv2_pending2o_vs_oplock_sane);
    5490        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-oplock-windows", test_dhv2_pending2o_vs_oplock_windows);
    5491        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-lease-sane", test_dhv2_pending2o_vs_lease_sane);
    5492        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending2o-vs-lease-windows", test_dhv2_pending2o_vs_lease_windows);
    5493        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-oplock-sane", test_dhv2_pending3n_vs_oplock_sane);
    5494        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-oplock-windows", test_dhv2_pending3n_vs_oplock_windows);
    5495        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-lease-sane", test_dhv2_pending3n_vs_lease_sane);
    5496        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3n-vs-lease-windows", test_dhv2_pending3n_vs_lease_windows);
    5497        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-oplock-sane",  test_dhv2_pending3l_vs_oplock_sane);
    5498        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-oplock-windows",  test_dhv2_pending3l_vs_oplock_windows);
    5499        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-lease-sane",  test_dhv2_pending3l_vs_lease_sane);
    5500        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3l-vs-lease-windows",  test_dhv2_pending3l_vs_lease_windows);
    5501        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-oplock-sane",  test_dhv2_pending3o_vs_oplock_sane);
    5502        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-oplock-windows",  test_dhv2_pending3o_vs_oplock_windows);
    5503        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-lease-sane",  test_dhv2_pending3o_vs_lease_sane);
    5504        2353 :         torture_suite_add_2smb2_test(suite, "dhv2-pending3o-vs-lease-windows",  test_dhv2_pending3o_vs_lease_windows);
    5505        2353 :         torture_suite_add_1smb2_test(suite, "channel-sequence", test_channel_sequence);
    5506        2353 :         torture_suite_add_1smb2_test(suite, "replay3", test_replay3);
    5507        2353 :         torture_suite_add_1smb2_test(suite, "replay4", test_replay4);
    5508        2353 :         torture_suite_add_1smb2_test(suite, "replay5", test_replay5);
    5509        2353 :         torture_suite_add_1smb2_test(suite, "replay6", test_replay6);
    5510        2353 :         torture_suite_add_1smb2_test(suite, "replay7", test_replay7);
    5511             : 
    5512        2353 :         suite->description = talloc_strdup(suite, "SMB2 REPLAY tests");
    5513             : 
    5514        2353 :         return suite;
    5515             : }

Generated by: LCOV version 1.13