LCOV - code coverage report
Current view: top level - source4/torture/smb2 - lock.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 1844 2118 87.1 %
Date: 2023-11-21 12:31:41 Functions: 30 30 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    SMB2 lock test suite
       5             : 
       6             :    Copyright (C) Stefan Metzmacher 2006
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libcli/smb2/smb2.h"
      24             : #include "libcli/smb2/smb2_calls.h"
      25             : #include "../libcli/smb/smbXcli_base.h"
      26             : 
      27             : #include "torture/torture.h"
      28             : #include "torture/smb2/proto.h"
      29             : #include "torture/util.h"
      30             : 
      31             : #include "lib/events/events.h"
      32             : #include "param/param.h"
      33             : 
      34             : #define CHECK_STATUS(status, correct) do { \
      35             :         const char *_cmt = "(" __location__ ")"; \
      36             :         torture_assert_ntstatus_equal_goto(torture,status,correct, \
      37             :                                            ret,done,_cmt); \
      38             :         } while (0)
      39             : 
      40             : #define CHECK_STATUS_CMT(status, correct, cmt) do { \
      41             :         torture_assert_ntstatus_equal_goto(torture,status,correct, \
      42             :                                            ret,done,cmt); \
      43             :         } while (0)
      44             : 
      45             : #define CHECK_STATUS_CONT(status, correct) do { \
      46             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      47             :                 torture_result(torture, TORTURE_FAIL, \
      48             :                         "(%s) Incorrect status %s - should be %s\n", \
      49             :                         __location__, nt_errstr(status), nt_errstr(correct)); \
      50             :                 ret = false; \
      51             :         }} while (0)
      52             : 
      53             : #define CHECK_VALUE(v, correct) do { \
      54             :         const char *_cmt = "(" __location__ ")"; \
      55             :         torture_assert_int_equal_goto(torture,v,correct,ret,done,_cmt); \
      56             :         } while (0)
      57             : 
      58             : #define BASEDIR "testlock"
      59             : 
      60             : #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
      61             :     (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
      62             : #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
      63             : 
      64             : #define WAIT_FOR_ASYNC_RESPONSE(req) \
      65             :         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \
      66             :                 if (tevent_loop_once(torture->ev) != 0) { \
      67             :                         break; \
      68             :                 } \
      69             :         }
      70             : 
      71           5 : static bool test_valid_request(struct torture_context *torture,
      72             :                                struct smb2_tree *tree)
      73             : {
      74           5 :         bool ret = true;
      75           0 :         NTSTATUS status;
      76           0 :         struct smb2_handle h;
      77           0 :         uint8_t buf[200];
      78           0 :         struct smb2_lock lck;
      79           0 :         struct smb2_lock_element el[2];
      80             : 
      81           5 :         ZERO_STRUCT(buf);
      82             : 
      83           5 :         status = torture_smb2_testfile(tree, "lock1.txt", &h);
      84           5 :         CHECK_STATUS(status, NT_STATUS_OK);
      85             : 
      86           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
      87           5 :         CHECK_STATUS(status, NT_STATUS_OK);
      88             : 
      89           5 :         lck.in.locks            = el;
      90             : 
      91           5 :         torture_comment(torture, "Test request with 0 locks.\n");
      92             : 
      93           5 :         lck.in.lock_count       = 0x0000;
      94           5 :         lck.in.lock_sequence    = 0x00000000;
      95           5 :         lck.in.file.handle      = h;
      96           5 :         el[0].offset            = 0x0000000000000000;
      97           5 :         el[0].length            = 0x0000000000000000;
      98           5 :         el[0].reserved          = 0x0000000000000000;
      99           5 :         el[0].flags             = 0x00000000;
     100           5 :         status = smb2_lock(tree, &lck);
     101           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     102             : 
     103           5 :         lck.in.lock_count       = 0x0000;
     104           5 :         lck.in.lock_sequence    = 0x00000000;
     105           5 :         lck.in.file.handle      = h;
     106           5 :         el[0].offset            = 0;
     107           5 :         el[0].length            = 0;
     108           5 :         el[0].reserved          = 0x00000000;
     109           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED;
     110           5 :         status = smb2_lock(tree, &lck);
     111           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     112             : 
     113           5 :         lck.in.lock_count       = 0x0001;
     114           5 :         lck.in.lock_sequence    = 0x00000000;
     115           5 :         lck.in.file.handle      = h;
     116           5 :         el[0].offset            = 0;
     117           5 :         el[0].length            = 0;
     118           5 :         el[0].reserved          = 0x00000000;
     119           5 :         el[0].flags             = SMB2_LOCK_FLAG_NONE;
     120           5 :         status = smb2_lock(tree, &lck);
     121           5 :         if (TARGET_IS_W2K8(torture)) {
     122           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     123           0 :                 torture_warning(torture, "Target has bug validating lock flags "
     124             :                                          "parameter.\n");
     125             :         } else {
     126           5 :                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     127             :         }
     128             : 
     129           5 :         torture_comment(torture, "Test >63-bit lock requests.\n");
     130             : 
     131           5 :         lck.in.file.handle.data[0] +=1;
     132           5 :         status = smb2_lock(tree, &lck);
     133           5 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
     134           5 :         lck.in.file.handle.data[0] -=1;
     135             : 
     136           5 :         lck.in.lock_count       = 0x0001;
     137           5 :         lck.in.lock_sequence    = 0x123ab1;
     138           5 :         lck.in.file.handle      = h;
     139           5 :         el[0].offset            = UINT64_MAX;
     140           5 :         el[0].length            = UINT64_MAX;
     141           5 :         el[0].reserved          = 0x00000000;
     142           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     143             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     144           5 :         status = smb2_lock(tree, &lck);
     145           5 :         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
     146           5 :                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
     147             :         } else {
     148           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     149           0 :                 CHECK_VALUE(lck.out.reserved, 0);
     150             :         }
     151             : 
     152           5 :         lck.in.lock_sequence    = 0x123ab2;
     153           5 :         status = smb2_lock(tree, &lck);
     154           5 :         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
     155           5 :                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
     156             :         } else {
     157           0 :                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     158             :         }
     159             : 
     160           5 :         torture_comment(torture, "Test basic lock stacking.\n");
     161             : 
     162           5 :         lck.in.lock_count       = 0x0001;
     163           5 :         lck.in.lock_sequence    = 0x12345678;
     164           5 :         lck.in.file.handle      = h;
     165           5 :         el[0].offset            = UINT32_MAX;
     166           5 :         el[0].length            = UINT32_MAX;
     167           5 :         el[0].reserved          = 0x87654321;
     168           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     169             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     170           5 :         status = smb2_lock(tree, &lck);
     171           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     172           5 :         CHECK_VALUE(lck.out.reserved, 0);
     173             : 
     174           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED;
     175           5 :         status = smb2_lock(tree, &lck);
     176           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     177           5 :         CHECK_VALUE(lck.out.reserved, 0);
     178             : 
     179           5 :         status = smb2_lock(tree, &lck);
     180           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     181           5 :         CHECK_VALUE(lck.out.reserved, 0);
     182             : 
     183           5 :         lck.in.lock_count       = 0x0001;
     184           5 :         lck.in.lock_sequence    = 0x87654321;
     185           5 :         lck.in.file.handle      = h;
     186           5 :         el[0].offset            = 0x00000000FFFFFFFF;
     187           5 :         el[0].length            = 0x00000000FFFFFFFF;
     188           5 :         el[0].reserved          = 0x1234567;
     189           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     190           5 :         status = smb2_lock(tree, &lck);
     191           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     192             : 
     193           5 :         lck.in.lock_count       = 0x0001;
     194           5 :         lck.in.lock_sequence    = 0x1234567;
     195           5 :         lck.in.file.handle      = h;
     196           5 :         el[0].offset            = 0x00000000FFFFFFFF;
     197           5 :         el[0].length            = 0x00000000FFFFFFFF;
     198           5 :         el[0].reserved          = 0x00000000;
     199           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     200           5 :         status = smb2_lock(tree, &lck);
     201           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     202             : 
     203           5 :         status = smb2_lock(tree, &lck);
     204           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     205           5 :         status = smb2_lock(tree, &lck);
     206           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     207             : 
     208           5 :         torture_comment(torture, "Test flags field permutations.\n");
     209             : 
     210           5 :         lck.in.lock_count       = 0x0001;
     211           5 :         lck.in.lock_sequence    = 0;
     212           5 :         lck.in.file.handle      = h;
     213           5 :         el[0].offset            = 1;
     214           5 :         el[0].length            = 1;
     215           5 :         el[0].reserved          = 0x00000000;
     216           5 :         el[0].flags             = ~SMB2_LOCK_FLAG_ALL_MASK;
     217             : 
     218           5 :         status = smb2_lock(tree, &lck);
     219           5 :         if (TARGET_IS_W2K8(torture)) {
     220           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     221           0 :                 torture_warning(torture, "Target has bug validating lock flags "
     222             :                                          "parameter.\n");
     223             :         } else {
     224           5 :                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     225             :         }
     226             : 
     227           5 :         if (TARGET_IS_W2K8(torture)) {
     228           0 :                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     229           0 :                 status = smb2_lock(tree, &lck);
     230           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     231             :         }
     232             : 
     233           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     234           5 :         status = smb2_lock(tree, &lck);
     235           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     236             : 
     237           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK |
     238             :                                   SMB2_LOCK_FLAG_EXCLUSIVE;
     239           5 :         status = smb2_lock(tree, &lck);
     240           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     241             : 
     242           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK |
     243             :                                   SMB2_LOCK_FLAG_SHARED;
     244           5 :         status = smb2_lock(tree, &lck);
     245           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     246             : 
     247           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK |
     248             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     249           5 :         status = smb2_lock(tree, &lck);
     250           5 :         if (TARGET_IS_W2K8(torture)) {
     251           0 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     252           0 :                 torture_warning(torture, "Target has bug validating lock flags "
     253             :                                          "parameter.\n");
     254             :         } else {
     255           5 :                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     256             :         }
     257             : 
     258           5 :         torture_comment(torture, "Test return error when 2 locks are "
     259             :                                  "requested\n");
     260             : 
     261           5 :         lck.in.lock_count       = 2;
     262           5 :         lck.in.lock_sequence    = 0;
     263           5 :         lck.in.file.handle      = h;
     264           5 :         el[0].offset            = 9999;
     265           5 :         el[0].length            = 1;
     266           5 :         el[0].reserved          = 0x00000000;
     267           5 :         el[1].offset            = 9999;
     268           5 :         el[1].length            = 1;
     269           5 :         el[1].reserved          = 0x00000000;
     270             : 
     271           5 :         lck.in.lock_count       = 2;
     272           5 :         el[0].flags             = 0;
     273           5 :         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
     274           5 :         status = smb2_lock(tree, &lck);
     275           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     276             : 
     277           5 :         lck.in.lock_count       = 2;
     278           5 :         el[0].flags = SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     279           5 :         el[1].flags = SMB2_LOCK_FLAG_SHARED;
     280           5 :         status = smb2_lock(tree, &lck);
     281           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     282             : 
     283           4 :         lck.in.lock_count       = 2;
     284           4 :         el[0].flags             = 0;
     285           4 :         el[1].flags             = 0;
     286           4 :         status = smb2_lock(tree, &lck);
     287           4 :         if (TARGET_IS_W2K8(torture)) {
     288           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     289           0 :                 torture_warning(torture, "Target has bug validating lock flags "
     290             :                                          "parameter.\n");
     291             :         } else {
     292           4 :                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     293             :         }
     294             : 
     295           4 :         lck.in.lock_count       = 2;
     296           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     297           4 :         el[1].flags             = 0;
     298           4 :         status = smb2_lock(tree, &lck);
     299           4 :         if (TARGET_IS_W2K8(torture)) {
     300           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     301           0 :                 torture_warning(torture, "Target has bug validating lock flags "
     302             :                                          "parameter.\n");
     303             :         } else {
     304           4 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     305             :         }
     306             : 
     307           4 :         lck.in.lock_count       = 1;
     308           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     309           4 :         status = smb2_lock(tree, &lck);
     310           4 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     311             : 
     312           4 :         lck.in.lock_count       = 1;
     313           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     314           4 :         status = smb2_lock(tree, &lck);
     315           4 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     316             : 
     317           4 :         lck.in.lock_count       = 1;
     318           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     319           4 :         status = smb2_lock(tree, &lck);
     320           4 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     321             : 
     322           4 :         lck.in.lock_count       = 1;
     323           4 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED;
     324           4 :         status = smb2_lock(tree, &lck);
     325           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     326             : 
     327           4 :         status = smb2_lock(tree, &lck);
     328           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     329             : 
     330           4 :         lck.in.lock_count       = 2;
     331           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     332           4 :         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
     333           4 :         status = smb2_lock(tree, &lck);
     334           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     335             : 
     336           4 :         lck.in.lock_count       = 1;
     337           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     338           4 :         status = smb2_lock(tree, &lck);
     339           4 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     340             : 
     341           5 : done:
     342           5 :         return ret;
     343             : }
     344             : 
     345             : struct test_lock_read_write_state {
     346             :         const char *fname;
     347             :         uint32_t lock_flags;
     348             :         NTSTATUS write_h1_status;
     349             :         NTSTATUS read_h1_status;
     350             :         NTSTATUS write_h2_status;
     351             :         NTSTATUS read_h2_status;
     352             : };
     353             : 
     354          10 : static bool test_lock_read_write(struct torture_context *torture,
     355             :                                  struct smb2_tree *tree,
     356             :                                  struct test_lock_read_write_state *s)
     357             : {
     358          10 :         bool ret = true;
     359           0 :         NTSTATUS status;
     360           0 :         struct smb2_handle h1, h2;
     361           0 :         uint8_t buf[200];
     362           0 :         struct smb2_lock lck;
     363           0 :         struct smb2_create cr;
     364           0 :         struct smb2_write wr;
     365           0 :         struct smb2_read rd;
     366           0 :         struct smb2_lock_element el[1];
     367             : 
     368          10 :         lck.in.locks            = el;
     369             : 
     370          10 :         ZERO_STRUCT(buf);
     371             : 
     372          10 :         status = torture_smb2_testfile(tree, s->fname, &h1);
     373          10 :         CHECK_STATUS(status, NT_STATUS_OK);
     374             : 
     375          10 :         status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
     376          10 :         CHECK_STATUS(status, NT_STATUS_OK);
     377             : 
     378          10 :         lck.in.lock_count       = 0x0001;
     379          10 :         lck.in.lock_sequence    = 0x00000000;
     380          10 :         lck.in.file.handle      = h1;
     381          10 :         el[0].offset            = 0;
     382          10 :         el[0].length            = ARRAY_SIZE(buf)/2;
     383          10 :         el[0].reserved          = 0x00000000;
     384          10 :         el[0].flags             = s->lock_flags;
     385          10 :         status = smb2_lock(tree, &lck);
     386          10 :         CHECK_STATUS(status, NT_STATUS_OK);
     387          10 :         CHECK_VALUE(lck.out.reserved, 0);
     388             : 
     389          10 :         lck.in.lock_count       = 0x0001;
     390          10 :         lck.in.lock_sequence    = 0x00000000;
     391          10 :         lck.in.file.handle      = h1;
     392          10 :         el[0].offset            = ARRAY_SIZE(buf)/2;
     393          10 :         el[0].length            = ARRAY_SIZE(buf)/2;
     394          10 :         el[0].reserved          = 0x00000000;
     395          10 :         el[0].flags             = s->lock_flags;
     396          10 :         status = smb2_lock(tree, &lck);
     397          10 :         CHECK_STATUS(status, NT_STATUS_OK);
     398          10 :         CHECK_VALUE(lck.out.reserved, 0);
     399             : 
     400          10 :         ZERO_STRUCT(cr);
     401          10 :         cr.in.oplock_level = 0;
     402          10 :         cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
     403          10 :         cr.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
     404          10 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     405          10 :         cr.in.share_access =
     406             :                 NTCREATEX_SHARE_ACCESS_DELETE|
     407             :                 NTCREATEX_SHARE_ACCESS_READ|
     408             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     409          10 :         cr.in.create_options = 0;
     410          10 :         cr.in.fname = s->fname;
     411             : 
     412          10 :         status = smb2_create(tree, tree, &cr);
     413          10 :         CHECK_STATUS(status, NT_STATUS_OK);
     414             : 
     415          10 :         h2 = cr.out.file.handle;
     416             : 
     417          10 :         ZERO_STRUCT(wr);
     418          10 :         wr.in.file.handle = h1;
     419          10 :         wr.in.offset      = ARRAY_SIZE(buf)/2;
     420          10 :         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
     421             : 
     422          10 :         status = smb2_write(tree, &wr);
     423          10 :         CHECK_STATUS(status, s->write_h1_status);
     424             : 
     425          10 :         ZERO_STRUCT(rd);
     426          10 :         rd.in.file.handle = h1;
     427          10 :         rd.in.offset      = ARRAY_SIZE(buf)/2;
     428          10 :         rd.in.length      = ARRAY_SIZE(buf)/2;
     429             : 
     430          10 :         status = smb2_read(tree, tree, &rd);
     431          10 :         CHECK_STATUS(status, s->read_h1_status);
     432             : 
     433          10 :         ZERO_STRUCT(wr);
     434          10 :         wr.in.file.handle = h2;
     435          10 :         wr.in.offset      = ARRAY_SIZE(buf)/2;
     436          10 :         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
     437             : 
     438          10 :         status = smb2_write(tree, &wr);
     439          10 :         CHECK_STATUS(status, s->write_h2_status);
     440             : 
     441          10 :         ZERO_STRUCT(rd);
     442          10 :         rd.in.file.handle = h2;
     443          10 :         rd.in.offset      = ARRAY_SIZE(buf)/2;
     444          10 :         rd.in.length      = ARRAY_SIZE(buf)/2;
     445             : 
     446          10 :         status = smb2_read(tree, tree, &rd);
     447          10 :         CHECK_STATUS(status, s->read_h2_status);
     448             : 
     449          10 :         lck.in.lock_count       = 0x0001;
     450          10 :         lck.in.lock_sequence    = 0x00000000;
     451          10 :         lck.in.file.handle      = h1;
     452          10 :         el[0].offset            = ARRAY_SIZE(buf)/2;
     453          10 :         el[0].length            = ARRAY_SIZE(buf)/2;
     454          10 :         el[0].reserved          = 0x00000000;
     455          10 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     456          10 :         status = smb2_lock(tree, &lck);
     457          10 :         CHECK_STATUS(status, NT_STATUS_OK);
     458          10 :         CHECK_VALUE(lck.out.reserved, 0);
     459             : 
     460          10 :         ZERO_STRUCT(wr);
     461          10 :         wr.in.file.handle = h2;
     462          10 :         wr.in.offset      = ARRAY_SIZE(buf)/2;
     463          10 :         wr.in.data        = data_blob_const(buf, ARRAY_SIZE(buf)/2);
     464             : 
     465          10 :         status = smb2_write(tree, &wr);
     466          10 :         CHECK_STATUS(status, NT_STATUS_OK);
     467             : 
     468          10 :         ZERO_STRUCT(rd);
     469          10 :         rd.in.file.handle = h2;
     470          10 :         rd.in.offset      = ARRAY_SIZE(buf)/2;
     471          10 :         rd.in.length      = ARRAY_SIZE(buf)/2;
     472             : 
     473          10 :         status = smb2_read(tree, tree, &rd);
     474          10 :         CHECK_STATUS(status, NT_STATUS_OK);
     475             : 
     476          10 : done:
     477          10 :         return ret;
     478             : }
     479             : 
     480           5 : static bool test_lock_rw_none(struct torture_context *torture,
     481             :                               struct smb2_tree *tree)
     482             : {
     483           5 :         struct test_lock_read_write_state s = {
     484             :                 .fname                  = "lock_rw_none.dat",
     485             :                 .lock_flags             = SMB2_LOCK_FLAG_NONE,
     486             :                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
     487             :                 .read_h1_status         = NT_STATUS_OK,
     488             :                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
     489             :                 .read_h2_status         = NT_STATUS_OK,
     490             :         };
     491             : 
     492           5 :         if (!TARGET_IS_W2K8(torture)) {
     493           5 :                 torture_skip(torture, "RW-NONE tests the behavior of a "
     494             :                              "NONE-type lock, which is the same as a SHARED "
     495             :                              "lock but is granted due to a bug in W2K8.  If "
     496             :                              "target is not W2K8 we skip this test.\n");
     497             :         }
     498             : 
     499           0 :         return test_lock_read_write(torture, tree, &s);
     500             : }
     501             : 
     502           5 : static bool test_lock_rw_shared(struct torture_context *torture,
     503             :                                 struct smb2_tree *tree)
     504             : {
     505           5 :         struct test_lock_read_write_state s = {
     506             :                 .fname                  = "lock_rw_shared.dat",
     507             :                 .lock_flags             = SMB2_LOCK_FLAG_SHARED,
     508             :                 .write_h1_status        = NT_STATUS_FILE_LOCK_CONFLICT,
     509             :                 .read_h1_status         = NT_STATUS_OK,
     510             :                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
     511             :                 .read_h2_status         = NT_STATUS_OK,
     512             :         };
     513             : 
     514           5 :         return test_lock_read_write(torture, tree, &s);
     515             : }
     516             : 
     517           5 : static bool test_lock_rw_exclusive(struct torture_context *torture,
     518             :                                    struct smb2_tree *tree)
     519             : {
     520           5 :         struct test_lock_read_write_state s = {
     521             :                 .fname                  = "lock_rw_exclusive.dat",
     522             :                 .lock_flags             = SMB2_LOCK_FLAG_EXCLUSIVE,
     523             :                 .write_h1_status        = NT_STATUS_OK,
     524             :                 .read_h1_status         = NT_STATUS_OK,
     525             :                 .write_h2_status        = NT_STATUS_FILE_LOCK_CONFLICT,
     526             :                 .read_h2_status         = NT_STATUS_FILE_LOCK_CONFLICT,
     527             :         };
     528             : 
     529           5 :         return test_lock_read_write(torture, tree, &s);
     530             : }
     531             : 
     532           5 : static bool test_lock_auto_unlock(struct torture_context *torture,
     533             :                                   struct smb2_tree *tree)
     534             : {
     535           5 :         bool ret = true;
     536           0 :         NTSTATUS status;
     537           0 :         struct smb2_handle h;
     538           0 :         uint8_t buf[200];
     539           0 :         struct smb2_lock lck;
     540           0 :         struct smb2_lock_element el[1];
     541             : 
     542           5 :         ZERO_STRUCT(buf);
     543             : 
     544           5 :         status = torture_smb2_testfile(tree, "autounlock.txt", &h);
     545           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     546             : 
     547           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
     548           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     549             : 
     550           5 :         ZERO_STRUCT(lck);
     551           5 :         ZERO_STRUCT(el[0]);
     552           5 :         lck.in.locks            = el;
     553           5 :         lck.in.lock_count       = 0x0001;
     554           5 :         lck.in.file.handle      = h;
     555           5 :         el[0].offset            = 0;
     556           5 :         el[0].length            = 1;
     557           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     558             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     559           5 :         status = smb2_lock(tree, &lck);
     560           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     561             : 
     562           5 :         status = smb2_lock(tree, &lck);
     563           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     564             : 
     565           5 :         status = smb2_lock(tree, &lck);
     566           5 :         if (TARGET_IS_W2K8(torture)) {
     567           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     568           0 :                 torture_warning(torture, "Target has \"pretty please\" bug. "
     569             :                                 "A contending lock request on the same handle "
     570             :                                 "unlocks the lock.\n");
     571             :         } else {
     572           5 :                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     573             :         }
     574             : 
     575           5 :         status = smb2_lock(tree, &lck);
     576           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     577             : 
     578           5 : done:
     579           5 :         return ret;
     580             : }
     581             : 
     582             : /*
     583             :   test different lock ranges and see if different handles conflict
     584             : */
     585           5 : static bool test_lock(struct torture_context *torture,
     586             :                       struct smb2_tree *tree)
     587             : {
     588           0 :         NTSTATUS status;
     589           5 :         bool ret = true;
     590           5 :         struct smb2_handle h = {{0}};
     591           5 :         struct smb2_handle h2 = {{0}};
     592           0 :         uint8_t buf[200];
     593           0 :         struct smb2_lock lck;
     594           0 :         struct smb2_lock_element el[2];
     595             : 
     596           5 :         const char *fname = BASEDIR "\\async.txt";
     597             : 
     598           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
     599           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     600           5 :         smb2_util_close(tree, h);
     601             : 
     602           5 :         status = torture_smb2_testfile(tree, fname, &h);
     603           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     604             : 
     605           5 :         ZERO_STRUCT(buf);
     606           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
     607           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     608             : 
     609           5 :         status = torture_smb2_testfile(tree, fname, &h2);
     610           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     611             : 
     612           5 :         lck.in.locks            = el;
     613             : 
     614           5 :         lck.in.lock_count       = 0x0001;
     615           5 :         lck.in.lock_sequence    = 0x00000000;
     616           5 :         lck.in.file.handle      = h;
     617           5 :         el[0].reserved          = 0x00000000;
     618           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     619             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     620             : 
     621           5 :         torture_comment(torture, "Trying 0/0 lock\n");
     622           5 :         el[0].offset            = 0x0000000000000000;
     623           5 :         el[0].length            = 0x0000000000000000;
     624           5 :         status = smb2_lock(tree, &lck);
     625           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     626           5 :         lck.in.file.handle      = h2;
     627           5 :         status = smb2_lock(tree, &lck);
     628           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     629           5 :         lck.in.file.handle      = h;
     630           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     631           5 :         status = smb2_lock(tree, &lck);
     632           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     633             : 
     634           5 :         torture_comment(torture, "Trying 0/1 lock\n");
     635           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     636             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     637           5 :         el[0].offset            = 0x0000000000000000;
     638           5 :         el[0].length            = 0x0000000000000001;
     639           5 :         status = smb2_lock(tree, &lck);
     640           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     641           5 :         lck.in.file.handle      = h2;
     642           5 :         status = smb2_lock(tree, &lck);
     643           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     644           5 :         lck.in.file.handle      = h;
     645           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     646           5 :         status = smb2_lock(tree, &lck);
     647           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     648           5 :         status = smb2_lock(tree, &lck);
     649           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     650             : 
     651           5 :         torture_comment(torture, "Trying 0xEEFFFFF lock\n");
     652           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     653             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     654           5 :         el[0].offset            = 0xEEFFFFFF;
     655           5 :         el[0].length            = 4000;
     656           5 :         status = smb2_lock(tree, &lck);
     657           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     658           5 :         lck.in.file.handle      = h2;
     659           5 :         status = smb2_lock(tree, &lck);
     660           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     661           5 :         lck.in.file.handle      = h;
     662           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     663           5 :         status = smb2_lock(tree, &lck);
     664           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     665           5 :         status = smb2_lock(tree, &lck);
     666           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     667             : 
     668           5 :         torture_comment(torture, "Trying 0xEF00000 lock\n");
     669           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     670             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     671           5 :         el[0].offset            = 0xEF000000;
     672           5 :         el[0].length            = 4000;
     673           5 :         status = smb2_lock(tree, &lck);
     674           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     675           5 :         lck.in.file.handle      = h2;
     676           5 :         status = smb2_lock(tree, &lck);
     677           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     678           5 :         lck.in.file.handle      = h;
     679           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     680           5 :         status = smb2_lock(tree, &lck);
     681           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     682           5 :         status = smb2_lock(tree, &lck);
     683           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     684             : 
     685           5 :         torture_comment(torture, "Trying (2^63 - 1)/1\n");
     686           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     687             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     688           5 :         el[0].offset            = 1;
     689           5 :         el[0].offset          <<= 63;
     690           5 :         el[0].offset--;
     691           5 :         el[0].length            = 1;
     692           5 :         status = smb2_lock(tree, &lck);
     693           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     694           5 :         lck.in.file.handle      = h2;
     695           5 :         status = smb2_lock(tree, &lck);
     696           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     697           5 :         lck.in.file.handle      = h;
     698           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     699           5 :         status = smb2_lock(tree, &lck);
     700           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     701           5 :         status = smb2_lock(tree, &lck);
     702           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     703             : 
     704           5 :         torture_comment(torture, "Trying 2^63/1\n");
     705           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     706             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     707           5 :         el[0].offset            = 1;
     708           5 :         el[0].offset          <<= 63;
     709           5 :         el[0].length            = 1;
     710           5 :         status = smb2_lock(tree, &lck);
     711           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     712           5 :         lck.in.file.handle      = h2;
     713           5 :         status = smb2_lock(tree, &lck);
     714           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     715           5 :         lck.in.file.handle      = h;
     716           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     717           5 :         status = smb2_lock(tree, &lck);
     718           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     719           5 :         status = smb2_lock(tree, &lck);
     720           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     721             : 
     722           5 :         torture_comment(torture, "Trying max/0 lock\n");
     723           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     724             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     725           5 :         el[0].offset            = ~0;
     726           5 :         el[0].length            = 0;
     727           5 :         status = smb2_lock(tree, &lck);
     728           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     729           5 :         lck.in.file.handle      = h2;
     730           5 :         status = smb2_lock(tree, &lck);
     731           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     732           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     733           5 :         status = smb2_lock(tree, &lck);
     734           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     735           5 :         lck.in.file.handle      = h;
     736           5 :         status = smb2_lock(tree, &lck);
     737           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     738           5 :         status = smb2_lock(tree, &lck);
     739           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     740             : 
     741           5 :         torture_comment(torture, "Trying max/1 lock\n");
     742           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     743             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     744           5 :         el[0].offset            = ~0;
     745           5 :         el[0].length            = 1;
     746           5 :         status = smb2_lock(tree, &lck);
     747           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     748           5 :         lck.in.file.handle      = h2;
     749           5 :         status = smb2_lock(tree, &lck);
     750           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     751           5 :         lck.in.file.handle      = h;
     752           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     753           5 :         status = smb2_lock(tree, &lck);
     754           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     755           5 :         status = smb2_lock(tree, &lck);
     756           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     757             : 
     758           5 :         torture_comment(torture, "Trying max/2 lock\n");
     759           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     760             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     761           5 :         el[0].offset            = ~0;
     762           5 :         el[0].length            = 2;
     763           5 :         status = smb2_lock(tree, &lck);
     764           5 :         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(torture)) {
     765           5 :                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
     766             :         } else {
     767           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     768           0 :                 el[0].flags     = SMB2_LOCK_FLAG_UNLOCK;
     769           0 :                 status = smb2_lock(tree, &lck);
     770           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     771             :         }
     772             : 
     773           5 :         torture_comment(torture, "Trying wrong handle unlock\n");
     774           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
     775             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     776           5 :         el[0].offset            = 10001;
     777           5 :         el[0].length            = 40002;
     778           5 :         status = smb2_lock(tree, &lck);
     779           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     780           5 :         lck.in.file.handle      = h2;
     781           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     782           5 :         status = smb2_lock(tree, &lck);
     783           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     784           5 :         lck.in.file.handle      = h;
     785           5 :         status = smb2_lock(tree, &lck);
     786           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     787             : 
     788           5 : done:
     789           5 :         smb2_util_close(tree, h2);
     790           5 :         smb2_util_close(tree, h);
     791           5 :         smb2_deltree(tree, BASEDIR);
     792           5 :         return ret;
     793             : }
     794             : 
     795             : /*
     796             :   test SMB2 LOCK async operation
     797             : */
     798           5 : static bool test_async(struct torture_context *torture,
     799             :                        struct smb2_tree *tree)
     800             : {
     801           0 :         NTSTATUS status;
     802           5 :         bool ret = true;
     803           5 :         struct smb2_handle h = {{0}};
     804           5 :         struct smb2_handle h2 = {{0}};
     805           0 :         uint8_t buf[200];
     806           0 :         struct smb2_lock lck;
     807           0 :         struct smb2_lock_element el[2];
     808           5 :         struct smb2_request *req = NULL;
     809             : 
     810           5 :         const char *fname = BASEDIR "\\async.txt";
     811             : 
     812           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
     813           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     814           5 :         smb2_util_close(tree, h);
     815             : 
     816           5 :         status = torture_smb2_testfile(tree, fname, &h);
     817           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     818             : 
     819           5 :         ZERO_STRUCT(buf);
     820           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
     821           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     822             : 
     823           5 :         status = torture_smb2_testfile(tree, fname, &h2);
     824           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     825             : 
     826           5 :         lck.in.locks            = el;
     827             : 
     828           5 :         lck.in.lock_count       = 0x0001;
     829           5 :         lck.in.lock_sequence    = 0x00000000;
     830           5 :         lck.in.file.handle      = h;
     831           5 :         el[0].offset            = 100;
     832           5 :         el[0].length            = 50;
     833           5 :         el[0].reserved          = 0x00000000;
     834           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
     835             : 
     836           5 :         torture_comment(torture, "  Acquire first lock\n");
     837           5 :         status = smb2_lock(tree, &lck);
     838           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     839             : 
     840           5 :         torture_comment(torture, "  Second lock should pend on first\n");
     841           5 :         lck.in.file.handle      = h2;
     842           5 :         req = smb2_lock_send(tree, &lck);
     843          25 :         WAIT_FOR_ASYNC_RESPONSE(req);
     844             : 
     845           5 :         torture_comment(torture, "  Unlock first lock\n");
     846           5 :         lck.in.file.handle      = h;
     847           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     848           5 :         status = smb2_lock(tree, &lck);
     849           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     850             : 
     851           5 :         torture_comment(torture, "  Second lock should now succeed\n");
     852           5 :         lck.in.file.handle      = h2;
     853           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
     854           5 :         status = smb2_lock_recv(req, &lck);
     855           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     856             : 
     857           5 : done:
     858           5 :         smb2_util_close(tree, h2);
     859           5 :         smb2_util_close(tree, h);
     860           5 :         smb2_deltree(tree, BASEDIR);
     861           5 :         return ret;
     862             : }
     863             : 
     864             : /*
     865             :   test SMB2 LOCK Cancel operation
     866             : */
     867           5 : static bool test_cancel(struct torture_context *torture,
     868             :                         struct smb2_tree *tree)
     869             : {
     870           0 :         NTSTATUS status;
     871           5 :         bool ret = true;
     872           5 :         struct smb2_handle h = {{0}};
     873           5 :         struct smb2_handle h2 = {{0}};
     874           0 :         uint8_t buf[200];
     875           0 :         struct smb2_lock lck;
     876           0 :         struct smb2_lock_element el[2];
     877           5 :         struct smb2_request *req = NULL;
     878             : 
     879           5 :         const char *fname = BASEDIR "\\cancel.txt";
     880             : 
     881           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
     882           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     883           5 :         smb2_util_close(tree, h);
     884             : 
     885           5 :         status = torture_smb2_testfile(tree, fname, &h);
     886           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     887             : 
     888           5 :         ZERO_STRUCT(buf);
     889           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
     890           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     891             : 
     892           5 :         status = torture_smb2_testfile(tree, fname, &h2);
     893           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     894             : 
     895           5 :         lck.in.locks            = el;
     896             : 
     897           5 :         lck.in.lock_count       = 0x0001;
     898           5 :         lck.in.lock_sequence    = 0x00000000;
     899           5 :         lck.in.file.handle      = h;
     900           5 :         el[0].offset            = 100;
     901           5 :         el[0].length            = 10;
     902           5 :         el[0].reserved          = 0x00000000;
     903           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
     904             : 
     905           5 :         torture_comment(torture, "Testing basic cancel\n");
     906             : 
     907           5 :         torture_comment(torture, "  Acquire first lock\n");
     908           5 :         status = smb2_lock(tree, &lck);
     909           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     910             : 
     911           5 :         torture_comment(torture, "  Second lock should pend on first\n");
     912           5 :         lck.in.file.handle      = h2;
     913           5 :         req = smb2_lock_send(tree, &lck);
     914          25 :         WAIT_FOR_ASYNC_RESPONSE(req);
     915             : 
     916           5 :         torture_comment(torture, "  Cancel the second lock\n");
     917           5 :         smb2_cancel(req);
     918           5 :         lck.in.file.handle      = h2;
     919           5 :         status = smb2_lock_recv(req, &lck);
     920           5 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
     921             : 
     922           5 :         torture_comment(torture, "  Unlock first lock\n");
     923           5 :         lck.in.file.handle      = h;
     924           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     925           5 :         status = smb2_lock(tree, &lck);
     926           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     927             : 
     928             : 
     929           5 :         torture_comment(torture, "Testing cancel by unlock\n");
     930             : 
     931           5 :         torture_comment(torture, "  Acquire first lock\n");
     932           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
     933           5 :         status = smb2_lock(tree, &lck);
     934           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     935             : 
     936           5 :         torture_comment(torture, "  Second lock should pend on first\n");
     937           5 :         lck.in.file.handle      = h2;
     938           5 :         req = smb2_lock_send(tree, &lck);
     939          25 :         WAIT_FOR_ASYNC_RESPONSE(req);
     940             : 
     941           5 :         torture_comment(torture, "  Attempt to unlock pending second lock\n");
     942           5 :         lck.in.file.handle      = h2;
     943           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     944           5 :         status = smb2_lock(tree, &lck);
     945           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     946             : 
     947           5 :         torture_comment(torture, "  Now cancel the second lock\n");
     948           5 :         smb2_cancel(req);
     949           5 :         lck.in.file.handle      = h2;
     950           5 :         status = smb2_lock_recv(req, &lck);
     951           5 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
     952             : 
     953           5 :         torture_comment(torture, "  Unlock first lock\n");
     954           5 :         lck.in.file.handle      = h;
     955           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     956           5 :         status = smb2_lock(tree, &lck);
     957           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     958             : 
     959             : 
     960           5 :         torture_comment(torture, "Testing cancel by close\n");
     961             : 
     962           5 :         torture_comment(torture, "  Acquire first lock\n");
     963           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
     964           5 :         status = smb2_lock(tree, &lck);
     965           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     966             : 
     967           5 :         torture_comment(torture, "  Second lock should pend on first\n");
     968           5 :         lck.in.file.handle      = h2;
     969           5 :         req = smb2_lock_send(tree, &lck);
     970          25 :         WAIT_FOR_ASYNC_RESPONSE(req);
     971             : 
     972           5 :         torture_comment(torture, "  Close the second lock handle\n");
     973           5 :         smb2_util_close(tree, h2);
     974           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     975             : 
     976           5 :         torture_comment(torture, "  Check pending lock reply\n");
     977           5 :         status = smb2_lock_recv(req, &lck);
     978           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     979             : 
     980           5 :         torture_comment(torture, "  Unlock first lock\n");
     981           5 :         lck.in.file.handle      = h;
     982           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
     983           5 :         status = smb2_lock(tree, &lck);
     984           5 :         CHECK_STATUS(status, NT_STATUS_OK);
     985             : 
     986           5 : done:
     987           5 :         smb2_util_close(tree, h2);
     988           5 :         smb2_util_close(tree, h);
     989           5 :         smb2_deltree(tree, BASEDIR);
     990           5 :         return ret;
     991             : }
     992             : 
     993             : /*
     994             :   test SMB2 LOCK Cancel by tree disconnect
     995             : */
     996           5 : static bool test_cancel_tdis(struct torture_context *torture,
     997             :                              struct smb2_tree *tree)
     998             : {
     999           0 :         NTSTATUS status;
    1000           5 :         bool ret = true;
    1001           5 :         struct smb2_handle h = {{0}};
    1002           5 :         struct smb2_handle h2 = {{0}};
    1003           0 :         uint8_t buf[200];
    1004           0 :         struct smb2_lock lck;
    1005           0 :         struct smb2_lock_element el[2];
    1006           5 :         struct smb2_request *req = NULL;
    1007             : 
    1008           5 :         const char *fname = BASEDIR "\\cancel_tdis.txt";
    1009             : 
    1010           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    1011           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1012           5 :         smb2_util_close(tree, h);
    1013             : 
    1014           5 :         status = torture_smb2_testfile(tree, fname, &h);
    1015           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1016             : 
    1017           5 :         ZERO_STRUCT(buf);
    1018           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    1019           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1020             : 
    1021           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    1022           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1023             : 
    1024           5 :         lck.in.locks            = el;
    1025             : 
    1026           5 :         lck.in.lock_count       = 0x0001;
    1027           5 :         lck.in.lock_sequence    = 0x00000000;
    1028           5 :         lck.in.file.handle      = h;
    1029           5 :         el[0].offset            = 100;
    1030           5 :         el[0].length            = 10;
    1031           5 :         el[0].reserved          = 0x00000000;
    1032           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
    1033             : 
    1034           5 :         torture_comment(torture, "Testing cancel by tree disconnect\n");
    1035             : 
    1036           5 :         status = torture_smb2_testfile(tree, fname, &h);
    1037           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1038             : 
    1039           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    1040           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1041             : 
    1042           5 :         torture_comment(torture, "  Acquire first lock\n");
    1043           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
    1044           5 :         status = smb2_lock(tree, &lck);
    1045           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1046             : 
    1047           5 :         torture_comment(torture, "  Second lock should pend on first\n");
    1048           5 :         lck.in.file.handle      = h2;
    1049           5 :         req = smb2_lock_send(tree, &lck);
    1050          25 :         WAIT_FOR_ASYNC_RESPONSE(req);
    1051             : 
    1052           5 :         torture_comment(torture, "  Disconnect the tree\n");
    1053           5 :         smb2_tdis(tree);
    1054           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1055             : 
    1056           5 :         torture_comment(torture, "  Check pending lock reply\n");
    1057           5 :         status = smb2_lock_recv(req, &lck);
    1058           5 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_RANGE_NOT_LOCKED)) {
    1059             :                 /*
    1060             :                  * The status depends on the server internals
    1061             :                  * the order in which the files are closed
    1062             :                  * by smb2_tdis().
    1063             :                  */
    1064           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1065             :         }
    1066             : 
    1067           5 :         torture_comment(torture, "  Attempt to unlock first lock\n");
    1068           5 :         lck.in.file.handle      = h;
    1069           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1070           5 :         status = smb2_lock(tree, &lck);
    1071             :         /*
    1072             :          * Most Windows versions have a strange order to
    1073             :          * verify the session id, tree id and file id.
    1074             :          * (They should be checked in that order, but windows
    1075             :          *  seems to check the file id before the others).
    1076             :          */
    1077           5 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
    1078           0 :                 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1079             :         }
    1080             : 
    1081           5 : done:
    1082           5 :         smb2_util_close(tree, h2);
    1083           5 :         smb2_util_close(tree, h);
    1084           5 :         smb2_deltree(tree, BASEDIR);
    1085           5 :         return ret;
    1086             : }
    1087             : 
    1088             : /*
    1089             :   test SMB2 LOCK Cancel by user logoff
    1090             : */
    1091           5 : static bool test_cancel_logoff(struct torture_context *torture,
    1092             :                                struct smb2_tree *tree)
    1093             : {
    1094           0 :         NTSTATUS status;
    1095           5 :         bool ret = true;
    1096           5 :         struct smb2_handle h = {{0}};
    1097           5 :         struct smb2_handle h2 = {{0}};
    1098           0 :         uint8_t buf[200];
    1099           0 :         struct smb2_lock lck;
    1100           0 :         struct smb2_lock_element el[2];
    1101           5 :         struct smb2_request *req = NULL;
    1102             : 
    1103           5 :         const char *fname = BASEDIR "\\cancel_logoff.txt";
    1104             : 
    1105           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    1106           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1107           5 :         smb2_util_close(tree, h);
    1108             : 
    1109           5 :         status = torture_smb2_testfile(tree, fname, &h);
    1110           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1111             : 
    1112           5 :         ZERO_STRUCT(buf);
    1113           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    1114           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1115             : 
    1116           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    1117           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1118             : 
    1119           5 :         lck.in.locks            = el;
    1120             : 
    1121           5 :         lck.in.lock_count       = 0x0001;
    1122           5 :         lck.in.lock_sequence    = 0x00000000;
    1123           5 :         lck.in.file.handle      = h;
    1124           5 :         el[0].offset            = 100;
    1125           5 :         el[0].length            = 10;
    1126           5 :         el[0].reserved          = 0x00000000;
    1127           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
    1128             : 
    1129           5 :         torture_comment(torture, "Testing cancel by ulogoff\n");
    1130             : 
    1131           5 :         torture_comment(torture, "  Acquire first lock\n");
    1132           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE;
    1133           5 :         status = smb2_lock(tree, &lck);
    1134           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1135             : 
    1136           5 :         torture_comment(torture, "  Second lock should pend on first\n");
    1137           5 :         lck.in.file.handle      = h2;
    1138           5 :         req = smb2_lock_send(tree, &lck);
    1139          25 :         WAIT_FOR_ASYNC_RESPONSE(req);
    1140             : 
    1141           5 :         torture_comment(torture, "  Logoff user\n");
    1142           5 :         smb2_logoff(tree->session);
    1143             : 
    1144           5 :         torture_comment(torture, "  Check pending lock reply\n");
    1145           5 :         status = smb2_lock_recv(req, &lck);
    1146           5 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_RANGE_NOT_LOCKED)) {
    1147             :                 /*
    1148             :                  * The status depends on the server internals
    1149             :                  * the order in which the files are closed
    1150             :                  * by smb2_logoff().
    1151             :                  */
    1152           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1153             :         }
    1154             : 
    1155           5 :         torture_comment(torture, "  Attempt to unlock first lock\n");
    1156           5 :         lck.in.file.handle      = h;
    1157           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1158           5 :         status = smb2_lock(tree, &lck);
    1159             :         /*
    1160             :          * Most Windows versions have a strange order to
    1161             :          * verify the session id, tree id and file id.
    1162             :          * (They should be checked in that order, but windows
    1163             :          *  seems to check the file id before the others).
    1164             :          */
    1165           5 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
    1166           0 :                 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1167             :         }
    1168             : 
    1169           5 : done:
    1170           5 :         smb2_util_close(tree, h2);
    1171           5 :         smb2_util_close(tree, h);
    1172           5 :         smb2_deltree(tree, BASEDIR);
    1173           5 :         return ret;
    1174             : }
    1175             : 
    1176             : /*
    1177             :  * Test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
    1178             :  *
    1179             :  * The SMBv1 protocol returns a different error code on lock acquisition
    1180             :  * failure depending on a number of parameters, including what error code
    1181             :  * was returned to the previous failure.
    1182             :  *
    1183             :  * SMBv2 has cleaned up these semantics and should always return
    1184             :  * NT_STATUS_LOCK_NOT_GRANTED to failed lock requests, and
    1185             :  * NT_STATUS_FILE_LOCK_CONFLICT to failed read/write requests due to a lock
    1186             :  * being held on that range.
    1187             : */
    1188           5 : static bool test_errorcode(struct torture_context *torture,
    1189             :                            struct smb2_tree *tree)
    1190             : {
    1191           0 :         NTSTATUS status;
    1192           5 :         bool ret = true;
    1193           5 :         struct smb2_handle h = {{0}};
    1194           5 :         struct smb2_handle h2 = {{0}};
    1195           0 :         uint8_t buf[200];
    1196           0 :         struct smb2_lock lck;
    1197           0 :         struct smb2_lock_element el[2];
    1198             : 
    1199           5 :         const char *fname = BASEDIR "\\errorcode.txt";
    1200             : 
    1201           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    1202           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1203           5 :         smb2_util_close(tree, h);
    1204             : 
    1205           5 :         status = torture_smb2_testfile(tree, fname, &h);
    1206           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1207             : 
    1208           5 :         ZERO_STRUCT(buf);
    1209           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    1210           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1211             : 
    1212           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    1213           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1214             : 
    1215           5 :         lck.in.locks            = el;
    1216             : 
    1217           5 :         lck.in.lock_count       = 0x0001;
    1218           5 :         lck.in.lock_sequence    = 0x00000000;
    1219           5 :         lck.in.file.handle      = h;
    1220           5 :         el[0].offset            = 100;
    1221           5 :         el[0].length            = 10;
    1222           5 :         el[0].reserved          = 0x00000000;
    1223           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1224             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1225             : 
    1226           5 :         torture_comment(torture, "Testing LOCK_NOT_GRANTED vs. "
    1227             :                                  "FILE_LOCK_CONFLICT\n");
    1228             : 
    1229           5 :         if (TARGET_IS_W2K8(torture)) {
    1230           0 :                 torture_result(torture, TORTURE_SKIP,
    1231             :                     "Target has \"pretty please\" bug. A contending lock "
    1232             :                     "request on the same handle unlocks the lock.");
    1233           0 :                 goto done;
    1234             :         }
    1235             : 
    1236           5 :         status = smb2_lock(tree, &lck);
    1237           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1238             : 
    1239             :         /* Demonstrate that the first conflicting lock on each handle gives
    1240             :          * LOCK_NOT_GRANTED. */
    1241           5 :         lck.in.file.handle      = h;
    1242           5 :         status = smb2_lock(tree, &lck);
    1243           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1244             : 
    1245           5 :         lck.in.file.handle      = h2;
    1246           5 :         status = smb2_lock(tree, &lck);
    1247           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1248             : 
    1249             :         /* Demonstrate that each following conflict also gives
    1250             :          * LOCK_NOT_GRANTED */
    1251           5 :         lck.in.file.handle      = h;
    1252           5 :         status = smb2_lock(tree, &lck);
    1253           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1254             : 
    1255           5 :         lck.in.file.handle      = h2;
    1256           5 :         status = smb2_lock(tree, &lck);
    1257           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1258             : 
    1259           5 :         lck.in.file.handle      = h;
    1260           5 :         status = smb2_lock(tree, &lck);
    1261           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1262             : 
    1263           5 :         lck.in.file.handle      = h2;
    1264           5 :         status = smb2_lock(tree, &lck);
    1265           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1266             : 
    1267             :         /* Demonstrate that the smbpid doesn't matter */
    1268           5 :         lck.in.file.handle      = h;
    1269           5 :         status = smb2_lock(tree, &lck);
    1270           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1271             : 
    1272           5 :         lck.in.file.handle      = h2;
    1273           5 :         status = smb2_lock(tree, &lck);
    1274           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1275             : 
    1276             :         /* Demonstrate that a 0-byte lock inside the locked range still
    1277             :          * gives the same error. */
    1278             : 
    1279           5 :         el[0].offset            = 102;
    1280           5 :         el[0].length            = 0;
    1281           5 :         lck.in.file.handle      = h;
    1282           5 :         status = smb2_lock(tree, &lck);
    1283           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1284             : 
    1285           5 :         lck.in.file.handle      = h2;
    1286           5 :         status = smb2_lock(tree, &lck);
    1287           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1288             : 
    1289             :         /* Demonstrate that a lock inside the locked range still gives the
    1290             :          * same error. */
    1291             : 
    1292           5 :         el[0].offset            = 102;
    1293           5 :         el[0].length            = 5;
    1294           5 :         lck.in.file.handle      = h;
    1295           5 :         status = smb2_lock(tree, &lck);
    1296           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1297             : 
    1298           5 :         lck.in.file.handle      = h2;
    1299           5 :         status = smb2_lock(tree, &lck);
    1300           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1301             : 
    1302           5 : done:
    1303           5 :         smb2_util_close(tree, h2);
    1304           5 :         smb2_util_close(tree, h);
    1305           5 :         smb2_deltree(tree, BASEDIR);
    1306           5 :         return ret;
    1307             : }
    1308             : 
    1309             : /**
    1310             :  * Tests zero byte locks.
    1311             :  */
    1312             : 
    1313             : struct double_lock_test {
    1314             :         struct smb2_lock_element lock1;
    1315             :         struct smb2_lock_element lock2;
    1316             :         NTSTATUS status;
    1317             : };
    1318             : 
    1319             : static struct double_lock_test zero_byte_tests[] = {
    1320             :         /* {offset, count, reserved, flags},
    1321             :          * {offset, count, reserved, flags},
    1322             :          * status */
    1323             : 
    1324             :         /** First, takes a zero byte lock at offset 10. Then:
    1325             :         *   - Taking 0 byte lock at 10 should succeed.
    1326             :         *   - Taking 1 byte locks at 9,10,11 should succeed.
    1327             :         *   - Taking 2 byte lock at 9 should fail.
    1328             :         *   - Taking 2 byte lock at 10 should succeed.
    1329             :         *   - Taking 3 byte lock at 9 should fail.
    1330             :         */
    1331             :         {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
    1332             :         {{10, 0, 0, 0}, {9, 1, 0, 0},  NT_STATUS_OK},
    1333             :         {{10, 0, 0, 0}, {10, 1, 0, 0}, NT_STATUS_OK},
    1334             :         {{10, 0, 0, 0}, {11, 1, 0, 0}, NT_STATUS_OK},
    1335             :         {{10, 0, 0, 0}, {9, 2, 0, 0},  NT_STATUS_LOCK_NOT_GRANTED},
    1336             :         {{10, 0, 0, 0}, {10, 2, 0, 0}, NT_STATUS_OK},
    1337             :         {{10, 0, 0, 0}, {9, 3, 0, 0},  NT_STATUS_LOCK_NOT_GRANTED},
    1338             : 
    1339             :         /** Same, but opposite order. */
    1340             :         {{10, 0, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
    1341             :         {{9, 1, 0, 0},  {10, 0, 0, 0}, NT_STATUS_OK},
    1342             :         {{10, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
    1343             :         {{11, 1, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
    1344             :         {{9, 2, 0, 0},  {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
    1345             :         {{10, 2, 0, 0}, {10, 0, 0, 0}, NT_STATUS_OK},
    1346             :         {{9, 3, 0, 0},  {10, 0, 0, 0}, NT_STATUS_LOCK_NOT_GRANTED},
    1347             : 
    1348             :         /** Zero zero case. */
    1349             :         {{0, 0, 0, 0},  {0, 0, 0, 0},  NT_STATUS_OK},
    1350             : };
    1351             : 
    1352           5 : static bool test_zerobytelength(struct torture_context *torture,
    1353             :                                 struct smb2_tree *tree)
    1354             : {
    1355           0 :         NTSTATUS status;
    1356           5 :         bool ret = true;
    1357           5 :         struct smb2_handle h = {{0}};
    1358           5 :         struct smb2_handle h2 = {{0}};
    1359           0 :         uint8_t buf[200];
    1360           0 :         struct smb2_lock lck;
    1361           0 :         int i;
    1362             : 
    1363           5 :         const char *fname = BASEDIR "\\zero.txt";
    1364             : 
    1365           5 :         torture_comment(torture, "Testing zero length byte range locks:\n");
    1366             : 
    1367           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    1368           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1369           5 :         smb2_util_close(tree, h);
    1370             : 
    1371           5 :         status = torture_smb2_testfile(tree, fname, &h);
    1372           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1373             : 
    1374           5 :         ZERO_STRUCT(buf);
    1375           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    1376           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1377             : 
    1378           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    1379           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1380             : 
    1381             :         /* Setup initial parameters */
    1382           5 :         lck.in.lock_count       = 0x0001;
    1383           5 :         lck.in.lock_sequence    = 0x00000000;
    1384           5 :         lck.in.file.handle      = h;
    1385             : 
    1386             :         /* Try every combination of locks in zero_byte_tests, using the same
    1387             :          * handle for both locks. The first lock is assumed to succeed. The
    1388             :          * second lock may contend, depending on the expected status. */
    1389          80 :         for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
    1390          75 :                 torture_comment(torture,
    1391             :                     "  ... {%llu, %llu} + {%llu, %llu} = %s\n",
    1392          75 :                     (unsigned long long) zero_byte_tests[i].lock1.offset,
    1393          75 :                     (unsigned long long) zero_byte_tests[i].lock1.length,
    1394          75 :                     (unsigned long long) zero_byte_tests[i].lock2.offset,
    1395          75 :                     (unsigned long long) zero_byte_tests[i].lock2.length,
    1396             :                     nt_errstr(zero_byte_tests[i].status));
    1397             : 
    1398             :                 /* Lock both locks. */
    1399          75 :                 lck.in.locks            = &zero_byte_tests[i].lock1;
    1400          75 :                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
    1401             :                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1402          75 :                 status = smb2_lock(tree, &lck);
    1403          75 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1404             : 
    1405          75 :                 lck.in.locks            = &zero_byte_tests[i].lock2;
    1406          75 :                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
    1407             :                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1408          75 :                 status = smb2_lock(tree, &lck);
    1409          75 :                 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
    1410             : 
    1411             :                 /* Unlock both locks in reverse order. */
    1412          75 :                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
    1413          75 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
    1414          55 :                         status = smb2_lock(tree, &lck);
    1415          55 :                         CHECK_STATUS(status, NT_STATUS_OK);
    1416             :                 }
    1417             : 
    1418          75 :                 lck.in.locks            = &zero_byte_tests[i].lock1;
    1419          75 :                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
    1420          75 :                 status = smb2_lock(tree, &lck);
    1421          75 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1422             :         }
    1423             : 
    1424             :         /* Try every combination of locks in zero_byte_tests, using two
    1425             :          * different handles. */
    1426          80 :         for (i = 0; i < ARRAY_SIZE(zero_byte_tests); i++) {
    1427          75 :                 torture_comment(torture,
    1428             :                     "  ... {%llu, %llu} + {%llu, %llu} = %s\n",
    1429          75 :                     (unsigned long long) zero_byte_tests[i].lock1.offset,
    1430          75 :                     (unsigned long long) zero_byte_tests[i].lock1.length,
    1431          75 :                     (unsigned long long) zero_byte_tests[i].lock2.offset,
    1432          75 :                     (unsigned long long) zero_byte_tests[i].lock2.length,
    1433             :                     nt_errstr(zero_byte_tests[i].status));
    1434             : 
    1435             :                 /* Lock both locks. */
    1436          75 :                 lck.in.file.handle      = h;
    1437          75 :                 lck.in.locks            = &zero_byte_tests[i].lock1;
    1438          75 :                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
    1439             :                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1440          75 :                 status = smb2_lock(tree, &lck);
    1441          75 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1442             : 
    1443          75 :                 lck.in.file.handle      = h2;
    1444          75 :                 lck.in.locks            = &zero_byte_tests[i].lock2;
    1445          75 :                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_EXCLUSIVE |
    1446             :                                           SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1447          75 :                 status = smb2_lock(tree, &lck);
    1448          75 :                 CHECK_STATUS_CONT(status, zero_byte_tests[i].status);
    1449             : 
    1450             :                 /* Unlock both locks in reverse order. */
    1451          75 :                 lck.in.file.handle      = h2;
    1452          75 :                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
    1453          75 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
    1454          55 :                         status = smb2_lock(tree, &lck);
    1455          55 :                         CHECK_STATUS(status, NT_STATUS_OK);
    1456             :                 }
    1457             : 
    1458          75 :                 lck.in.file.handle      = h;
    1459          75 :                 lck.in.locks            = &zero_byte_tests[i].lock1;
    1460          75 :                 lck.in.locks[0].flags   = SMB2_LOCK_FLAG_UNLOCK;
    1461          75 :                 status = smb2_lock(tree, &lck);
    1462          75 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1463             :         }
    1464             : 
    1465           5 : done:
    1466           5 :         smb2_util_close(tree, h2);
    1467           5 :         smb2_util_close(tree, h);
    1468           5 :         smb2_deltree(tree, BASEDIR);
    1469           5 :         return ret;
    1470             : }
    1471             : 
    1472           5 : static bool test_zerobyteread(struct torture_context *torture,
    1473             :                               struct smb2_tree *tree)
    1474             : {
    1475           0 :         NTSTATUS status;
    1476           5 :         bool ret = true;
    1477           5 :         struct smb2_handle h = {{0}};
    1478           5 :         struct smb2_handle h2 = {{0}};
    1479           0 :         uint8_t buf[200];
    1480           0 :         struct smb2_lock lck;
    1481           0 :         struct smb2_lock_element el[1];
    1482           0 :         struct smb2_read rd;
    1483             : 
    1484           5 :         const char *fname = BASEDIR "\\zerobyteread.txt";
    1485             : 
    1486           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    1487           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1488           5 :         smb2_util_close(tree, h);
    1489             : 
    1490           5 :         status = torture_smb2_testfile(tree, fname, &h);
    1491           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1492             : 
    1493           5 :         ZERO_STRUCT(buf);
    1494           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    1495           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1496             : 
    1497           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    1498           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1499             : 
    1500             :         /* Setup initial parameters */
    1501           5 :         lck.in.locks            = el;
    1502           5 :         lck.in.lock_count       = 0x0001;
    1503           5 :         lck.in.lock_sequence    = 0x00000000;
    1504           5 :         lck.in.file.handle      = h;
    1505             : 
    1506           5 :         ZERO_STRUCT(rd);
    1507           5 :         rd.in.file.handle = h2;
    1508             : 
    1509           5 :         torture_comment(torture, "Testing zero byte read on lock range:\n");
    1510             : 
    1511             :         /* Take an exclusive lock */
    1512           5 :         torture_comment(torture, "  taking exclusive lock.\n");
    1513           5 :         el[0].offset            = 0;
    1514           5 :         el[0].length            = 10;
    1515           5 :         el[0].reserved          = 0x00000000;
    1516           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1517             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1518           5 :         status = smb2_lock(tree, &lck);
    1519           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1520           5 :         CHECK_VALUE(lck.out.reserved, 0);
    1521             : 
    1522             :         /* Try a zero byte read */
    1523           5 :         torture_comment(torture, "  reading 0 bytes.\n");
    1524           5 :         rd.in.offset      = 5;
    1525           5 :         rd.in.length      = 0;
    1526           5 :         status = smb2_read(tree, tree, &rd);
    1527           5 :         torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
    1528             :                                       "zero byte read did not return 0 bytes");
    1529           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1530             : 
    1531             :         /* Unlock lock */
    1532           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1533           4 :         status = smb2_lock(tree, &lck);
    1534           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1535           4 :         CHECK_VALUE(lck.out.reserved, 0);
    1536             : 
    1537           4 :         torture_comment(torture, "Testing zero byte read on zero byte lock "
    1538             :                                  "range:\n");
    1539             : 
    1540             :         /* Take an exclusive lock */
    1541           4 :         torture_comment(torture, "  taking exclusive 0-byte lock.\n");
    1542           4 :         el[0].offset            = 5;
    1543           4 :         el[0].length            = 0;
    1544           4 :         el[0].reserved          = 0x00000000;
    1545           4 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1546             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1547           4 :         status = smb2_lock(tree, &lck);
    1548           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1549           4 :         CHECK_VALUE(lck.out.reserved, 0);
    1550             : 
    1551             :         /* Try a zero byte read before the lock */
    1552           4 :         torture_comment(torture, "  reading 0 bytes before the lock.\n");
    1553           4 :         rd.in.offset      = 4;
    1554           4 :         rd.in.length      = 0;
    1555           4 :         status = smb2_read(tree, tree, &rd);
    1556           4 :         torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
    1557             :                                       "zero byte read did not return 0 bytes");
    1558           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1559             : 
    1560             :         /* Try a zero byte read on the lock */
    1561           4 :         torture_comment(torture, "  reading 0 bytes on the lock.\n");
    1562           4 :         rd.in.offset      = 5;
    1563           4 :         rd.in.length      = 0;
    1564           4 :         status = smb2_read(tree, tree, &rd);
    1565           4 :         torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
    1566             :                                       "zero byte read did not return 0 bytes");
    1567           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1568             : 
    1569             :         /* Try a zero byte read after the lock */
    1570           4 :         torture_comment(torture, "  reading 0 bytes after the lock.\n");
    1571           4 :         rd.in.offset      = 6;
    1572           4 :         rd.in.length      = 0;
    1573           4 :         status = smb2_read(tree, tree, &rd);
    1574           4 :         torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
    1575             :                                       "zero byte read did not return 0 bytes");
    1576           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1577             : 
    1578             :         /* Unlock lock */
    1579           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1580           4 :         status = smb2_lock(tree, &lck);
    1581           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1582           4 :         CHECK_VALUE(lck.out.reserved, 0);
    1583             : 
    1584           4 : done:
    1585           5 :         smb2_util_close(tree, h2);
    1586           5 :         smb2_util_close(tree, h);
    1587           5 :         smb2_deltree(tree, BASEDIR);
    1588           5 :         return ret;
    1589             : }
    1590             : 
    1591           5 : static bool test_unlock(struct torture_context *torture,
    1592             :                         struct smb2_tree *tree)
    1593             : {
    1594           0 :         NTSTATUS status;
    1595           5 :         bool ret = true;
    1596           5 :         struct smb2_handle h = {{0}};
    1597           5 :         struct smb2_handle h2 = {{0}};
    1598           0 :         uint8_t buf[200];
    1599           0 :         struct smb2_lock lck;
    1600           0 :         struct smb2_lock_element el1[1];
    1601           0 :         struct smb2_lock_element el2[1];
    1602             : 
    1603           5 :         const char *fname = BASEDIR "\\unlock.txt";
    1604             : 
    1605           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    1606           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1607           5 :         smb2_util_close(tree, h);
    1608             : 
    1609           5 :         status = torture_smb2_testfile(tree, fname, &h);
    1610           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1611             : 
    1612           5 :         ZERO_STRUCT(buf);
    1613           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    1614           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1615             : 
    1616           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    1617           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1618             : 
    1619             :         /* Setup initial parameters */
    1620           5 :         lck.in.locks            = el1;
    1621           5 :         lck.in.lock_count       = 0x0001;
    1622           5 :         lck.in.lock_sequence    = 0x00000000;
    1623           5 :         el1[0].offset           = 0;
    1624           5 :         el1[0].length           = 10;
    1625           5 :         el1[0].reserved         = 0x00000000;
    1626             : 
    1627             :         /* Take exclusive lock, then unlock it with a shared-unlock call. */
    1628             : 
    1629           5 :         torture_comment(torture, "Testing unlock exclusive with shared\n");
    1630             : 
    1631           5 :         torture_comment(torture, "  taking exclusive lock.\n");
    1632           5 :         lck.in.file.handle      = h;
    1633           5 :         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE;
    1634           5 :         status = smb2_lock(tree, &lck);
    1635           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1636             : 
    1637           5 :         torture_comment(torture, "  try to unlock the exclusive with a shared "
    1638             :                                  "unlock call.\n");
    1639           5 :         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
    1640             :                                   SMB2_LOCK_FLAG_UNLOCK;
    1641           5 :         status = smb2_lock(tree, &lck);
    1642           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1643             : 
    1644           5 :         torture_comment(torture, "  try shared lock on h2, to test the "
    1645             :                                  "unlock.\n");
    1646           5 :         lck.in.file.handle      = h2;
    1647           5 :         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
    1648             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1649           5 :         status = smb2_lock(tree, &lck);
    1650           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1651             : 
    1652           5 :         torture_comment(torture, "  unlock the exclusive lock\n");
    1653           5 :         lck.in.file.handle      = h;
    1654           5 :         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
    1655           5 :         status = smb2_lock(tree, &lck);
    1656           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1657             : 
    1658             :         /* Unlock a shared lock with an exclusive-unlock call. */
    1659             : 
    1660           5 :         torture_comment(torture, "Testing unlock shared with exclusive\n");
    1661             : 
    1662           5 :         torture_comment(torture, "  taking shared lock.\n");
    1663           5 :         lck.in.file.handle      = h;
    1664           5 :         el1[0].flags            = SMB2_LOCK_FLAG_SHARED;
    1665           5 :         status = smb2_lock(tree, &lck);
    1666           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1667             : 
    1668           5 :         torture_comment(torture, "  try to unlock the shared with an exclusive "
    1669             :                                  "unlock call.\n");
    1670           5 :         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
    1671             :                                   SMB2_LOCK_FLAG_UNLOCK;
    1672           5 :         status = smb2_lock(tree, &lck);
    1673           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1674             : 
    1675           5 :         torture_comment(torture, "  try exclusive lock on h2, to test the "
    1676             :                                  "unlock.\n");
    1677           5 :         lck.in.file.handle      = h2;
    1678           5 :         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
    1679             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1680           5 :         status = smb2_lock(tree, &lck);
    1681           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1682             : 
    1683           5 :         torture_comment(torture, "  unlock the exclusive lock\n");
    1684           5 :         lck.in.file.handle      = h;
    1685           5 :         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
    1686           5 :         status = smb2_lock(tree, &lck);
    1687           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1688             : 
    1689             :         /* Test unlocking of stacked 0-byte locks. SMB2 0-byte lock behavior
    1690             :          * should be the same as >0-byte behavior.  Exclusive locks should be
    1691             :          * unlocked before shared. */
    1692             : 
    1693           5 :         torture_comment(torture, "Test unlocking stacked 0-byte locks\n");
    1694             : 
    1695           5 :         lck.in.locks            = el1;
    1696           5 :         lck.in.file.handle      = h;
    1697           5 :         el1[0].offset           = 10;
    1698           5 :         el1[0].length           = 0;
    1699           5 :         el1[0].reserved         = 0x00000000;
    1700           5 :         el2[0].offset           = 5;
    1701           5 :         el2[0].length           = 10;
    1702           5 :         el2[0].reserved         = 0x00000000;
    1703             : 
    1704             :         /* lock 0-byte exclusive */
    1705           5 :         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
    1706             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1707           5 :         status = smb2_lock(tree, &lck);
    1708           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1709             : 
    1710             :         /* lock 0-byte shared */
    1711           5 :         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
    1712             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1713           5 :         status = smb2_lock(tree, &lck);
    1714           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1715             : 
    1716             :         /* test contention */
    1717           5 :         lck.in.locks            = el2;
    1718           5 :         lck.in.file.handle      = h2;
    1719           5 :         el2[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
    1720             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1721           5 :         status = smb2_lock(tree, &lck);
    1722           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1723             : 
    1724           5 :         lck.in.locks            = el2;
    1725           5 :         lck.in.file.handle      = h2;
    1726           5 :         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
    1727             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1728           5 :         status = smb2_lock(tree, &lck);
    1729           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1730             : 
    1731             :         /* unlock */
    1732           5 :         lck.in.locks            = el1;
    1733           5 :         lck.in.file.handle      = h;
    1734           5 :         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
    1735           5 :         status = smb2_lock(tree, &lck);
    1736           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1737             : 
    1738             :         /* test - can we take a shared lock? */
    1739           5 :         lck.in.locks            = el2;
    1740           5 :         lck.in.file.handle      = h2;
    1741           5 :         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
    1742             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1743           5 :         status = smb2_lock(tree, &lck);
    1744           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1745             : 
    1746           5 :         el2[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
    1747           5 :         status = smb2_lock(tree, &lck);
    1748           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1749             : 
    1750             :         /* cleanup */
    1751           5 :         lck.in.locks            = el1;
    1752           5 :         lck.in.file.handle      = h;
    1753           5 :         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
    1754           5 :         status = smb2_lock(tree, &lck);
    1755           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1756             : 
    1757             :         /* Test unlocking of stacked exclusive, shared locks. Exclusive
    1758             :          * should be unlocked before any shared. */
    1759             : 
    1760           5 :         torture_comment(torture, "Test unlocking stacked exclusive/shared "
    1761             :                                  "locks\n");
    1762             : 
    1763           5 :         lck.in.locks            = el1;
    1764           5 :         lck.in.file.handle      = h;
    1765           5 :         el1[0].offset           = 10;
    1766           5 :         el1[0].length           = 10;
    1767           5 :         el1[0].reserved         = 0x00000000;
    1768           5 :         el2[0].offset           = 5;
    1769           5 :         el2[0].length           = 10;
    1770           5 :         el2[0].reserved         = 0x00000000;
    1771             : 
    1772             :         /* lock exclusive */
    1773           5 :         el1[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
    1774             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1775           5 :         status = smb2_lock(tree, &lck);
    1776           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1777             : 
    1778             :         /* lock shared */
    1779           5 :         el1[0].flags            = SMB2_LOCK_FLAG_SHARED |
    1780             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1781           5 :         status = smb2_lock(tree, &lck);
    1782           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1783             : 
    1784             :         /* test contention */
    1785           5 :         lck.in.locks            = el2;
    1786           5 :         lck.in.file.handle      = h2;
    1787           5 :         el2[0].flags            = SMB2_LOCK_FLAG_EXCLUSIVE |
    1788             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1789           5 :         status = smb2_lock(tree, &lck);
    1790           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1791             : 
    1792           5 :         lck.in.locks            = el2;
    1793           5 :         lck.in.file.handle      = h2;
    1794           5 :         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
    1795             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1796           5 :         status = smb2_lock(tree, &lck);
    1797           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1798             : 
    1799             :         /* unlock */
    1800           5 :         lck.in.locks            = el1;
    1801           5 :         lck.in.file.handle      = h;
    1802           5 :         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
    1803           5 :         status = smb2_lock(tree, &lck);
    1804           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1805             : 
    1806             :         /* test - can we take a shared lock? */
    1807           5 :         lck.in.locks            = el2;
    1808           5 :         lck.in.file.handle      = h2;
    1809           5 :         el2[0].flags            = SMB2_LOCK_FLAG_SHARED |
    1810             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1811           5 :         status = smb2_lock(tree, &lck);
    1812           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1813             : 
    1814           5 :         el2[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
    1815           5 :         status = smb2_lock(tree, &lck);
    1816           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1817             : 
    1818             :         /* cleanup */
    1819           5 :         lck.in.locks            = el1;
    1820           5 :         lck.in.file.handle      = h;
    1821           5 :         el1[0].flags            = SMB2_LOCK_FLAG_UNLOCK;
    1822           5 :         status = smb2_lock(tree, &lck);
    1823           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1824             : 
    1825           5 : done:
    1826           5 :         smb2_util_close(tree, h2);
    1827           5 :         smb2_util_close(tree, h);
    1828           5 :         smb2_deltree(tree, BASEDIR);
    1829           5 :         return ret;
    1830             : }
    1831             : 
    1832           5 : static bool test_multiple_unlock(struct torture_context *torture,
    1833             :                                  struct smb2_tree *tree)
    1834             : {
    1835           0 :         NTSTATUS status;
    1836           5 :         bool ret = true;
    1837           0 :         struct smb2_handle h;
    1838           0 :         uint8_t buf[200];
    1839           0 :         struct smb2_lock lck;
    1840           0 :         struct smb2_lock_element el[2];
    1841             : 
    1842           5 :         const char *fname = BASEDIR "\\unlock_multiple.txt";
    1843             : 
    1844           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    1845           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1846           5 :         smb2_util_close(tree, h);
    1847             : 
    1848           5 :         status = torture_smb2_testfile(tree, fname, &h);
    1849           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1850             : 
    1851           5 :         ZERO_STRUCT(buf);
    1852           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    1853           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1854             : 
    1855           5 :         torture_comment(torture, "Testing multiple unlocks:\n");
    1856             : 
    1857             :         /* Setup initial parameters */
    1858           5 :         lck.in.lock_count       = 0x0002;
    1859           5 :         lck.in.lock_sequence    = 0x00000000;
    1860           5 :         lck.in.file.handle      = h;
    1861           5 :         el[0].offset            = 0;
    1862           5 :         el[0].length            = 10;
    1863           5 :         el[0].reserved          = 0x00000000;
    1864           5 :         el[1].offset            = 10;
    1865           5 :         el[1].length            = 10;
    1866           5 :         el[1].reserved          = 0x00000000;
    1867             : 
    1868             :         /* Test1: Acquire second lock, but not first. */
    1869           5 :         torture_comment(torture, "  unlock 2 locks, first one not locked. "
    1870             :                                  "Expect no locks unlocked. \n");
    1871             : 
    1872           5 :         lck.in.lock_count       = 0x0001;
    1873           5 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1874             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1875           5 :         lck.in.locks            = &el[1];
    1876           5 :         status = smb2_lock(tree, &lck);
    1877           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1878             : 
    1879             :         /* Try to unlock both locks */
    1880           5 :         lck.in.lock_count       = 0x0002;
    1881           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1882           5 :         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1883           5 :         lck.in.locks            = el;
    1884           5 :         status = smb2_lock(tree, &lck);
    1885           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    1886             : 
    1887             :         /* Second lock should not be unlocked. */
    1888           5 :         lck.in.lock_count       = 0x0001;
    1889           5 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1890             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1891           5 :         lck.in.locks            = &el[1];
    1892           5 :         status = smb2_lock(tree, &lck);
    1893           5 :         if (TARGET_IS_W2K8(torture)) {
    1894           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1895           0 :                 torture_warning(torture, "Target has \"pretty please\" bug. "
    1896             :                                 "A contending lock request on the same handle "
    1897             :                                 "unlocks the lock.\n");
    1898             :         } else {
    1899           5 :                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1900             :         }
    1901             : 
    1902             :         /* cleanup */
    1903           5 :         lck.in.lock_count       = 0x0001;
    1904           5 :         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1905           5 :         lck.in.locks            = &el[1];
    1906           5 :         status = smb2_lock(tree, &lck);
    1907           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1908             : 
    1909             :         /* Test2: Acquire first lock, but not second. */
    1910           5 :         torture_comment(torture, "  unlock 2 locks, second one not locked. "
    1911             :                                  "Expect first lock unlocked.\n");
    1912             : 
    1913           5 :         lck.in.lock_count       = 0x0001;
    1914           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1915             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1916           5 :         lck.in.locks            = &el[0];
    1917           5 :         status = smb2_lock(tree, &lck);
    1918           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1919             : 
    1920             :         /* Try to unlock both locks */
    1921           5 :         lck.in.lock_count       = 0x0002;
    1922           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1923           5 :         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1924           5 :         lck.in.locks            = el;
    1925           5 :         status = smb2_lock(tree, &lck);
    1926           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    1927             : 
    1928             :         /* First lock should be unlocked. */
    1929           5 :         lck.in.lock_count       = 0x0001;
    1930           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1931             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1932           5 :         lck.in.locks            = &el[0];
    1933           5 :         status = smb2_lock(tree, &lck);
    1934           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1935             : 
    1936             :         /* cleanup */
    1937           5 :         lck.in.lock_count       = 0x0001;
    1938           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1939           5 :         lck.in.locks            = &el[0];
    1940           5 :         status = smb2_lock(tree, &lck);
    1941           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1942             : 
    1943             :         /* Test3: Request 2 locks, second will contend.  What happens to the
    1944             :          * first? */
    1945           5 :         torture_comment(torture, "  request 2 locks, second one will contend. "
    1946             :                                  "Expect both to fail.\n");
    1947             : 
    1948             :         /* Lock the second range */
    1949           5 :         lck.in.lock_count       = 0x0001;
    1950           5 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1951             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1952           5 :         lck.in.locks            = &el[1];
    1953           5 :         status = smb2_lock(tree, &lck);
    1954           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1955             : 
    1956             :         /* Request both locks */
    1957           5 :         lck.in.lock_count       = 0x0002;
    1958           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    1959             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1960           5 :         lck.in.locks            = el;
    1961           5 :         status = smb2_lock(tree, &lck);
    1962           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1963             : 
    1964             :         /* First lock should be unlocked. */
    1965           5 :         lck.in.lock_count       = 0x0001;
    1966           5 :         lck.in.locks            = &el[0];
    1967           5 :         status = smb2_lock(tree, &lck);
    1968           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    1969             : 
    1970             :         /* cleanup */
    1971           5 :         if (TARGET_IS_W2K8(torture)) {
    1972           0 :                 lck.in.lock_count       = 0x0001;
    1973           0 :                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1974           0 :                 lck.in.locks            = &el[0];
    1975           0 :                 status = smb2_lock(tree, &lck);
    1976           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1977           0 :                 torture_warning(torture, "Target has \"pretty please\" bug. "
    1978             :                                 "A contending lock request on the same handle "
    1979             :                                 "unlocks the lock.\n");
    1980             :         } else {
    1981           5 :                 lck.in.lock_count       = 0x0002;
    1982           5 :                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1983           5 :                 el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
    1984           5 :                 lck.in.locks            = el;
    1985           5 :                 status = smb2_lock(tree, &lck);
    1986           5 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1987             :         }
    1988             : 
    1989             :         /* Test4: Request unlock and lock.  The lock contends, is the unlock
    1990             :          * then relocked?  SMB2 doesn't like the lock and unlock requests in the
    1991             :          * same packet. The unlock will succeed, but the lock will return
    1992             :          * INVALID_PARAMETER.  This behavior is described in MS-SMB2
    1993             :          * 3.3.5.14.1 */
    1994           5 :         torture_comment(torture, "  request unlock and lock, second one will "
    1995             :                                  "error. Expect the unlock to succeed.\n");
    1996             : 
    1997             :         /* Lock both ranges */
    1998           5 :         lck.in.lock_count       = 0x0002;
    1999           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2000             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2001           5 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2002             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2003           5 :         lck.in.locks            = el;
    2004           5 :         status = smb2_lock(tree, &lck);
    2005           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2006             : 
    2007             :         /* Attempt to unlock the first range and lock the second. The lock
    2008             :          * request will error. */
    2009           5 :         lck.in.lock_count       = 0x0002;
    2010           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2011           5 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2012             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2013           5 :         lck.in.locks            = el;
    2014           5 :         status = smb2_lock(tree, &lck);
    2015           5 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    2016             : 
    2017             :         /* The first lock should've been unlocked */
    2018           5 :         lck.in.lock_count       = 0x0001;
    2019           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2020             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2021           5 :         lck.in.locks            = &el[0];
    2022           5 :         status = smb2_lock(tree, &lck);
    2023           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2024             : 
    2025             :         /* cleanup */
    2026           4 :         lck.in.lock_count       = 0x0002;
    2027           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2028           4 :         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2029           4 :         lck.in.locks            = el;
    2030           4 :         status = smb2_lock(tree, &lck);
    2031           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2032             : 
    2033             :         /* Test10: SMB2 only test. Request unlock and lock in same packet.
    2034             :          * Neither contend. SMB2 doesn't like lock and unlock requests in the
    2035             :          * same packet.  The unlock will succeed, but the lock will return
    2036             :          * INVALID_PARAMETER. */
    2037           4 :         torture_comment(torture, "  request unlock and lock.  Unlock will "
    2038             :                                  "succeed, but lock will fail.\n");
    2039             : 
    2040             :         /* Lock first range */
    2041           4 :         lck.in.lock_count       = 0x0001;
    2042           4 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2043             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2044           4 :         lck.in.locks            = &el[0];
    2045           4 :         status = smb2_lock(tree, &lck);
    2046           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2047             : 
    2048             :         /* Attempt to unlock the first range and lock the second */
    2049           4 :         lck.in.lock_count       = 0x0002;
    2050           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2051           4 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2052             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2053           4 :         lck.in.locks            = el;
    2054           4 :         status = smb2_lock(tree, &lck);
    2055           4 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    2056             : 
    2057             :         /* Neither lock should still be locked */
    2058           4 :         lck.in.lock_count       = 0x0002;
    2059           4 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2060             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2061           4 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2062             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2063           4 :         lck.in.locks            = el;
    2064           4 :         status = smb2_lock(tree, &lck);
    2065           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2066             : 
    2067             :         /* cleanup */
    2068           4 :         lck.in.lock_count       = 0x0002;
    2069           4 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2070           4 :         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2071           4 :         lck.in.locks            = el;
    2072           4 :         status = smb2_lock(tree, &lck);
    2073           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2074             : 
    2075             :         /* Test11: SMB2 only test. Request lock and unlock in same packet.
    2076             :          * Neither contend. SMB2 doesn't like lock and unlock requests in the
    2077             :          * same packet.  The lock will succeed, the unlock will fail with
    2078             :          * INVALID_PARAMETER, and the lock will be unlocked before return. */
    2079           4 :         torture_comment(torture, "  request lock and unlock.  Both will "
    2080             :                                  "fail.\n");
    2081             : 
    2082             :         /* Lock second range */
    2083           4 :         lck.in.lock_count       = 0x0001;
    2084           4 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2085             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2086           4 :         lck.in.locks            = &el[1];
    2087           4 :         status = smb2_lock(tree, &lck);
    2088           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2089             : 
    2090             :         /* Attempt to lock the first range and unlock the second */
    2091           4 :         lck.in.lock_count       = 0x0002;
    2092           4 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2093             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2094           4 :         el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2095           4 :         lck.in.locks            = el;
    2096           4 :         status = smb2_lock(tree, &lck);
    2097           4 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    2098             : 
    2099             :         /* First range should be unlocked, second locked. */
    2100           4 :         lck.in.lock_count       = 0x0001;
    2101           4 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2102             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2103           4 :         lck.in.locks            = &el[0];
    2104           4 :         status = smb2_lock(tree, &lck);
    2105           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2106             : 
    2107           4 :         lck.in.lock_count       = 0x0001;
    2108           4 :         el[1].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2109             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2110           4 :         lck.in.locks            = &el[1];
    2111           4 :         status = smb2_lock(tree, &lck);
    2112           4 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2113             : 
    2114             :         /* cleanup */
    2115           4 :         if (TARGET_IS_W2K8(torture)) {
    2116           0 :                 lck.in.lock_count       = 0x0001;
    2117           0 :                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2118           0 :                 lck.in.locks            = &el[0];
    2119           0 :                 status = smb2_lock(tree, &lck);
    2120           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2121           0 :                 torture_warning(torture, "Target has \"pretty please\" bug. "
    2122             :                                 "A contending lock request on the same handle "
    2123             :                                 "unlocks the lock.\n");
    2124             :         } else {
    2125           4 :                 lck.in.lock_count       = 0x0002;
    2126           4 :                 el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2127           4 :                 el[1].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2128           4 :                 lck.in.locks            = el;
    2129           4 :                 status = smb2_lock(tree, &lck);
    2130           4 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2131             :         }
    2132             : 
    2133           5 : done:
    2134           5 :         smb2_util_close(tree, h);
    2135           5 :         smb2_deltree(tree, BASEDIR);
    2136           5 :         return ret;
    2137             : }
    2138             : 
    2139             : /**
    2140             :  * Test lock stacking
    2141             :  *  - some tests ported from BASE-LOCK-LOCK5
    2142             :  */
    2143           5 : static bool test_stacking(struct torture_context *torture,
    2144             :                           struct smb2_tree *tree)
    2145             : {
    2146           0 :         NTSTATUS status;
    2147           5 :         bool ret = true;
    2148           5 :         struct smb2_handle h = {{0}};
    2149           5 :         struct smb2_handle h2 = {{0}};
    2150           0 :         uint8_t buf[200];
    2151           0 :         struct smb2_lock lck;
    2152           0 :         struct smb2_lock_element el[1];
    2153             : 
    2154           5 :         const char *fname = BASEDIR "\\stacking.txt";
    2155             : 
    2156           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    2157           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2158           5 :         smb2_util_close(tree, h);
    2159             : 
    2160           5 :         status = torture_smb2_testfile(tree, fname, &h);
    2161           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2162             : 
    2163           5 :         ZERO_STRUCT(buf);
    2164           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    2165           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2166             : 
    2167           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    2168           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2169             : 
    2170           5 :         torture_comment(torture, "Testing lock stacking:\n");
    2171             : 
    2172             :         /* Setup initial parameters */
    2173           5 :         lck.in.locks            = el;
    2174           5 :         lck.in.lock_count       = 0x0001;
    2175           5 :         lck.in.lock_sequence    = 0x00000000;
    2176           5 :         lck.in.file.handle      = h;
    2177           5 :         el[0].offset            = 0;
    2178           5 :         el[0].length            = 10;
    2179           5 :         el[0].reserved          = 0x00000000;
    2180             : 
    2181             :         /* Try to take a shared lock, then a shared lock on same handle */
    2182           5 :         torture_comment(torture, "  stacking a shared on top of a shared"
    2183             :                                  "lock succeeds.\n");
    2184             : 
    2185           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2186             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2187           5 :         status = smb2_lock(tree, &lck);
    2188           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2189             : 
    2190           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2191             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2192           5 :         status = smb2_lock(tree, &lck);
    2193           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2194             : 
    2195             :         /* cleanup */
    2196           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2197           5 :         status = smb2_lock(tree, &lck);
    2198           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2199             : 
    2200           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2201           5 :         status = smb2_lock(tree, &lck);
    2202           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2203             : 
    2204             : 
    2205             :         /* Try to take an exclusive lock, then a shared lock on same handle */
    2206           5 :         torture_comment(torture, "  stacking a shared on top of an exclusive "
    2207             :                                  "lock succeeds.\n");
    2208             : 
    2209           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2210             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2211           5 :         status = smb2_lock(tree, &lck);
    2212           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2213             : 
    2214           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2215             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2216           5 :         status = smb2_lock(tree, &lck);
    2217           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2218             : 
    2219           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2220             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2221           5 :         status = smb2_lock(tree, &lck);
    2222           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2223             : 
    2224             :         /* stacking a shared from a different handle should fail */
    2225           5 :         lck.in.file.handle      = h2;
    2226           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2227             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2228           5 :         status = smb2_lock(tree, &lck);
    2229           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2230             : 
    2231             :         /* cleanup */
    2232           5 :         lck.in.file.handle      = h;
    2233           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2234           5 :         status = smb2_lock(tree, &lck);
    2235           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2236             : 
    2237           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2238           5 :         status = smb2_lock(tree, &lck);
    2239           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2240             : 
    2241           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2242           5 :         status = smb2_lock(tree, &lck);
    2243           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2244             : 
    2245             :         /* ensure the 4th unlock fails */
    2246           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2247           5 :         status = smb2_lock(tree, &lck);
    2248           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    2249             : 
    2250             :         /* ensure a second handle can now take an exclusive lock */
    2251           5 :         lck.in.file.handle      = h2;
    2252           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2253             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2254           5 :         status = smb2_lock(tree, &lck);
    2255           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2256             : 
    2257           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2258           5 :         status = smb2_lock(tree, &lck);
    2259           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2260             : 
    2261             :         /* Try to take an exclusive lock, then a shared lock on a
    2262             :          * different handle */
    2263           5 :         torture_comment(torture, "  stacking a shared on top of an exclusive "
    2264             :                                  "lock with different handles fails.\n");
    2265             : 
    2266           5 :         lck.in.file.handle      = h;
    2267           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2268             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2269           5 :         status = smb2_lock(tree, &lck);
    2270           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2271             : 
    2272           5 :         lck.in.file.handle      = h2;
    2273           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2274             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2275           5 :         status = smb2_lock(tree, &lck);
    2276           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2277             : 
    2278             :         /* cleanup */
    2279           5 :         lck.in.file.handle      = h;
    2280           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2281           5 :         status = smb2_lock(tree, &lck);
    2282           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2283             : 
    2284             :         /* Try to take a shared lock, then stack an exclusive with same
    2285             :          * handle.  */
    2286           5 :         torture_comment(torture, "  stacking an exclusive on top of a shared "
    2287             :                                  "lock fails.\n");
    2288             : 
    2289           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2290             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2291           5 :         status = smb2_lock(tree, &lck);
    2292           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2293             : 
    2294           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2295             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2296           5 :         status = smb2_lock(tree, &lck);
    2297           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2298             : 
    2299             :         /* cleanup */
    2300           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2301           5 :         status = smb2_lock(tree, &lck);
    2302           5 :         if (TARGET_IS_W2K8(torture)) {
    2303           0 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    2304           0 :                 torture_warning(torture, "Target has \"pretty please\" bug. "
    2305             :                                 "A contending lock request on the same handle "
    2306             :                                 "unlocks the lock.\n");
    2307             :         } else {
    2308           5 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2309             :         }
    2310             : 
    2311             :         /* Prove that two exclusive locks do not stack on the same handle. */
    2312           5 :         torture_comment(torture, "  two exclusive locks do not stack.\n");
    2313             : 
    2314           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2315             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2316           5 :         status = smb2_lock(tree, &lck);
    2317           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2318             : 
    2319           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2320             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2321           5 :         status = smb2_lock(tree, &lck);
    2322           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2323             : 
    2324             :         /* cleanup */
    2325           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2326           5 :         status = smb2_lock(tree, &lck);
    2327           5 :         if (TARGET_IS_W2K8(torture)) {
    2328           0 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    2329           0 :                 torture_warning(torture, "Target has \"pretty please\" bug. "
    2330             :                                 "A contending lock request on the same handle "
    2331             :                                 "unlocks the lock.\n");
    2332             :         } else {
    2333           5 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2334             :         }
    2335             : 
    2336           5 : done:
    2337           5 :         smb2_util_close(tree, h2);
    2338           5 :         smb2_util_close(tree, h);
    2339           5 :         smb2_deltree(tree, BASEDIR);
    2340           5 :         return ret;
    2341             : }
    2342             : 
    2343             : /**
    2344             :  * Test lock contention
    2345             :  * - shared lock should contend with exclusive lock on different handle
    2346             :  */
    2347           5 : static bool test_contend(struct torture_context *torture,
    2348             :                          struct smb2_tree *tree)
    2349             : {
    2350           0 :         NTSTATUS status;
    2351           5 :         bool ret = true;
    2352           5 :         struct smb2_handle h = {{0}};
    2353           5 :         struct smb2_handle h2 = {{0}};
    2354           0 :         uint8_t buf[200];
    2355           0 :         struct smb2_lock lck;
    2356           0 :         struct smb2_lock_element el[1];
    2357             : 
    2358           5 :         const char *fname = BASEDIR "\\contend.txt";
    2359             : 
    2360           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    2361           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2362           5 :         smb2_util_close(tree, h);
    2363             : 
    2364           5 :         status = torture_smb2_testfile(tree, fname, &h);
    2365           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2366             : 
    2367           5 :         ZERO_STRUCT(buf);
    2368           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    2369           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2370             : 
    2371           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    2372           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2373             : 
    2374           5 :         torture_comment(torture, "Testing lock contention:\n");
    2375             : 
    2376             :         /* Setup initial parameters */
    2377           5 :         lck.in.locks            = el;
    2378           5 :         lck.in.lock_count       = 0x0001;
    2379           5 :         lck.in.lock_sequence    = 0x00000000;
    2380           5 :         lck.in.file.handle      = h;
    2381           5 :         el[0].offset            = 0;
    2382           5 :         el[0].length            = 10;
    2383           5 :         el[0].reserved          = 0x00000000;
    2384             : 
    2385             :         /* Take an exclusive lock, then a shared lock on different handle */
    2386           5 :         torture_comment(torture, "  shared should contend on exclusive on "
    2387             :                                  "different handle.\n");
    2388             : 
    2389           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2390             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2391           5 :         status = smb2_lock(tree, &lck);
    2392           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2393             : 
    2394           5 :         lck.in.file.handle      = h2;
    2395           5 :         el[0].flags             = SMB2_LOCK_FLAG_SHARED |
    2396             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2397           5 :         status = smb2_lock(tree, &lck);
    2398           5 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2399             : 
    2400             :         /* cleanup */
    2401           5 :         lck.in.file.handle      = h;
    2402           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2403           5 :         status = smb2_lock(tree, &lck);
    2404           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2405             : 
    2406           5 : done:
    2407           5 :         smb2_util_close(tree, h2);
    2408           5 :         smb2_util_close(tree, h);
    2409           5 :         smb2_deltree(tree, BASEDIR);
    2410           5 :         return ret;
    2411             : }
    2412             : 
    2413             : /**
    2414             :  * Test locker context
    2415             :  * - test that pid does not affect the locker context
    2416             :  */
    2417           5 : static bool test_context(struct torture_context *torture,
    2418             :                          struct smb2_tree *tree)
    2419             : {
    2420           0 :         NTSTATUS status;
    2421           5 :         bool ret = true;
    2422           5 :         struct smb2_handle h = {{0}};
    2423           5 :         struct smb2_handle h2 = {{0}};
    2424           0 :         uint8_t buf[200];
    2425           0 :         struct smb2_lock lck;
    2426           0 :         struct smb2_lock_element el[1];
    2427             : 
    2428           5 :         const char *fname = BASEDIR "\\context.txt";
    2429             : 
    2430           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    2431           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2432           5 :         smb2_util_close(tree, h);
    2433             : 
    2434           5 :         status = torture_smb2_testfile(tree, fname, &h);
    2435           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2436             : 
    2437           5 :         ZERO_STRUCT(buf);
    2438           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    2439           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2440             : 
    2441           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    2442           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2443             : 
    2444           5 :         torture_comment(torture, "Testing locker context:\n");
    2445             : 
    2446             :         /* Setup initial parameters */
    2447           5 :         lck.in.locks            = el;
    2448           5 :         lck.in.lock_count       = 0x0001;
    2449           5 :         lck.in.lock_sequence    = 0x00000000;
    2450           5 :         lck.in.file.handle      = h;
    2451           5 :         el[0].offset            = 0;
    2452           5 :         el[0].length            = 10;
    2453           5 :         el[0].reserved          = 0x00000000;
    2454             : 
    2455             :         /* Take an exclusive lock, then try to unlock with a different pid,
    2456             :          * same handle.  This shows that the pid doesn't affect the locker
    2457             :          * context in SMB2. */
    2458           5 :         torture_comment(torture, "  pid shouldn't affect locker context\n");
    2459             : 
    2460           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2461             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2462           5 :         status = smb2_lock(tree, &lck);
    2463           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2464             : 
    2465           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2466           5 :         status = smb2_lock(tree, &lck);
    2467           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2468             : 
    2469           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2470           5 :         status = smb2_lock(tree, &lck);
    2471           5 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    2472             : 
    2473           5 : done:
    2474           5 :         smb2_util_close(tree, h2);
    2475           5 :         smb2_util_close(tree, h);
    2476           5 :         smb2_deltree(tree, BASEDIR);
    2477           5 :         return ret;
    2478             : }
    2479             : 
    2480             : /**
    2481             :  * Test as much of the potential lock range as possible
    2482             :  *  - test ported from BASE-LOCK-LOCK3
    2483             :  */
    2484           5 : static bool test_range(struct torture_context *torture,
    2485             :                        struct smb2_tree *tree)
    2486             : {
    2487           0 :         NTSTATUS status;
    2488           5 :         bool ret = true;
    2489           5 :         struct smb2_handle h = {{0}};
    2490           5 :         struct smb2_handle h2 = {{0}};
    2491           0 :         uint8_t buf[200];
    2492           0 :         struct smb2_lock lck;
    2493           0 :         struct smb2_lock_element el[1];
    2494           0 :         uint64_t offset, i;
    2495           0 :         extern int torture_numops;
    2496             : 
    2497           5 :         const char *fname = BASEDIR "\\range.txt";
    2498             : 
    2499             : #define NEXT_OFFSET offset += (~(uint64_t)0) / torture_numops
    2500             : 
    2501           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    2502           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2503           5 :         smb2_util_close(tree, h);
    2504             : 
    2505           5 :         status = torture_smb2_testfile(tree, fname, &h);
    2506           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2507             : 
    2508           5 :         ZERO_STRUCT(buf);
    2509           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    2510           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2511             : 
    2512           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    2513           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2514             : 
    2515           5 :         torture_comment(torture, "Testing locks spread across the 64-bit "
    2516             :                                  "offset range\n");
    2517             : 
    2518           5 :         if (TARGET_IS_W2K8(torture)) {
    2519           0 :                 torture_result(torture, TORTURE_SKIP,
    2520             :                     "Target has \"pretty please\" bug. A contending lock "
    2521             :                     "request on the same handle unlocks the lock.");
    2522           0 :                 goto done;
    2523             :         }
    2524             : 
    2525             :         /* Setup initial parameters */
    2526           5 :         lck.in.locks            = el;
    2527           5 :         lck.in.lock_count       = 0x0001;
    2528           5 :         lck.in.lock_sequence    = 0x00000000;
    2529           5 :         lck.in.file.handle      = h;
    2530           5 :         el[0].offset            = 0;
    2531           5 :         el[0].length            = 1;
    2532           5 :         el[0].reserved          = 0x00000000;
    2533           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2534             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2535             : 
    2536           5 :         torture_comment(torture, "  establishing %d locks\n", torture_numops);
    2537             : 
    2538          55 :         for (offset=i=0; i<torture_numops; i++) {
    2539          50 :                 NEXT_OFFSET;
    2540             : 
    2541          50 :                 lck.in.file.handle      = h;
    2542          50 :                 el[0].offset            = offset - 1;
    2543          50 :                 status = smb2_lock(tree, &lck);
    2544          50 :                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
    2545             :                                  talloc_asprintf(torture,
    2546             :                                      "lock h failed at offset %#llx ",
    2547             :                                      (unsigned long long) el[0].offset));
    2548             : 
    2549          50 :                 lck.in.file.handle      = h2;
    2550          50 :                 el[0].offset            = offset - 2;
    2551          50 :                 status = smb2_lock(tree, &lck);
    2552          50 :                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
    2553             :                                  talloc_asprintf(torture,
    2554             :                                      "lock h2 failed at offset %#llx ",
    2555             :                                      (unsigned long long) el[0].offset));
    2556             :         }
    2557             : 
    2558           5 :         torture_comment(torture, "  testing %d locks\n", torture_numops);
    2559             : 
    2560          55 :         for (offset=i=0; i<torture_numops; i++) {
    2561          50 :                 NEXT_OFFSET;
    2562             : 
    2563          50 :                 lck.in.file.handle      = h;
    2564          50 :                 el[0].offset            = offset - 1;
    2565          50 :                 status = smb2_lock(tree, &lck);
    2566          50 :                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
    2567             :                                  talloc_asprintf(torture,
    2568             :                                      "lock h at offset %#llx should not have "
    2569             :                                      "succeeded ",
    2570             :                                      (unsigned long long) el[0].offset));
    2571             : 
    2572          50 :                 lck.in.file.handle      = h;
    2573          50 :                 el[0].offset            = offset - 2;
    2574          50 :                 status = smb2_lock(tree, &lck);
    2575          50 :                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
    2576             :                                  talloc_asprintf(torture,
    2577             :                                      "lock h2 at offset %#llx should not have "
    2578             :                                      "succeeded ",
    2579             :                                      (unsigned long long) el[0].offset));
    2580             : 
    2581          50 :                 lck.in.file.handle      = h2;
    2582          50 :                 el[0].offset            = offset - 1;
    2583          50 :                 status = smb2_lock(tree, &lck);
    2584          50 :                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
    2585             :                                  talloc_asprintf(torture,
    2586             :                                      "lock h at offset %#llx should not have "
    2587             :                                      "succeeded ",
    2588             :                                      (unsigned long long) el[0].offset));
    2589             : 
    2590          50 :                 lck.in.file.handle      = h2;
    2591          50 :                 el[0].offset            = offset - 2;
    2592          50 :                 status = smb2_lock(tree, &lck);
    2593          50 :                 CHECK_STATUS_CMT(status, NT_STATUS_LOCK_NOT_GRANTED,
    2594             :                                  talloc_asprintf(torture,
    2595             :                                      "lock h2 at offset %#llx should not have "
    2596             :                                      "succeeded ",
    2597             :                                      (unsigned long long) el[0].offset));
    2598             :         }
    2599             : 
    2600           5 :         torture_comment(torture, "  removing %d locks\n", torture_numops);
    2601             : 
    2602           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2603             : 
    2604          55 :         for (offset=i=0; i<torture_numops; i++) {
    2605          50 :                 NEXT_OFFSET;
    2606             : 
    2607          50 :                 lck.in.file.handle      = h;
    2608          50 :                 el[0].offset            = offset - 1;
    2609          50 :                 status = smb2_lock(tree, &lck);
    2610          50 :                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
    2611             :                                  talloc_asprintf(torture,
    2612             :                                      "unlock from h failed at offset %#llx ",
    2613             :                                      (unsigned long long) el[0].offset));
    2614             : 
    2615          50 :                 lck.in.file.handle      = h2;
    2616          50 :                 el[0].offset            = offset - 2;
    2617          50 :                 status = smb2_lock(tree, &lck);
    2618          50 :                 CHECK_STATUS_CMT(status, NT_STATUS_OK,
    2619             :                                  talloc_asprintf(torture,
    2620             :                                      "unlock from h2 failed at offset %#llx ",
    2621             :                                      (unsigned long long) el[0].offset));
    2622             :         }
    2623             : 
    2624           5 : done:
    2625           5 :         smb2_util_close(tree, h2);
    2626           5 :         smb2_util_close(tree, h);
    2627           5 :         smb2_deltree(tree, BASEDIR);
    2628           5 :         return ret;
    2629             : }
    2630             : 
    2631          85 : static NTSTATUS test_smb2_lock(struct smb2_tree *tree, struct smb2_handle h,
    2632             :                                uint64_t offset, uint64_t length, bool exclusive)
    2633             : {
    2634           0 :         struct smb2_lock lck;
    2635           0 :         struct smb2_lock_element el[1];
    2636           0 :         NTSTATUS status;
    2637             : 
    2638          85 :         lck.in.locks            = el;
    2639          85 :         lck.in.lock_count       = 0x0001;
    2640          85 :         lck.in.lock_sequence    = 0x00000000;
    2641          85 :         lck.in.file.handle      = h;
    2642          85 :         el[0].offset            = offset;
    2643          85 :         el[0].length            = length;
    2644          85 :         el[0].reserved          = 0x00000000;
    2645          85 :         el[0].flags             = (exclusive ?
    2646             :                                   SMB2_LOCK_FLAG_EXCLUSIVE :
    2647          85 :                                   SMB2_LOCK_FLAG_SHARED) |
    2648             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2649             : 
    2650          85 :         status = smb2_lock(tree, &lck);
    2651             : 
    2652          85 :         return status;
    2653             : }
    2654             : 
    2655           5 : static NTSTATUS test_smb2_unlock(struct smb2_tree *tree, struct smb2_handle h,
    2656             :                                  uint64_t offset, uint64_t length)
    2657             : {
    2658           0 :         struct smb2_lock lck;
    2659           0 :         struct smb2_lock_element el[1];
    2660           0 :         NTSTATUS status;
    2661             : 
    2662           5 :         lck.in.locks            = el;
    2663           5 :         lck.in.lock_count       = 0x0001;
    2664           5 :         lck.in.lock_sequence    = 0x00000000;
    2665           5 :         lck.in.file.handle      = h;
    2666           5 :         el[0].offset            = offset;
    2667           5 :         el[0].length            = length;
    2668           5 :         el[0].reserved          = 0x00000000;
    2669           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2670             : 
    2671           5 :         status = smb2_lock(tree, &lck);
    2672             : 
    2673           5 :         return status;
    2674             : }
    2675             : 
    2676             : #define EXPECTED(ret, v) if ((ret) != (v)) { \
    2677             :         torture_result(torture, TORTURE_FAIL, __location__": subtest failed");\
    2678             :         torture_comment(torture, "** "); correct = false; \
    2679             :         }
    2680             : 
    2681             : /**
    2682             :  * Test overlapping lock ranges from various lockers
    2683             :  *  - some tests ported from BASE-LOCK-LOCK4
    2684             :  */
    2685           5 : static bool test_overlap(struct torture_context *torture,
    2686             :                          struct smb2_tree *tree,
    2687             :                          struct smb2_tree *tree2)
    2688             : {
    2689           0 :         NTSTATUS status;
    2690           5 :         bool ret = true;
    2691           5 :         struct smb2_handle h = {{0}};
    2692           5 :         struct smb2_handle h2 = {{0}};
    2693           5 :         struct smb2_handle h3 = {{0}};
    2694           0 :         uint8_t buf[200];
    2695           5 :         bool correct = true;
    2696             : 
    2697           5 :         const char *fname = BASEDIR "\\overlap.txt";
    2698             : 
    2699           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    2700           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2701           5 :         smb2_util_close(tree, h);
    2702             : 
    2703           5 :         status = torture_smb2_testfile(tree, fname, &h);
    2704           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2705             : 
    2706           5 :         ZERO_STRUCT(buf);
    2707           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    2708           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2709             : 
    2710           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    2711           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2712             : 
    2713           5 :         status = torture_smb2_testfile(tree2, fname, &h3);
    2714           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2715             : 
    2716           5 :         torture_comment(torture, "Testing overlapping locks:\n");
    2717             : 
    2718          10 :         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 0, 4, true)) &&
    2719           5 :               NT_STATUS_IS_OK(test_smb2_lock(tree, h, 2, 4, true));
    2720           5 :         EXPECTED(ret, false);
    2721           5 :         torture_comment(torture, "the same session/handle %s set overlapping "
    2722             :                                  "exclusive locks\n", ret?"can":"cannot");
    2723             : 
    2724          10 :         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 10, 4, false)) &&
    2725           5 :               NT_STATUS_IS_OK(test_smb2_lock(tree, h, 12, 4, false));
    2726           5 :         EXPECTED(ret, true);
    2727           5 :         torture_comment(torture, "the same session/handle %s set overlapping "
    2728             :                                  "shared locks\n", ret?"can":"cannot");
    2729             : 
    2730          10 :         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 20, 4, true)) &&
    2731           5 :               NT_STATUS_IS_OK(test_smb2_lock(tree2, h3, 22, 4, true));
    2732           5 :         EXPECTED(ret, false);
    2733           5 :         torture_comment(torture, "a different session %s set overlapping "
    2734             :                                  "exclusive locks\n", ret?"can":"cannot");
    2735             : 
    2736          10 :         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 30, 4, false)) &&
    2737           5 :               NT_STATUS_IS_OK(test_smb2_lock(tree2, h3, 32, 4, false));
    2738           5 :         EXPECTED(ret, true);
    2739           5 :         torture_comment(torture, "a different session %s set overlapping "
    2740             :                                  "shared locks\n", ret?"can":"cannot");
    2741             : 
    2742          10 :         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 40, 4, true)) &&
    2743           5 :               NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 42, 4, true));
    2744           5 :         EXPECTED(ret, false);
    2745           5 :         torture_comment(torture, "a different handle %s set overlapping "
    2746             :                                  "exclusive locks\n", ret?"can":"cannot");
    2747             : 
    2748          10 :         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 50, 4, false)) &&
    2749           5 :               NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 52, 4, false));
    2750           5 :         EXPECTED(ret, true);
    2751           5 :         torture_comment(torture, "a different handle %s set overlapping "
    2752             :                                  "shared locks\n", ret?"can":"cannot");
    2753             : 
    2754           5 :         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 110, 4, false)) &&
    2755          10 :               NT_STATUS_IS_OK(test_smb2_lock(tree, h, 112, 4, false)) &&
    2756           5 :               NT_STATUS_IS_OK(test_smb2_unlock(tree, h, 110, 6));
    2757           5 :         EXPECTED(ret, false);
    2758           5 :         torture_comment(torture, "the same handle %s coalesce read locks\n",
    2759             :                                  ret?"can":"cannot");
    2760             : 
    2761           5 :         smb2_util_close(tree, h2);
    2762           5 :         smb2_util_close(tree, h);
    2763           5 :         status = torture_smb2_testfile(tree, fname, &h);
    2764           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2765           5 :         status = torture_smb2_testfile(tree, fname, &h2);
    2766           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2767           5 :         ret = NT_STATUS_IS_OK(test_smb2_lock(tree, h, 0, 8, false)) &&
    2768           5 :               NT_STATUS_IS_OK(test_smb2_lock(tree, h2, 0, 1, false)) &&
    2769           5 :               NT_STATUS_IS_OK(smb2_util_close(tree, h)) &&
    2770          15 :               NT_STATUS_IS_OK(torture_smb2_testfile(tree, fname, &h)) &&
    2771           5 :               NT_STATUS_IS_OK(test_smb2_lock(tree, h, 7, 1, true));
    2772           5 :         EXPECTED(ret, true);
    2773           5 :         torture_comment(torture, "the server %s have the NT byte range lock "
    2774           5 :                                  "bug\n", !ret?"does":"doesn't");
    2775             : 
    2776           5 : done:
    2777           5 :         smb2_util_close(tree2, h3);
    2778           5 :         smb2_util_close(tree, h2);
    2779           5 :         smb2_util_close(tree, h);
    2780           5 :         smb2_deltree(tree, BASEDIR);
    2781           5 :         return correct;
    2782             : }
    2783             : 
    2784             : /**
    2785             :  * Test truncation of locked file
    2786             :  *  - some tests ported from BASE-LOCK-LOCK7
    2787             :  */
    2788           5 : static bool test_truncate(struct torture_context *torture,
    2789             :                           struct smb2_tree *tree)
    2790             : {
    2791           0 :         NTSTATUS status;
    2792           5 :         bool ret = true;
    2793           5 :         struct smb2_handle h = {{0}};
    2794           5 :         struct smb2_handle h2 = {{0}};
    2795           0 :         uint8_t buf[200];
    2796           0 :         struct smb2_lock lck;
    2797           0 :         struct smb2_lock_element el[1];
    2798           0 :         struct smb2_create io;
    2799             : 
    2800           5 :         const char *fname = BASEDIR "\\truncate.txt";
    2801             : 
    2802           5 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    2803           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2804           5 :         smb2_util_close(tree, h);
    2805             : 
    2806           5 :         status = torture_smb2_testfile(tree, fname, &h);
    2807           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2808             : 
    2809           5 :         ZERO_STRUCT(buf);
    2810           5 :         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
    2811           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2812             : 
    2813           5 :         torture_comment(torture, "Testing truncation of locked file:\n");
    2814             : 
    2815             :         /* Setup initial parameters */
    2816           5 :         lck.in.locks            = el;
    2817           5 :         lck.in.lock_count       = 0x0001;
    2818           5 :         lck.in.lock_sequence    = 0x00000000;
    2819           5 :         lck.in.file.handle      = h;
    2820           5 :         el[0].offset            = 0;
    2821           5 :         el[0].length            = 10;
    2822           5 :         el[0].reserved          = 0x00000000;
    2823             : 
    2824           5 :         ZERO_STRUCT(io);
    2825           5 :         io.in.oplock_level = 0;
    2826           5 :         io.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2827           5 :         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
    2828           5 :         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
    2829           5 :         io.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
    2830             :                              NTCREATEX_SHARE_ACCESS_READ |
    2831             :                              NTCREATEX_SHARE_ACCESS_WRITE;
    2832           5 :         io.in.create_options = 0;
    2833           5 :         io.in.fname = fname;
    2834             : 
    2835             :         /* Take an exclusive lock */
    2836           5 :         el[0].flags             = SMB2_LOCK_FLAG_EXCLUSIVE |
    2837             :                                   SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2838           5 :         status = smb2_lock(tree, &lck);
    2839           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2840             : 
    2841             :         /* On second handle open the file with OVERWRITE disposition */
    2842           5 :         torture_comment(torture, "  overwrite disposition is allowed on a "
    2843             :                                  "locked file.\n");
    2844             : 
    2845           5 :         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
    2846           5 :         status = smb2_create(tree, tree, &io);
    2847           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2848           5 :         h2 = io.out.file.handle;
    2849           5 :         smb2_util_close(tree, h2);
    2850             : 
    2851             :         /* On second handle open the file with SUPERSEDE disposition */
    2852           5 :         torture_comment(torture, "  supersede disposition is allowed on a "
    2853             :                                  "locked file.\n");
    2854             : 
    2855           5 :         io.in.create_disposition = NTCREATEX_DISP_SUPERSEDE;
    2856           5 :         status = smb2_create(tree, tree, &io);
    2857           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2858           5 :         h2 = io.out.file.handle;
    2859           5 :         smb2_util_close(tree, h2);
    2860             : 
    2861             :         /* cleanup */
    2862           5 :         lck.in.file.handle      = h;
    2863           5 :         el[0].flags             = SMB2_LOCK_FLAG_UNLOCK;
    2864           5 :         status = smb2_lock(tree, &lck);
    2865           5 :         CHECK_STATUS(status, NT_STATUS_OK);
    2866             : 
    2867           5 : done:
    2868           5 :         smb2_util_close(tree, h2);
    2869           5 :         smb2_util_close(tree, h);
    2870           5 :         smb2_deltree(tree, BASEDIR);
    2871           5 :         return ret;
    2872             : }
    2873             : 
    2874             : /**
    2875             :  * Test lock replay detection
    2876             :  *
    2877             :  * This test checks the SMB 2.1.0 behaviour of lock sequence checking,
    2878             :  * which is only turned on for resilient handles.
    2879             :  *
    2880             :  * Make it clear that this test is supposed to pass against the legacy
    2881             :  * Windows servers which violate the specification:
    2882             :  *
    2883             :  *   [MS-SMB2] 3.3.5.14 Receiving an SMB2 LOCK Request
    2884             :  *
    2885             :  *   ...
    2886             :  *
    2887             :  *   ... if Open.IsResilient or Open.IsDurable or Open.IsPersistent is
    2888             :  *   TRUE or if Connection.Dialect belongs to the SMB 3.x dialect family
    2889             :  *   and Connection.ServerCapabilities includes
    2890             :  *   SMB2_GLOBAL_CAP_MULTI_CHANNEL bit, the server SHOULD<314>
    2891             :  *   perform lock sequence verification ...
    2892             :  *
    2893             :  *   ...
    2894             :  *
    2895             :  *   <314> Section 3.3.5.14: Windows 7 and Windows Server 2008 R2 perform
    2896             :  *   lock sequence verification only when Open.IsResilient is TRUE.
    2897             :  *   Windows 8 through Windows 10 v1909 and Windows Server 2012 through
    2898             :  *   Windows Server v1909 perform lock sequence verification only when
    2899             :  *   Open.IsResilient or Open.IsPersistent is TRUE.
    2900             :  *
    2901             :  * Note <314> also applies to all versions (at least) up to Windows Server v2004.
    2902             :  *
    2903             :  * Hopefully this will be fixed in future Windows versions and they
    2904             :  * will avoid Note <314>.
    2905             :  */
    2906           5 : static bool test_replay_broken_windows(struct torture_context *torture,
    2907             :                                        struct smb2_tree *tree)
    2908             : {
    2909           0 :         NTSTATUS status;
    2910           5 :         bool ret = true;
    2911           0 :         struct smb2_handle h;
    2912           0 :         struct smb2_ioctl ioctl;
    2913           0 :         struct smb2_lock lck;
    2914           0 :         struct smb2_lock_element el;
    2915           0 :         uint8_t res_req[8];
    2916           5 :         const char *fname = BASEDIR "\\replay_broken_windows.txt";
    2917           5 :         struct smb2_transport *transport = tree->session->transport;
    2918             : 
    2919           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB2_10) {
    2920           1 :                 torture_skip(torture, "SMB 2.1.0 Dialect family or above \
    2921             :                                 required for Lock Replay tests\n");
    2922             :         }
    2923             : 
    2924           4 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    2925           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2926           4 :         smb2_util_close(tree, h);
    2927             : 
    2928           4 :         torture_comment(torture, "Testing Open File:\n");
    2929           4 :         status = torture_smb2_testfile(tree, fname, &h);
    2930           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2931             : 
    2932             :         /*
    2933             :          * Setup initial parameters
    2934             :          */
    2935           4 :         el = (struct smb2_lock_element) {
    2936             :                 .length = 100,
    2937             :                 .offset = 100,
    2938             :         };
    2939           4 :         lck = (struct smb2_lock) {
    2940             :                 .in.locks = &el,
    2941             :                 .in.lock_count  = 0x0001,
    2942             :                 .in.file.handle = h
    2943             :         };
    2944             : 
    2945           4 :         torture_comment(torture, "Testing Lock Replay detection [ignored]:\n");
    2946           4 :         lck.in.lock_sequence = 0x010 + 0x1;
    2947           4 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    2948           4 :         status = smb2_lock(tree, &lck);
    2949           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    2950           4 :         status = smb2_lock(tree, &lck);
    2951           4 :         if (NT_STATUS_IS_OK(status)) {
    2952           4 :                 lck.in.lock_sequence = 0x020 + 0x2;
    2953           4 :                 status = smb2_lock(tree, &lck);
    2954           4 :                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2955           4 :                 lck.in.lock_sequence = 0x010 + 0x1;
    2956           4 :                 status = smb2_lock(tree, &lck);
    2957           4 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2958           4 :                 if (smbXcli_conn_protocol(transport->conn) > PROTOCOL_SMB2_10) {
    2959           4 :                         torture_skip_goto(torture, done,
    2960             :                                           "SMB3 Server implements LockSequence "
    2961             :                                           "for all handles\n");
    2962             :                 }
    2963             :         }
    2964           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2965           0 :         if (smbXcli_conn_protocol(transport->conn) > PROTOCOL_SMB2_10) {
    2966           0 :                 torture_comment(torture,
    2967             :                                 "\nSMB3 Server implements LockSequence as SMB 2.1.0"
    2968             :                                 " LEGACY BROKEN Windows!!!\n\n");
    2969             :         }
    2970           0 :         torture_comment(torture,
    2971             :                         "Testing SMB 2.1.0 LockSequence for ResilientHandles\n");
    2972             : 
    2973           0 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    2974           0 :         status = smb2_lock(tree, &lck);
    2975           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2976           0 :         status = smb2_lock(tree, &lck);
    2977           0 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    2978             : 
    2979           0 :         torture_comment(torture, "Testing Set Resiliency:\n");
    2980           0 :         SIVAL(res_req, 0, 1000); /* timeout */
    2981           0 :         SIVAL(res_req, 4, 0);    /* reserved */
    2982           0 :         ioctl = (struct smb2_ioctl) {
    2983             :                 .level = RAW_IOCTL_SMB2,
    2984             :                 .in.file.handle = h,
    2985             :                 .in.function = FSCTL_LMR_REQ_RESILIENCY,
    2986             :                 .in.max_output_response = 0,
    2987             :                 .in.flags = SMB2_IOCTL_FLAG_IS_FSCTL,
    2988             :                 .in.out.data = res_req,
    2989             :                 .in.out.length = sizeof(res_req)
    2990             :         };
    2991           0 :         status = smb2_ioctl(tree, torture, &ioctl);
    2992           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2993             : 
    2994             :         /*
    2995             :          * Test with an invalid bucket number (only 1..64 are valid).
    2996             :          * With an invalid number, lock replay detection is not performed.
    2997             :          */
    2998           0 :         torture_comment(torture, "Testing Lock (ignored) Replay detection "
    2999             :                                  "(Bucket No: 0 (invalid)) [ignored]:\n");
    3000           0 :         lck.in.lock_sequence = 0x000 + 0x1;
    3001           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3002           0 :         status = smb2_lock(tree, &lck);
    3003           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3004           0 :         status = smb2_lock(tree, &lck);
    3005           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3006             : 
    3007           0 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3008           0 :         status = smb2_lock(tree, &lck);
    3009           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3010           0 :         status = smb2_lock(tree, &lck);
    3011           0 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    3012             : 
    3013           0 :         torture_comment(torture, "Testing Lock Replay detection "
    3014             :                                  "(Bucket No: 1):\n");
    3015             : 
    3016             :         /*
    3017             :          * Obtain Exclusive Lock of length 100 bytes using Bucket Num 1
    3018             :          * and Bucket Seq 1.
    3019             :          */
    3020           0 :         lck.in.lock_sequence = 0x010 + 0x1;
    3021           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3022           0 :         status = smb2_lock(tree, &lck);
    3023           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3024             : 
    3025             :         /*
    3026             :          * Server detects Replay of Byte Range locks using the Lock Sequence
    3027             :          * Numbers. And ignores the requests completely.
    3028             :          */
    3029           0 :         status = smb2_lock(tree, &lck);
    3030           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3031           0 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3032           0 :         status = smb2_lock(tree, &lck);
    3033           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3034           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3035           0 :         status = smb2_lock(tree, &lck);
    3036           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3037           0 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3038           0 :         status = smb2_lock(tree, &lck);
    3039           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3040           0 :         status = smb2_lock(tree, &lck);
    3041           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3042             : 
    3043             :         /* status: still locked */
    3044             : 
    3045             :         /*
    3046             :          * Server will not grant same Byte Range using a different Bucket Seq
    3047             :          */
    3048           0 :         lck.in.lock_sequence = 0x010 + 0x2;
    3049           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3050           0 :         status = smb2_lock(tree, &lck);
    3051           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3052           0 :         status = smb2_lock(tree, &lck);
    3053           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3054             : 
    3055           0 :         torture_comment(torture, "Testing Lock Replay detection "
    3056             :                                  "(Bucket No: 2):\n");
    3057             : 
    3058             :         /*
    3059             :          * Server will not grant same Byte Range using a different Bucket Num
    3060             :          */
    3061           0 :         lck.in.lock_sequence = 0x020 + 0x1;
    3062           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3063           0 :         status = smb2_lock(tree, &lck);
    3064           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3065           0 :         status = smb2_lock(tree, &lck);
    3066           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3067             : 
    3068             :         /* status: still locked */
    3069             : 
    3070             :         /* test with invalid bucket when file is locked */
    3071             : 
    3072           0 :         torture_comment(torture, "Testing Lock Replay detection "
    3073             :                                  "(Bucket No: 65 (invalid)) [ignored]:\n");
    3074             : 
    3075           0 :         lck.in.lock_sequence = 0x410 + 0x1;
    3076           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3077           0 :         status = smb2_lock(tree, &lck);
    3078           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3079           0 :         status = smb2_lock(tree, &lck);
    3080           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3081             : 
    3082           0 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3083           0 :         status = smb2_lock(tree, &lck);
    3084           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3085           0 :         status = smb2_lock(tree, &lck);
    3086           0 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    3087             : 
    3088             :         /* status: unlocked */
    3089             : 
    3090             :         /*
    3091             :          * Lock again for the unlock replay test
    3092             :          */
    3093           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3094           0 :         status = smb2_lock(tree, &lck);
    3095           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3096             : 
    3097           0 :         torture_comment(torture, "Testing Lock Replay detection "
    3098             :                                  "(Bucket No: 64):\n");
    3099             : 
    3100             :         /*
    3101             :          * Server will not grant same Byte Range using a different Bucket Num
    3102             :          */
    3103           0 :         lck.in.lock_sequence = 0x400 + 0x1;
    3104           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3105           0 :         status = smb2_lock(tree, &lck);
    3106           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3107           0 :         status = smb2_lock(tree, &lck);
    3108           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3109             : 
    3110             :         /*
    3111             :          * Test Unlock replay detection
    3112             :          */
    3113           0 :         lck.in.lock_sequence = 0x400 + 0x2;
    3114           0 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3115           0 :         status = smb2_lock(tree, &lck);
    3116           0 :         CHECK_STATUS(status, NT_STATUS_OK); /* new seq num ==> unlocked */
    3117           0 :         status = smb2_lock(tree, &lck);
    3118           0 :         CHECK_STATUS(status, NT_STATUS_OK); /* replay detected ==> ignored */
    3119             : 
    3120           0 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3121           0 :         status = smb2_lock(tree, &lck);     /* same seq num ==> ignored */
    3122           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3123             : 
    3124             :         /* verify it's unlocked: */
    3125           0 :         lck.in.lock_sequence = 0x400 + 0x3;
    3126           0 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3127           0 :         status = smb2_lock(tree, &lck);
    3128           0 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    3129             : 
    3130             :         /* status: not locked */
    3131             : 
    3132           4 : done:
    3133           4 :         smb2_util_close(tree, h);
    3134           4 :         smb2_deltree(tree, BASEDIR);
    3135           4 :         return ret;
    3136             : }
    3137             : 
    3138             : /**
    3139             :  * Test lock replay detection
    3140             :  *
    3141             :  * This test check the SMB 3 behaviour of lock sequence checking,
    3142             :  * which should be implemented for all handles.
    3143             :  *
    3144             :  * Make it clear that this test is supposed to pass a
    3145             :  * server implementing the specification:
    3146             :  *
    3147             :  *   [MS-SMB2] 3.3.5.14 Receiving an SMB2 LOCK Request
    3148             :  *
    3149             :  *   ...
    3150             :  *
    3151             :  *   ... if Open.IsResilient or Open.IsDurable or Open.IsPersistent is
    3152             :  *   TRUE or if Connection.Dialect belongs to the SMB 3.x dialect family
    3153             :  *   and Connection.ServerCapabilities includes
    3154             :  *   SMB2_GLOBAL_CAP_MULTI_CHANNEL bit, the server SHOULD<314>
    3155             :  *   perform lock sequence verification ...
    3156             :  *
    3157             :  *   ...
    3158             :  *
    3159             :  *   <314> Section 3.3.5.14: Windows 7 and Windows Server 2008 R2 perform
    3160             :  *   lock sequence verification only when Open.IsResilient is TRUE.
    3161             :  *   Windows 8 through Windows 10 v1909 and Windows Server 2012 through
    3162             :  *   Windows Server v1909 perform lock sequence verification only when
    3163             :  *   Open.IsResilient or Open.IsPersistent is TRUE.
    3164             :  *
    3165             :  * Note <314> also applies to all versions (at least) up to Windows Server v2004.
    3166             :  *
    3167             :  * Hopefully this will be fixed in future Windows versions and they
    3168             :  * will avoid Note <314>.
    3169             :  */
    3170           8 : static bool _test_replay_smb3_specification(struct torture_context *torture,
    3171             :                                             struct smb2_tree *tree,
    3172             :                                             const char *testname,
    3173             :                                             bool use_durable)
    3174             : {
    3175           0 :         NTSTATUS status;
    3176           8 :         bool ret = true;
    3177           0 :         struct smb2_create io;
    3178           0 :         struct smb2_handle h;
    3179           0 :         struct smb2_lock lck;
    3180           0 :         struct smb2_lock_element el;
    3181           0 :         char fname[256];
    3182           8 :         struct smb2_transport *transport = tree->session->transport;
    3183             : 
    3184           8 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
    3185           0 :                 torture_skip(torture, "SMB 3.0.0 Dialect family or above \
    3186             :                                 required for Lock Replay tests\n");
    3187             :         }
    3188             : 
    3189           8 :         snprintf(fname, sizeof(fname), "%s\\%s.dat", BASEDIR, testname);
    3190             : 
    3191           8 :         status = torture_smb2_testdir(tree, BASEDIR, &h);
    3192           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3193           8 :         smb2_util_close(tree, h);
    3194             : 
    3195           8 :         torture_comment(torture, "%s: Testing Open File:\n", testname);
    3196             : 
    3197           8 :         smb2_oplock_create_share(&io, fname,
    3198             :                                  smb2_util_share_access(""),
    3199           8 :                                  smb2_util_oplock_level("b"));
    3200           8 :         io.in.durable_open = use_durable;
    3201             : 
    3202           8 :         status = smb2_create(tree, torture, &io);
    3203           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3204           8 :         h = io.out.file.handle;
    3205           8 :         CHECK_VALUE(io.out.oplock_level, smb2_util_oplock_level("b"));
    3206           8 :         CHECK_VALUE(io.out.durable_open, use_durable);
    3207           8 :         CHECK_VALUE(io.out.durable_open_v2, false);
    3208           8 :         CHECK_VALUE(io.out.persistent_open, false);
    3209             : 
    3210             :         /*
    3211             :          * Setup initial parameters
    3212             :          */
    3213           8 :         el = (struct smb2_lock_element) {
    3214             :                 .length = 100,
    3215             :                 .offset = 100,
    3216             :         };
    3217           8 :         lck = (struct smb2_lock) {
    3218             :                 .in.locks = &el,
    3219             :                 .in.lock_count  = 0x0001,
    3220             :                 .in.file.handle = h
    3221             :         };
    3222             : 
    3223           8 :         torture_comment(torture,
    3224             :                         "Testing SMB 3 LockSequence for all Handles\n");
    3225             : 
    3226             :         /*
    3227             :          * Test with an invalid bucket number (only 1..64 are valid).
    3228             :          * With an invalid number, lock replay detection is not performed.
    3229             :          */
    3230           8 :         torture_comment(torture, "Testing Lock (ignored) Replay detection "
    3231             :                                  "(Bucket No: 0 (invalid)) [ignored]:\n");
    3232           8 :         lck.in.lock_sequence = 0x000 + 0x1;
    3233           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3234           8 :         status = smb2_lock(tree, &lck);
    3235           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3236           8 :         status = smb2_lock(tree, &lck);
    3237           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3238             : 
    3239           8 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3240           8 :         status = smb2_lock(tree, &lck);
    3241           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3242           8 :         status = smb2_lock(tree, &lck);
    3243           8 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    3244             : 
    3245           8 :         torture_comment(torture, "Testing Lock Replay detection "
    3246             :                                  "(Bucket No: 1):\n");
    3247             : 
    3248             :         /*
    3249             :          * Obtain Exclusive Lock of length 100 bytes using Bucket Num 1
    3250             :          * and Bucket Seq 1.
    3251             :          */
    3252           8 :         lck.in.lock_sequence = 0x010 + 0x1;
    3253           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3254           8 :         status = smb2_lock(tree, &lck);
    3255           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3256             : 
    3257             :         /*
    3258             :          * Server detects Replay of Byte Range locks using the Lock Sequence
    3259             :          * Numbers. And ignores the requests completely.
    3260             :          */
    3261           8 :         status = smb2_lock(tree, &lck);
    3262           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3263           8 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3264           8 :         status = smb2_lock(tree, &lck);
    3265           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3266           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3267           8 :         status = smb2_lock(tree, &lck);
    3268           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3269           8 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3270           8 :         status = smb2_lock(tree, &lck);
    3271           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3272           8 :         status = smb2_lock(tree, &lck);
    3273           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3274             : 
    3275             :         /* status: still locked */
    3276             : 
    3277             :         /*
    3278             :          * Server will not grant same Byte Range using a different Bucket Seq
    3279             :          */
    3280           8 :         lck.in.lock_sequence = 0x010 + 0x2;
    3281           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3282           8 :         status = smb2_lock(tree, &lck);
    3283           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3284           8 :         status = smb2_lock(tree, &lck);
    3285           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3286             : 
    3287           8 :         torture_comment(torture, "Testing Lock Replay detection "
    3288             :                                  "(Bucket No: 2):\n");
    3289             : 
    3290             :         /*
    3291             :          * Server will not grant same Byte Range using a different Bucket Num
    3292             :          */
    3293           8 :         lck.in.lock_sequence = 0x020 + 0x1;
    3294           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3295           8 :         status = smb2_lock(tree, &lck);
    3296           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3297           8 :         status = smb2_lock(tree, &lck);
    3298           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3299             : 
    3300             :         /* status: still locked */
    3301             : 
    3302             :         /* test with invalid bucket when file is locked */
    3303             : 
    3304           8 :         torture_comment(torture, "Testing Lock Replay detection "
    3305             :                                  "(Bucket No: 65 (invalid)) [ignored]:\n");
    3306             : 
    3307           8 :         lck.in.lock_sequence = 0x410 + 0x1;
    3308           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3309           8 :         status = smb2_lock(tree, &lck);
    3310           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3311           8 :         status = smb2_lock(tree, &lck);
    3312           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3313             : 
    3314           8 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3315           8 :         status = smb2_lock(tree, &lck);
    3316           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3317           8 :         status = smb2_lock(tree, &lck);
    3318           8 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    3319             : 
    3320             :         /* status: unlocked */
    3321             : 
    3322             :         /*
    3323             :          * Lock again for the unlock replay test
    3324             :          */
    3325           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3326           8 :         status = smb2_lock(tree, &lck);
    3327           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3328             : 
    3329           8 :         torture_comment(torture, "Testing Lock Replay detection "
    3330             :                                  "(Bucket No: 64):\n");
    3331             : 
    3332             :         /*
    3333             :          * Server will not grant same Byte Range using a different Bucket Num
    3334             :          */
    3335           8 :         lck.in.lock_sequence = 0x400 + 0x1;
    3336           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3337           8 :         status = smb2_lock(tree, &lck);
    3338           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3339           8 :         status = smb2_lock(tree, &lck);
    3340           8 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3341             : 
    3342             :         /*
    3343             :          * Test Unlock replay detection
    3344             :          */
    3345           8 :         lck.in.lock_sequence = 0x400 + 0x2;
    3346           8 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3347           8 :         status = smb2_lock(tree, &lck);
    3348           8 :         CHECK_STATUS(status, NT_STATUS_OK); /* new seq num ==> unlocked */
    3349           8 :         status = smb2_lock(tree, &lck);
    3350           8 :         CHECK_STATUS(status, NT_STATUS_OK); /* replay detected ==> ignored */
    3351             : 
    3352           8 :         el.flags = SMB2_LOCK_FLAG_EXCLUSIVE | SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    3353           8 :         status = smb2_lock(tree, &lck);     /* same seq num ==> ignored */
    3354           8 :         CHECK_STATUS(status, NT_STATUS_OK);
    3355             : 
    3356             :         /* verify it's unlocked: */
    3357           8 :         lck.in.lock_sequence = 0x400 + 0x3;
    3358           8 :         el.flags = SMB2_LOCK_FLAG_UNLOCK;
    3359           8 :         status = smb2_lock(tree, &lck);
    3360           8 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    3361             : 
    3362             :         /* status: not locked */
    3363             : 
    3364           8 : done:
    3365           8 :         smb2_util_close(tree, h);
    3366           8 :         smb2_deltree(tree, BASEDIR);
    3367           8 :         return ret;
    3368             : }
    3369             : 
    3370           5 : static bool test_replay_smb3_specification_durable(struct torture_context *torture,
    3371             :                                                    struct smb2_tree *tree)
    3372             : {
    3373           5 :         const char *testname = "replay_smb3_specification_durable";
    3374           5 :         struct smb2_transport *transport = tree->session->transport;
    3375             : 
    3376           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB2_10) {
    3377           1 :                 torture_skip(torture, "SMB 2.1.0 Dialect family or above \
    3378             :                                 required for Lock Replay tests on durable handles\n");
    3379             :         }
    3380             : 
    3381           4 :         return _test_replay_smb3_specification(torture, tree, testname, true);
    3382             : }
    3383             : 
    3384           5 : static bool test_replay_smb3_specification_multi(struct torture_context *torture,
    3385             :                                                  struct smb2_tree *tree)
    3386             : {
    3387           5 :         const char *testname = "replay_smb3_specification_multi";
    3388           5 :         struct smb2_transport *transport = tree->session->transport;
    3389           0 :         uint32_t server_capabilities;
    3390             : 
    3391           5 :         if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) {
    3392           1 :                 torture_skip(torture, "SMB 3.0.0 Dialect family or above \
    3393             :                         required for Lock Replay tests on without durable handles\n");
    3394             :         }
    3395             : 
    3396           4 :         server_capabilities = smb2cli_conn_server_capabilities(transport->conn);
    3397           4 :         if (!(server_capabilities & SMB2_CAP_MULTI_CHANNEL)) {
    3398           0 :                 torture_skip(torture, "MULTI_CHANNEL is \
    3399             :                         required for Lock Replay tests on without durable handles\n");
    3400             :         }
    3401             : 
    3402           4 :         return _test_replay_smb3_specification(torture, tree, testname, false);
    3403             : }
    3404             : 
    3405             : /**
    3406             :  * Test lock interaction between smbd and ctdb with tombstone records.
    3407             :  *
    3408             :  * Re-locking an unlocked record could lead to a deadlock between
    3409             :  * smbd and ctdb. Make sure we don't regress.
    3410             :  *
    3411             :  * https://bugzilla.samba.org/show_bug.cgi?id=12005
    3412             :  * https://bugzilla.samba.org/show_bug.cgi?id=10008
    3413             :  */
    3414           5 : static bool test_deadlock(struct torture_context *torture,
    3415             :                           struct smb2_tree *tree)
    3416             : {
    3417           0 :         NTSTATUS status;
    3418           5 :         bool ret = true;
    3419           0 :         struct smb2_handle _h;
    3420           5 :         struct smb2_handle *h = NULL;
    3421           0 :         uint8_t buf[200];
    3422           5 :         const char *fname = BASEDIR "\\deadlock.txt";
    3423             : 
    3424           5 :         if (!lpcfg_clustering(torture->lp_ctx)) {
    3425           5 :                 torture_skip(torture, "Test must be run on a ctdb cluster\n");
    3426             :                 return true;
    3427             :         }
    3428             : 
    3429           0 :         status = torture_smb2_testdir(tree, BASEDIR, &_h);
    3430           0 :         torture_assert_ntstatus_ok(torture, status,
    3431             :                                    "torture_smb2_testdir failed");
    3432           0 :         smb2_util_close(tree, _h);
    3433             : 
    3434           0 :         status = torture_smb2_testfile(tree, fname, &_h);
    3435           0 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    3436             :                                         "torture_smb2_testfile failed");
    3437           0 :         h = &_h;
    3438             : 
    3439           0 :         ZERO_STRUCT(buf);
    3440           0 :         status = smb2_util_write(tree, *h, buf, 0, ARRAY_SIZE(buf));
    3441           0 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    3442             :                                         "smb2_util_write failed");
    3443             : 
    3444           0 :         status = test_smb2_lock(tree, *h, 0, 1, true);
    3445           0 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    3446             :                                         "test_smb2_lock failed");
    3447             : 
    3448           0 :         status = test_smb2_unlock(tree, *h, 0, 1);
    3449           0 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    3450             :                                         "test_smb2_unlock failed");
    3451             : 
    3452           0 :         status = test_smb2_lock(tree, *h, 0, 1, true);
    3453           0 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    3454             :                                         "test_smb2_lock failed");
    3455             : 
    3456           0 :         status = test_smb2_unlock(tree, *h, 0, 1);
    3457           0 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    3458             :                                         "test_smb2_unlock failed");
    3459             : 
    3460           0 : done:
    3461           0 :         if (h != NULL) {
    3462           0 :                 smb2_util_close(tree, *h);
    3463             :         }
    3464           0 :         smb2_deltree(tree, BASEDIR);
    3465           0 :         return ret;
    3466             : }
    3467             : 
    3468             : /* basic testing of SMB2 locking
    3469             : */
    3470        2358 : struct torture_suite *torture_smb2_lock_init(TALLOC_CTX *ctx)
    3471             : {
    3472         125 :         struct torture_suite *suite =
    3473        2358 :             torture_suite_create(ctx, "lock");
    3474        2358 :         torture_suite_add_1smb2_test(suite, "valid-request",
    3475             :             test_valid_request);
    3476        2358 :         torture_suite_add_1smb2_test(suite, "rw-none", test_lock_rw_none);
    3477        2358 :         torture_suite_add_1smb2_test(suite, "rw-shared", test_lock_rw_shared);
    3478        2358 :         torture_suite_add_1smb2_test(suite, "rw-exclusive",
    3479             :             test_lock_rw_exclusive);
    3480        2358 :         torture_suite_add_1smb2_test(suite, "auto-unlock",
    3481             :             test_lock_auto_unlock);
    3482        2358 :         torture_suite_add_1smb2_test(suite, "lock", test_lock);
    3483        2358 :         torture_suite_add_1smb2_test(suite, "async", test_async);
    3484        2358 :         torture_suite_add_1smb2_test(suite, "cancel", test_cancel);
    3485        2358 :         torture_suite_add_1smb2_test(suite, "cancel-tdis", test_cancel_tdis);
    3486        2358 :         torture_suite_add_1smb2_test(suite, "cancel-logoff",
    3487             :             test_cancel_logoff);
    3488        2358 :         torture_suite_add_1smb2_test(suite, "errorcode", test_errorcode);
    3489        2358 :         torture_suite_add_1smb2_test(suite, "zerobytelength",
    3490             :             test_zerobytelength);
    3491        2358 :         torture_suite_add_1smb2_test(suite, "zerobyteread",
    3492             :             test_zerobyteread);
    3493        2358 :         torture_suite_add_1smb2_test(suite, "unlock", test_unlock);
    3494        2358 :         torture_suite_add_1smb2_test(suite, "multiple-unlock",
    3495             :             test_multiple_unlock);
    3496        2358 :         torture_suite_add_1smb2_test(suite, "stacking", test_stacking);
    3497        2358 :         torture_suite_add_1smb2_test(suite, "contend", test_contend);
    3498        2358 :         torture_suite_add_1smb2_test(suite, "context", test_context);
    3499        2358 :         torture_suite_add_1smb2_test(suite, "range", test_range);
    3500        2358 :         torture_suite_add_2smb2_test(suite, "overlap", test_overlap);
    3501        2358 :         torture_suite_add_1smb2_test(suite, "truncate", test_truncate);
    3502        2358 :         torture_suite_add_1smb2_test(suite, "replay_broken_windows",
    3503             :                                      test_replay_broken_windows);
    3504        2358 :         torture_suite_add_1smb2_test(suite, "replay_smb3_specification_durable",
    3505             :                                      test_replay_smb3_specification_durable);
    3506        2358 :         torture_suite_add_1smb2_test(suite, "replay_smb3_specification_multi",
    3507             :                                      test_replay_smb3_specification_multi);
    3508        2358 :         torture_suite_add_1smb2_test(suite, "ctdb-delrec-deadlock", test_deadlock);
    3509             : 
    3510        2358 :         suite->description = talloc_strdup(suite, "SMB2-LOCK tests");
    3511             : 
    3512        2358 :         return suite;
    3513             : }

Generated by: LCOV version 1.14