LCOV - code coverage report
Current view: top level - source4/torture/smb2 - rename.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 838 1005 83.4 %
Date: 2024-04-21 15:09:00 Functions: 25 25 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    SMB2 rename test suite
       5             : 
       6             :    Copyright (C) Christian Ambach 2012
       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 <tevent.h>
      26             : #include "lib/util/tevent_ntstatus.h"
      27             : 
      28             : #include "torture/torture.h"
      29             : #include "torture/util.h"
      30             : #include "torture/smb2/proto.h"
      31             : 
      32             : #include "librpc/gen_ndr/security.h"
      33             : 
      34             : #define CHECK_VAL(v, correct) \
      35             :         do { \
      36             :                 if ((v) != (correct)) { \
      37             :                         torture_result(torture, \
      38             :                                 TORTURE_FAIL, \
      39             :                                 "(%s): wrong value for %s got " \
      40             :                                 "0x%llx - should be 0x%llx\n", \
      41             :                                 __location__, #v, \
      42             :                                 (unsigned long long)v, \
      43             :                                 (unsigned long long)correct); \
      44             :                         ret = false; \
      45             :                         goto done; \
      46             :         }} while (0)
      47             : 
      48             : #define CHECK_CREATED(__io, __created, __attribute)                     \
      49             :         do {                                                            \
      50             :                 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
      51             :                 CHECK_VAL((__io)->out.size, 0);                         \
      52             :                 CHECK_VAL((__io)->out.file_attr, (__attribute));        \
      53             :                 CHECK_VAL((__io)->out.reserved2, 0);                    \
      54             :         } while(0)
      55             : 
      56             : #define CHECK_STATUS(status, correct) do { \
      57             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      58             :                 torture_result(torture, TORTURE_FAIL, \
      59             :                        "(%s) Incorrect status %s - should be %s\n", \
      60             :                        __location__, nt_errstr(status), nt_errstr(correct)); \
      61             :                 ret = false; \
      62             :                 goto done; \
      63             :         }} while (0)
      64             : 
      65             : #define BASEDIR "test_rename"
      66             : 
      67             : /*
      68             :  * basic testing of rename: open file with DELETE access
      69             :  * this should pass
      70             :  */
      71             : 
      72           2 : static bool torture_smb2_rename_simple(struct torture_context *torture,
      73             :                 struct smb2_tree *tree1)
      74             : {
      75           2 :         bool ret = true;
      76           0 :         NTSTATUS status;
      77           0 :         union smb_open io;
      78           0 :         union smb_close cl;
      79           0 :         union smb_setfileinfo sinfo;
      80           0 :         union smb_fileinfo fi;
      81           0 :         struct smb2_handle h1;
      82             : 
      83           2 :         ZERO_STRUCT(h1);
      84             : 
      85           2 :         smb2_deltree(tree1, BASEDIR);
      86           2 :         smb2_util_rmdir(tree1, BASEDIR);
      87             : 
      88           2 :         torture_comment(torture, "Creating base directory\n");
      89             : 
      90           2 :         smb2_util_mkdir(tree1, BASEDIR);
      91             : 
      92             : 
      93           2 :         torture_comment(torture, "Creating test file\n");
      94             : 
      95           2 :         ZERO_STRUCT(io.smb2);
      96           2 :         io.generic.level = RAW_OPEN_SMB2;
      97           2 :         io.smb2.in.create_flags = 0;
      98           2 :         io.smb2.in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE;
      99           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     100           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     101           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     102             :                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
     103           2 :         io.smb2.in.alloc_size = 0;
     104           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     105           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     106           2 :         io.smb2.in.security_flags = 0;
     107           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
     108             : 
     109           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     110           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     111           2 :         h1 = io.smb2.out.file.handle;
     112             : 
     113           2 :         torture_comment(torture, "Renaming test file\n");
     114             : 
     115           2 :         ZERO_STRUCT(sinfo);
     116           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     117           2 :         sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
     118           2 :         sinfo.rename_information.in.overwrite = 0;
     119           2 :         sinfo.rename_information.in.root_fid = 0;
     120           2 :         sinfo.rename_information.in.new_name =
     121             :                 BASEDIR "\\newname.txt";
     122           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     123           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     124             : 
     125           2 :         torture_comment(torture, "Checking for new filename\n");
     126             : 
     127           2 :         ZERO_STRUCT(fi);
     128           2 :         fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
     129           2 :         fi.generic.in.file.handle = h1;
     130           2 :         status = smb2_getinfo_file(tree1, torture, &fi);
     131           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     132             : 
     133             : 
     134           2 :         torture_comment(torture, "Closing test file\n");
     135             : 
     136           2 :         ZERO_STRUCT(cl.smb2);
     137           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     138           2 :         cl.smb2.in.file.handle = h1;
     139           2 :         status = smb2_close(tree1, &(cl.smb2));
     140           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     141             : 
     142           2 :         ZERO_STRUCT(h1);
     143             : 
     144           2 : done:
     145             : 
     146           2 :         torture_comment(torture, "Cleaning up\n");
     147             : 
     148           2 :         if (h1.data[0] || h1.data[1]) {
     149           0 :                 ZERO_STRUCT(cl.smb2);
     150           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     151           0 :                 cl.smb2.in.file.handle = h1;
     152           0 :                 status = smb2_close(tree1, &(cl.smb2));
     153             :         }
     154           2 :         smb2_deltree(tree1, BASEDIR);
     155           2 :         return ret;
     156             : }
     157             : 
     158             : /*
     159             :  * basic testing of rename, this time do not request DELETE access
     160             :  * for the file, this should fail
     161             :  */
     162             : 
     163           2 : static bool torture_smb2_rename_simple2(struct torture_context *torture,
     164             :                 struct smb2_tree *tree1)
     165             : {
     166           2 :         bool ret = true;
     167           0 :         NTSTATUS status;
     168           0 :         union smb_open io;
     169           0 :         union smb_close cl;
     170           0 :         union smb_setfileinfo sinfo;
     171           0 :         struct smb2_handle h1;
     172             : 
     173           2 :         ZERO_STRUCT(h1);
     174             : 
     175           2 :         smb2_deltree(tree1, BASEDIR);
     176           2 :         smb2_util_rmdir(tree1, BASEDIR);
     177             : 
     178           2 :         torture_comment(torture, "Creating base directory\n");
     179             : 
     180           2 :         smb2_util_mkdir(tree1, BASEDIR);
     181             : 
     182             : 
     183           2 :         torture_comment(torture, "Creating test file\n");
     184             : 
     185           2 :         ZERO_STRUCT(io.smb2);
     186           2 :         io.generic.level = RAW_OPEN_SMB2;
     187           2 :         io.smb2.in.create_flags = 0;
     188           2 :         io.smb2.in.desired_access = SEC_FILE_ALL;
     189           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     190           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     191           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     192             :                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
     193           2 :         io.smb2.in.alloc_size = 0;
     194           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     195           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     196           2 :         io.smb2.in.security_flags = 0;
     197           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
     198             : 
     199           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     200           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     201           2 :         h1 = io.smb2.out.file.handle;
     202             : 
     203           2 :         torture_comment(torture, "Renaming test file\n");
     204             : 
     205           2 :         ZERO_STRUCT(sinfo);
     206           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     207           2 :         sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
     208           2 :         sinfo.rename_information.in.overwrite = 0;
     209           2 :         sinfo.rename_information.in.root_fid = 0;
     210           2 :         sinfo.rename_information.in.new_name =
     211             :                 BASEDIR "\\newname.txt";
     212           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     213           2 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
     214             : 
     215           0 :         torture_comment(torture, "Closing test file\n");
     216             : 
     217           0 :         ZERO_STRUCT(cl.smb2);
     218           0 :         cl.smb2.level = RAW_CLOSE_SMB2;
     219           0 :         cl.smb2.in.file.handle = h1;
     220           0 :         status = smb2_close(tree1, &(cl.smb2));
     221           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     222             : 
     223           0 :         ZERO_STRUCT(h1);
     224             : 
     225           2 : done:
     226             : 
     227           2 :         torture_comment(torture, "Cleaning up\n");
     228             : 
     229           2 :         if (h1.data[0] || h1.data[1]) {
     230           2 :                 ZERO_STRUCT(cl.smb2);
     231           2 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     232           2 :                 cl.smb2.in.file.handle = h1;
     233           2 :                 status = smb2_close(tree1, &(cl.smb2));
     234             :         }
     235           2 :         smb2_deltree(tree1, BASEDIR);
     236           2 :         return ret;
     237             : }
     238             : 
     239             : 
     240             : /*
     241             :  * testing of rename with no sharing allowed on file
     242             :  * this should work
     243             :  */
     244             : 
     245           2 : static bool torture_smb2_rename_no_sharemode(struct torture_context *torture,
     246             :                 struct smb2_tree *tree1)
     247             : {
     248           2 :         bool ret = true;
     249           0 :         NTSTATUS status;
     250           0 :         union smb_open io;
     251           0 :         union smb_close cl;
     252           0 :         union smb_setfileinfo sinfo;
     253           0 :         union smb_fileinfo fi;
     254           0 :         struct smb2_handle h1;
     255             : 
     256           2 :         ZERO_STRUCT(h1);
     257             : 
     258           2 :         smb2_deltree(tree1, BASEDIR);
     259           2 :         smb2_util_rmdir(tree1, BASEDIR);
     260             : 
     261           2 :         torture_comment(torture, "Creating base directory\n");
     262             : 
     263           2 :         smb2_util_mkdir(tree1, BASEDIR);
     264             : 
     265             : 
     266           2 :         torture_comment(torture, "Creating test file\n");
     267             : 
     268           2 :         ZERO_STRUCT(io.smb2);
     269           2 :         io.generic.level = RAW_OPEN_SMB2;
     270           2 :         io.smb2.in.create_flags = 0;
     271           2 :         io.smb2.in.desired_access = 0x0017019f;
     272           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     273           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     274           2 :         io.smb2.in.share_access = 0;
     275           2 :         io.smb2.in.alloc_size = 0;
     276           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     277           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     278           2 :         io.smb2.in.security_flags = 0;
     279           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
     280             : 
     281           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     282           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     283           2 :         h1 = io.smb2.out.file.handle;
     284             : 
     285           2 :         torture_comment(torture, "Renaming test file\n");
     286             : 
     287           2 :         ZERO_STRUCT(sinfo);
     288           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     289           2 :         sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
     290           2 :         sinfo.rename_information.in.overwrite = 0;
     291           2 :         sinfo.rename_information.in.root_fid = 0;
     292           2 :         sinfo.rename_information.in.new_name =
     293             :                 BASEDIR "\\newname.txt";
     294           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     295           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     296             : 
     297           2 :         torture_comment(torture, "Checking for new filename\n");
     298             : 
     299           2 :         ZERO_STRUCT(fi);
     300           2 :         fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
     301           2 :         fi.generic.in.file.handle = h1;
     302           2 :         status = smb2_getinfo_file(tree1, torture, &fi);
     303           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     304             : 
     305             : 
     306           2 :         torture_comment(torture, "Closing test file\n");
     307             : 
     308           2 :         ZERO_STRUCT(cl.smb2);
     309           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     310           2 :         cl.smb2.in.file.handle = h1;
     311           2 :         status = smb2_close(tree1, &(cl.smb2));
     312           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     313             : 
     314           2 :         ZERO_STRUCT(h1);
     315             : 
     316           2 : done:
     317             : 
     318           2 :         torture_comment(torture, "Cleaning up\n");
     319             : 
     320           2 :         if (h1.data[0] || h1.data[1]) {
     321           0 :                 ZERO_STRUCT(cl.smb2);
     322           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     323           0 :                 cl.smb2.in.file.handle = h1;
     324           0 :                 status = smb2_close(tree1, &(cl.smb2));
     325             :         }
     326           2 :         smb2_deltree(tree1, BASEDIR);
     327           2 :         return ret;
     328             : }
     329             : 
     330             : /*
     331             :  * testing of rename when opening parent dir with delete access and delete
     332             :  * sharing allowed
     333             :  * should result in sharing violation
     334             :  */
     335             : 
     336           2 : static bool torture_smb2_rename_with_delete_access(struct torture_context *torture,
     337             :                 struct smb2_tree *tree1)
     338             : {
     339           2 :         bool ret = true;
     340           0 :         NTSTATUS status;
     341           0 :         union smb_open io;
     342           0 :         union smb_close cl;
     343           0 :         union smb_setfileinfo sinfo;
     344           0 :         struct smb2_handle fh, dh;
     345             : 
     346           2 :         ZERO_STRUCT(fh);
     347           2 :         ZERO_STRUCT(dh);
     348             : 
     349           2 :         smb2_deltree(tree1, BASEDIR);
     350           2 :         smb2_util_rmdir(tree1, BASEDIR);
     351             : 
     352           2 :         torture_comment(torture, "Creating base directory\n");
     353             : 
     354           2 :         smb2_util_mkdir(tree1, BASEDIR);
     355             : 
     356           2 :         torture_comment(torture, "Opening parent directory\n");
     357             : 
     358           2 :         ZERO_STRUCT(io.smb2);
     359           2 :         io.generic.level = RAW_OPEN_SMB2;
     360           2 :         io.smb2.in.create_flags = 0;
     361           2 :         io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
     362             :                 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
     363             :                 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
     364             :                 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
     365             :                 SEC_FILE_WRITE_DATA;
     366           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     367           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
     368           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     369             :                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
     370           2 :         io.smb2.in.alloc_size = 0;
     371           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     372           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     373           2 :         io.smb2.in.security_flags = 0;
     374           2 :         io.smb2.in.fname = BASEDIR;
     375             : 
     376           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     377           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     378           2 :         dh = io.smb2.out.file.handle;
     379             : 
     380             : 
     381           2 :         torture_comment(torture, "Creating test file\n");
     382             : 
     383           2 :         ZERO_STRUCT(io.smb2);
     384           2 :         io.generic.level = RAW_OPEN_SMB2;
     385           2 :         io.smb2.in.create_flags = 0;
     386           2 :         io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
     387             :                 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
     388             :                 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
     389             :                 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
     390           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     391           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     392           2 :         io.smb2.in.share_access = 0;
     393           2 :         io.smb2.in.alloc_size = 0;
     394           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     395           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     396           2 :         io.smb2.in.security_flags = 0;
     397           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
     398             : 
     399           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     400           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     401           2 :         fh = io.smb2.out.file.handle;
     402             : 
     403           2 :         torture_comment(torture, "Renaming test file\n");
     404             : 
     405           2 :         ZERO_STRUCT(sinfo);
     406           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     407           2 :         sinfo.rename_information.in.file.handle = fh;
     408           2 :         sinfo.rename_information.in.overwrite = 0;
     409           2 :         sinfo.rename_information.in.root_fid = 0;
     410           2 :         sinfo.rename_information.in.new_name =
     411             :                 BASEDIR "\\newname.txt";
     412           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     413           2 :         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
     414             : 
     415           2 :         torture_comment(torture, "Closing test file\n");
     416             : 
     417           2 :         ZERO_STRUCT(cl.smb2);
     418           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     419           2 :         cl.smb2.in.file.handle = fh;
     420           2 :         status = smb2_close(tree1, &(cl.smb2));
     421           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     422             : 
     423           2 :         ZERO_STRUCT(fh);
     424             : 
     425           2 :         torture_comment(torture, "Closing directory\n");
     426             : 
     427           2 :         ZERO_STRUCT(cl.smb2);
     428           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     429           2 :         cl.smb2.in.file.handle = dh;
     430           2 :         status = smb2_close(tree1, &(cl.smb2));
     431           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     432             : 
     433           2 :         ZERO_STRUCT(dh);
     434             : 
     435             : 
     436           2 : done:
     437             : 
     438           2 :         torture_comment(torture, "Cleaning up\n");
     439             : 
     440           2 :         if (fh.data[0] || fh.data[1]) {
     441           0 :                 ZERO_STRUCT(cl.smb2);
     442           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     443           0 :                 cl.smb2.in.file.handle = fh;
     444           0 :                 status = smb2_close(tree1, &(cl.smb2));
     445             :         }
     446           2 :         if (dh.data[0] || dh.data[1]) {
     447           0 :                 ZERO_STRUCT(cl.smb2);
     448           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     449           0 :                 cl.smb2.in.file.handle = dh;
     450           0 :                 status = smb2_close(tree1, &(cl.smb2));
     451             :         }
     452             : 
     453           2 :         smb2_deltree(tree1, BASEDIR);
     454           2 :         return ret;
     455             : }
     456             : 
     457             : 
     458             : /*
     459             :  * testing of rename with delete access on parent dir
     460             :  * this is a variation of the test above: parent dir is opened
     461             :  * without share_delete, so rename must fail
     462             :  */
     463             : 
     464           2 : static bool torture_smb2_rename_with_delete_access2(struct torture_context *torture,
     465             :                 struct smb2_tree *tree1)
     466             : {
     467           2 :         bool ret = true;
     468           0 :         NTSTATUS status;
     469           0 :         union smb_open io;
     470           0 :         union smb_close cl;
     471           0 :         union smb_setfileinfo sinfo;
     472           0 :         struct smb2_handle fh, dh;
     473             : 
     474           2 :         ZERO_STRUCT(fh);
     475           2 :         ZERO_STRUCT(dh);
     476             : 
     477           2 :         smb2_deltree(tree1, BASEDIR);
     478           2 :         smb2_util_rmdir(tree1, BASEDIR);
     479             : 
     480           2 :         torture_comment(torture, "Creating base directory\n");
     481             : 
     482           2 :         smb2_util_mkdir(tree1, BASEDIR);
     483             : 
     484           2 :         torture_comment(torture, "Opening parent directory\n");
     485             : 
     486           2 :         ZERO_STRUCT(io.smb2);
     487           2 :         io.generic.level = RAW_OPEN_SMB2;
     488           2 :         io.smb2.in.create_flags = 0;
     489           2 :         io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
     490             :                 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
     491             :                 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
     492             :                 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
     493             :                 SEC_FILE_WRITE_DATA;
     494           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     495           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
     496           2 :         io.smb2.in.share_access = 0;
     497           2 :         io.smb2.in.alloc_size = 0;
     498           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     499           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     500           2 :         io.smb2.in.security_flags = 0;
     501           2 :         io.smb2.in.fname = BASEDIR;
     502             : 
     503           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     504           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     505           2 :         dh = io.smb2.out.file.handle;
     506             : 
     507             : 
     508           2 :         torture_comment(torture, "Creating test file\n");
     509             : 
     510           2 :         ZERO_STRUCT(io.smb2);
     511           2 :         io.generic.level = RAW_OPEN_SMB2;
     512           2 :         io.smb2.in.create_flags = 0;
     513           2 :         io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
     514             :                 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
     515             :                 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
     516             :                 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
     517           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     518           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     519           2 :         io.smb2.in.share_access = 0;
     520           2 :         io.smb2.in.alloc_size = 0;
     521           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     522           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     523           2 :         io.smb2.in.security_flags = 0;
     524           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
     525             : 
     526           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     527           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     528           2 :         fh = io.smb2.out.file.handle;
     529             : 
     530           2 :         torture_comment(torture, "Renaming test file\n");
     531             : 
     532           2 :         ZERO_STRUCT(sinfo);
     533           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     534           2 :         sinfo.rename_information.in.file.handle = fh;
     535           2 :         sinfo.rename_information.in.overwrite = 0;
     536           2 :         sinfo.rename_information.in.root_fid = 0;
     537           2 :         sinfo.rename_information.in.new_name =
     538             :                 BASEDIR "\\newname.txt";
     539           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     540           2 :         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
     541             : 
     542           2 :         torture_comment(torture, "Closing test file\n");
     543             : 
     544           2 :         ZERO_STRUCT(cl.smb2);
     545           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     546           2 :         cl.smb2.in.file.handle = fh;
     547           2 :         status = smb2_close(tree1, &(cl.smb2));
     548           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     549             : 
     550           2 :         ZERO_STRUCT(fh);
     551             : 
     552           2 :         torture_comment(torture, "Closing directory\n");
     553             : 
     554           2 :         ZERO_STRUCT(cl.smb2);
     555           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     556           2 :         cl.smb2.in.file.handle = dh;
     557           2 :         status = smb2_close(tree1, &(cl.smb2));
     558           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     559             : 
     560           2 :         ZERO_STRUCT(dh);
     561             : 
     562             : 
     563           2 : done:
     564             : 
     565           2 :         torture_comment(torture, "Cleaning up\n");
     566             : 
     567           2 :         if (fh.data[0] || fh.data[1]) {
     568           0 :                 ZERO_STRUCT(cl.smb2);
     569           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     570           0 :                 cl.smb2.in.file.handle = fh;
     571           0 :                 status = smb2_close(tree1, &(cl.smb2));
     572             :         }
     573           2 :         if (dh.data[0] || dh.data[1]) {
     574           0 :                 ZERO_STRUCT(cl.smb2);
     575           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     576           0 :                 cl.smb2.in.file.handle = dh;
     577           0 :                 status = smb2_close(tree1, &(cl.smb2));
     578             :         }
     579             : 
     580           2 :         smb2_deltree(tree1, BASEDIR);
     581           2 :         return ret;
     582             : }
     583             : 
     584             : /*
     585             :  * testing of rename when opening parent dir with no delete access and delete
     586             :  * sharing allowed
     587             :  * this should pass
     588             :  */
     589             : 
     590           2 : static bool torture_smb2_rename_no_delete_access(struct torture_context *torture,
     591             :                 struct smb2_tree *tree1)
     592             : {
     593           2 :         bool ret = true;
     594           0 :         NTSTATUS status;
     595           0 :         union smb_open io;
     596           0 :         union smb_close cl;
     597           0 :         union smb_setfileinfo sinfo;
     598           0 :         union smb_fileinfo fi;
     599           0 :         struct smb2_handle fh, dh;
     600             : 
     601           2 :         ZERO_STRUCT(fh);
     602           2 :         ZERO_STRUCT(dh);
     603             : 
     604           2 :         smb2_deltree(tree1, BASEDIR);
     605           2 :         smb2_util_rmdir(tree1, BASEDIR);
     606             : 
     607           2 :         torture_comment(torture, "Creating base directory\n");
     608             : 
     609           2 :         smb2_util_mkdir(tree1, BASEDIR);
     610             : 
     611           2 :         torture_comment(torture, "Opening parent directory\n");
     612             : 
     613           2 :         ZERO_STRUCT(io.smb2);
     614           2 :         io.generic.level = RAW_OPEN_SMB2;
     615           2 :         io.smb2.in.create_flags = 0;
     616           2 :         io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
     617             :                 SEC_STD_READ_CONTROL | SEC_FILE_WRITE_ATTRIBUTE |
     618             :                 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
     619             :                 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
     620             :                 SEC_FILE_WRITE_DATA;
     621           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     622           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
     623           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     624             :                 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
     625           2 :         io.smb2.in.alloc_size = 0;
     626           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     627           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     628           2 :         io.smb2.in.security_flags = 0;
     629           2 :         io.smb2.in.fname = BASEDIR;
     630             : 
     631           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     632           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     633           2 :         dh = io.smb2.out.file.handle;
     634             : 
     635             : 
     636           2 :         torture_comment(torture, "Creating test file\n");
     637             : 
     638           2 :         ZERO_STRUCT(io.smb2);
     639           2 :         io.generic.level = RAW_OPEN_SMB2;
     640           2 :         io.smb2.in.create_flags = 0;
     641           2 :         io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
     642             :                 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
     643             :                 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
     644             :                 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
     645           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     646           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     647           2 :         io.smb2.in.share_access = 0;
     648           2 :         io.smb2.in.alloc_size = 0;
     649           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     650           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     651           2 :         io.smb2.in.security_flags = 0;
     652           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
     653             : 
     654           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     655           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     656           2 :         fh = io.smb2.out.file.handle;
     657             : 
     658           2 :         torture_comment(torture, "Renaming test file\n");
     659             : 
     660           2 :         ZERO_STRUCT(sinfo);
     661           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     662           2 :         sinfo.rename_information.in.file.handle = fh;
     663           2 :         sinfo.rename_information.in.overwrite = 0;
     664           2 :         sinfo.rename_information.in.root_fid = 0;
     665           2 :         sinfo.rename_information.in.new_name =
     666             :                 BASEDIR "\\newname.txt";
     667           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     668           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     669             : 
     670           2 :         torture_comment(torture, "Checking for new filename\n");
     671             : 
     672           2 :         ZERO_STRUCT(fi);
     673           2 :         fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
     674           2 :         fi.generic.in.file.handle = fh;
     675           2 :         status = smb2_getinfo_file(tree1, torture, &fi);
     676           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     677             : 
     678             : 
     679           2 :         torture_comment(torture, "Closing test file\n");
     680             : 
     681           2 :         ZERO_STRUCT(cl.smb2);
     682           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     683           2 :         cl.smb2.in.file.handle = fh;
     684           2 :         status = smb2_close(tree1, &(cl.smb2));
     685           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     686             : 
     687           2 :         ZERO_STRUCT(fh);
     688             : 
     689           2 :         torture_comment(torture, "Closing directory\n");
     690             : 
     691           2 :         ZERO_STRUCT(cl.smb2);
     692           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     693           2 :         cl.smb2.in.file.handle = dh;
     694           2 :         status = smb2_close(tree1, &(cl.smb2));
     695           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     696             : 
     697           2 :         ZERO_STRUCT(dh);
     698             : 
     699             : 
     700           2 : done:
     701             : 
     702           2 :         torture_comment(torture, "Cleaning up\n");
     703             : 
     704           2 :         if (fh.data[0] || fh.data[1]) {
     705           0 :                 ZERO_STRUCT(cl.smb2);
     706           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     707           0 :                 cl.smb2.in.file.handle = fh;
     708           0 :                 status = smb2_close(tree1, &(cl.smb2));
     709             :         }
     710           2 :         if (dh.data[0] || dh.data[1]) {
     711           0 :                 ZERO_STRUCT(cl.smb2);
     712           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     713           0 :                 cl.smb2.in.file.handle = dh;
     714           0 :                 status = smb2_close(tree1, &(cl.smb2));
     715             :         }
     716             : 
     717           2 :         smb2_deltree(tree1, BASEDIR);
     718           2 :         return ret;
     719             : }
     720             : 
     721             : 
     722             : /*
     723             :  * testing of rename with no delete access on parent dir
     724             :  * this is the negative case of the test above: parent dir is opened
     725             :  * without share_delete, so rename must fail
     726             :  */
     727             : 
     728           2 : static bool torture_smb2_rename_no_delete_access2(struct torture_context *torture,
     729             :                 struct smb2_tree *tree1)
     730             : {
     731           2 :         bool ret = true;
     732           0 :         NTSTATUS status;
     733           0 :         union smb_open io;
     734           0 :         union smb_close cl;
     735           0 :         union smb_setfileinfo sinfo;
     736           0 :         struct smb2_handle fh, dh;
     737             : 
     738           2 :         ZERO_STRUCT(fh);
     739           2 :         ZERO_STRUCT(dh);
     740             : 
     741           2 :         smb2_deltree(tree1, BASEDIR);
     742           2 :         smb2_util_rmdir(tree1, BASEDIR);
     743             : 
     744           2 :         torture_comment(torture, "Creating base directory\n");
     745             : 
     746           2 :         smb2_util_mkdir(tree1, BASEDIR);
     747             : 
     748           2 :         torture_comment(torture, "Opening parent directory\n");
     749             : 
     750           2 :         ZERO_STRUCT(io.smb2);
     751           2 :         io.generic.level = RAW_OPEN_SMB2;
     752           2 :         io.smb2.in.create_flags = 0;
     753           2 :         io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
     754             :                 SEC_STD_READ_CONTROL | SEC_FILE_WRITE_ATTRIBUTE |
     755             :                 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
     756             :                 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
     757             :                 SEC_FILE_WRITE_DATA;
     758           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     759           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
     760           2 :         io.smb2.in.share_access = 0;
     761           2 :         io.smb2.in.alloc_size = 0;
     762           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     763           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     764           2 :         io.smb2.in.security_flags = 0;
     765           2 :         io.smb2.in.fname = BASEDIR;
     766             : 
     767           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     768           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     769           2 :         dh = io.smb2.out.file.handle;
     770             : 
     771             : 
     772           2 :         torture_comment(torture, "Creating test file\n");
     773             : 
     774           2 :         ZERO_STRUCT(io.smb2);
     775           2 :         io.generic.level = RAW_OPEN_SMB2;
     776           2 :         io.smb2.in.create_flags = 0;
     777           2 :         io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
     778             :                 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
     779             :                 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
     780             :                 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
     781           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     782           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     783           2 :         io.smb2.in.share_access = 0;
     784           2 :         io.smb2.in.alloc_size = 0;
     785           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     786           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     787           2 :         io.smb2.in.security_flags = 0;
     788           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
     789             : 
     790           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     791           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     792           2 :         fh = io.smb2.out.file.handle;
     793             : 
     794           2 :         torture_comment(torture, "Renaming test file\n");
     795             : 
     796           2 :         ZERO_STRUCT(sinfo);
     797           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     798           2 :         sinfo.rename_information.in.file.handle = fh;
     799           2 :         sinfo.rename_information.in.overwrite = 0;
     800           2 :         sinfo.rename_information.in.root_fid = 0;
     801           2 :         sinfo.rename_information.in.new_name =
     802             :                 BASEDIR "\\newname.txt";
     803           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     804           2 :         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
     805             : 
     806           0 :         torture_comment(torture, "Closing test file\n");
     807             : 
     808           0 :         ZERO_STRUCT(cl.smb2);
     809           0 :         cl.smb2.level = RAW_CLOSE_SMB2;
     810           0 :         cl.smb2.in.file.handle = fh;
     811           0 :         status = smb2_close(tree1, &(cl.smb2));
     812           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     813             : 
     814           0 :         ZERO_STRUCT(fh);
     815             : 
     816           0 :         torture_comment(torture, "Closing directory\n");
     817             : 
     818           0 :         ZERO_STRUCT(cl.smb2);
     819           0 :         cl.smb2.level = RAW_CLOSE_SMB2;
     820           0 :         cl.smb2.in.file.handle = dh;
     821           0 :         status = smb2_close(tree1, &(cl.smb2));
     822           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     823             : 
     824           0 :         ZERO_STRUCT(dh);
     825             : 
     826             : 
     827           2 : done:
     828             : 
     829           2 :         torture_comment(torture, "Cleaning up\n");
     830             : 
     831           2 :         if (fh.data[0] || fh.data[1]) {
     832           2 :                 ZERO_STRUCT(cl.smb2);
     833           2 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     834           2 :                 cl.smb2.in.file.handle = fh;
     835           2 :                 status = smb2_close(tree1, &(cl.smb2));
     836             :         }
     837           2 :         if (dh.data[0] || dh.data[1]) {
     838           2 :                 ZERO_STRUCT(cl.smb2);
     839           2 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     840           2 :                 cl.smb2.in.file.handle = dh;
     841           2 :                 status = smb2_close(tree1, &(cl.smb2));
     842             :         }
     843             : 
     844           2 :         smb2_deltree(tree1, BASEDIR);
     845           2 :         return ret;
     846             : }
     847             : 
     848             : /*
     849             :  * this is a replay of how Word 2010 saves a file
     850             :  * this should pass
     851             :  */
     852             : 
     853           2 : static bool torture_smb2_rename_msword(struct torture_context *torture,
     854             :                 struct smb2_tree *tree1)
     855             : {
     856           2 :         bool ret = true;
     857           0 :         NTSTATUS status;
     858           0 :         union smb_open io;
     859           0 :         union smb_close cl;
     860           0 :         union smb_setfileinfo sinfo;
     861           0 :         union smb_fileinfo fi;
     862           0 :         struct smb2_handle fh, dh;
     863             : 
     864           2 :         ZERO_STRUCT(fh);
     865           2 :         ZERO_STRUCT(dh);
     866             : 
     867           2 :         smb2_deltree(tree1, BASEDIR);
     868           2 :         smb2_util_rmdir(tree1, BASEDIR);
     869             : 
     870           2 :         torture_comment(torture, "Creating base directory\n");
     871             : 
     872           2 :         smb2_util_mkdir(tree1, BASEDIR);
     873             : 
     874           2 :         torture_comment(torture, "Creating test file\n");
     875             : 
     876           2 :         ZERO_STRUCT(io.smb2);
     877           2 :         io.generic.level = RAW_OPEN_SMB2;
     878           2 :         io.smb2.in.create_flags = 0;
     879           2 :         io.smb2.in.desired_access = 0x0017019f;
     880           2 :         io.smb2.in.create_options = 0x60;
     881           2 :         io.smb2.in.file_attributes = 0;
     882           2 :         io.smb2.in.share_access = 0;
     883           2 :         io.smb2.in.alloc_size = 0;
     884           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     885           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     886           2 :         io.smb2.in.security_flags = 0;
     887           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
     888             : 
     889           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     890           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     891           2 :         fh = io.smb2.out.file.handle;
     892             : 
     893           2 :         torture_comment(torture, "Opening parent directory\n");
     894             : 
     895           2 :         ZERO_STRUCT(io.smb2);
     896           2 :         io.generic.level = RAW_OPEN_SMB2;
     897           2 :         io.smb2.in.create_flags = 0;
     898           2 :         io.smb2.in.desired_access = 0x00100080;
     899           2 :         io.smb2.in.create_options = 0x00800021;
     900           2 :         io.smb2.in.file_attributes = 0;
     901           2 :         io.smb2.in.share_access = 0;
     902           2 :         io.smb2.in.alloc_size = 0;
     903           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     904           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     905           2 :         io.smb2.in.security_flags = 0;
     906           2 :         io.smb2.in.fname = BASEDIR;
     907             : 
     908           2 :         status = smb2_create(tree1, torture, &(io.smb2));
     909           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     910           2 :         dh = io.smb2.out.file.handle;
     911             : 
     912           2 :         torture_comment(torture, "Renaming test file\n");
     913             : 
     914           2 :         ZERO_STRUCT(sinfo);
     915           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     916           2 :         sinfo.rename_information.in.file.handle = fh;
     917           2 :         sinfo.rename_information.in.overwrite = 0;
     918           2 :         sinfo.rename_information.in.root_fid = 0;
     919           2 :         sinfo.rename_information.in.new_name =
     920             :                 BASEDIR "\\newname.txt";
     921           2 :         status = smb2_setinfo_file(tree1, &sinfo);
     922           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     923             : 
     924           2 :         torture_comment(torture, "Checking for new filename\n");
     925             : 
     926           2 :         ZERO_STRUCT(fi);
     927           2 :         fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
     928           2 :         fi.generic.in.file.handle = fh;
     929           2 :         status = smb2_getinfo_file(tree1, torture, &fi);
     930           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     931             : 
     932             : 
     933           2 :         torture_comment(torture, "Closing test file\n");
     934             : 
     935           2 :         ZERO_STRUCT(cl.smb2);
     936           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     937           2 :         cl.smb2.in.file.handle = fh;
     938           2 :         status = smb2_close(tree1, &(cl.smb2));
     939           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     940             : 
     941           2 :         ZERO_STRUCT(fh);
     942             : 
     943           2 :         torture_comment(torture, "Closing directory\n");
     944             : 
     945           2 :         ZERO_STRUCT(cl.smb2);
     946           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
     947           2 :         cl.smb2.in.file.handle = dh;
     948           2 :         status = smb2_close(tree1, &(cl.smb2));
     949           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     950             : 
     951           2 :         ZERO_STRUCT(dh);
     952             : 
     953             : 
     954           2 : done:
     955             : 
     956           2 :         torture_comment(torture, "Cleaning up\n");
     957             : 
     958           2 :         if (fh.data[0] || fh.data[1]) {
     959           0 :                 ZERO_STRUCT(cl.smb2);
     960           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     961           0 :                 cl.smb2.in.file.handle = fh;
     962           0 :                 status = smb2_close(tree1, &(cl.smb2));
     963             :         }
     964           2 :         if (dh.data[0] || dh.data[1]) {
     965           0 :                 ZERO_STRUCT(cl.smb2);
     966           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
     967           0 :                 cl.smb2.in.file.handle = dh;
     968           0 :                 status = smb2_close(tree1, &(cl.smb2));
     969             :         }
     970             : 
     971           2 :         smb2_deltree(tree1, BASEDIR);
     972           2 :         return ret;
     973             : }
     974             : 
     975           2 : static bool torture_smb2_rename_dir_openfile(struct torture_context *torture,
     976             :                                              struct smb2_tree *tree1)
     977             : {
     978           2 :         bool ret = true;
     979           0 :         NTSTATUS status;
     980           0 :         union smb_open io;
     981           0 :         union smb_close cl;
     982           0 :         union smb_setfileinfo sinfo;
     983           0 :         struct smb2_handle d1, h1;
     984             : 
     985           2 :         ZERO_STRUCT(d1);
     986           2 :         ZERO_STRUCT(h1);
     987             : 
     988           2 :         smb2_deltree(tree1, BASEDIR);
     989           2 :         smb2_util_rmdir(tree1, BASEDIR);
     990             : 
     991           2 :         torture_comment(torture, "Creating base directory\n");
     992             : 
     993           2 :         ZERO_STRUCT(io.smb2);
     994           2 :         io.generic.level = RAW_OPEN_SMB2;
     995           2 :         io.smb2.in.create_flags = 0;
     996           2 :         io.smb2.in.desired_access = 0x0017019f;
     997           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     998           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
     999           2 :         io.smb2.in.share_access = 0;
    1000           2 :         io.smb2.in.alloc_size = 0;
    1001           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1002           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1003           2 :         io.smb2.in.security_flags = 0;
    1004           2 :         io.smb2.in.fname = BASEDIR;
    1005             : 
    1006           2 :         status = smb2_create(tree1, torture, &(io.smb2));
    1007           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1008           2 :         d1 = io.smb2.out.file.handle;
    1009             : 
    1010           2 :         torture_comment(torture, "Creating test file\n");
    1011             : 
    1012           2 :         ZERO_STRUCT(io.smb2);
    1013           2 :         io.generic.level = RAW_OPEN_SMB2;
    1014           2 :         io.smb2.in.create_flags = 0;
    1015           2 :         io.smb2.in.desired_access = 0x0017019f;
    1016           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
    1017           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1018           2 :         io.smb2.in.share_access = 0;
    1019           2 :         io.smb2.in.alloc_size = 0;
    1020           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1021           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1022           2 :         io.smb2.in.security_flags = 0;
    1023           2 :         io.smb2.in.fname = BASEDIR "\\file.txt";
    1024             : 
    1025           2 :         status = smb2_create(tree1, torture, &(io.smb2));
    1026           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1027           2 :         h1 = io.smb2.out.file.handle;
    1028             : 
    1029           2 :         torture_comment(torture, "Renaming directory\n");
    1030             : 
    1031           2 :         ZERO_STRUCT(sinfo);
    1032           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
    1033           2 :         sinfo.rename_information.in.file.handle = d1;
    1034           2 :         sinfo.rename_information.in.overwrite = 0;
    1035           2 :         sinfo.rename_information.in.root_fid = 0;
    1036           2 :         sinfo.rename_information.in.new_name =
    1037             :                 BASEDIR "-new";
    1038           2 :         status = smb2_setinfo_file(tree1, &sinfo);
    1039           2 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1040             : 
    1041           2 :         torture_comment(torture, "Closing directory\n");
    1042             : 
    1043           2 :         ZERO_STRUCT(cl.smb2);
    1044           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
    1045           2 :         cl.smb2.in.file.handle = d1;
    1046           2 :         status = smb2_close(tree1, &(cl.smb2));
    1047           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1048           2 :         ZERO_STRUCT(d1);
    1049             : 
    1050           2 :         torture_comment(torture, "Closing test file\n");
    1051             : 
    1052           2 :         cl.smb2.in.file.handle = h1;
    1053           2 :         status = smb2_close(tree1, &(cl.smb2));
    1054           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1055           2 :         ZERO_STRUCT(h1);
    1056             : 
    1057           2 : done:
    1058             : 
    1059           2 :         torture_comment(torture, "Cleaning up\n");
    1060             : 
    1061           2 :         if (h1.data[0] || h1.data[1]) {
    1062           0 :                 ZERO_STRUCT(cl.smb2);
    1063           0 :                 cl.smb2.level = RAW_CLOSE_SMB2;
    1064           0 :                 cl.smb2.in.file.handle = h1;
    1065           0 :                 status = smb2_close(tree1, &(cl.smb2));
    1066             :         }
    1067           2 :         smb2_deltree(tree1, BASEDIR);
    1068           2 :         return ret;
    1069             : }
    1070             : 
    1071             : struct rename_one_dir_cycle_state {
    1072             :         struct tevent_context *ev;
    1073             :         struct smb2_tree *tree;
    1074             :         struct smb2_handle file;
    1075             :         const char *base_name;
    1076             :         char *new_name;
    1077             :         unsigned *rename_counter;
    1078             : 
    1079             :         unsigned current;
    1080             :         unsigned max;
    1081             :         union smb_setfileinfo sinfo;
    1082             : };
    1083             : 
    1084             : static void rename_one_dir_cycle_done(struct smb2_request *subreq);
    1085             : 
    1086           6 : static struct tevent_req *rename_one_dir_cycle_send(TALLOC_CTX *mem_ctx,
    1087             :                                                     struct tevent_context *ev,
    1088             :                                                     struct smb2_tree *tree,
    1089             :                                                     struct smb2_handle file,
    1090             :                                                     unsigned max_renames,
    1091             :                                                     const char *base_name,
    1092             :                                                     unsigned *rename_counter)
    1093             : {
    1094           0 :         struct tevent_req *req;
    1095           0 :         struct rename_one_dir_cycle_state *state;
    1096           0 :         struct smb2_request *subreq;
    1097             : 
    1098           6 :         req = tevent_req_create(mem_ctx, &state,
    1099             :                                 struct rename_one_dir_cycle_state);
    1100           6 :         if (req == NULL) {
    1101           0 :                 return NULL;
    1102             :         }
    1103           6 :         state->ev = ev;
    1104           6 :         state->tree = tree;
    1105           6 :         state->file = file;
    1106           6 :         state->base_name = base_name;
    1107           6 :         state->rename_counter = rename_counter;
    1108           6 :         state->current = 0;
    1109           6 :         state->max = max_renames;
    1110             : 
    1111           6 :         ZERO_STRUCT(state->sinfo);
    1112           6 :         state->sinfo.rename_information.level =
    1113             :                 RAW_SFILEINFO_RENAME_INFORMATION;
    1114           6 :         state->sinfo.rename_information.in.file.handle = state->file;
    1115           6 :         state->sinfo.rename_information.in.overwrite = 0;
    1116           6 :         state->sinfo.rename_information.in.root_fid = 0;
    1117             : 
    1118          12 :         state->new_name = talloc_asprintf(
    1119           6 :                 state, "%s-%u", state->base_name, state->current);
    1120           6 :         if (tevent_req_nomem(state->new_name, req)) {
    1121           0 :                 return tevent_req_post(req, ev);
    1122             :         }
    1123           6 :         state->sinfo.rename_information.in.new_name = state->new_name;
    1124             : 
    1125           6 :         subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
    1126           6 :         if (tevent_req_nomem(subreq, req)) {
    1127           0 :                 return tevent_req_post(req, ev);
    1128             :         }
    1129           6 :         subreq->async.fn = rename_one_dir_cycle_done;
    1130           6 :         subreq->async.private_data = req;
    1131           6 :         return req;
    1132             : }
    1133             : 
    1134          60 : static void rename_one_dir_cycle_done(struct smb2_request *subreq)
    1135             : {
    1136          60 :         struct tevent_req *req = talloc_get_type_abort(
    1137             :                 subreq->async.private_data, struct tevent_req);
    1138          60 :         struct rename_one_dir_cycle_state *state = tevent_req_data(
    1139             :                 req, struct rename_one_dir_cycle_state);
    1140           0 :         NTSTATUS status;
    1141             : 
    1142          60 :         status = smb2_setinfo_recv(subreq);
    1143          60 :         if (tevent_req_nterror(req, status)) {
    1144           6 :                 return;
    1145             :         }
    1146          60 :         TALLOC_FREE(state->new_name);
    1147             : 
    1148          60 :         *state->rename_counter += 1;
    1149             : 
    1150          60 :         state->current += 1;
    1151          60 :         if (state->current >= state->max) {
    1152           6 :                 tevent_req_done(req);
    1153           6 :                 return;
    1154             :         }
    1155             : 
    1156          54 :         ZERO_STRUCT(state->sinfo);
    1157          54 :         state->sinfo.rename_information.level =
    1158             :                 RAW_SFILEINFO_RENAME_INFORMATION;
    1159          54 :         state->sinfo.rename_information.in.file.handle = state->file;
    1160          54 :         state->sinfo.rename_information.in.overwrite = 0;
    1161          54 :         state->sinfo.rename_information.in.root_fid = 0;
    1162             : 
    1163          54 :         state->new_name = talloc_asprintf(
    1164             :                 state, "%s-%u", state->base_name, state->current);
    1165          54 :         if (tevent_req_nomem(state->new_name, req)) {
    1166           0 :                 return;
    1167             :         }
    1168          54 :         state->sinfo.rename_information.in.new_name = state->new_name;
    1169             : 
    1170          54 :         subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
    1171          54 :         if (tevent_req_nomem(subreq, req)) {
    1172           0 :                 return;
    1173             :         }
    1174          54 :         subreq->async.fn = rename_one_dir_cycle_done;
    1175          54 :         subreq->async.private_data = req;
    1176             : }
    1177             : 
    1178           6 : static NTSTATUS rename_one_dir_cycle_recv(struct tevent_req *req)
    1179             : {
    1180           6 :         return tevent_req_simple_recv_ntstatus(req);
    1181             : }
    1182             : 
    1183             : struct rename_dir_bench_state {
    1184             :         struct tevent_context *ev;
    1185             :         struct smb2_tree *tree;
    1186             :         const char *base_name;
    1187             :         unsigned max_renames;
    1188             :         unsigned *rename_counter;
    1189             : 
    1190             :         struct smb2_create io;
    1191             :         union smb_setfileinfo sinfo;
    1192             :         struct smb2_close cl;
    1193             : 
    1194             :         struct smb2_handle file;
    1195             : };
    1196             : 
    1197             : static void rename_dir_bench_opened(struct smb2_request *subreq);
    1198             : static void rename_dir_bench_renamed(struct tevent_req *subreq);
    1199             : static void rename_dir_bench_set_doc(struct smb2_request *subreq);
    1200             : static void rename_dir_bench_closed(struct smb2_request *subreq);
    1201             : 
    1202           6 : static struct tevent_req *rename_dir_bench_send(TALLOC_CTX *mem_ctx,
    1203             :                                                 struct tevent_context *ev,
    1204             :                                                 struct smb2_tree *tree,
    1205             :                                                 const char *base_name,
    1206             :                                                 unsigned max_renames,
    1207             :                                                 unsigned *rename_counter)
    1208             : {
    1209           0 :         struct tevent_req *req;
    1210           0 :         struct rename_dir_bench_state *state;
    1211           0 :         struct smb2_request *subreq;
    1212             : 
    1213           6 :         req = tevent_req_create(mem_ctx, &state,
    1214             :                                 struct rename_dir_bench_state);
    1215           6 :         if (req == NULL) {
    1216           0 :                 return NULL;
    1217             :         }
    1218           6 :         state->ev = ev;
    1219           6 :         state->tree = tree;
    1220           6 :         state->base_name = base_name;
    1221           6 :         state->max_renames = max_renames;
    1222           6 :         state->rename_counter = rename_counter;
    1223             : 
    1224           6 :         ZERO_STRUCT(state->io);
    1225           6 :         state->io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    1226           6 :         state->io.in.share_access =
    1227             :                 NTCREATEX_SHARE_ACCESS_READ|
    1228             :                 NTCREATEX_SHARE_ACCESS_WRITE;
    1229           6 :         state->io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1230           6 :         state->io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    1231           6 :         state->io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1232           6 :         state->io.in.fname = state->base_name;
    1233             : 
    1234           6 :         subreq = smb2_create_send(state->tree, &state->io);
    1235           6 :         if (tevent_req_nomem(subreq, req)) {
    1236           0 :                 return tevent_req_post(req, ev);
    1237             :         }
    1238           6 :         subreq->async.fn = rename_dir_bench_opened;
    1239           6 :         subreq->async.private_data = req;
    1240           6 :         return req;
    1241             : }
    1242             : 
    1243           6 : static void rename_dir_bench_opened(struct smb2_request *subreq)
    1244             : {
    1245           6 :         struct tevent_req *req = talloc_get_type_abort(
    1246             :                 subreq->async.private_data, struct tevent_req);
    1247           6 :         struct rename_dir_bench_state *state = tevent_req_data(
    1248             :                 req, struct rename_dir_bench_state);
    1249           0 :         struct smb2_create *io;
    1250           0 :         struct tevent_req *subreq2;
    1251           0 :         NTSTATUS status;
    1252             : 
    1253           6 :         io = talloc(state, struct smb2_create);
    1254           6 :         if (tevent_req_nomem(io, req)) {
    1255           0 :                 return;
    1256             :         }
    1257             : 
    1258           6 :         status = smb2_create_recv(subreq, io, io);
    1259           6 :         if (tevent_req_nterror(req, status)) {
    1260           0 :                 return;
    1261             :         }
    1262           6 :         state->file = io->out.file.handle;
    1263           6 :         TALLOC_FREE(io);
    1264             : 
    1265           6 :         subreq2 = rename_one_dir_cycle_send(
    1266             :                 state, state->ev, state->tree, state->file,
    1267             :                 state->max_renames, state->base_name,
    1268             :                 state->rename_counter);
    1269           6 :         if (tevent_req_nomem(subreq2, req)) {
    1270           0 :                 return;
    1271             :         }
    1272           6 :         tevent_req_set_callback(subreq2, rename_dir_bench_renamed, req);
    1273             : }
    1274             : 
    1275           6 : static void rename_dir_bench_renamed(struct tevent_req *subreq)
    1276             : {
    1277           6 :         struct tevent_req *req = tevent_req_callback_data(
    1278             :                 subreq, struct tevent_req);
    1279           6 :         struct rename_dir_bench_state *state = tevent_req_data(
    1280             :                 req, struct rename_dir_bench_state);
    1281           0 :         struct smb2_request *subreq2;
    1282           0 :         NTSTATUS status;
    1283             : 
    1284           6 :         status = rename_one_dir_cycle_recv(subreq);
    1285           6 :         TALLOC_FREE(subreq);
    1286           6 :         if (tevent_req_nterror(req, status)) {
    1287           0 :                 return;
    1288             :         }
    1289             : 
    1290           6 :         ZERO_STRUCT(state->sinfo);
    1291           6 :         state->sinfo.disposition_info.level =
    1292             :                 RAW_SFILEINFO_DISPOSITION_INFORMATION;
    1293           6 :         state->sinfo.disposition_info.in.file.handle = state->file;
    1294           6 :         state->sinfo.disposition_info.in.delete_on_close = true;
    1295             : 
    1296           6 :         subreq2 = smb2_setinfo_file_send(state->tree, &state->sinfo);
    1297           6 :         if (tevent_req_nomem(subreq2, req)) {
    1298           0 :                 return;
    1299             :         }
    1300           6 :         subreq2->async.fn = rename_dir_bench_set_doc;
    1301           6 :         subreq2->async.private_data = req;
    1302             : }
    1303             : 
    1304           6 : static void rename_dir_bench_set_doc(struct smb2_request *subreq)
    1305             : {
    1306           6 :         struct tevent_req *req = talloc_get_type_abort(
    1307             :                 subreq->async.private_data, struct tevent_req);
    1308           6 :         struct rename_dir_bench_state *state = tevent_req_data(
    1309             :                 req, struct rename_dir_bench_state);
    1310           0 :         NTSTATUS status;
    1311             : 
    1312           6 :         status = smb2_setinfo_recv(subreq);
    1313           6 :         if (tevent_req_nterror(req, status)) {
    1314           0 :                 return;
    1315             :         }
    1316             : 
    1317           6 :         ZERO_STRUCT(state->cl);
    1318           6 :         state->cl.in.file.handle = state->file;
    1319             : 
    1320           6 :         subreq = smb2_close_send(state->tree, &state->cl);
    1321           6 :         if (tevent_req_nomem(subreq, req)) {
    1322           0 :                 return;
    1323             :         }
    1324           6 :         subreq->async.fn = rename_dir_bench_closed;
    1325           6 :         subreq->async.private_data = req;
    1326             : }
    1327             : 
    1328           6 : static void rename_dir_bench_closed(struct smb2_request *subreq)
    1329             : {
    1330           6 :         struct tevent_req *req = talloc_get_type_abort(
    1331             :                 subreq->async.private_data, struct tevent_req);
    1332           0 :         struct smb2_close cl;
    1333           0 :         NTSTATUS status;
    1334             : 
    1335           6 :         status = smb2_close_recv(subreq, &cl);
    1336           6 :         if (tevent_req_nterror(req, status)) {
    1337           0 :                 return;
    1338             :         }
    1339           6 :         tevent_req_done(req);
    1340             : }
    1341             : 
    1342           6 : static NTSTATUS rename_dir_bench_recv(struct tevent_req *req)
    1343             : {
    1344           6 :         return tevent_req_simple_recv_ntstatus(req);
    1345             : }
    1346             : 
    1347             : struct rename_dirs_bench_state {
    1348             :         unsigned num_reqs;
    1349             :         unsigned num_done;
    1350             : };
    1351             : 
    1352             : static void rename_dirs_bench_done(struct tevent_req *subreq);
    1353             : 
    1354           2 : static struct tevent_req *rename_dirs_bench_send(TALLOC_CTX *mem_ctx,
    1355             :                                                  struct tevent_context *ev,
    1356             :                                                  struct smb2_tree *tree,
    1357             :                                                  const char *base_name,
    1358             :                                                  unsigned num_parallel,
    1359             :                                                  unsigned max_renames,
    1360             :                                                  unsigned *rename_counter)
    1361             : {
    1362           0 :         struct tevent_req *req;
    1363           0 :         struct rename_dirs_bench_state *state;
    1364           0 :         unsigned i;
    1365             : 
    1366           2 :         req = tevent_req_create(mem_ctx, &state,
    1367             :                                 struct rename_dirs_bench_state);
    1368           2 :         if (req == NULL) {
    1369           0 :                 return NULL;
    1370             :         }
    1371           2 :         state->num_reqs = num_parallel;
    1372           2 :         state->num_done = 0;
    1373             : 
    1374           8 :         for (i=0; i<num_parallel; i++) {
    1375           0 :                 struct tevent_req *subreq;
    1376           0 :                 char *sub_base;
    1377             : 
    1378           6 :                 sub_base = talloc_asprintf(state, "%s-%u", base_name, i);
    1379           6 :                 if (tevent_req_nomem(sub_base, req)) {
    1380           0 :                         return tevent_req_post(req, ev);
    1381             :                 }
    1382             : 
    1383           6 :                 subreq = rename_dir_bench_send(state, ev, tree, sub_base,
    1384             :                                                max_renames, rename_counter);
    1385           6 :                 if (tevent_req_nomem(subreq, req)) {
    1386           0 :                         return tevent_req_post(req, ev);
    1387             :                 }
    1388           6 :                 tevent_req_set_callback(subreq, rename_dirs_bench_done, req);
    1389             :         }
    1390           2 :         return req;
    1391             : }
    1392             : 
    1393           6 : static void rename_dirs_bench_done(struct tevent_req *subreq)
    1394             : {
    1395           6 :         struct tevent_req *req = tevent_req_callback_data(
    1396             :                 subreq, struct tevent_req);
    1397           6 :         struct rename_dirs_bench_state *state = tevent_req_data(
    1398             :                 req, struct rename_dirs_bench_state);
    1399           0 :         NTSTATUS status;
    1400             : 
    1401           6 :         status = rename_dir_bench_recv(subreq);
    1402           6 :         TALLOC_FREE(subreq);
    1403           6 :         if (tevent_req_nterror(req, status)) {
    1404           0 :                 return;
    1405             :         }
    1406             : 
    1407           6 :         state->num_done += 1;
    1408           6 :         if (state->num_done >= state->num_reqs) {
    1409           2 :                 tevent_req_done(req);
    1410             :         }
    1411             : }
    1412             : 
    1413           2 : static NTSTATUS rename_dirs_bench_recv(struct tevent_req *req)
    1414             : {
    1415           2 :         return tevent_req_simple_recv_ntstatus(req);
    1416             : }
    1417             : 
    1418           2 : static bool torture_smb2_rename_dir_bench(struct torture_context *tctx,
    1419             :                                           struct smb2_tree *tree)
    1420             : {
    1421           0 :         struct tevent_req *req;
    1422           0 :         NTSTATUS status;
    1423           2 :         unsigned counter = 0;
    1424           0 :         bool ret;
    1425             : 
    1426           2 :         req = rename_dirs_bench_send(tctx, tctx->ev, tree, "dir", 3, 10,
    1427             :                                      &counter);
    1428           2 :         torture_assert(tctx, req != NULL, "rename_dirs_bench_send failed");
    1429             : 
    1430           2 :         ret = tevent_req_poll(req, tctx->ev);
    1431           2 :         torture_assert(tctx, ret, "tevent_req_poll failed");
    1432             : 
    1433           2 :         status = rename_dirs_bench_recv(req);
    1434           2 :         torture_comment(tctx, "rename_dirs_bench returned %s\n",
    1435             :                         nt_errstr(status));
    1436           2 :         TALLOC_FREE(req);
    1437           2 :         torture_assert_ntstatus_ok(tctx, status, "bench failed");
    1438           2 :         return true;
    1439             : }
    1440             : 
    1441             : /*
    1442             :  * This test basically verifies that modify and change timestamps are preserved
    1443             :  * after file rename with outstanding open file handles.
    1444             :  */
    1445             : 
    1446           2 : static bool torture_smb2_rename_simple_modtime(
    1447             :                         struct torture_context *torture,
    1448             :                         struct smb2_tree *tree1)
    1449             : {
    1450           0 :         struct smb2_create c1, c2;
    1451           0 :         union smb_fileinfo gi;
    1452           0 :         union smb_setfileinfo si;
    1453           2 :         struct smb2_handle h1 = {{0}};
    1454           2 :         struct smb2_handle h2 = {{0}};
    1455           0 :         NTSTATUS status;
    1456           2 :         bool ret = true;
    1457             : 
    1458           2 :         smb2_deltree(tree1, BASEDIR);
    1459           2 :         smb2_util_mkdir(tree1, BASEDIR);
    1460             : 
    1461           2 :         torture_comment(torture, "Creating test file: file1.txt\n");
    1462             : 
    1463           2 :         c1 = (struct smb2_create) {
    1464             :                 .in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE,
    1465             :                 .in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
    1466             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    1467             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1468             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    1469             :                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
    1470             :                 .in.fname = BASEDIR "\\file1.txt",
    1471             :         };
    1472             : 
    1473           2 :         status = smb2_create(tree1, torture, &c1);
    1474           2 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    1475             :                                         "smb2_create failed\n");
    1476           2 :         h1 = c1.out.file.handle;
    1477             : 
    1478           2 :         torture_comment(torture, "Waitig for 5 secs..\n");
    1479           2 :         sleep(5);
    1480             : 
    1481           2 :         torture_comment(torture, "Creating test file: file2.txt\n");
    1482             : 
    1483           2 :         c2 = (struct smb2_create) {
    1484             :                 .in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE,
    1485             :                 .in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
    1486             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    1487             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1488             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    1489             :                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
    1490             :                 .in.fname = BASEDIR "\\file2.txt",
    1491             :         };
    1492             : 
    1493           2 :         status = smb2_create(tree1, torture, &c2);
    1494           2 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    1495             :                                         "smb2_create failed\n");
    1496           2 :         h2 = c2.out.file.handle;
    1497             : 
    1498           2 :         torture_comment(torture, "Renaming file1.txt --> tmp1.txt\n");
    1499             : 
    1500           2 :         si = (union smb_setfileinfo) {
    1501             :                 .rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION,
    1502             :                 .rename_information.in.file.handle = h1,
    1503             :                 .rename_information.in.new_name =
    1504             :                         BASEDIR "\\tmp1.txt",
    1505             :         };
    1506             : 
    1507           2 :         status = smb2_setinfo_file(tree1, &si);
    1508           2 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    1509             :                                         "smb2_setinfo_file failed\n");
    1510             : 
    1511           2 :         torture_comment(torture, "GetInfo of tmp1.txt\n");
    1512             : 
    1513           2 :         gi = (union smb_fileinfo) {
    1514             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    1515             :                 .generic.in.file.handle = h1,
    1516             :         };
    1517             : 
    1518           2 :         status = smb2_getinfo_file(tree1, torture, &gi);
    1519           2 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    1520             :                                         "smb2_getinfo_file failed\n");
    1521             : 
    1522           2 :         torture_comment(torture, "Check if timestamps are good after rename(file1.txt --> tmp1.txt).\n");
    1523             : 
    1524           2 :         torture_assert_nttime_equal(
    1525             :                 torture, c1.out.write_time, gi.all_info.out.write_time,
    1526             :                 "Bad timestamp\n");
    1527           2 :         torture_assert_nttime_equal(
    1528             :                 torture, c1.out.change_time, gi.all_info.out.change_time,
    1529             :                 "Bad timestamp\n");
    1530             : 
    1531           2 :         torture_comment(torture, "Renaming file2.txt --> file1.txt\n");
    1532             : 
    1533           2 :         si = (union smb_setfileinfo) {
    1534             :                 .rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION,
    1535             :                 .rename_information.in.file.handle = h2,
    1536             :                 .rename_information.in.new_name =
    1537             :                         BASEDIR "\\file1.txt",
    1538             :         };
    1539           2 :         status = smb2_setinfo_file(tree1, &si);
    1540           2 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    1541             :                                         "smb2_setinfo_file failed\n");
    1542             : 
    1543           2 :         torture_comment(torture, "GetInfo of file1.txt\n");
    1544             : 
    1545           2 :         gi = (union smb_fileinfo) {
    1546             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    1547             :                 .generic.in.file.handle = h2,
    1548             :         };
    1549             : 
    1550           2 :         status = smb2_getinfo_file(tree1, torture, &gi);
    1551           2 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done,
    1552             :                                         "smb2_getinfo_file failed\n");
    1553             : 
    1554           2 :         torture_comment(torture, "Check if timestamps are good after rename(file2.txt --> file1.txt).\n");
    1555             : 
    1556           2 :         torture_assert_nttime_equal(
    1557             :                 torture, c2.out.write_time, gi.all_info.out.write_time,
    1558             :                 "Bad timestamp\n");
    1559           2 :         torture_assert_nttime_equal(
    1560             :                 torture, c2.out.change_time, gi.all_info.out.change_time,
    1561             :                 "Bad timestamp\n");
    1562             : 
    1563           2 : done:
    1564           2 :         if (!smb2_util_handle_empty(h1)) {
    1565           2 :                 smb2_util_close(tree1, h1);
    1566             :         }
    1567           2 :         if (!smb2_util_handle_empty(h2)) {
    1568           2 :                 smb2_util_close(tree1, h2);
    1569             :         }
    1570           2 :         smb2_deltree(tree1, BASEDIR);
    1571           2 :         return ret;
    1572             : }
    1573             : 
    1574           2 : static bool test_smb2_close_full_information(struct torture_context *torture,
    1575             :                                         struct smb2_tree *tree1,
    1576             :                                         struct smb2_tree *tree2)
    1577             : {
    1578           0 :         union smb_close cl;
    1579           2 :         struct smb2_create io = {0};
    1580           2 :         struct smb2_handle h1 = {{0}};
    1581           2 :         struct smb2_handle h2 = {{0}};
    1582           2 :         struct smb2_handle h3 = {{0}};
    1583           0 :         union smb_setfileinfo sinfo;
    1584           0 :         NTSTATUS status;
    1585           2 :         const char *fname_src = "request.dat";
    1586           2 :         const char *fname_dst = "renamed.dat";
    1587           2 :         bool ret = true;
    1588             : 
    1589             :         /* Start with a tidy share. */
    1590           2 :         smb2_util_unlink(tree1, fname_src);
    1591           2 :         smb2_util_unlink(tree1, fname_dst);
    1592             : 
    1593             :         /* Create the test file, and leave it open. */
    1594           2 :         io.in.fname = fname_src;
    1595           2 :         io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE;
    1596           2 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
    1597           2 :         io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1598             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1599             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1600           2 :         status = smb2_create(tree1, tree1, &io);
    1601           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1602           2 :         h1 = io.out.file.handle;
    1603           2 :         CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    1604             : 
    1605             :         /* Open the test file on the second connection. */
    1606           2 :         ZERO_STRUCT(io);
    1607           2 :         io.in.fname = fname_src;
    1608           2 :         io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE;
    1609           2 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    1610           2 :         io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1611             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1612             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1613           2 :         status = smb2_create(tree2, tree2, &io);
    1614           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1615           2 :         h2 = io.out.file.handle;
    1616             : 
    1617             :         /* Now open for rename on the first connection. */
    1618           2 :         ZERO_STRUCT(io);
    1619           2 :         io.in.fname = fname_src;
    1620           2 :         io.in.desired_access = SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE;
    1621           2 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    1622           2 :         io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1623             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1624             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1625           2 :         status = smb2_create(tree1, tree1, &io);
    1626           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1627           2 :         h3 = io.out.file.handle;
    1628             : 
    1629             :         /* Do the rename. */
    1630           2 :         ZERO_STRUCT(sinfo);
    1631           2 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
    1632           2 :         sinfo.rename_information.in.file.handle = h3;
    1633           2 :         sinfo.rename_information.in.new_name = fname_dst;
    1634           2 :         status = smb2_setinfo_file(tree1, &sinfo);
    1635           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1636             : 
    1637             :         /* And close h3. */
    1638           2 :         ZERO_STRUCT(cl.smb2);
    1639           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
    1640           2 :         cl.smb2.in.file.handle = h3;
    1641           2 :         status = smb2_close(tree1, &cl.smb2);
    1642           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1643           2 :         ZERO_STRUCT(h3);
    1644             : 
    1645             :         /*
    1646             :          * Close h1 with SMB2_CLOSE_FLAGS_FULL_INFORMATION.
    1647             :          * Ensure we get data.
    1648             :          */
    1649           2 :         ZERO_STRUCT(cl.smb2);
    1650           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
    1651           2 :         cl.smb2.in.file.handle = h1;
    1652           2 :         cl.smb2.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
    1653           2 :         status = smb2_close(tree1, &cl.smb2);
    1654           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1655           2 :         ZERO_STRUCT(h1);
    1656           2 :         CHECK_VAL(cl.smb2.out.file_attr, 0x20);
    1657             : 
    1658             :         /*
    1659             :          * Wait 3 seconds for name change to propagate
    1660             :          * to the other connection.
    1661             :          */
    1662           2 :         sleep(3);
    1663             : 
    1664             :         /*
    1665             :          * Close h2 with SMB2_CLOSE_FLAGS_FULL_INFORMATION.
    1666             :          * This is on connection2.
    1667             :          * Ensure we get data.
    1668             :          */
    1669           2 :         ZERO_STRUCT(cl.smb2);
    1670           2 :         cl.smb2.level = RAW_CLOSE_SMB2;
    1671           2 :         cl.smb2.in.file.handle = h2;
    1672           2 :         cl.smb2.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
    1673           2 :         status = smb2_close(tree2, &cl.smb2);
    1674           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1675           2 :         ZERO_STRUCT(h2);
    1676           2 :         CHECK_VAL(cl.smb2.out.file_attr, 0x20);
    1677             : 
    1678           2 :   done:
    1679             : 
    1680           2 :         if (h1.data[0] != 0 || h1.data[1] != 0) {
    1681           0 :                 smb2_util_close(tree1, h1);
    1682             :         }
    1683           2 :         if (h2.data[0] != 0 || h2.data[1] != 0) {
    1684           0 :                 smb2_util_close(tree2, h2);
    1685             :         }
    1686           2 :         if (h3.data[0] != 0 || h3.data[1] != 0) {
    1687           0 :                 smb2_util_close(tree1, h3);
    1688             :         }
    1689             : 
    1690           2 :         smb2_util_unlink(tree1, fname_src);
    1691           2 :         smb2_util_unlink(tree1, fname_dst);
    1692             : 
    1693           2 :         return ret;
    1694             : }
    1695             : 
    1696             : /*
    1697             :    basic testing of SMB2 rename
    1698             :  */
    1699        2354 : struct torture_suite *torture_smb2_rename_init(TALLOC_CTX *ctx)
    1700             : {
    1701         125 :         struct torture_suite *suite =
    1702        2354 :                 torture_suite_create(ctx, "rename");
    1703             : 
    1704        2354 :         torture_suite_add_1smb2_test(suite, "simple",
    1705             :                 torture_smb2_rename_simple);
    1706             : 
    1707        2354 :         torture_suite_add_1smb2_test(suite, "simple_modtime",
    1708             :                 torture_smb2_rename_simple_modtime);
    1709             : 
    1710        2354 :         torture_suite_add_1smb2_test(suite, "simple_nodelete",
    1711             :                 torture_smb2_rename_simple2);
    1712             : 
    1713        2354 :         torture_suite_add_1smb2_test(suite, "no_sharing",
    1714             :                 torture_smb2_rename_no_sharemode);
    1715             : 
    1716        2354 :         torture_suite_add_1smb2_test(suite,
    1717             :                 "share_delete_and_delete_access",
    1718             :                 torture_smb2_rename_with_delete_access);
    1719             : 
    1720        2354 :         torture_suite_add_1smb2_test(suite,
    1721             :                 "no_share_delete_but_delete_access",
    1722             :                 torture_smb2_rename_with_delete_access2);
    1723             : 
    1724        2354 :         torture_suite_add_1smb2_test(suite,
    1725             :                 "share_delete_no_delete_access",
    1726             :                 torture_smb2_rename_no_delete_access);
    1727             : 
    1728        2354 :         torture_suite_add_1smb2_test(suite,
    1729             :                 "no_share_delete_no_delete_access",
    1730             :                 torture_smb2_rename_no_delete_access2);
    1731             : 
    1732        2354 :         torture_suite_add_1smb2_test(suite,
    1733             :                 "msword",
    1734             :                 torture_smb2_rename_msword);
    1735             : 
    1736        2354 :         torture_suite_add_1smb2_test(
    1737             :                 suite, "rename_dir_openfile",
    1738             :                 torture_smb2_rename_dir_openfile);
    1739             : 
    1740        2354 :         torture_suite_add_1smb2_test(suite,
    1741             :                 "rename_dir_bench",
    1742             :                 torture_smb2_rename_dir_bench);
    1743             : 
    1744        2354 :         torture_suite_add_2smb2_test(suite,
    1745             :                 "close-full-information",
    1746             :                 test_smb2_close_full_information);
    1747             : 
    1748        2354 :         suite->description = talloc_strdup(suite, "smb2.rename tests");
    1749             : 
    1750        2354 :         return suite;
    1751             : }

Generated by: LCOV version 1.14