LCOV - code coverage report
Current view: top level - source4/torture/smb2 - create.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 1418 1666 85.1 %
Date: 2023-11-21 12:31:41 Functions: 31 32 96.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    SMB2 create test suite
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libcli/smb2/smb2.h"
      24             : #include "libcli/smb2/smb2_calls.h"
      25             : #include "libcli/smb/smbXcli_base.h"
      26             : #include "torture/torture.h"
      27             : #include "torture/util.h"
      28             : #include "torture/smb2/proto.h"
      29             : #include "librpc/gen_ndr/ndr_security.h"
      30             : #include "libcli/security/security.h"
      31             : 
      32             : #include "system/filesys.h"
      33             : #include "auth/credentials/credentials.h"
      34             : #include "lib/cmdline/cmdline.h"
      35             : #include "librpc/gen_ndr/security.h"
      36             : #include "lib/events/events.h"
      37             : 
      38             : #define FNAME "test_create.dat"
      39             : #define DNAME "smb2_open"
      40             : 
      41             : #define CHECK_STATUS(status, correct) do { \
      42             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      43             :                 torture_result(tctx, TORTURE_FAIL, \
      44             :                         "(%s) Incorrect status %s - should be %s\n", \
      45             :                          __location__, nt_errstr(status), nt_errstr(correct)); \
      46             :                 return false; \
      47             :         }} while (0)
      48             : 
      49             : #define CHECK_EQUAL(v, correct) do { \
      50             :         if (v != correct) { \
      51             :                 torture_result(tctx, TORTURE_FAIL, \
      52             :                         "(%s) Incorrect value for %s 0x%08llx - " \
      53             :                         "should be 0x%08llx\n", \
      54             :                          __location__, #v, \
      55             :                         (unsigned long long)v, \
      56             :                         (unsigned long long)correct); \
      57             :                 return false;                                   \
      58             :         }} while (0)
      59             : 
      60             : #define CHECK_TIME(t, field) do { \
      61             :         time_t t1, t2; \
      62             :         finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
      63             :         finfo.all_info.in.file.handle = h1; \
      64             :         status = smb2_getinfo_file(tree, tctx, &finfo); \
      65             :         CHECK_STATUS(status, NT_STATUS_OK); \
      66             :         t1 = t & ~1; \
      67             :         t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
      68             :         if (abs(t1-t2) > 2) { \
      69             :                 torture_result(tctx, TORTURE_FAIL, \
      70             :                         "(%s) wrong time for field %s  %s - %s\n", \
      71             :                         __location__, #field, \
      72             :                         timestring(tctx, t1), \
      73             :                         timestring(tctx, t2)); \
      74             :                 dump_all_info(tctx, &finfo); \
      75             :                 ret = false; \
      76             :         }} while (0)
      77             : 
      78             : #define CHECK_NTTIME(t, field) do { \
      79             :         NTTIME t2; \
      80             :         finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
      81             :         finfo.all_info.in.file.handle = h1; \
      82             :         status = smb2_getinfo_file(tree, tctx, &finfo); \
      83             :         CHECK_STATUS(status, NT_STATUS_OK); \
      84             :         t2 = finfo.all_info.out.field; \
      85             :         if (llabs((int64_t)(t-t2)) > 20000) { \
      86             :                 torture_result(tctx, TORTURE_FAIL, \
      87             :                         "(%s) wrong time for field %s  %s - %s\n", \
      88             :                        __location__, #field, \
      89             :                        nt_time_string(tctx, t), \
      90             :                        nt_time_string(tctx, t2)); \
      91             :                 dump_all_info(tctx, &finfo); \
      92             :                 ret = false; \
      93             :         }} while (0)
      94             : 
      95             : #define CHECK_ALL_INFO(v, field) do { \
      96             :         finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
      97             :         finfo.all_info.in.file.handle = h1; \
      98             :         status = smb2_getinfo_file(tree, tctx, &finfo); \
      99             :         CHECK_STATUS(status, NT_STATUS_OK); \
     100             :         if ((v) != (finfo.all_info.out.field)) { \
     101             :                torture_result(tctx, TORTURE_FAIL, \
     102             :                         "(%s) wrong value for field %s  0x%x - 0x%x\n", \
     103             :                         __location__, #field, (int)v,\
     104             :                         (int)(finfo.all_info.out.field)); \
     105             :                 dump_all_info(tctx, &finfo); \
     106             :                 ret = false; \
     107             :         }} while (0)
     108             : 
     109             : #define CHECK_VAL(v, correct) do { \
     110             :         if ((v) != (correct)) { \
     111             :                 torture_result(tctx, TORTURE_FAIL, \
     112             :                         "(%s) wrong value for %s  0x%x - should be 0x%x\n", \
     113             :                        __location__, #v, (int)(v), (int)correct); \
     114             :                 ret = false; \
     115             :         }} while (0)
     116             : 
     117             : #define SET_ATTRIB(sattrib) do { \
     118             :         union smb_setfileinfo sfinfo; \
     119             :         ZERO_STRUCT(sfinfo.basic_info.in); \
     120             :         sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
     121             :         sfinfo.basic_info.in.file.handle = h1; \
     122             :         sfinfo.basic_info.in.attrib = sattrib; \
     123             :         status = smb2_setinfo_file(tree, &sfinfo); \
     124             :         if (!NT_STATUS_IS_OK(status)) { \
     125             :                 torture_comment(tctx, \
     126             :                     "(%s) Failed to set attrib 0x%x on %s\n", \
     127             :                        __location__, (unsigned int)(sattrib), fname); \
     128             :         }} while (0)
     129             : 
     130             : /*
     131             :   test some interesting combinations found by gentest
     132             :  */
     133           6 : static bool test_create_gentest(struct torture_context *tctx, struct smb2_tree *tree)
     134             : {
     135           0 :         struct smb2_create io;
     136           0 :         NTSTATUS status;
     137           0 :         uint32_t access_mask, file_attributes_set;
     138           0 :         uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
     139           0 :         uint32_t not_a_directory_mask, unexpected_mask;
     140           0 :         union smb_fileinfo q;
     141             : 
     142           6 :         ZERO_STRUCT(io);
     143           6 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     144           6 :         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
     145           6 :         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     146           6 :         io.in.share_access =
     147             :                 NTCREATEX_SHARE_ACCESS_DELETE|
     148             :                 NTCREATEX_SHARE_ACCESS_READ|
     149             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     150           6 :         io.in.create_options = 0;
     151           6 :         io.in.fname = FNAME;
     152             : 
     153           6 :         status = smb2_create(tree, tctx, &io);
     154           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     155             : 
     156           6 :         status = smb2_util_close(tree, io.out.file.handle);
     157           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     158             : 
     159           6 :         io.in.create_options = 0xF0000000;
     160           6 :         status = smb2_create(tree, tctx, &io);
     161           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     162             : 
     163           6 :         io.in.create_options = 0;
     164             : 
     165           6 :         io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
     166           6 :         status = smb2_create(tree, tctx, &io);
     167           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     168             : 
     169           1 :         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
     170           1 :         status = smb2_create(tree, tctx, &io);
     171           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     172             : 
     173           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
     174           1 :         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
     175           1 :         status = smb2_create(tree, tctx, &io);
     176           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     177             : 
     178           1 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
     179           1 :         io.in.desired_access = 0x08000000;
     180           1 :         status = smb2_create(tree, tctx, &io);
     181           1 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
     182             : 
     183           1 :         io.in.desired_access = 0x04000000;
     184           1 :         status = smb2_create(tree, tctx, &io);
     185           1 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
     186             : 
     187           1 :         io.in.file_attributes = 0;
     188           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     189           1 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     190           1 :         ok_mask = 0;
     191           1 :         not_supported_mask = 0;
     192           1 :         invalid_parameter_mask = 0;
     193           1 :         not_a_directory_mask = 0;
     194           1 :         unexpected_mask = 0;
     195             :         {
     196           0 :                 int i;
     197          33 :                 for (i=0;i<32;i++) {
     198          32 :                         io.in.create_options = (uint32_t)1<<i;
     199          32 :                         if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
     200           1 :                                 continue;
     201             :                         }
     202          31 :                         status = smb2_create(tree, tctx, &io);
     203          31 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
     204           3 :                                 not_supported_mask |= 1<<i;
     205          28 :                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
     206           8 :                                 invalid_parameter_mask |= 1<<i;
     207          20 :                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
     208           1 :                                 not_a_directory_mask |= 1<<i;
     209          19 :                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
     210          19 :                                 ok_mask |= 1<<i;
     211          19 :                                 status = smb2_util_close(tree, io.out.file.handle);
     212          19 :                                 CHECK_STATUS(status, NT_STATUS_OK);
     213             :                         } else {
     214           0 :                                 unexpected_mask |= 1<<i;
     215           0 :                                 torture_comment(tctx,
     216             :                                     "create option 0x%08x returned %s\n",
     217             :                                     1<<i, nt_errstr(status));
     218             :                         }
     219             :                 }
     220             :         }
     221           1 :         io.in.create_options = 0;
     222             : 
     223           1 :         CHECK_EQUAL(ok_mask,                0x00efcf7e);
     224           1 :         CHECK_EQUAL(not_a_directory_mask,   0x00000001);
     225           1 :         CHECK_EQUAL(not_supported_mask,     0x00102080);
     226           1 :         CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
     227           1 :         CHECK_EQUAL(unexpected_mask,        0x00000000);
     228             : 
     229           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     230           1 :         io.in.file_attributes = 0;
     231           1 :         access_mask = 0;
     232             :         {
     233           0 :                 int i;
     234          33 :                 for (i=0;i<32;i++) {
     235          32 :                         io.in.desired_access = (uint32_t)1<<i;
     236          32 :                         status = smb2_create(tree, tctx, &io);
     237          32 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
     238          19 :                             NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
     239          13 :                                 access_mask |= io.in.desired_access;
     240             :                         } else {
     241          19 :                                 CHECK_STATUS(status, NT_STATUS_OK);
     242          19 :                                 status = smb2_util_close(tree, io.out.file.handle);
     243          19 :                                 CHECK_STATUS(status, NT_STATUS_OK);
     244             :                         }
     245             :                 }
     246             :         }
     247             : 
     248           1 :         if (TARGET_IS_WIN7(tctx)) {
     249           0 :                 CHECK_EQUAL(access_mask, 0x0de0fe00);
     250           1 :         } else if (torture_setting_bool(tctx, "samba4", false)) {
     251           1 :                 CHECK_EQUAL(access_mask, 0x0cf0fe00);
     252             :         } else {
     253           0 :                 CHECK_EQUAL(access_mask, 0x0df0fe00);
     254             :         }
     255             : 
     256           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     257           1 :         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
     258           1 :         io.in.file_attributes = 0;
     259           1 :         ok_mask = 0;
     260           1 :         invalid_parameter_mask = 0;
     261           1 :         unexpected_mask = 0;
     262           1 :         file_attributes_set = 0;
     263             :         {
     264           0 :                 int i;
     265          33 :                 for (i=0;i<32;i++) {
     266          32 :                         io.in.file_attributes = (uint32_t)1<<i;
     267          32 :                         if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
     268           1 :                                 continue;
     269             :                         }
     270          31 :                         smb2_deltree(tree, FNAME);
     271          31 :                         status = smb2_create(tree, tctx, &io);
     272          31 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
     273          19 :                                 invalid_parameter_mask |= 1<<i;
     274          12 :                         } else if (NT_STATUS_IS_OK(status)) {
     275           0 :                                 uint32_t expected;
     276          12 :                                 ok_mask |= 1<<i;
     277             : 
     278          12 :                                 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
     279          12 :                                 io.out.file_attr &= ~FILE_ATTRIBUTE_NONINDEXED;
     280          12 :                                 CHECK_EQUAL(io.out.file_attr, expected);
     281          12 :                                 file_attributes_set |= io.out.file_attr;
     282             : 
     283          12 :                                 status = smb2_util_close(tree, io.out.file.handle);
     284          12 :                                 CHECK_STATUS(status, NT_STATUS_OK);
     285             :                         } else {
     286           0 :                                 unexpected_mask |= 1<<i;
     287           0 :                                 torture_comment(tctx,
     288             :                                     "file attribute 0x%08x returned %s\n",
     289             :                                     1<<i, nt_errstr(status));
     290             :                         }
     291             :                 }
     292             :         }
     293             : 
     294           1 :         CHECK_EQUAL(ok_mask,                0x00003fb7);
     295           1 :         CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
     296           1 :         CHECK_EQUAL(unexpected_mask,        0x00000000);
     297           1 :         CHECK_EQUAL(file_attributes_set,    0x00001127);
     298             : 
     299           1 :         smb2_deltree(tree, FNAME);
     300             : 
     301             :         /*
     302             :          * Standalone servers doesn't support encryption
     303             :          */
     304           1 :         io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
     305           1 :         status = smb2_create(tree, tctx, &io);
     306           1 :         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
     307           1 :                 torture_comment(tctx,
     308             :                     "FILE_ATTRIBUTE_ENCRYPTED returned %s\n",
     309             :                     nt_errstr(status));
     310             :         } else {
     311           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     312           0 :                 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
     313           0 :                 status = smb2_util_close(tree, io.out.file.handle);
     314           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     315             :         }
     316             : 
     317           1 :         smb2_deltree(tree, FNAME);
     318             : 
     319           1 :         ZERO_STRUCT(io);
     320           1 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     321           1 :         io.in.file_attributes    = 0;
     322           1 :         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     323           1 :         io.in.share_access =
     324             :                 NTCREATEX_SHARE_ACCESS_READ|
     325             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     326           1 :         io.in.create_options = 0;
     327           1 :         io.in.fname = FNAME ":stream1";
     328           1 :         status = smb2_create(tree, tctx, &io);
     329           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     330             : 
     331           1 :         status = smb2_util_close(tree, io.out.file.handle);
     332           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     333             : 
     334           1 :         io.in.fname = FNAME;
     335           1 :         io.in.file_attributes = 0x8040;
     336           1 :         io.in.share_access =
     337             :                 NTCREATEX_SHARE_ACCESS_READ;
     338           1 :         status = smb2_create(tree, tctx, &io);
     339           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     340             : 
     341           1 :         io.in.fname = FNAME;
     342           1 :         io.in.file_attributes = 0;
     343           1 :         io.in.desired_access  = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
     344           1 :         io.in.query_maximal_access = true;
     345           1 :         status = smb2_create(tree, tctx, &io);
     346           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     347           1 :         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
     348             : 
     349           1 :         q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
     350           1 :         q.access_information.in.file.handle = io.out.file.handle;
     351           1 :         status = smb2_getinfo_file(tree, tctx, &q);
     352           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     353           1 :         CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
     354             : 
     355           1 :         io.in.file_attributes = 0;
     356           1 :         io.in.desired_access  = 0;
     357           1 :         io.in.query_maximal_access = false;
     358           1 :         io.in.share_access = 0;
     359           1 :         status = smb2_create(tree, tctx, &io);
     360           1 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
     361             : 
     362           1 :         smb2_deltree(tree, FNAME);
     363             : 
     364           1 :         return true;
     365             : }
     366             : 
     367             : 
     368             : /*
     369             :   try the various request blobs
     370             :  */
     371           6 : static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tree)
     372             : {
     373           0 :         struct smb2_create io;
     374           0 :         NTSTATUS status;
     375             : 
     376           6 :         smb2_deltree(tree, FNAME);
     377             : 
     378           6 :         ZERO_STRUCT(io);
     379           6 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     380           6 :         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
     381           6 :         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     382           6 :         io.in.share_access =
     383             :                 NTCREATEX_SHARE_ACCESS_DELETE|
     384             :                 NTCREATEX_SHARE_ACCESS_READ|
     385             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     386           6 :         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
     387             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
     388             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
     389             :                                           0x00200000;
     390           6 :         io.in.fname = FNAME;
     391             : 
     392           6 :         status = smb2_create(tree, tctx, &io);
     393           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     394             : 
     395           6 :         status = smb2_util_close(tree, io.out.file.handle);
     396           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     397             : 
     398           6 :         torture_comment(tctx, "Testing alloc size\n");
     399             :         /* FIXME We use 1M cause that's the rounded size of Samba.
     400             :          * We should ask the server for the cluster size and calculate it
     401             :          * correctly. */
     402           6 :         io.in.alloc_size = 0x00100000;
     403           6 :         status = smb2_create(tree, tctx, &io);
     404           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     405           6 :         CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
     406             : 
     407           6 :         status = smb2_util_close(tree, io.out.file.handle);
     408           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     409             : 
     410           6 :         torture_comment(tctx, "Testing durable open\n");
     411           6 :         io.in.durable_open = true;
     412           6 :         status = smb2_create(tree, tctx, &io);
     413           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     414             : 
     415           6 :         status = smb2_util_close(tree, io.out.file.handle);
     416           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     417             : 
     418           6 :         torture_comment(tctx, "Testing query maximal access\n");
     419           6 :         io.in.query_maximal_access = true;
     420           6 :         status = smb2_create(tree, tctx, &io);
     421           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     422           6 :         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
     423             : 
     424           6 :         status = smb2_util_close(tree, io.out.file.handle);
     425           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     426             : 
     427           6 :         torture_comment(tctx, "Testing timewarp\n");
     428           6 :         io.in.timewarp = 10000;
     429           6 :         status = smb2_create(tree, tctx, &io);
     430           6 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     431           1 :         io.in.timewarp = 0;
     432             : 
     433           1 :         torture_comment(tctx, "Testing query_on_disk\n");
     434           1 :         io.in.query_on_disk_id = true;
     435           1 :         status = smb2_create(tree, tctx, &io);
     436           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     437             : 
     438           1 :         status = smb2_util_close(tree, io.out.file.handle);
     439           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     440             : 
     441           1 :         torture_comment(tctx, "Testing unknown tag\n");
     442           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     443             :                                       "FooO", data_blob(NULL, 0));
     444           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     445             : 
     446           1 :         status = smb2_create(tree, tctx, &io);
     447           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     448             : 
     449           1 :         status = smb2_util_close(tree, io.out.file.handle);
     450           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     451             : 
     452           1 :         torture_comment(tctx, "Testing bad tag length 0\n");
     453           1 :         ZERO_STRUCT(io.in.blobs);
     454           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     455             :                                       "x", data_blob(NULL, 0));
     456           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     457           1 :         status = smb2_create(tree, tctx, &io);
     458           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     459             : 
     460           1 :         torture_comment(tctx, "Testing bad tag length 1\n");
     461           1 :         ZERO_STRUCT(io.in.blobs);
     462           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     463             :                                       "x", data_blob(NULL, 0));
     464           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     465           1 :         status = smb2_create(tree, tctx, &io);
     466           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     467             : 
     468           1 :         torture_comment(tctx, "Testing bad tag length 2\n");
     469           1 :         ZERO_STRUCT(io.in.blobs);
     470           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     471             :                                       "xx", data_blob(NULL, 0));
     472           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     473           1 :         status = smb2_create(tree, tctx, &io);
     474           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     475             : 
     476           1 :         torture_comment(tctx, "Testing bad tag length 3\n");
     477           1 :         ZERO_STRUCT(io.in.blobs);
     478           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     479             :                                       "xxx", data_blob(NULL, 0));
     480           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     481           1 :         status = smb2_create(tree, tctx, &io);
     482           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     483             : 
     484           1 :         torture_comment(tctx, "Testing tag length 4\n");
     485           1 :         ZERO_STRUCT(io.in.blobs);
     486           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     487             :                                       "xxxx", data_blob(NULL, 0));
     488           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     489           1 :         status = smb2_create(tree, tctx, &io);
     490           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     491             : 
     492           1 :         torture_comment(tctx, "Testing tag length 5\n");
     493           1 :         ZERO_STRUCT(io.in.blobs);
     494           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     495             :                                       "xxxxx", data_blob(NULL, 0));
     496           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     497           1 :         status = smb2_create(tree, tctx, &io);
     498           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     499             : 
     500           1 :         torture_comment(tctx, "Testing tag length 6\n");
     501           1 :         ZERO_STRUCT(io.in.blobs);
     502           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     503             :                                       "xxxxxx", data_blob(NULL, 0));
     504           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     505           1 :         status = smb2_create(tree, tctx, &io);
     506           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     507             : 
     508           1 :         torture_comment(tctx, "Testing tag length 7\n");
     509           1 :         ZERO_STRUCT(io.in.blobs);
     510           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     511             :                                       "xxxxxxx", data_blob(NULL, 0));
     512           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     513           1 :         status = smb2_create(tree, tctx, &io);
     514           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     515             : 
     516           1 :         torture_comment(tctx, "Testing tag length 8\n");
     517           1 :         ZERO_STRUCT(io.in.blobs);
     518           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     519             :                                       "xxxxxxxx", data_blob(NULL, 0));
     520           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     521           1 :         status = smb2_create(tree, tctx, &io);
     522           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     523             : 
     524           1 :         torture_comment(tctx, "Testing tag length 16\n");
     525           1 :         ZERO_STRUCT(io.in.blobs);
     526           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     527             :                                       "xxxxxxxxxxxxxxxx", data_blob(NULL, 0));
     528           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     529           1 :         status = smb2_create(tree, tctx, &io);
     530           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     531             : 
     532           1 :         torture_comment(tctx, "Testing tag length 17\n");
     533           1 :         ZERO_STRUCT(io.in.blobs);
     534           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     535             :                                       "xxxxxxxxxxxxxxxxx", data_blob(NULL, 0));
     536           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     537           1 :         status = smb2_create(tree, tctx, &io);
     538           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     539             : 
     540           1 :         torture_comment(tctx, "Testing tag length 34\n");
     541           1 :         ZERO_STRUCT(io.in.blobs);
     542           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     543             :                                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     544             :                                       data_blob(NULL, 0));
     545           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     546           1 :         status = smb2_create(tree, tctx, &io);
     547           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     548             : 
     549           1 :         smb2_deltree(tree, FNAME);
     550             : 
     551           1 :         return true;
     552             : }
     553             : 
     554             : #define FAIL_UNLESS(__cond)                                     \
     555             :         do {                                                    \
     556             :                 if (__cond) {} else {                           \
     557             :                         torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n",    \
     558             :                                __location__, #__cond);          \
     559             :                         ret = false; goto done;                 \
     560             :                 }                                               \
     561             :         } while(0)
     562             : 
     563             : /*
     564             :   try creating with acls
     565             :  */
     566          12 : static bool test_create_acl_ext(struct torture_context *tctx, struct smb2_tree *tree, bool test_dir)
     567             : {
     568          12 :         bool ret = true;
     569           0 :         struct smb2_create io;
     570           0 :         NTSTATUS status;
     571           0 :         struct security_ace ace;
     572           0 :         struct security_descriptor *sd;
     573           0 :         struct dom_sid *test_sid;
     574          12 :         union smb_fileinfo q = {};
     575          12 :         uint32_t attrib =
     576             :             FILE_ATTRIBUTE_HIDDEN |
     577             :             FILE_ATTRIBUTE_SYSTEM |
     578             :             (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
     579          12 :         NTSTATUS (*delete_func)(struct smb2_tree *, const char *) =
     580          12 :             test_dir ? smb2_util_rmdir : smb2_util_unlink;
     581             : 
     582          12 :         ZERO_STRUCT(ace);
     583             : 
     584          12 :         smb2_deltree(tree, FNAME);
     585             : 
     586          12 :         ZERO_STRUCT(io);
     587          12 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     588          12 :         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
     589          12 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
     590          12 :         io.in.share_access =
     591             :                 NTCREATEX_SHARE_ACCESS_DELETE |
     592             :                 NTCREATEX_SHARE_ACCESS_READ |
     593             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     594          12 :         io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT | 0x00200000 |
     595             :             (test_dir ?  NTCREATEX_OPTIONS_DIRECTORY :
     596             :                 (NTCREATEX_OPTIONS_NON_DIRECTORY_FILE));
     597             : 
     598          12 :         io.in.fname = FNAME;
     599             : 
     600          12 :         torture_comment(tctx, "basic create\n");
     601             : 
     602          12 :         status = smb2_create(tree, tctx, &io);
     603          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     604             : 
     605          12 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
     606          12 :         q.query_secdesc.in.file.handle = io.out.file.handle;
     607          12 :         q.query_secdesc.in.secinfo_flags =
     608             :                 SECINFO_OWNER |
     609             :                 SECINFO_GROUP |
     610             :                 SECINFO_DACL;
     611          12 :         status = smb2_getinfo_file(tree, tctx, &q);
     612          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     613          12 :         sd = q.query_secdesc.out.sd;
     614             : 
     615          12 :         status = smb2_util_close(tree, io.out.file.handle);
     616          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     617          12 :         status = delete_func(tree, FNAME);
     618          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     619             : 
     620          12 :         torture_comment(tctx, "adding a new ACE\n");
     621          12 :         test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS);
     622             : 
     623          12 :         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
     624          12 :         ace.flags = 0;
     625          12 :         ace.access_mask = SEC_STD_ALL;
     626          12 :         ace.trustee = *test_sid;
     627             : 
     628          12 :         status = security_descriptor_dacl_add(sd, &ace);
     629          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     630             : 
     631          12 :         torture_comment(tctx, "creating a file with an initial ACL\n");
     632             : 
     633          12 :         io.in.sec_desc = sd;
     634          12 :         status = smb2_create(tree, tctx, &io);
     635          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     636             : 
     637          12 :         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
     638             : 
     639          12 :         status = smb2_util_close(tree, io.out.file.handle);
     640          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     641          12 :         status = delete_func(tree, FNAME);
     642          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     643             : 
     644          12 :         torture_comment(tctx, "creating with attributes\n");
     645             : 
     646          12 :         io.in.sec_desc = NULL;
     647          12 :         io.in.file_attributes = attrib;
     648          12 :         status = smb2_create(tree, tctx, &io);
     649          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     650             : 
     651          12 :         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
     652             : 
     653          11 :         status = smb2_util_close(tree, io.out.file.handle);
     654          11 :         CHECK_STATUS(status, NT_STATUS_OK);
     655          11 :         status = delete_func(tree, FNAME);
     656          11 :         CHECK_STATUS(status, NT_STATUS_OK);
     657             : 
     658          11 :         torture_comment(tctx, "creating with attributes and ACL\n");
     659             : 
     660          11 :         io.in.sec_desc = sd;
     661          11 :         io.in.file_attributes = attrib;
     662          11 :         status = smb2_create(tree, tctx, &io);
     663          11 :         CHECK_STATUS(status, NT_STATUS_OK);
     664             : 
     665          11 :         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
     666          11 :         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
     667             : 
     668          11 :         status = smb2_util_close(tree, io.out.file.handle);
     669          11 :         CHECK_STATUS(status, NT_STATUS_OK);
     670          11 :         status = delete_func(tree, FNAME);
     671          11 :         CHECK_STATUS(status, NT_STATUS_OK);
     672             : 
     673          11 :         torture_comment(tctx, "creating with attributes, ACL and owner\n");
     674          11 :         sd = security_descriptor_dacl_create(tctx,
     675             :                                         0, SID_WORLD, SID_BUILTIN_USERS,
     676             :                                         SID_WORLD,
     677             :                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
     678             :                                         SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
     679             :                                         0,
     680             :                                         NULL);
     681             : 
     682          11 :         io.in.sec_desc = sd;
     683          11 :         io.in.file_attributes = attrib;
     684          11 :         status = smb2_create(tree, tctx, &io);
     685          11 :         CHECK_STATUS(status, NT_STATUS_OK);
     686             : 
     687          11 :         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
     688          11 :         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
     689             : 
     690          12 :  done:
     691          12 :         status = smb2_util_close(tree, io.out.file.handle);
     692          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     693          12 :         status = delete_func(tree, FNAME);
     694          12 :         CHECK_STATUS(status, NT_STATUS_OK);
     695             : 
     696          12 :         return ret;
     697             : }
     698             : 
     699             : /*
     700             :   test SMB2 open
     701             : */
     702           6 : static bool test_smb2_open(struct torture_context *tctx,
     703             :                            struct smb2_tree *tree)
     704             : {
     705           0 :         union smb_open io;
     706           0 :         union smb_fileinfo finfo;
     707           6 :         const char *fname = DNAME "\\torture_ntcreatex.txt";
     708           6 :         const char *dname = DNAME "\\torture_ntcreatex.dir";
     709           0 :         NTSTATUS status;
     710           6 :         struct smb2_handle h = {{0}};
     711           6 :         struct smb2_handle h1 = {{0}};
     712           6 :         bool ret = true;
     713           0 :         size_t i;
     714           0 :         struct {
     715             :                 uint32_t create_disp;
     716             :                 bool with_file;
     717             :                 NTSTATUS correct_status;
     718           6 :         } open_funcs[] = {
     719             :                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_OK },
     720             :                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_OK },
     721             :                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
     722             :                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
     723             :                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
     724             :                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
     725             :                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
     726             :                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
     727             :                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_OK },
     728             :                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
     729             :                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_OK },
     730             :                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_OK },
     731             :                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
     732             :                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
     733             :         };
     734             : 
     735           6 :         torture_comment(tctx, "Checking SMB2 Open\n");
     736             : 
     737           6 :         smb2_util_unlink(tree, fname);
     738           6 :         smb2_util_rmdir(tree, dname);
     739             : 
     740           6 :         status = torture_smb2_testdir(tree, DNAME, &h);
     741           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     742             : 
     743           6 :         ZERO_STRUCT(io.smb2);
     744             :         /* reasonable default parameters */
     745           6 :         io.generic.level = RAW_OPEN_SMB2;
     746           6 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     747           6 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     748           6 :         io.smb2.in.alloc_size = 1024*1024;
     749           6 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     750           6 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     751           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     752           6 :         io.smb2.in.create_options = 0;
     753           6 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     754           6 :         io.smb2.in.security_flags = 0;
     755           6 :         io.smb2.in.fname = fname;
     756             : 
     757             :         /* test the create disposition */
     758          90 :         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
     759          84 :                 if (open_funcs[i].with_file) {
     760          42 :                         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     761          42 :                         status= smb2_create(tree, tctx, &(io.smb2));
     762          42 :                         if (!NT_STATUS_IS_OK(status)) {
     763           0 :                                 torture_comment(tctx,
     764             :                                     "Failed to create file %s status %s %zu\n",
     765             :                                     fname, nt_errstr(status), i);
     766             : 
     767           0 :                                 ret = false;
     768           0 :                                 goto done;
     769             :                         }
     770          42 :                         smb2_util_close(tree, io.smb2.out.file.handle);
     771             :                 }
     772          84 :                 io.smb2.in.create_disposition = open_funcs[i].create_disp;
     773          84 :                 status = smb2_create(tree, tctx, &(io.smb2));
     774          84 :                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
     775           0 :                         torture_comment(tctx,
     776             :                             "(%s) incorrect status %s should be %s (i=%zu "
     777             :                             "with_file=%d open_disp=%d)\n",
     778             :                          __location__, nt_errstr(status),
     779             :                         nt_errstr(open_funcs[i].correct_status),
     780           0 :                         i, (int)open_funcs[i].with_file,
     781           0 :                         (int)open_funcs[i].create_disp);
     782             : 
     783           0 :                         ret = false;
     784           0 :                         goto done;
     785             :                 }
     786          84 :                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
     787          66 :                         smb2_util_close(tree, io.smb2.out.file.handle);
     788          66 :                         smb2_util_unlink(tree, fname);
     789             :                 }
     790             :         }
     791             : 
     792             :         /* basic field testing */
     793           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     794             : 
     795           6 :         status = smb2_create(tree, tctx, &(io.smb2));
     796           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     797           6 :         h1 = io.smb2.out.file.handle;
     798             : 
     799           6 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
     800           6 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
     801           6 :         CHECK_NTTIME(io.smb2.out.create_time, create_time);
     802           6 :         CHECK_NTTIME(io.smb2.out.access_time, access_time);
     803           6 :         CHECK_NTTIME(io.smb2.out.write_time, write_time);
     804           6 :         CHECK_NTTIME(io.smb2.out.change_time, change_time);
     805           6 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
     806           6 :         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
     807           6 :         CHECK_ALL_INFO(io.smb2.out.size, size);
     808             : 
     809             :         /* check fields when the file already existed */
     810           6 :         smb2_util_close(tree, h1);
     811           6 :         smb2_util_unlink(tree, fname);
     812             : 
     813           6 :         status = smb2_create_complex_file(tctx, tree, fname, &h1);
     814           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     815             : 
     816           1 :         smb2_util_close(tree, h1);
     817             : 
     818           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     819           1 :         status = smb2_create(tree, tctx, &(io.smb2));
     820           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     821           1 :         h1 = io.smb2.out.file.handle;
     822             : 
     823           1 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
     824           1 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_EXISTED);
     825           1 :         CHECK_NTTIME(io.smb2.out.create_time, create_time);
     826           1 :         CHECK_NTTIME(io.smb2.out.access_time, access_time);
     827           1 :         CHECK_NTTIME(io.smb2.out.write_time, write_time);
     828           1 :         CHECK_NTTIME(io.smb2.out.change_time, change_time);
     829           1 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
     830           1 :         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
     831           1 :         CHECK_ALL_INFO(io.smb2.out.size, size);
     832           1 :         smb2_util_close(tree, h1);
     833           1 :         smb2_util_unlink(tree, fname);
     834             : 
     835             :         /* create a directory */
     836           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     837           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
     838           1 :         io.smb2.in.alloc_size = 0;
     839           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
     840           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     841           1 :         io.smb2.in.create_options = 0;
     842           1 :         io.smb2.in.fname = dname;
     843           1 :         fname = dname;
     844             : 
     845           1 :         smb2_util_rmdir(tree, fname);
     846           1 :         smb2_util_unlink(tree, fname);
     847             : 
     848           1 :         io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
     849           1 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     850           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     851           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     852             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     853           1 :         status = smb2_create(tree, tctx, &(io.smb2));
     854           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     855           1 :         h1 = io.smb2.out.file.handle;
     856             : 
     857           1 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
     858           1 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
     859           1 :         CHECK_NTTIME(io.smb2.out.create_time, create_time);
     860           1 :         CHECK_NTTIME(io.smb2.out.access_time, access_time);
     861           1 :         CHECK_NTTIME(io.smb2.out.write_time, write_time);
     862           1 :         CHECK_NTTIME(io.smb2.out.change_time, change_time);
     863           1 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
     864           1 :         CHECK_VAL(io.smb2.out.file_attr & ~FILE_ATTRIBUTE_NONINDEXED,
     865             :                   FILE_ATTRIBUTE_DIRECTORY);
     866           1 :         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
     867           1 :         CHECK_ALL_INFO(io.smb2.out.size, size);
     868           1 :         CHECK_VAL(io.smb2.out.size, 0);
     869           1 :         smb2_util_unlink(tree, fname);
     870             : 
     871           1 : done:
     872           1 :         smb2_util_close(tree, h1);
     873           1 :         smb2_util_unlink(tree, fname);
     874           1 :         smb2_deltree(tree, DNAME);
     875           1 :         return ret;
     876             : }
     877             : 
     878             : /*
     879             :   test with an already opened and byte range locked file
     880             : */
     881             : 
     882           6 : static bool test_smb2_open_brlocked(struct torture_context *tctx,
     883             :                                     struct smb2_tree *tree)
     884             : {
     885           0 :         union smb_open io, io1;
     886           0 :         union smb_lock io2;
     887           0 :         struct smb2_lock_element lock[1];
     888           6 :         const char *fname = DNAME "\\torture_ntcreatex.txt";
     889           0 :         NTSTATUS status;
     890           6 :         bool ret = true;
     891           0 :         struct smb2_handle h;
     892           6 :         char b = 42;
     893             : 
     894           6 :         torture_comment(tctx,
     895             :                 "Testing SMB2 open with a byte range locked file\n");
     896             : 
     897           6 :         smb2_util_unlink(tree, fname);
     898             : 
     899           6 :         status = torture_smb2_testdir(tree, DNAME, &h);
     900           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     901             : 
     902           6 :         ZERO_STRUCT(io.smb2);
     903           6 :         io.generic.level = RAW_OPEN_SMB2;
     904           6 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     905           6 :         io.smb2.in.desired_access = 0x2019f;
     906           6 :         io.smb2.in.alloc_size = 0;
     907           6 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     908           6 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     909             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     910           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     911           6 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     912           6 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
     913           6 :         io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
     914           6 :         io.smb2.in.fname = fname;
     915             : 
     916           6 :         status = smb2_create(tree, tctx, &(io.smb2));
     917           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     918             : 
     919           6 :         status = smb2_util_write(tree, io.smb2.out.file.handle, &b, 0, 1);
     920           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     921             : 
     922           6 :         ZERO_STRUCT(io2.smb2);
     923           6 :         io2.smb2.level = RAW_LOCK_SMB2;
     924           6 :         io2.smb2.in.file.handle = io.smb2.out.file.handle;
     925           6 :         io2.smb2.in.lock_count = 1;
     926             : 
     927           6 :         ZERO_STRUCT(lock);
     928           6 :         lock[0].offset = 0;
     929           6 :         lock[0].length = 1;
     930           6 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
     931             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
     932           6 :         io2.smb2.in.locks = &lock[0];
     933           6 :         status = smb2_lock(tree, &(io2.smb2));
     934           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     935             : 
     936           6 :         ZERO_STRUCT(io1.smb2);
     937           6 :         io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     938           6 :         io1.smb2.in.desired_access = 0x20196;
     939           6 :         io1.smb2.in.alloc_size = 0;
     940           6 :         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     941           6 :         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     942             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     943           6 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     944           6 :         io1.smb2.in.create_options = 0;
     945           6 :         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
     946           6 :         io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
     947           6 :         io1.smb2.in.fname = fname;
     948             : 
     949           6 :         status = smb2_create(tree, tctx, &(io1.smb2));
     950           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     951             : 
     952           6 :         smb2_util_close(tree, io.smb2.out.file.handle);
     953           6 :         smb2_util_close(tree, io1.smb2.out.file.handle);
     954           6 :         smb2_util_unlink(tree, fname);
     955           6 :         smb2_deltree(tree, DNAME);
     956             : 
     957           6 :         return ret;
     958             : }
     959             : 
     960             : /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
     961             : 
     962           6 : static bool test_smb2_open_multi(struct torture_context *tctx,
     963             :                                 struct smb2_tree *tree)
     964             : {
     965           6 :         const char *fname = "test_oplock.dat";
     966           0 :         NTSTATUS status;
     967           6 :         bool ret = true;
     968           0 :         union smb_open io;
     969           0 :         struct smb2_tree **trees;
     970           0 :         struct smb2_request **requests;
     971           0 :         union smb_open *ios;
     972           6 :         int i, num_files = 3;
     973           6 :         int num_ok = 0;
     974           6 :         int num_collision = 0;
     975             : 
     976           6 :         torture_comment(tctx,
     977             :                 "Testing SMB2 Open with multiple connections\n");
     978           6 :         trees = talloc_array(tctx, struct smb2_tree *, num_files);
     979           6 :         requests = talloc_array(tctx, struct smb2_request *, num_files);
     980           6 :         ios = talloc_array(tctx, union smb_open, num_files);
     981           6 :         if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
     982             :             (ios == NULL)) {
     983           0 :                 torture_comment(tctx, ("talloc failed\n"));
     984           0 :                 ret = false;
     985           0 :                 goto done;
     986             :         }
     987             : 
     988           6 :         tree->session->transport->options.request_timeout = 60;
     989             : 
     990          24 :         for (i=0; i<num_files; i++) {
     991          18 :                 if (!torture_smb2_connection(tctx, &(trees[i]))) {
     992           0 :                         torture_comment(tctx,
     993             :                                 "Could not open %d'th connection\n", i);
     994           0 :                         ret = false;
     995           0 :                         goto done;
     996             :                 }
     997          18 :                 trees[i]->session->transport->options.request_timeout = 60;
     998             :         }
     999             : 
    1000             :         /* cleanup */
    1001           6 :         smb2_util_unlink(tree, fname);
    1002             : 
    1003             :         /*
    1004             :           base ntcreatex parms
    1005             :         */
    1006           6 :         ZERO_STRUCT(io.smb2);
    1007           6 :         io.generic.level = RAW_OPEN_SMB2;
    1008           6 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1009           6 :         io.smb2.in.alloc_size = 0;
    1010           6 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1011           6 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1012             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1013             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1014           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1015           6 :         io.smb2.in.create_options = 0;
    1016           6 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1017           6 :         io.smb2.in.security_flags = 0;
    1018           6 :         io.smb2.in.fname = fname;
    1019           6 :         io.smb2.in.create_flags = 0;
    1020             : 
    1021          24 :         for (i=0; i<num_files; i++) {
    1022          18 :                 ios[i] = io;
    1023          18 :                 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
    1024          18 :                 if (requests[i] == NULL) {
    1025           0 :                         torture_comment(tctx,
    1026             :                                 "could not send %d'th request\n", i);
    1027           0 :                         ret = false;
    1028           0 :                         goto done;
    1029             :                 }
    1030             :         }
    1031             : 
    1032           6 :         torture_comment(tctx, "waiting for replies\n");
    1033          72 :         while (1) {
    1034          78 :                 bool unreplied = false;
    1035         107 :                 for (i=0; i<num_files; i++) {
    1036         101 :                         if (requests[i] == NULL) {
    1037          11 :                                 continue;
    1038             :                         }
    1039          90 :                         if (requests[i]->state < SMB2_REQUEST_DONE) {
    1040          72 :                                 unreplied = true;
    1041          72 :                                 break;
    1042             :                         }
    1043          18 :                         status = smb2_create_recv(requests[i], tctx,
    1044          18 :                                                   &(ios[i].smb2));
    1045             : 
    1046          18 :                         torture_comment(tctx,
    1047             :                                 "File %d returned status %s\n", i,
    1048             :                                 nt_errstr(status));
    1049             : 
    1050          18 :                         if (NT_STATUS_IS_OK(status)) {
    1051           6 :                                 num_ok += 1;
    1052             :                         }
    1053             : 
    1054          18 :                         if (NT_STATUS_EQUAL(status,
    1055             :                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
    1056          12 :                                 num_collision += 1;
    1057             :                         }
    1058             : 
    1059          18 :                         requests[i] = NULL;
    1060             :                 }
    1061          78 :                 if (!unreplied) {
    1062           6 :                         break;
    1063             :                 }
    1064             : 
    1065          72 :                 if (tevent_loop_once(tctx->ev) != 0) {
    1066           0 :                         torture_comment(tctx, "tevent_loop_once failed\n");
    1067           0 :                         ret = false;
    1068           0 :                         goto done;
    1069             :                 }
    1070             :         }
    1071             : 
    1072           6 :         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
    1073           0 :                 ret = false;
    1074             :         }
    1075           6 : done:
    1076           6 :         smb2_deltree(tree, fname);
    1077             : 
    1078           6 :         return ret;
    1079             : }
    1080             : 
    1081             : /*
    1082             :   test opening for delete on a read-only attribute file.
    1083             : */
    1084             : 
    1085           6 : static bool test_smb2_open_for_delete(struct torture_context *tctx,
    1086             :                                       struct smb2_tree *tree)
    1087             : {
    1088           0 :         union smb_open io;
    1089           0 :         union smb_fileinfo finfo;
    1090           6 :         const char *fname = DNAME "\\torture_open_for_delete.txt";
    1091           0 :         NTSTATUS status;
    1092           0 :         struct smb2_handle h, h1;
    1093           6 :         bool ret = true;
    1094             : 
    1095           6 :         torture_comment(tctx,
    1096             :                 "Checking SMB2_OPEN for delete on a readonly file.\n");
    1097           6 :         smb2_util_unlink(tree, fname);
    1098           6 :         smb2_deltree(tree, fname);
    1099             : 
    1100           6 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1101           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1102             : 
    1103             :         /* reasonable default parameters */
    1104           6 :         ZERO_STRUCT(io.smb2);
    1105           6 :         io.generic.level = RAW_OPEN_SMB2;
    1106           6 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1107           6 :         io.smb2.in.alloc_size = 0;
    1108           6 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1109           6 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY;
    1110           6 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1111           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1112           6 :         io.smb2.in.create_options = 0;
    1113           6 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1114           6 :         io.smb2.in.security_flags = 0;
    1115           6 :         io.smb2.in.fname = fname;
    1116             : 
    1117             :         /* Create the readonly file. */
    1118             : 
    1119           6 :         status = smb2_create(tree, tctx, &(io.smb2));
    1120           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1121           6 :         h1 = io.smb2.out.file.handle;
    1122             : 
    1123           6 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
    1124           6 :         io.smb2.in.create_options = 0;
    1125           6 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
    1126           6 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    1127           6 :         smb2_util_close(tree, h1);
    1128             : 
    1129             :         /* Now try and open for delete only - should succeed. */
    1130           6 :         io.smb2.in.desired_access = SEC_STD_DELETE;
    1131           6 :         io.smb2.in.file_attributes = 0;
    1132           6 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1133             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1134             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1135           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1136           6 :         status = smb2_create(tree, tctx, &(io.smb2));
    1137           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1138           6 :         smb2_util_close(tree, io.smb2.out.file.handle);
    1139             : 
    1140             :         /* Clear readonly flag to allow file deletion */
    1141           6 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1142             :                                 SEC_FILE_WRITE_ATTRIBUTE;
    1143           6 :         status = smb2_create(tree, tctx, &(io.smb2));
    1144           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1145           6 :         h1 = io.smb2.out.file.handle;
    1146           6 :         SET_ATTRIB(FILE_ATTRIBUTE_ARCHIVE);
    1147           6 :         smb2_util_close(tree, h1);
    1148             : 
    1149           6 :         smb2_util_close(tree, h);
    1150           6 :         smb2_util_unlink(tree, fname);
    1151           6 :         smb2_deltree(tree, DNAME);
    1152             : 
    1153           6 :         return ret;
    1154             : }
    1155             : 
    1156             : /*
    1157             :   test SMB2 open with a leading slash on the path.
    1158             :   Trying to create a directory with a leading slash
    1159             :   should give NT_STATUS_INVALID_PARAMETER error
    1160             : */
    1161           6 : static bool test_smb2_leading_slash(struct torture_context *tctx,
    1162             :                                     struct smb2_tree *tree)
    1163             : {
    1164           0 :         union smb_open io;
    1165           6 :         const char *dnameslash = "\\"DNAME;
    1166           0 :         NTSTATUS status;
    1167           6 :         bool ret = true;
    1168             : 
    1169           6 :         torture_comment(tctx,
    1170             :                 "Trying to create a directory with leading slash on path\n");
    1171           6 :         smb2_deltree(tree, dnameslash);
    1172             : 
    1173           6 :         ZERO_STRUCT(io.smb2);
    1174           6 :         io.generic.level = RAW_OPEN_SMB2;
    1175           6 :         io.smb2.in.oplock_level = 0;
    1176           6 :         io.smb2.in.desired_access = SEC_RIGHTS_DIR_ALL;
    1177           6 :         io.smb2.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
    1178           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1179           6 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1180             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1181             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1182           6 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1183           6 :         io.smb2.in.fname = dnameslash;
    1184             : 
    1185           6 :         status = smb2_create(tree, tree, &(io.smb2));
    1186           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1187             : 
    1188           6 :         smb2_deltree(tree, dnameslash);
    1189           6 :         return ret;
    1190             : }
    1191             : 
    1192             : /*
    1193             :   test SMB2 open with an invalid impersonation level.
    1194             :   Should give NT_STATUS_BAD_IMPERSONATION_LEVEL error
    1195             : */
    1196           6 : static bool test_smb2_impersonation_level(struct torture_context *tctx,
    1197             :                                     struct smb2_tree *tree)
    1198             : {
    1199           0 :         union smb_open io;
    1200           6 :         const char *fname = DNAME "\\torture_invalid_impersonation_level.txt";
    1201           0 :         NTSTATUS status;
    1202           0 :         struct smb2_handle h;
    1203           6 :         bool ret = true;
    1204             : 
    1205           6 :         torture_comment(tctx,
    1206             :                 "Testing SMB2 open with an invalid impersonation level.\n");
    1207             : 
    1208           6 :         smb2_util_unlink(tree, fname);
    1209           6 :         smb2_util_rmdir(tree, DNAME);
    1210             : 
    1211           6 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1212           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1213             : 
    1214           6 :         ZERO_STRUCT(io.smb2);
    1215           6 :         io.generic.level = RAW_OPEN_SMB2;
    1216           6 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1217           6 :         io.smb2.in.alloc_size = 0;
    1218           6 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1219           6 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1220             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1221             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1222           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1223           6 :         io.smb2.in.create_options = 0;
    1224           6 :         io.smb2.in.impersonation_level = 0x12345678;
    1225           6 :         io.smb2.in.security_flags = 0;
    1226           6 :         io.smb2.in.fname = fname;
    1227           6 :         io.smb2.in.create_flags = 0;
    1228             : 
    1229           6 :         status = smb2_create(tree, tree, &(io.smb2));
    1230           6 :         CHECK_STATUS(status, NT_STATUS_BAD_IMPERSONATION_LEVEL);
    1231             : 
    1232           5 :         smb2_util_close(tree, h);
    1233           5 :         smb2_util_unlink(tree, fname);
    1234           5 :         smb2_deltree(tree, DNAME);
    1235           5 :         return ret;
    1236             : }
    1237             : 
    1238           6 : static bool test_create_acl_file(struct torture_context *tctx,
    1239             :     struct smb2_tree *tree)
    1240             : {
    1241           6 :         torture_comment(tctx, "Testing nttrans create with sec_desc on files\n");
    1242             : 
    1243           6 :         return test_create_acl_ext(tctx, tree, false);
    1244             : }
    1245             : 
    1246           6 : static bool test_create_acl_dir(struct torture_context *tctx,
    1247             :     struct smb2_tree *tree)
    1248             : {
    1249           6 :         torture_comment(tctx, "Testing nttrans create with sec_desc on directories\n");
    1250             : 
    1251           6 :         return test_create_acl_ext(tctx, tree, true);
    1252             : }
    1253             : 
    1254             : #define CHECK_ACCESS_FLAGS(_fh, flags) do { \
    1255             :         union smb_fileinfo _q; \
    1256             :         _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
    1257             :         _q.access_information.in.file.handle = (_fh); \
    1258             :         status = smb2_getinfo_file(tree, tctx, &_q); \
    1259             :         CHECK_STATUS(status, NT_STATUS_OK); \
    1260             :         if (_q.access_information.out.access_flags != (flags)) { \
    1261             :                 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
    1262             :                        __location__, _q.access_information.out.access_flags, (flags)); \
    1263             :                 ret = false; \
    1264             :                 goto done; \
    1265             :         } \
    1266             : } while (0)
    1267             : 
    1268             : /*
    1269             :  * Test creating a file with a NULL DACL.
    1270             :  */
    1271           6 : static bool test_create_null_dacl(struct torture_context *tctx,
    1272             :     struct smb2_tree *tree)
    1273             : {
    1274           0 :         NTSTATUS status;
    1275           0 :         struct smb2_create io;
    1276           6 :         const char *fname = "nulldacl.txt";
    1277           6 :         bool ret = true;
    1278           0 :         struct smb2_handle handle;
    1279           0 :         union smb_fileinfo q;
    1280           0 :         union smb_setfileinfo s;
    1281           6 :         struct security_descriptor *sd = security_descriptor_initialise(tctx);
    1282           0 :         struct security_acl dacl;
    1283             : 
    1284           6 :         torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n");
    1285             : 
    1286           6 :         smb2_util_unlink(tree, fname);
    1287             : 
    1288           6 :         ZERO_STRUCT(io);
    1289           6 :         io.level = RAW_OPEN_SMB2;
    1290           6 :         io.in.create_flags = 0;
    1291           6 :         io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC
    1292             :                 | SEC_STD_WRITE_OWNER;
    1293           6 :         io.in.create_options = 0;
    1294           6 :         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1295           6 :         io.in.share_access =
    1296             :                 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
    1297           6 :         io.in.alloc_size = 0;
    1298           6 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
    1299           6 :         io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
    1300           6 :         io.in.security_flags = 0;
    1301           6 :         io.in.fname = fname;
    1302           6 :         io.in.sec_desc = sd;
    1303             :         /* XXX create_options ? */
    1304           6 :         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1305             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
    1306             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1307             :                                           0x00200000;
    1308             : 
    1309           6 :         torture_comment(tctx, "creating a file with a empty sd\n");
    1310           6 :         status = smb2_create(tree, tctx, &io);
    1311           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1312           6 :         handle = io.out.file.handle;
    1313             : 
    1314           6 :         torture_comment(tctx, "get the original sd\n");
    1315           6 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1316           6 :         q.query_secdesc.in.file.handle = handle;
    1317           6 :         q.query_secdesc.in.secinfo_flags =
    1318             :                 SECINFO_OWNER |
    1319             :                 SECINFO_GROUP |
    1320             :                 SECINFO_DACL;
    1321           6 :         status = smb2_getinfo_file(tree, tctx, &q);
    1322           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1323             : 
    1324             :         /*
    1325             :          * Testing the created DACL,
    1326             :          * the server should add the inherited DACL
    1327             :          * when SEC_DESC_DACL_PRESENT isn't specified
    1328             :          */
    1329           6 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1330           0 :                 ret = false;
    1331           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1332             :         }
    1333           6 :         if (q.query_secdesc.out.sd->dacl == NULL) {
    1334           0 :                 ret = false;
    1335           0 :                 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
    1336             :         }
    1337             : 
    1338           6 :         torture_comment(tctx, "set NULL DACL\n");
    1339           6 :         sd->type |= SEC_DESC_DACL_PRESENT;
    1340             : 
    1341           6 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1342           6 :         s.set_secdesc.in.file.handle = handle;
    1343           6 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1344           6 :         s.set_secdesc.in.sd = sd;
    1345           6 :         status = smb2_setinfo_file(tree, &s);
    1346           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1347             : 
    1348           6 :         torture_comment(tctx, "get the sd\n");
    1349           6 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1350           6 :         q.query_secdesc.in.file.handle = handle;
    1351           6 :         q.query_secdesc.in.secinfo_flags =
    1352             :                 SECINFO_OWNER |
    1353             :                 SECINFO_GROUP |
    1354             :                 SECINFO_DACL;
    1355           6 :         status = smb2_getinfo_file(tree, tctx, &q);
    1356           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1357             : 
    1358             :         /* Testing the modified DACL */
    1359           6 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1360           0 :                 ret = false;
    1361           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1362             :         }
    1363           6 :         if (q.query_secdesc.out.sd->dacl != NULL) {
    1364           0 :                 ret = false;
    1365           0 :                 torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
    1366             :         }
    1367             : 
    1368           6 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    1369             : 
    1370           6 :         torture_comment(tctx, "try open for read control\n");
    1371           6 :         io.in.desired_access = SEC_STD_READ_CONTROL;
    1372           6 :         status = smb2_create(tree, tctx, &io);
    1373           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1374           6 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1375             :                 SEC_STD_READ_CONTROL);
    1376           6 :         smb2_util_close(tree, io.out.file.handle);
    1377             : 
    1378           6 :         torture_comment(tctx, "try open for write\n");
    1379           6 :         io.in.desired_access = SEC_FILE_WRITE_DATA;
    1380           6 :         status = smb2_create(tree, tctx, &io);
    1381           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1382           6 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1383             :                 SEC_FILE_WRITE_DATA);
    1384           6 :         smb2_util_close(tree, io.out.file.handle);
    1385             : 
    1386           6 :         torture_comment(tctx, "try open for read\n");
    1387           6 :         io.in.desired_access = SEC_FILE_READ_DATA;
    1388           6 :         status = smb2_create(tree, tctx, &io);
    1389           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1390           6 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1391             :                 SEC_FILE_READ_DATA);
    1392           6 :         smb2_util_close(tree, io.out.file.handle);
    1393             : 
    1394           6 :         torture_comment(tctx, "try open for generic write\n");
    1395           6 :         io.in.desired_access = SEC_GENERIC_WRITE;
    1396           6 :         status = smb2_create(tree, tctx, &io);
    1397           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1398           6 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1399             :                 SEC_RIGHTS_FILE_WRITE);
    1400           6 :         smb2_util_close(tree, io.out.file.handle);
    1401             : 
    1402           6 :         torture_comment(tctx, "try open for generic read\n");
    1403           6 :         io.in.desired_access = SEC_GENERIC_READ;
    1404           6 :         status = smb2_create(tree, tctx, &io);
    1405           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1406           6 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1407             :                 SEC_RIGHTS_FILE_READ);
    1408           6 :         smb2_util_close(tree, io.out.file.handle);
    1409             : 
    1410           6 :         torture_comment(tctx, "set DACL with 0 aces\n");
    1411           6 :         ZERO_STRUCT(dacl);
    1412           6 :         dacl.revision = SECURITY_ACL_REVISION_NT4;
    1413           6 :         dacl.num_aces = 0;
    1414           6 :         sd->dacl = &dacl;
    1415             : 
    1416           6 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1417           6 :         s.set_secdesc.in.file.handle = handle;
    1418           6 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1419           6 :         s.set_secdesc.in.sd = sd;
    1420           6 :         status = smb2_setinfo_file(tree, &s);
    1421           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1422             : 
    1423           6 :         torture_comment(tctx, "get the sd\n");
    1424           6 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1425           6 :         q.query_secdesc.in.file.handle = handle;
    1426           6 :         q.query_secdesc.in.secinfo_flags =
    1427             :                 SECINFO_OWNER |
    1428             :                 SECINFO_GROUP |
    1429             :                 SECINFO_DACL;
    1430           6 :         status = smb2_getinfo_file(tree, tctx, &q);
    1431           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1432             : 
    1433             :         /* Testing the modified DACL */
    1434           6 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1435           0 :                 ret = false;
    1436           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1437             :         }
    1438           6 :         if (q.query_secdesc.out.sd->dacl == NULL) {
    1439           0 :                 ret = false;
    1440           0 :                 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
    1441             :         }
    1442           6 :         if (q.query_secdesc.out.sd->dacl->num_aces != 0) {
    1443           0 :                 torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n",
    1444           0 :                        q.query_secdesc.out.sd->dacl->num_aces);
    1445           0 :                 ret = false;
    1446           0 :                 goto done;
    1447             :         }
    1448             : 
    1449           6 :         torture_comment(tctx, "try open for read control\n");
    1450           6 :         io.in.desired_access = SEC_STD_READ_CONTROL;
    1451           6 :         status = smb2_create(tree, tctx, &io);
    1452           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1453           6 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1454             :                 SEC_STD_READ_CONTROL);
    1455           6 :         smb2_util_close(tree, io.out.file.handle);
    1456             : 
    1457           6 :         torture_comment(tctx, "try open for write => access_denied\n");
    1458           6 :         io.in.desired_access = SEC_FILE_WRITE_DATA;
    1459           6 :         status = smb2_create(tree, tctx, &io);
    1460           6 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1461           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1462             :         } else {
    1463           6 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1464             :         }
    1465             : 
    1466           6 :         torture_comment(tctx, "try open for read => access_denied\n");
    1467           6 :         io.in.desired_access = SEC_FILE_READ_DATA;
    1468           6 :         status = smb2_create(tree, tctx, &io);
    1469           6 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1470           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1471             :         } else {
    1472           6 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1473             :         }
    1474             : 
    1475           6 :         torture_comment(tctx, "try open for generic write => access_denied\n");
    1476           6 :         io.in.desired_access = SEC_GENERIC_WRITE;
    1477           6 :         status = smb2_create(tree, tctx, &io);
    1478           6 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1479           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1480             :         } else {
    1481           6 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1482             :         }
    1483             : 
    1484           6 :         torture_comment(tctx, "try open for generic read => access_denied\n");
    1485           6 :         io.in.desired_access = SEC_GENERIC_READ;
    1486           6 :         status = smb2_create(tree, tctx, &io);
    1487           6 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1488           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1489             :         } else {
    1490           6 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1491             :         }
    1492             : 
    1493           6 :         torture_comment(tctx, "set empty sd\n");
    1494           6 :         sd->type &= ~SEC_DESC_DACL_PRESENT;
    1495           6 :         sd->dacl = NULL;
    1496             : 
    1497           6 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1498           6 :         s.set_secdesc.in.file.handle = handle;
    1499           6 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1500           6 :         s.set_secdesc.in.sd = sd;
    1501           6 :         status = smb2_setinfo_file(tree, &s);
    1502           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1503             : 
    1504           6 :         torture_comment(tctx, "get the sd\n");
    1505           6 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1506           6 :         q.query_secdesc.in.file.handle = handle;
    1507           6 :         q.query_secdesc.in.secinfo_flags =
    1508             :                 SECINFO_OWNER |
    1509             :                 SECINFO_GROUP |
    1510             :                 SECINFO_DACL;
    1511           6 :         status = smb2_getinfo_file(tree, tctx, &q);
    1512           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1513             : 
    1514             :         /* Testing the modified DACL */
    1515           6 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1516           0 :                 ret = false;
    1517           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1518             :         }
    1519           6 :         if (q.query_secdesc.out.sd->dacl != NULL) {
    1520           0 :                 ret = false;
    1521           0 :                 torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
    1522             :         }
    1523           6 : done:
    1524           6 :         smb2_util_close(tree, handle);
    1525           6 :         smb2_util_unlink(tree, fname);
    1526           6 :         smb2_tdis(tree);
    1527           6 :         smb2_logoff(tree->session);
    1528           6 :         return ret;
    1529             : }
    1530             : 
    1531             : /*
    1532             :   test SMB2 mkdir with OPEN_IF on the same name twice.
    1533             :   Must use 2 connections to hit the race.
    1534             : */
    1535             : 
    1536           6 : static bool test_mkdir_dup(struct torture_context *tctx,
    1537             :                                 struct smb2_tree *tree)
    1538             : {
    1539           6 :         const char *fname = "mkdir_dup";
    1540           0 :         NTSTATUS status;
    1541           6 :         bool ret = true;
    1542           0 :         union smb_open io;
    1543           0 :         struct smb2_tree **trees;
    1544           0 :         struct smb2_request **requests;
    1545           0 :         union smb_open *ios;
    1546           6 :         int i, num_files = 2;
    1547           6 :         int num_ok = 0;
    1548           6 :         int num_created = 0;
    1549           6 :         int num_existed = 0;
    1550             : 
    1551           6 :         torture_comment(tctx,
    1552             :                 "Testing SMB2 Create Directory with multiple connections\n");
    1553           6 :         trees = talloc_array(tctx, struct smb2_tree *, num_files);
    1554           6 :         requests = talloc_array(tctx, struct smb2_request *, num_files);
    1555           6 :         ios = talloc_array(tctx, union smb_open, num_files);
    1556           6 :         if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
    1557             :             (ios == NULL)) {
    1558           0 :                 torture_fail(tctx, ("talloc failed\n"));
    1559             :                 ret = false;
    1560             :                 goto done;
    1561             :         }
    1562             : 
    1563           6 :         tree->session->transport->options.request_timeout = 60;
    1564             : 
    1565          18 :         for (i=0; i<num_files; i++) {
    1566          12 :                 if (!torture_smb2_connection(tctx, &(trees[i]))) {
    1567           0 :                         torture_fail(tctx,
    1568             :                                 talloc_asprintf(tctx,
    1569             :                                         "Could not open %d'th connection\n", i));
    1570             :                         ret = false;
    1571             :                         goto done;
    1572             :                 }
    1573          12 :                 trees[i]->session->transport->options.request_timeout = 60;
    1574             :         }
    1575             : 
    1576             :         /* cleanup */
    1577           6 :         smb2_util_unlink(tree, fname);
    1578           6 :         smb2_util_rmdir(tree, fname);
    1579             : 
    1580             :         /*
    1581             :           base ntcreatex parms
    1582             :         */
    1583           6 :         ZERO_STRUCT(io.smb2);
    1584           6 :         io.generic.level = RAW_OPEN_SMB2;
    1585           6 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1586           6 :         io.smb2.in.alloc_size = 0;
    1587           6 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1588           6 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1589             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1590             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1591           6 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1592           6 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1593           6 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1594           6 :         io.smb2.in.security_flags = 0;
    1595           6 :         io.smb2.in.fname = fname;
    1596           6 :         io.smb2.in.create_flags = 0;
    1597             : 
    1598          18 :         for (i=0; i<num_files; i++) {
    1599          12 :                 ios[i] = io;
    1600          12 :                 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
    1601          12 :                 if (requests[i] == NULL) {
    1602           0 :                         torture_fail(tctx,
    1603             :                                 talloc_asprintf(tctx,
    1604             :                                 "could not send %d'th request\n", i));
    1605             :                         ret = false;
    1606             :                         goto done;
    1607             :                 }
    1608             :         }
    1609             : 
    1610           6 :         torture_comment(tctx, "waiting for replies\n");
    1611          48 :         while (1) {
    1612          54 :                 bool unreplied = false;
    1613          80 :                 for (i=0; i<num_files; i++) {
    1614          74 :                         if (requests[i] == NULL) {
    1615          14 :                                 continue;
    1616             :                         }
    1617          60 :                         if (requests[i]->state < SMB2_REQUEST_DONE) {
    1618          48 :                                 unreplied = true;
    1619          48 :                                 break;
    1620             :                         }
    1621          12 :                         status = smb2_create_recv(requests[i], tctx,
    1622          12 :                                                   &(ios[i].smb2));
    1623             : 
    1624          12 :                         if (NT_STATUS_IS_OK(status)) {
    1625          12 :                                 num_ok += 1;
    1626             : 
    1627          12 :                                 if (ios[i].smb2.out.create_action ==
    1628             :                                                 NTCREATEX_ACTION_CREATED) {
    1629           6 :                                         num_created++;
    1630             :                                 }
    1631          12 :                                 if (ios[i].smb2.out.create_action ==
    1632             :                                                 NTCREATEX_ACTION_EXISTED) {
    1633           6 :                                         num_existed++;
    1634             :                                 }
    1635             :                         } else {
    1636           0 :                                 torture_fail(tctx,
    1637             :                                         talloc_asprintf(tctx,
    1638             :                                         "File %d returned status %s\n", i,
    1639             :                                         nt_errstr(status)));
    1640             :                         }
    1641             : 
    1642             : 
    1643          12 :                         requests[i] = NULL;
    1644             :                 }
    1645          54 :                 if (!unreplied) {
    1646           6 :                         break;
    1647             :                 }
    1648             : 
    1649          48 :                 if (tevent_loop_once(tctx->ev) != 0) {
    1650           0 :                         torture_fail(tctx, "tevent_loop_once failed\n");
    1651             :                         ret = false;
    1652             :                         goto done;
    1653             :                 }
    1654             :         }
    1655             : 
    1656           6 :         if (num_ok != 2) {
    1657           0 :                 torture_fail(tctx,
    1658             :                         talloc_asprintf(tctx,
    1659             :                         "num_ok == %d\n", num_ok));
    1660             :                 ret = false;
    1661             :         }
    1662           6 :         if (num_created != 1) {
    1663           0 :                 torture_fail(tctx,
    1664             :                         talloc_asprintf(tctx,
    1665             :                         "num_created == %d\n", num_created));
    1666             :                 ret = false;
    1667             :         }
    1668           6 :         if (num_existed != 1) {
    1669           0 :                 torture_fail(tctx,
    1670             :                         talloc_asprintf(tctx,
    1671             :                         "num_existed == %d\n", num_existed));
    1672             :                 ret = false;
    1673             :         }
    1674           6 : done:
    1675           6 :         smb2_deltree(tree, fname);
    1676             : 
    1677           6 :         return ret;
    1678             : }
    1679             : 
    1680             : /*
    1681             :   test directory creation with an initial allocation size > 0
    1682             : */
    1683           6 : static bool test_dir_alloc_size(struct torture_context *tctx,
    1684             :                                 struct smb2_tree *tree)
    1685             : {
    1686           6 :         bool ret = true;
    1687           6 :         const char *dname = DNAME "\\torture_alloc_size.dir";
    1688           0 :         NTSTATUS status;
    1689           0 :         struct smb2_create c;
    1690           6 :         struct smb2_handle h1 = {{0}}, h2;
    1691             : 
    1692           6 :         torture_comment(tctx, "Checking initial allocation size on directories\n");
    1693             : 
    1694           6 :         smb2_deltree(tree, dname);
    1695             : 
    1696           6 :         status = torture_smb2_testdir(tree, DNAME, &h1);
    1697           6 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
    1698             : 
    1699           6 :         ZERO_STRUCT(c);
    1700           6 :         c.in.create_disposition = NTCREATEX_DISP_CREATE;
    1701           6 :         c.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    1702           6 :         c.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    1703           6 :         c.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1704           6 :         c.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1705           6 :         c.in.fname = dname;
    1706             :         /*
    1707             :          * An insanely large value so we can check the value is
    1708             :          * ignored: Samba either returns 0 (current behaviour), or,
    1709             :          * once vfswrap_get_alloc_size() is fixed to allow retrieving
    1710             :          * the allocated size for directories, returns
    1711             :          * smb_roundup(..., stat.st_size) which would be 1 MB by
    1712             :          * default.
    1713             :          *
    1714             :          * Windows returns 0 for empty directories, once directories
    1715             :          * have a few entries it starts replying with values > 0.
    1716             :          */
    1717           6 :         c.in.alloc_size = 1024*1024*1024;
    1718             : 
    1719           6 :         status = smb2_create(tree, tctx, &c);
    1720           6 :         h2 = c.out.file.handle;
    1721           6 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1722             :                                         "dir create with initial alloc size failed");
    1723             : 
    1724           6 :         smb2_util_close(tree, h2);
    1725             : 
    1726           6 :         torture_comment(tctx, "Got directory alloc size: %ju\n", (uintmax_t)c.out.alloc_size);
    1727             : 
    1728             :         /*
    1729             :          * See above for the rational for this test
    1730             :          */
    1731           6 :         if (c.out.alloc_size > 1024*1024) {
    1732           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "bad alloc size: %ju",
    1733             :                                                               (uintmax_t)c.out.alloc_size));
    1734             :         }
    1735             : 
    1736           6 : done:
    1737           6 :         if (!smb2_util_handle_empty(h1)) {
    1738           6 :                 smb2_util_close(tree, h1);
    1739             :         }
    1740           6 :         smb2_deltree(tree, DNAME);
    1741           6 :         return ret;
    1742             : }
    1743             : 
    1744           2 : static bool test_twrp_write(struct torture_context *tctx, struct smb2_tree *tree)
    1745             : {
    1746           0 :         struct smb2_create io;
    1747           2 :         struct smb2_handle h1 = {{0}};
    1748           0 :         NTSTATUS status;
    1749           2 :         bool ret = true;
    1750           2 :         char *p = NULL;
    1751           0 :         struct tm tm;
    1752           0 :         time_t t;
    1753           0 :         uint64_t nttime;
    1754           2 :         const char *file = NULL;
    1755           2 :         const char *snapshot = NULL;
    1756             : 
    1757           2 :         file = torture_setting_string(tctx, "twrp_file", NULL);
    1758           2 :         if (file == NULL) {
    1759           0 :                 torture_skip(tctx, "missing 'twrp_file' option\n");
    1760             :         }
    1761             : 
    1762           2 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    1763           2 :         if (snapshot == NULL) {
    1764           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    1765             :         }
    1766             : 
    1767           2 :         torture_comment(tctx, "Testing timewarp (%s) (%s)\n", file, snapshot);
    1768             : 
    1769           2 :         setenv("TZ", "GMT", 1);
    1770             : 
    1771             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    1772             :          * effect if it is greater than 1. */
    1773           2 :         ZERO_STRUCT(tm);
    1774             : 
    1775           2 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    1776           2 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    1777           2 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    1778             : 
    1779           2 :         t = mktime(&tm);
    1780           2 :         unix_to_nt_time(&nttime, t);
    1781             : 
    1782           2 :         io = (struct smb2_create) {
    1783             :                 .in.desired_access = SEC_FILE_READ_DATA,
    1784             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    1785             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    1786             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1787             :                 .in.fname = file,
    1788             :                 .in.query_maximal_access = true,
    1789             :                 .in.timewarp = nttime,
    1790             :         };
    1791             : 
    1792           2 :         status = smb2_create(tree, tctx, &io);
    1793           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1794             :                                         "smb2_create\n");
    1795           2 :         smb2_util_close(tree, io.out.file.handle);
    1796             : 
    1797           2 :         ret = io.out.maximal_access & (SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA);
    1798           2 :         torture_assert_goto(tctx, ret, ret, done, "Bad access\n");
    1799             : 
    1800           2 :         io = (struct smb2_create) {
    1801             :                 .in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
    1802             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    1803             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    1804             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1805             :                 .in.fname = file,
    1806             :                 .in.timewarp = nttime,
    1807             :         };
    1808             : 
    1809           2 :         status = smb2_create(tree, tctx, &io);
    1810           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1811             :                                         "smb2_create\n");
    1812           2 :         h1 = io.out.file.handle;
    1813             : 
    1814           2 :         status = smb2_util_write(tree, h1, "123", 0, 3);
    1815           2 :         torture_assert_ntstatus_equal_goto(tctx, status,
    1816             :                                            NT_STATUS_MEDIA_WRITE_PROTECTED,
    1817             :                                            ret, done, "smb2_create\n");
    1818             : 
    1819           2 :         smb2_util_close(tree, h1);
    1820             : 
    1821           2 : done:
    1822           2 :         return ret;
    1823             : }
    1824             : 
    1825           2 : static bool test_twrp_stream(struct torture_context *tctx,
    1826             :                              struct smb2_tree *tree)
    1827             : {
    1828           0 :         struct smb2_create io;
    1829           0 :         NTSTATUS status;
    1830           2 :         bool ret = true;
    1831           2 :         char *p = NULL;
    1832           0 :         struct tm tm;
    1833           0 :         time_t t;
    1834           0 :         uint64_t nttime;
    1835           2 :         const char *file = NULL;
    1836           2 :         const char *stream = NULL;
    1837           2 :         const char *snapshot = NULL;
    1838           0 :         int stream_size;
    1839           2 :         char *path = NULL;
    1840           2 :         uint8_t *buf = NULL;
    1841           2 :         struct smb2_handle h1 = {{0}};
    1842           0 :         struct smb2_read r;
    1843             : 
    1844           2 :         file = torture_setting_string(tctx, "twrp_file", NULL);
    1845           2 :         if (file == NULL) {
    1846           0 :                 torture_skip(tctx, "missing 'twrp_file' option\n");
    1847             :         }
    1848             : 
    1849           2 :         stream = torture_setting_string(tctx, "twrp_stream", NULL);
    1850           2 :         if (stream == NULL) {
    1851           0 :                 torture_skip(tctx, "missing 'twrp_stream' option\n");
    1852             :         }
    1853             : 
    1854           2 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    1855           2 :         if (snapshot == NULL) {
    1856           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    1857             :         }
    1858             : 
    1859           2 :         stream_size = torture_setting_int(tctx, "twrp_stream_size", 0);
    1860           2 :         if (stream_size == 0) {
    1861           0 :                 torture_skip(tctx, "missing 'twrp_stream_size' option\n");
    1862             :         }
    1863             : 
    1864           2 :         torture_comment(tctx, "Testing timewarp on stream (%s) (%s)\n",
    1865             :                         file, snapshot);
    1866             : 
    1867           2 :         path = talloc_asprintf(tree, "%s:%s", file, stream);
    1868           2 :         torture_assert_not_null_goto(tctx, path, ret, done, "path\n");
    1869             : 
    1870           2 :         buf = talloc_zero_array(tree, uint8_t, stream_size);
    1871           2 :         torture_assert_not_null_goto(tctx, buf, ret, done, "buf\n");
    1872             : 
    1873           2 :         setenv("TZ", "GMT", 1);
    1874             : 
    1875             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    1876             :          * effect if it is greater than 1. */
    1877           2 :         ZERO_STRUCT(tm);
    1878             : 
    1879           2 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    1880           2 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    1881           2 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    1882             : 
    1883           2 :         t = mktime(&tm);
    1884           2 :         unix_to_nt_time(&nttime, t);
    1885             : 
    1886           2 :         io = (struct smb2_create) {
    1887             :                 .in.desired_access = SEC_FILE_READ_DATA,
    1888             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    1889             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    1890             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1891             :                 .in.fname = path,
    1892             :                 .in.timewarp = nttime,
    1893             :         };
    1894             : 
    1895           2 :         status = smb2_create(tree, tctx, &io);
    1896           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1897             :                                         "smb2_create\n");
    1898           2 :         h1 = io.out.file.handle;
    1899             : 
    1900           2 :         r = (struct smb2_read) {
    1901             :                 .in.file.handle = h1,
    1902             :                 .in.length = stream_size,
    1903             :                 .in.offset = 0,
    1904             :         };
    1905             : 
    1906           2 :         status = smb2_read(tree, tree, &r);
    1907           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1908             :                                         "smb2_create\n");
    1909             : 
    1910           2 :         smb2_util_close(tree, h1);
    1911             : 
    1912           2 : done:
    1913           2 :         return ret;
    1914             : }
    1915             : 
    1916           2 : static bool test_twrp_openroot(struct torture_context *tctx, struct smb2_tree *tree)
    1917             : {
    1918           0 :         struct smb2_create io;
    1919           0 :         NTSTATUS status;
    1920           2 :         bool ret = true;
    1921           2 :         char *p = NULL;
    1922           0 :         struct tm tm;
    1923           0 :         time_t t;
    1924           0 :         uint64_t nttime;
    1925           2 :         const char *snapshot = NULL;
    1926             : 
    1927           2 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    1928           2 :         if (snapshot == NULL) {
    1929           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    1930             :         }
    1931             : 
    1932           2 :         torture_comment(tctx, "Testing open of root of "
    1933             :                 "share with timewarp (%s)\n",
    1934             :                 snapshot);
    1935             : 
    1936           2 :         setenv("TZ", "GMT", 1);
    1937             : 
    1938             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    1939             :          * effect if it is greater than 1. */
    1940           2 :         ZERO_STRUCT(tm);
    1941             : 
    1942           2 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    1943           2 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    1944           2 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    1945             : 
    1946           2 :         t = mktime(&tm);
    1947           2 :         unix_to_nt_time(&nttime, t);
    1948             : 
    1949           2 :         io = (struct smb2_create) {
    1950             :                 .in.desired_access = SEC_FILE_READ_DATA,
    1951             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    1952             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    1953             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1954             :                 .in.fname = "",
    1955             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    1956             :                 .in.timewarp = nttime,
    1957             :         };
    1958             : 
    1959           2 :         status = smb2_create(tree, tctx, &io);
    1960           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1961             :                                         "smb2_create\n");
    1962           2 :         smb2_util_close(tree, io.out.file.handle);
    1963             : 
    1964           2 : done:
    1965           2 :         return ret;
    1966             : }
    1967             : 
    1968           2 : static bool test_twrp_listdir(struct torture_context *tctx,
    1969             :                               struct smb2_tree *tree)
    1970             : {
    1971           0 :         struct smb2_create create;
    1972           2 :         struct smb2_handle h = {{0}};
    1973           0 :         struct smb2_find find;
    1974           0 :         unsigned int count;
    1975           0 :         union smb_search_data *d;
    1976           2 :         char *p = NULL;
    1977           0 :         struct tm tm;
    1978           0 :         time_t t;
    1979           0 :         uint64_t nttime;
    1980           2 :         const char *snapshot = NULL;
    1981           0 :         uint64_t normal_fileid;
    1982           0 :         uint64_t snapshot_fileid;
    1983           0 :         NTSTATUS status;
    1984           2 :         bool ret = true;
    1985             : 
    1986           2 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    1987           2 :         if (snapshot == NULL) {
    1988           0 :                 torture_fail(tctx, "missing 'twrp_snapshot' option\n");
    1989             :         }
    1990             : 
    1991           2 :         torture_comment(tctx, "Testing File-Ids of directory listing "
    1992             :                         "with timewarp (%s)\n",
    1993             :                         snapshot);
    1994             : 
    1995           2 :         setenv("TZ", "GMT", 1);
    1996             : 
    1997             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    1998             :          * effect if it is greater than 1. */
    1999           2 :         ZERO_STRUCT(tm);
    2000             : 
    2001           2 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2002           2 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2003           2 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2004             : 
    2005           2 :         t = mktime(&tm);
    2006           2 :         unix_to_nt_time(&nttime, t);
    2007             : 
    2008             :         /*
    2009             :          * 1: Query the file's File-Id
    2010             :          */
    2011           2 :         create = (struct smb2_create) {
    2012             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2013             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2014             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2015             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2016             :                 .in.fname = "subdir/hardlink",
    2017             :                 .in.query_on_disk_id = true,
    2018             :         };
    2019             : 
    2020           2 :         status = smb2_create(tree, tctx, &create);
    2021           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2022             :                                         "test file could not be created\n");
    2023           2 :         smb2_util_close(tree, create.out.file.handle);
    2024           2 :         normal_fileid = BVAL(&create.out.on_disk_id, 0);
    2025             : 
    2026             :         /*
    2027             :          * 2: check directory listing of the file returns same File-Id
    2028             :          */
    2029             : 
    2030           2 :         create = (struct smb2_create) {
    2031             :                 .in.desired_access = SEC_DIR_LIST,
    2032             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2033             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2034             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2035             :                 .in.fname = "subdir",
    2036             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2037             :         };
    2038             : 
    2039           2 :         status = smb2_create(tree, tctx, &create);
    2040           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2041             :                                         "smb2_create\n");
    2042           2 :         h = create.out.file.handle;
    2043             : 
    2044           2 :         find = (struct smb2_find) {
    2045             :                 .in.file.handle = h,
    2046             :                 .in.pattern = "*",
    2047             :                 .in.max_response_size = 0x1000,
    2048             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2049             :         };
    2050             : 
    2051           2 :         status = smb2_find_level(tree, tree, &find, &count, &d);
    2052           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2053             :                                         "smb2_find_level failed\n");
    2054             : 
    2055           2 :         smb2_util_close(tree, h);
    2056             : 
    2057           2 :         torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
    2058           2 :         torture_assert_str_equal_goto(tctx,
    2059             :                                       d[2].id_both_directory_info.name.s,
    2060             :                                       "hardlink",
    2061             :                                       ret, done, "bad name");
    2062           2 :         torture_assert_u64_equal_goto(tctx,
    2063             :                                       d[2].id_both_directory_info.file_id,
    2064             :                                       normal_fileid,
    2065             :                                       ret, done, "bad fileid\n");
    2066             : 
    2067             :         /*
    2068             :          * 3: Query File-Id of snapshot of the file and check the File-Id is
    2069             :          * different compared to the basefile
    2070             :          */
    2071             : 
    2072           2 :         create = (struct smb2_create) {
    2073             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2074             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2075             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2076             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2077             :                 .in.fname = "subdir/hardlink",
    2078             :                 .in.query_on_disk_id = true,
    2079             :                 .in.timewarp = nttime,
    2080             :         };
    2081             : 
    2082           2 :         status = smb2_create(tree, tctx, &create);
    2083           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2084             :                                         "test file could not be created\n");
    2085           2 :         smb2_util_close(tree, create.out.file.handle);
    2086             : 
    2087           2 :         snapshot_fileid = BVAL(&create.out.on_disk_id, 0);
    2088             : 
    2089             :         /*
    2090             :          * 4: List directory of the snapshot and check the File-Id returned here
    2091             :          * is the same as in 3.
    2092             :          */
    2093             : 
    2094           2 :         create = (struct smb2_create) {
    2095             :                 .in.desired_access = SEC_DIR_LIST,
    2096             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2097             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2098             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2099             :                 .in.fname = "subdir",
    2100             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2101             :                 .in.timewarp = nttime,
    2102             :         };
    2103             : 
    2104           2 :         status = smb2_create(tree, tctx, &create);
    2105           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2106             :                                         "smb2_create\n");
    2107           2 :         h = create.out.file.handle;
    2108             : 
    2109           2 :         find = (struct smb2_find) {
    2110             :                 .in.file.handle = h,
    2111             :                 .in.pattern = "*",
    2112             :                 .in.max_response_size = 0x1000,
    2113             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2114             :         };
    2115             : 
    2116           2 :         status = smb2_find_level(tree, tree, &find, &count, &d);
    2117           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2118             :                                         "smb2_find_level failed\n");
    2119           2 :         smb2_util_close(tree, h);
    2120             : 
    2121           2 :         torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
    2122           2 :         torture_assert_str_equal_goto(tctx,
    2123             :                                       d[2].id_both_directory_info.name.s,
    2124             :                                       "hardlink",
    2125             :                                       ret, done, "bad name");
    2126           2 :         torture_assert_u64_equal_goto(tctx,
    2127             :                                       snapshot_fileid,
    2128             :                                       d[2].id_both_directory_info.file_id,
    2129             :                                       ret, done, "bad fileid\n");
    2130             : 
    2131           2 : done:
    2132           2 :         return ret;
    2133             : }
    2134             : 
    2135           2 : static bool test_fileid(struct torture_context *tctx,
    2136             :                         struct smb2_tree *tree)
    2137             : {
    2138           2 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2139           2 :         const char *fname = DNAME "\\foo";
    2140           2 :         const char *sname = DNAME "\\foo:bar";
    2141           0 :         struct smb2_handle testdirh;
    2142           0 :         struct smb2_handle h1;
    2143           0 :         struct smb2_create create;
    2144           0 :         union smb_fileinfo finfo;
    2145           0 :         union smb_setfileinfo sinfo;
    2146           0 :         struct smb2_find f;
    2147           0 :         unsigned int count;
    2148           0 :         union smb_search_data *d;
    2149           0 :         uint64_t expected_fileid;
    2150           0 :         uint64_t returned_fileid;
    2151           0 :         NTSTATUS status;
    2152           2 :         bool ret = true;
    2153             : 
    2154           2 :         smb2_deltree(tree, DNAME);
    2155             : 
    2156           2 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    2157           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2158             :                                         "torture_smb2_testdir failed\n");
    2159             : 
    2160             :         /*
    2161             :          * Initial create with QFID
    2162             :          */
    2163           2 :         create = (struct smb2_create) {
    2164             :                 .in.desired_access = SEC_FILE_ALL,
    2165             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2166             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2167             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    2168             :                 .in.fname = fname,
    2169             :                 .in.query_on_disk_id = true,
    2170             :         };
    2171             : 
    2172           2 :         status = smb2_create(tree, tctx, &create);
    2173           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2174             :                                         "test file could not be created\n");
    2175           2 :         h1 = create.out.file.handle;
    2176           2 :         expected_fileid = BVAL(&create.out.on_disk_id, 0);
    2177             : 
    2178             :         /*
    2179             :          * Getinfo the File-ID on the just opened handle
    2180             :          */
    2181           2 :         finfo = (union smb_fileinfo) {
    2182             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2183             :                 .generic.in.file.handle = h1,
    2184             :         };
    2185             : 
    2186           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2187           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2188             :                                         "torture_smb2_testdir\n");
    2189           2 :         smb2_util_close(tree, h1);
    2190           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2191             :                                       expected_fileid,
    2192             :                                       ret, done, "bad fileid\n");
    2193             : 
    2194             :         /*
    2195             :          * Open existing with QFID
    2196             :          */
    2197           2 :         create = (struct smb2_create) {
    2198             :                 .in.desired_access = SEC_FILE_ALL,
    2199             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2200             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2201             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2202             :                 .in.fname = fname,
    2203             :                 .in.query_on_disk_id = true,
    2204             :         };
    2205             : 
    2206           2 :         status = smb2_create(tree, tctx, &create);
    2207           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2208             :                                         "test file could not be created\n");
    2209           2 :         h1 = create.out.file.handle;
    2210           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2211           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2212             :                                       ret, done, "bad fileid\n");
    2213             : 
    2214             :         /*
    2215             :          * Getinfo the File-ID on the just opened handle
    2216             :          */
    2217           2 :         finfo = (union smb_fileinfo) {
    2218             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2219             :                 .generic.in.file.handle = h1,
    2220             :         };
    2221             : 
    2222           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2223           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2224             :                                         "torture_smb2_testdir\n");
    2225           2 :         smb2_util_close(tree, h1);
    2226           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2227             :                                       expected_fileid,
    2228             :                                       ret, done, "bad fileid\n");
    2229             : 
    2230             :         /*
    2231             :          * Overwrite with QFID
    2232             :          */
    2233           2 :         create = (struct smb2_create) {
    2234             :                 .in.desired_access = SEC_FILE_ALL,
    2235             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2236             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2237             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2238             :                 .in.fname = fname,
    2239             :                 .in.query_on_disk_id = true,
    2240             :         };
    2241             : 
    2242           2 :         status = smb2_create(tree, tctx, &create);
    2243           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2244             :                                         "test file could not be created\n");
    2245           2 :         h1 = create.out.file.handle;
    2246           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2247           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2248             :                                       ret, done, "bad fileid\n");
    2249             : 
    2250             :         /*
    2251             :          * Getinfo the File-ID on the open with overwrite handle
    2252             :          */
    2253           2 :         finfo = (union smb_fileinfo) {
    2254             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2255             :                 .generic.in.file.handle = h1,
    2256             :         };
    2257             : 
    2258           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2259           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2260             :                                         "torture_smb2_testdir\n");
    2261           2 :         smb2_util_close(tree, h1);
    2262           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2263             :                                       expected_fileid,
    2264             :                                       ret, done, "bad fileid\n");
    2265             : 
    2266             :         /*
    2267             :          * Do some modifications on the basefile (IO, setinfo), verifying
    2268             :          * File-ID after each step.
    2269             :          */
    2270           2 :         create = (struct smb2_create) {
    2271             :                 .in.desired_access = SEC_FILE_ALL,
    2272             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2273             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2274             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2275             :                 .in.fname = fname,
    2276             :                 .in.query_on_disk_id = true,
    2277             :         };
    2278             : 
    2279           2 :         status = smb2_create(tree, tctx, &create);
    2280           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2281             :                                         "test file could not be created\n");
    2282           2 :         h1 = create.out.file.handle;
    2283             : 
    2284           2 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    2285           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2286             :                                         "smb2_util_write failed\n");
    2287             : 
    2288           2 :         finfo = (union smb_fileinfo) {
    2289             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2290             :                 .generic.in.file.handle = h1,
    2291             :         };
    2292           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2293           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2294             :                                         "smb2_getinfo_file failed\n");
    2295           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2296             :                                       expected_fileid,
    2297             :                                       ret, done, "bad fileid\n");
    2298             : 
    2299           2 :         sinfo = (union smb_setfileinfo) {
    2300             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    2301             :                 .basic_info.in.file.handle = h1,
    2302             :         };
    2303           2 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    2304             : 
    2305           2 :         status = smb2_setinfo_file(tree, &sinfo);
    2306           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2307             :                                         "smb2_setinfo_file failed\n");
    2308             : 
    2309           2 :         finfo = (union smb_fileinfo) {
    2310             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2311             :                 .generic.in.file.handle = h1,
    2312             :         };
    2313           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2314           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2315             :                                         "smb2_getinfo_file failed\n");
    2316           2 :         smb2_util_close(tree, h1);
    2317           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2318             :                                       expected_fileid,
    2319             :                                       ret, done, "bad fileid\n");
    2320             : 
    2321             :         /*
    2322             :          * Create stream, check the stream's File-ID, should be the same as the
    2323             :          * base file (sic!, tested against Windows).
    2324             :          */
    2325           2 :         create = (struct smb2_create) {
    2326             :                 .in.desired_access = SEC_FILE_ALL,
    2327             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2328             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2329             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    2330             :                 .in.fname = sname,
    2331             :                 .in.query_on_disk_id = true,
    2332             :         };
    2333             : 
    2334           2 :         status = smb2_create(tree, tctx, &create);
    2335           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2336             :                                         "test file could not be created\n");
    2337           2 :         h1 = create.out.file.handle;
    2338           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2339           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2340             :                                       ret, done, "bad fileid\n");
    2341             : 
    2342             :         /*
    2343             :          * Getinfo the File-ID on the created stream
    2344             :          */
    2345           2 :         finfo = (union smb_fileinfo) {
    2346             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2347             :                 .generic.in.file.handle = h1,
    2348             :         };
    2349             : 
    2350           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2351           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2352             :                                         "smb2_getinfo_file failed\n");
    2353           2 :         smb2_util_close(tree, h1);
    2354           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2355             :                                       expected_fileid,
    2356             :                                       ret, done, "bad fileid\n");
    2357             : 
    2358             :         /*
    2359             :          * Open stream, check the stream's File-ID, should be the same as the
    2360             :          * base file (sic!, tested against Windows).
    2361             :          */
    2362           2 :         create = (struct smb2_create) {
    2363             :                 .in.desired_access = SEC_FILE_ALL,
    2364             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2365             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2366             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2367             :                 .in.fname = sname,
    2368             :                 .in.query_on_disk_id = true,
    2369             :         };
    2370             : 
    2371           2 :         status = smb2_create(tree, tctx, &create);
    2372           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2373             :                                         "test file could not be created\n");
    2374           2 :         h1 = create.out.file.handle;
    2375           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2376           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2377             :                                       ret, done, "bad fileid\n");
    2378             : 
    2379             :         /*
    2380             :          * Getinfo the File-ID on the opened stream
    2381             :          */
    2382           2 :         finfo = (union smb_fileinfo) {
    2383             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2384             :                 .generic.in.file.handle = h1,
    2385             :         };
    2386             : 
    2387           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2388           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2389             :                                         "smb2_getinfo_file failed\n");
    2390           2 :         smb2_util_close(tree, h1);
    2391           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2392             :                                       expected_fileid,
    2393             :                                       ret, done, "bad fileid\n");
    2394             : 
    2395             :         /*
    2396             :          * Overwrite stream, check the stream's File-ID, should be the same as
    2397             :          * the base file (sic!, tested against Windows).
    2398             :          */
    2399           2 :         create = (struct smb2_create) {
    2400             :                 .in.desired_access = SEC_FILE_ALL,
    2401             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2402             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2403             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2404             :                 .in.fname = sname,
    2405             :                 .in.query_on_disk_id = true,
    2406             :         };
    2407             : 
    2408           2 :         status = smb2_create(tree, tctx, &create);
    2409           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2410             :                                         "test file could not be created\n");
    2411           2 :         h1 = create.out.file.handle;
    2412           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2413           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2414             :                                       ret, done, "bad fileid\n");
    2415             : 
    2416             :         /*
    2417             :          * Getinfo the File-ID on the overwritten stream
    2418             :          */
    2419           2 :         finfo = (union smb_fileinfo) {
    2420             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2421             :                 .generic.in.file.handle = h1,
    2422             :         };
    2423             : 
    2424           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2425           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2426             :                                         "smb2_getinfo_file failed\n");
    2427           2 :         smb2_util_close(tree, h1);
    2428           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2429             :                                       expected_fileid,
    2430             :                                       ret, done, "bad fileid\n");
    2431             : 
    2432             :         /*
    2433             :          * Do some modifications on the stream (IO, setinfo), verifying File-ID
    2434             :          * after each step.
    2435             :          */
    2436           2 :         create = (struct smb2_create) {
    2437             :                 .in.desired_access = SEC_FILE_ALL,
    2438             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2439             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2440             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2441             :                 .in.fname = sname,
    2442             :                 .in.query_on_disk_id = true,
    2443             :         };
    2444             : 
    2445           2 :         status = smb2_create(tree, tctx, &create);
    2446           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2447             :                                         "test file could not be created\n");
    2448           2 :         h1 = create.out.file.handle;
    2449             : 
    2450           2 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    2451           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2452             :                                         "smb2_util_write failed\n");
    2453             : 
    2454           2 :         finfo = (union smb_fileinfo) {
    2455             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2456             :                 .generic.in.file.handle = h1,
    2457             :         };
    2458           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2459           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2460             :                                         "smb2_getinfo_file failed\n");
    2461           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2462             :                                       expected_fileid,
    2463             :                                       ret, done, "bad fileid\n");
    2464             : 
    2465           2 :         sinfo = (union smb_setfileinfo) {
    2466             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    2467             :                 .basic_info.in.file.handle = h1,
    2468             :         };
    2469           2 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    2470             : 
    2471           2 :         status = smb2_setinfo_file(tree, &sinfo);
    2472           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2473             :                                         "smb2_setinfo_file failed\n");
    2474             : 
    2475           2 :         finfo = (union smb_fileinfo) {
    2476             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2477             :                 .generic.in.file.handle = h1,
    2478             :         };
    2479           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2480           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2481             :                                         "smb2_getinfo_file failed\n");
    2482           2 :         smb2_util_close(tree, h1);
    2483           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2484             :                                       expected_fileid,
    2485             :                                       ret, done, "bad fileid\n");
    2486             : 
    2487             :         /*
    2488             :          * Final open of the basefile with QFID
    2489             :          */
    2490           2 :         create = (struct smb2_create) {
    2491             :                 .in.desired_access = SEC_FILE_ALL,
    2492             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2493             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2494             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2495             :                 .in.fname = fname,
    2496             :                 .in.query_on_disk_id = true,
    2497             :         };
    2498             : 
    2499           2 :         status = smb2_create(tree, tctx, &create);
    2500           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2501             :                                         "test file could not be created\n");
    2502           2 :         h1 = create.out.file.handle;
    2503           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2504           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2505             :                                       ret, done, "bad fileid\n");
    2506             : 
    2507             :         /*
    2508             :          * Final Getinfo checking File-ID
    2509             :          */
    2510           2 :         finfo = (union smb_fileinfo) {
    2511             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2512             :                 .generic.in.file.handle = h1,
    2513             :         };
    2514             : 
    2515           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2516           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2517             :                                         "torture_smb2_testdir\n");
    2518           2 :         smb2_util_close(tree, h1);
    2519           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2520             :                                       expected_fileid,
    2521             :                                       ret, done, "bad fileid\n");
    2522             : 
    2523             :         /*
    2524             :          * Final list directory, verifying the operations on basefile and stream
    2525             :          * didn't modify the base file metadata.
    2526             :          */
    2527           2 :         f = (struct smb2_find) {
    2528             :                 .in.file.handle = testdirh,
    2529             :                 .in.pattern = "foo",
    2530             :                 .in.max_response_size = 0x1000,
    2531             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2532             :                 .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
    2533             :         };
    2534             : 
    2535           2 :         status = smb2_find_level(tree, tree, &f, &count, &d);
    2536           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2537             :                                         "smb2_find_level failed\n");
    2538           2 :         torture_assert_u64_equal_goto(tctx,
    2539             :                                       d->id_both_directory_info.file_id,
    2540             :                                       expected_fileid,
    2541             :                                       ret, done, "bad fileid\n");
    2542             : 
    2543           2 : done:
    2544           2 :         smb2_util_close(tree, testdirh);
    2545           2 :         smb2_deltree(tree, DNAME);
    2546           2 :         talloc_free(mem_ctx);
    2547           2 :         return ret;
    2548             : }
    2549             : 
    2550           2 : static bool test_fileid_dir(struct torture_context *tctx,
    2551             :                             struct smb2_tree *tree)
    2552             : {
    2553           2 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2554           2 :         const char *dname = DNAME "\\foo";
    2555           2 :         const char *sname = DNAME "\\foo:bar";
    2556           0 :         struct smb2_handle testdirh;
    2557           0 :         struct smb2_handle h1;
    2558           0 :         struct smb2_create create;
    2559           0 :         union smb_fileinfo finfo;
    2560           0 :         union smb_setfileinfo sinfo;
    2561           0 :         struct smb2_find f;
    2562           0 :         unsigned int count;
    2563           0 :         union smb_search_data *d;
    2564           0 :         uint64_t expected_fileid;
    2565           0 :         uint64_t returned_fileid;
    2566           0 :         NTSTATUS status;
    2567           2 :         bool ret = true;
    2568             : 
    2569           2 :         smb2_deltree(tree, DNAME);
    2570             : 
    2571           2 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    2572           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2573             :                                         "torture_smb2_testdir failed\n");
    2574             : 
    2575             :         /*
    2576             :          * Initial directory create with QFID
    2577             :          */
    2578           2 :         create = (struct smb2_create) {
    2579             :                 .in.desired_access = SEC_FILE_ALL,
    2580             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2581             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    2582             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2583             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2584             :                 .in.fname = dname,
    2585             :                 .in.query_on_disk_id = true,
    2586             :         };
    2587             : 
    2588           2 :         status = smb2_create(tree, tctx, &create);
    2589           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2590             :                                         "test file could not be created\n");
    2591           2 :         h1 = create.out.file.handle;
    2592           2 :         expected_fileid = BVAL(&create.out.on_disk_id, 0);
    2593             : 
    2594             :         /*
    2595             :          * Getinfo the File-ID on the just opened handle
    2596             :          */
    2597           2 :         finfo = (union smb_fileinfo) {
    2598             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2599             :                 .generic.in.file.handle = h1,
    2600             :         };
    2601             : 
    2602           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2603           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2604             :                                         "torture_smb2_testdir\n");
    2605           2 :         smb2_util_close(tree, h1);
    2606           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2607             :                                       expected_fileid,
    2608             :                                       ret, done, "bad fileid\n");
    2609             : 
    2610             :         /*
    2611             :          * Open existing directory with QFID
    2612             :          */
    2613           2 :         create = (struct smb2_create) {
    2614             :                 .in.desired_access = SEC_FILE_ALL,
    2615             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2616             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2617             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2618             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2619             :                 .in.fname = dname,
    2620             :                 .in.query_on_disk_id = true,
    2621             :         };
    2622             : 
    2623           2 :         status = smb2_create(tree, tctx, &create);
    2624           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2625             :                                         "test file could not be created\n");
    2626           2 :         h1 = create.out.file.handle;
    2627           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2628           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2629             :                                       ret, done, "bad fileid\n");
    2630             : 
    2631             :         /*
    2632             :          * Getinfo the File-ID on the just opened handle
    2633             :          */
    2634           2 :         finfo = (union smb_fileinfo) {
    2635             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2636             :                 .generic.in.file.handle = h1,
    2637             :         };
    2638             : 
    2639           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2640           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2641             :                                         "torture_smb2_testdir\n");
    2642           2 :         smb2_util_close(tree, h1);
    2643           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2644             :                                       expected_fileid,
    2645             :                                       ret, done, "bad fileid\n");
    2646             : 
    2647             :         /*
    2648             :          * Create stream, check the stream's File-ID, should be the same as the
    2649             :          * base file (sic!, tested against Windows).
    2650             :          */
    2651           2 :         create = (struct smb2_create) {
    2652             :                 .in.desired_access = SEC_FILE_ALL,
    2653             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2654             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2655             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    2656             :                 .in.fname = sname,
    2657             :                 .in.query_on_disk_id = true,
    2658             :         };
    2659             : 
    2660           2 :         status = smb2_create(tree, tctx, &create);
    2661           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2662             :                                         "test file could not be created\n");
    2663           2 :         h1 = create.out.file.handle;
    2664           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2665           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2666             :                                       ret, done, "bad fileid\n");
    2667             : 
    2668             :         /*
    2669             :          * Getinfo the File-ID on the created stream
    2670             :          */
    2671           2 :         finfo = (union smb_fileinfo) {
    2672             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2673             :                 .generic.in.file.handle = h1,
    2674             :         };
    2675             : 
    2676           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2677           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2678             :                                         "smb2_getinfo_file failed\n");
    2679           2 :         smb2_util_close(tree, h1);
    2680           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2681             :                                       expected_fileid,
    2682             :                                       ret, done, "bad fileid\n");
    2683             : 
    2684             :         /*
    2685             :          * Open stream, check the stream's File-ID, should be the same as the
    2686             :          * base file (sic!, tested against Windows).
    2687             :          */
    2688           2 :         create = (struct smb2_create) {
    2689             :                 .in.desired_access = SEC_FILE_ALL,
    2690             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2691             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2692             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2693             :                 .in.fname = sname,
    2694             :                 .in.query_on_disk_id = true,
    2695             :         };
    2696             : 
    2697           2 :         status = smb2_create(tree, tctx, &create);
    2698           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2699             :                                         "test file could not be created\n");
    2700           2 :         h1 = create.out.file.handle;
    2701           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2702           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2703             :                                       ret, done, "bad fileid\n");
    2704             : 
    2705             :         /*
    2706             :          * Getinfo the File-ID on the opened stream
    2707             :          */
    2708           2 :         finfo = (union smb_fileinfo) {
    2709             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2710             :                 .generic.in.file.handle = h1,
    2711             :         };
    2712             : 
    2713           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2714           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2715             :                                         "smb2_getinfo_file failed\n");
    2716           2 :         smb2_util_close(tree, h1);
    2717           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2718             :                                       expected_fileid,
    2719             :                                       ret, done, "bad fileid\n");
    2720             : 
    2721             :         /*
    2722             :          * Overwrite stream, check the stream's File-ID, should be the same as
    2723             :          * the base file (sic!, tested against Windows).
    2724             :          */
    2725           2 :         create = (struct smb2_create) {
    2726             :                 .in.desired_access = SEC_FILE_ALL,
    2727             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2728             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2729             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2730             :                 .in.fname = sname,
    2731             :                 .in.query_on_disk_id = true,
    2732             :         };
    2733             : 
    2734           2 :         status = smb2_create(tree, tctx, &create);
    2735           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2736             :                                         "test file could not be created\n");
    2737           2 :         h1 = create.out.file.handle;
    2738           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2739           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2740             :                                       ret, done, "bad fileid\n");
    2741             : 
    2742             :         /*
    2743             :          * Getinfo the File-ID on the overwritten stream
    2744             :          */
    2745           2 :         finfo = (union smb_fileinfo) {
    2746             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2747             :                 .generic.in.file.handle = h1,
    2748             :         };
    2749             : 
    2750           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2751           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2752             :                                         "smb2_getinfo_file failed\n");
    2753           2 :         smb2_util_close(tree, h1);
    2754           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2755             :                                       expected_fileid,
    2756             :                                       ret, done, "bad fileid\n");
    2757             : 
    2758             :         /*
    2759             :          * Do some modifications on the stream (IO, setinfo), verifying File-ID
    2760             :          * after each step.
    2761             :          */
    2762           2 :         create = (struct smb2_create) {
    2763             :                 .in.desired_access = SEC_FILE_ALL,
    2764             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2765             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2766             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2767             :                 .in.fname = sname,
    2768             :                 .in.query_on_disk_id = true,
    2769             :         };
    2770             : 
    2771           2 :         status = smb2_create(tree, tctx, &create);
    2772           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2773             :                                         "test file could not be created\n");
    2774           2 :         h1 = create.out.file.handle;
    2775             : 
    2776           2 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    2777           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2778             :                                         "smb2_util_write failed\n");
    2779             : 
    2780           2 :         finfo = (union smb_fileinfo) {
    2781             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2782             :                 .generic.in.file.handle = h1,
    2783             :         };
    2784           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2785           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2786             :                                         "smb2_getinfo_file failed\n");
    2787           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2788             :                                       expected_fileid,
    2789             :                                       ret, done, "bad fileid\n");
    2790             : 
    2791           2 :         sinfo = (union smb_setfileinfo) {
    2792             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    2793             :                 .basic_info.in.file.handle = h1,
    2794             :         };
    2795           2 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    2796             : 
    2797           2 :         status = smb2_setinfo_file(tree, &sinfo);
    2798           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2799             :                                         "smb2_setinfo_file failed\n");
    2800             : 
    2801           2 :         finfo = (union smb_fileinfo) {
    2802             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2803             :                 .generic.in.file.handle = h1,
    2804             :         };
    2805           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2806           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2807             :                                         "smb2_getinfo_file failed\n");
    2808           2 :         smb2_util_close(tree, h1);
    2809           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2810             :                                       expected_fileid,
    2811             :                                       ret, done, "bad fileid\n");
    2812             : 
    2813             :         /*
    2814             :          * Final open of the directory with QFID
    2815             :          */
    2816           2 :         create = (struct smb2_create) {
    2817             :                 .in.desired_access = SEC_FILE_ALL,
    2818             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2819             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2820             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2821             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2822             :                 .in.fname = dname,
    2823             :                 .in.query_on_disk_id = true,
    2824             :         };
    2825             : 
    2826           2 :         status = smb2_create(tree, tctx, &create);
    2827           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2828             :                                         "test file could not be created\n");
    2829           2 :         h1 = create.out.file.handle;
    2830           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2831           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2832             :                                       ret, done, "bad fileid\n");
    2833             : 
    2834             :         /*
    2835             :          * Final Getinfo checking File-ID
    2836             :          */
    2837           2 :         finfo = (union smb_fileinfo) {
    2838             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2839             :                 .generic.in.file.handle = h1,
    2840             :         };
    2841             : 
    2842           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2843           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2844             :                                         "torture_smb2_testdir\n");
    2845           2 :         smb2_util_close(tree, h1);
    2846           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2847             :                                       expected_fileid,
    2848             :                                       ret, done, "bad fileid\n");
    2849             : 
    2850             :         /*
    2851             :          * Final list directory, verifying the operations on basefile and stream
    2852             :          * didn't modify the base file metadata.
    2853             :          */
    2854           2 :         f = (struct smb2_find) {
    2855             :                 .in.file.handle = testdirh,
    2856             :                 .in.pattern = "foo",
    2857             :                 .in.max_response_size = 0x1000,
    2858             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2859             :                 .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
    2860             :         };
    2861             : 
    2862           2 :         status = smb2_find_level(tree, tree, &f, &count, &d);
    2863           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2864             :                                         "smb2_find_level failed\n");
    2865           2 :         torture_assert_u64_equal_goto(tctx,
    2866             :                                       d->id_both_directory_info.file_id,
    2867             :                                       expected_fileid,
    2868             :                                       ret, done, "bad fileid\n");
    2869             : 
    2870           2 : done:
    2871           2 :         smb2_util_close(tree, testdirh);
    2872           2 :         smb2_deltree(tree, DNAME);
    2873           2 :         talloc_free(mem_ctx);
    2874           2 :         return ret;
    2875             : }
    2876             : 
    2877           4 : static bool test_fileid_unique_object(
    2878             :                         struct torture_context *tctx,
    2879             :                         struct smb2_tree *tree,
    2880             :                         unsigned int num_objs,
    2881             :                         bool create_dirs)
    2882           4 : {
    2883           4 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2884           4 :         char *fname = NULL;
    2885           0 :         struct smb2_handle testdirh;
    2886           0 :         struct smb2_handle h1;
    2887           0 :         struct smb2_create create;
    2888           0 :         unsigned int i;
    2889           4 :         uint64_t fileid_array[num_objs];
    2890           0 :         NTSTATUS status;
    2891           4 :         bool ret = true;
    2892             : 
    2893           4 :         smb2_deltree(tree, DNAME);
    2894             : 
    2895           4 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    2896           4 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2897             :                                         "test_fileid_unique failed\n");
    2898           4 :         smb2_util_close(tree, testdirh);
    2899             : 
    2900             :         /* Create num_obj files as rapidly as we can. */
    2901         404 :         for (i = 0; i < num_objs; i++) {
    2902         400 :                 fname = talloc_asprintf(mem_ctx,
    2903             :                                         "%s\\testfile.%u",
    2904             :                                         DNAME,
    2905             :                                         i);
    2906         400 :                 torture_assert_goto(tctx,
    2907             :                                 fname != NULL,
    2908             :                                 ret,
    2909             :                                 done,
    2910             :                                 "talloc failed\n");
    2911             : 
    2912         400 :                 create = (struct smb2_create) {
    2913             :                         .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
    2914             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2915             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2916             :                         .in.create_disposition = NTCREATEX_DISP_CREATE,
    2917             :                         .in.fname = fname,
    2918             :                 };
    2919             : 
    2920         400 :                 if (create_dirs) {
    2921         200 :                         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    2922         200 :                         create.in.create_options = FILE_DIRECTORY_FILE;
    2923             :                 }
    2924             : 
    2925         400 :                 status = smb2_create(tree, tctx, &create);
    2926         400 :                 if (!NT_STATUS_IS_OK(status)) {
    2927           0 :                         torture_fail(tctx,
    2928             :                                 talloc_asprintf(tctx,
    2929             :                                         "test file %s could not be created\n",
    2930             :                                         fname));
    2931             :                         TALLOC_FREE(fname);
    2932             :                         ret = false;
    2933             :                         goto done;
    2934             :                 }
    2935             : 
    2936         400 :                 h1 = create.out.file.handle;
    2937         400 :                 smb2_util_close(tree, h1);
    2938         400 :                 TALLOC_FREE(fname);
    2939             :         }
    2940             : 
    2941             :         /*
    2942             :          * Get the file ids.
    2943             :          */
    2944         404 :         for (i = 0; i < num_objs; i++) {
    2945           0 :                 union smb_fileinfo finfo;
    2946             : 
    2947         400 :                 fname = talloc_asprintf(mem_ctx,
    2948             :                                         "%s\\testfile.%u",
    2949             :                                         DNAME,
    2950             :                                         i);
    2951         400 :                 torture_assert_goto(tctx,
    2952             :                                 fname != NULL,
    2953             :                                 ret,
    2954             :                                 done,
    2955             :                                 "talloc failed\n");
    2956             : 
    2957         400 :                 create = (struct smb2_create) {
    2958             :                         .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
    2959             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2960             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2961             :                         .in.create_disposition = NTCREATEX_DISP_OPEN,
    2962             :                         .in.fname = fname,
    2963             :                 };
    2964             : 
    2965         400 :                 if (create_dirs) {
    2966         200 :                         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    2967         200 :                         create.in.create_options = FILE_DIRECTORY_FILE;
    2968             :                 }
    2969             : 
    2970         400 :                 status = smb2_create(tree, tctx, &create);
    2971         400 :                 if (!NT_STATUS_IS_OK(status)) {
    2972           0 :                         torture_fail(tctx,
    2973             :                                 talloc_asprintf(tctx,
    2974             :                                         "test file %s could not "
    2975             :                                         "be opened: %s\n",
    2976             :                                         fname,
    2977             :                                         nt_errstr(status)));
    2978             :                         TALLOC_FREE(fname);
    2979             :                         ret = false;
    2980             :                         goto done;
    2981             :                 }
    2982             : 
    2983         400 :                 h1 = create.out.file.handle;
    2984             : 
    2985         400 :                 finfo = (union smb_fileinfo) {
    2986             :                         .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2987             :                         .generic.in.file.handle = h1,
    2988             :                 };
    2989             : 
    2990         400 :                 status = smb2_getinfo_file(tree, tctx, &finfo);
    2991         400 :                 if (!NT_STATUS_IS_OK(status)) {
    2992           0 :                         torture_fail(tctx,
    2993             :                                 talloc_asprintf(tctx,
    2994             :                                         "failed to get fileid for "
    2995             :                                         "test file %s: %s\n",
    2996             :                                         fname,
    2997             :                                         nt_errstr(status)));
    2998             :                         TALLOC_FREE(fname);
    2999             :                         ret = false;
    3000             :                         goto done;
    3001             :                 }
    3002         400 :                 smb2_util_close(tree, h1);
    3003             : 
    3004         400 :                 fileid_array[i] = finfo.all_info2.out.file_id;
    3005         400 :                 TALLOC_FREE(fname);
    3006             :         }
    3007             : 
    3008             :         /* All returned fileids must be unique. 100 is small so brute force. */
    3009         400 :         for (i = 0; i < num_objs - 1; i++) {
    3010           0 :                 unsigned int j;
    3011       20196 :                 for (j = i + 1; j < num_objs; j++) {
    3012       19800 :                         if (fileid_array[i] == fileid_array[j]) {
    3013           0 :                                 torture_fail(tctx,
    3014             :                                         talloc_asprintf(tctx,
    3015             :                                                 "fileid %u == fileid %u (0x%"PRIu64")\n",
    3016             :                                                 i,
    3017             :                                                 j,
    3018             :                                                 fileid_array[i]));
    3019             :                                 ret = false;
    3020             :                                 goto done;
    3021             :                         }
    3022             :                 }
    3023             :         }
    3024             : 
    3025           4 : done:
    3026             : 
    3027           4 :         smb2_util_close(tree, testdirh);
    3028           4 :         smb2_deltree(tree, DNAME);
    3029           4 :         talloc_free(mem_ctx);
    3030           4 :         return ret;
    3031             : }
    3032             : 
    3033           2 : static bool test_fileid_unique(
    3034             :                         struct torture_context *tctx,
    3035             :                         struct smb2_tree *tree)
    3036             : {
    3037           2 :         return test_fileid_unique_object(tctx, tree, 100, false);
    3038             : }
    3039             : 
    3040           2 : static bool test_fileid_unique_dir(
    3041             :                         struct torture_context *tctx,
    3042             :                         struct smb2_tree *tree)
    3043             : {
    3044           2 :         return test_fileid_unique_object(tctx, tree, 100, true);
    3045             : }
    3046             : 
    3047           6 : static bool test_dosattr_tmp_dir(struct torture_context *tctx,
    3048             :                                  struct smb2_tree *tree)
    3049             : {
    3050           6 :         bool ret = true;
    3051           0 :         NTSTATUS status;
    3052           0 :         struct smb2_create c;
    3053           6 :         struct smb2_handle h1 = {{0}};
    3054           6 :         const char *fname = DNAME;
    3055             : 
    3056           6 :         smb2_deltree(tree, fname);
    3057           6 :         smb2_util_rmdir(tree, fname);
    3058             : 
    3059           6 :         c = (struct smb2_create) {
    3060             :                 .in.desired_access = SEC_RIGHTS_DIR_ALL,
    3061             :                 .in.file_attributes  = FILE_ATTRIBUTE_DIRECTORY,
    3062             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    3063             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3064             :                         NTCREATEX_SHARE_ACCESS_WRITE |
    3065             :                         NTCREATEX_SHARE_ACCESS_DELETE,
    3066             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3067             :                 .in.fname = DNAME,
    3068             :         };
    3069             : 
    3070           6 :         status = smb2_create(tree, tctx, &c);
    3071           6 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3072             :                                         "smb2_create\n");
    3073           6 :         h1 = c.out.file.handle;
    3074             : 
    3075             :         /* Try to set temporary attribute on directory */
    3076           6 :         SET_ATTRIB(FILE_ATTRIBUTE_TEMPORARY);
    3077             : 
    3078           6 :         torture_assert_ntstatus_equal_goto(tctx, status,
    3079             :                                            NT_STATUS_INVALID_PARAMETER,
    3080             :                                            ret, done,
    3081             :                                            "Unexpected setinfo result\n");
    3082             : 
    3083           6 : done:
    3084           6 :         if (!smb2_util_handle_empty(h1)) {
    3085           6 :                 smb2_util_close(tree, h1);
    3086             :         }
    3087           6 :         smb2_util_unlink(tree, fname);
    3088           6 :         smb2_deltree(tree, fname);
    3089             : 
    3090           6 :         return ret;
    3091             : }
    3092             : 
    3093             : /*
    3094             :   test opening quota fakefile handle and returned attributes
    3095             : */
    3096           6 : static bool test_smb2_open_quota_fake_file(struct torture_context *tctx,
    3097             :                                            struct smb2_tree *tree)
    3098             : {
    3099           6 :         const char *fname = "$Extend\\$Quota:$Q:$INDEX_ALLOCATION";
    3100           0 :         struct smb2_create create;
    3101           6 :         struct smb2_handle h = {{0}};
    3102           0 :         NTSTATUS status;
    3103           6 :         bool ret = true;
    3104             : 
    3105           6 :         create = (struct smb2_create) {
    3106             :                 .in.desired_access = SEC_RIGHTS_FILE_READ,
    3107             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3108             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3109             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3110             :                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
    3111             :                 .in.fname = fname,
    3112             :         };
    3113             : 
    3114           6 :         status = smb2_create(tree, tree, &create);
    3115           6 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3116             :                                         "smb2_create failed\n");
    3117           5 :         h = create.out.file.handle;
    3118             : 
    3119           5 :         torture_assert_u64_equal_goto(tctx,
    3120             :                                       create.out.file_attr,
    3121             :                                       FILE_ATTRIBUTE_HIDDEN
    3122             :                                       | FILE_ATTRIBUTE_SYSTEM
    3123             :                                       | FILE_ATTRIBUTE_DIRECTORY
    3124             :                                       | FILE_ATTRIBUTE_ARCHIVE,
    3125             :                                       ret,
    3126             :                                       done,
    3127             :                                       "Wrong attributes\n");
    3128             : 
    3129           5 :         torture_assert_u64_equal_goto(tctx,
    3130             :                                       create.out.create_time, 0,
    3131             :                                       ret,
    3132             :                                       done,
    3133             :                                       "create_time is not 0\n");
    3134           5 :         torture_assert_u64_equal_goto(tctx,
    3135             :                                       create.out.access_time, 0,
    3136             :                                       ret,
    3137             :                                       done,
    3138             :                                       "access_time is not 0\n");
    3139           5 :         torture_assert_u64_equal_goto(tctx,
    3140             :                                       create.out.write_time, 0,
    3141             :                                       ret,
    3142             :                                       done,
    3143             :                                       "write_time is not 0\n");
    3144           5 :         torture_assert_u64_equal_goto(tctx,
    3145             :                                       create.out.change_time, 0,
    3146             :                                       ret,
    3147             :                                       done,
    3148             :                                       "change_time is not 0\n");
    3149             : 
    3150           5 : done:
    3151           6 :         smb2_util_close(tree, h);
    3152           6 :         return ret;
    3153             : }
    3154             : 
    3155             : /**
    3156             :   Find Maximum Path Length
    3157             :  */
    3158           0 : static bool generate_path(const size_t len,
    3159             :                           char *buffer,
    3160             :                           const size_t buf_len)
    3161             : {
    3162             :         size_t i;
    3163             : 
    3164           0 :         if (len >= buf_len) {
    3165           0 :                 return false;
    3166             :         }
    3167             : 
    3168           0 :         for (i = 0; i < len ; i++) {
    3169           0 :                 buffer[i] = (char)(i % 10) + 48;
    3170             :         }
    3171           0 :         buffer[i] = '\0';
    3172           0 :         return true;
    3173             : }
    3174             : 
    3175           6 : static bool test_path_length_test(struct torture_context *tctx,
    3176             :                                   struct smb2_tree *tree)
    3177             : {
    3178           6 :         const size_t max_name = 2048;
    3179           6 :         char *name = talloc_array(tctx, char, max_name);
    3180           6 :         struct smb2_handle fh = {{0}};
    3181           6 :         size_t length = 128;
    3182           6 :         size_t max_file_name = 0;
    3183           6 :         size_t max_path_length = 0;
    3184           6 :         char *path_ok = NULL;
    3185           6 :         char *path_next = NULL;
    3186           6 :         char *topdir = NULL;
    3187           6 :         bool is_interactive = torture_setting_bool(tctx, "interactive", false);
    3188           0 :         NTSTATUS status;
    3189           6 :         bool ret = true;
    3190             : 
    3191           6 :         if (!is_interactive) {
    3192           6 :                 torture_result(tctx, TORTURE_SKIP,
    3193             :                                "Interactive Test: Skipping... "
    3194             :                                "(enable with --interactive)\n");
    3195           6 :                 return ret;
    3196             :         }
    3197             : 
    3198           0 :         torture_comment(tctx, "Testing filename and path lengths\n");
    3199             : 
    3200             :         /* Find Longest File Name */
    3201           0 :         for (length = 128; length < max_name; length++) {
    3202           0 :                 if (!generate_path(length, name, max_name))  {
    3203           0 :                         torture_result(tctx, TORTURE_FAIL,
    3204             :                                        "Failed to generate path.");
    3205           0 :                         return false;
    3206             :                 }
    3207             : 
    3208           0 :                 status = torture_smb2_testfile(tree, name, &fh);
    3209           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3210           0 :                         break;
    3211             :                 }
    3212             : 
    3213           0 :                 smb2_util_close(tree, fh);
    3214           0 :                 smb2_util_unlink(tree, name);
    3215             : 
    3216           0 :                 max_file_name = length;
    3217             :         }
    3218             : 
    3219           0 :         torture_assert_int_not_equal_goto(tctx, length, max_name, ret, done,
    3220             :                                           "Name too big\n");
    3221             : 
    3222           0 :         torture_comment(tctx, "Max file name length: %zu\n", max_file_name);
    3223             : 
    3224             :         /* Remove one char that caused the failure above */
    3225           0 :         name[max_file_name] = '\0';
    3226             : 
    3227           0 :         path_ok = talloc_strdup(tree, name);
    3228           0 :         torture_assert_not_null_goto(tctx, path_ok, ret, done,
    3229             :                                      "talloc_strdup failed\n");
    3230             : 
    3231           0 :         topdir = talloc_strdup(tree, name);
    3232           0 :         torture_assert_not_null_goto(tctx, topdir, ret, done,
    3233             :                                      "talloc_strdup failed\n");
    3234             : 
    3235           0 :         status = smb2_util_mkdir(tree, path_ok);
    3236           0 :         if (!NT_STATUS_IS_OK(status)) {
    3237           0 :                 torture_comment(tctx, "mkdir [%s] failed: %s\n",
    3238             :                                 path_ok, nt_errstr(status));
    3239           0 :                 torture_result(tctx, TORTURE_FAIL, "Initial mkdir failed");
    3240           0 :                 return false;
    3241             :         }
    3242             : 
    3243           0 :         while (true) {
    3244           0 :                 path_next = talloc_asprintf(tctx, "%s\\%s", path_ok, name);
    3245           0 :                 torture_assert_not_null_goto(tctx, path_next, ret, done,
    3246             :                                              "talloc_asprintf failed\n");
    3247             : 
    3248           0 :                 status = smb2_util_mkdir(tree, path_next);
    3249           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3250           0 :                         break;
    3251             :                 }
    3252             : 
    3253           0 :                 path_ok = path_next;
    3254             :         }
    3255             : 
    3256           0 :         for (length = 1; length < max_name; length++) {
    3257           0 :                 if (!generate_path(length, name, max_name))  {
    3258           0 :                         torture_result(tctx, TORTURE_FAIL,
    3259             :                                        "Failed to generate path.");
    3260           0 :                         return false;
    3261             :                 }
    3262             : 
    3263           0 :                 path_next = talloc_asprintf(tctx, "%s\\%s", path_ok, name);
    3264           0 :                 torture_assert_not_null_goto(tctx, path_next, ret, done,
    3265             :                                              "talloc_asprintf failed\n");
    3266             : 
    3267           0 :                 status = torture_smb2_testfile(tree, path_next, &fh);
    3268           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3269           0 :                         break;
    3270             :                 }
    3271           0 :                 smb2_util_close(tree, fh);
    3272           0 :                 path_ok = path_next;
    3273             :         }
    3274             : 
    3275           0 :         max_path_length = talloc_array_length(path_ok);
    3276             : 
    3277           0 :         torture_comment(tctx, "Max path name length: %zu\n", max_path_length);
    3278             : 
    3279           0 : done:
    3280           0 :         return ret;
    3281             : }
    3282             : 
    3283             : /*
    3284             :    basic testing of SMB2 read
    3285             : */
    3286        2358 : struct torture_suite *torture_smb2_create_init(TALLOC_CTX *ctx)
    3287             : {
    3288        2358 :         struct torture_suite *suite = torture_suite_create(ctx, "create");
    3289             : 
    3290        2358 :         torture_suite_add_1smb2_test(suite, "gentest", test_create_gentest);
    3291        2358 :         torture_suite_add_1smb2_test(suite, "blob", test_create_blob);
    3292        2358 :         torture_suite_add_1smb2_test(suite, "open", test_smb2_open);
    3293        2358 :         torture_suite_add_1smb2_test(suite, "brlocked", test_smb2_open_brlocked);
    3294        2358 :         torture_suite_add_1smb2_test(suite, "multi", test_smb2_open_multi);
    3295        2358 :         torture_suite_add_1smb2_test(suite, "delete", test_smb2_open_for_delete);
    3296        2358 :         torture_suite_add_1smb2_test(suite, "leading-slash", test_smb2_leading_slash);
    3297        2358 :         torture_suite_add_1smb2_test(suite, "impersonation", test_smb2_impersonation_level);
    3298        2358 :         torture_suite_add_1smb2_test(suite, "aclfile", test_create_acl_file);
    3299        2358 :         torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir);
    3300        2358 :         torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl);
    3301        2358 :         torture_suite_add_1smb2_test(suite, "mkdir-dup", test_mkdir_dup);
    3302        2358 :         torture_suite_add_1smb2_test(suite, "dir-alloc-size", test_dir_alloc_size);
    3303        2358 :         torture_suite_add_1smb2_test(suite, "dosattr_tmp_dir", test_dosattr_tmp_dir);
    3304        2358 :         torture_suite_add_1smb2_test(suite, "quota-fake-file", test_smb2_open_quota_fake_file);
    3305        2358 :         torture_suite_add_1smb2_test(suite, "path-length", test_path_length_test);
    3306        2358 :         torture_suite_add_1smb2_test(suite, "bench-path-contention-shared", test_smb2_bench_path_contention_shared);
    3307             : 
    3308        2358 :         suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
    3309             : 
    3310        2358 :         return suite;
    3311             : }
    3312             : 
    3313        2358 : struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx)
    3314             : {
    3315        2358 :         struct torture_suite *suite = torture_suite_create(ctx, "twrp");
    3316             : 
    3317        2358 :         torture_suite_add_1smb2_test(suite, "write", test_twrp_write);
    3318        2358 :         torture_suite_add_1smb2_test(suite, "stream", test_twrp_stream);
    3319        2358 :         torture_suite_add_1smb2_test(suite, "openroot", test_twrp_openroot);
    3320        2358 :         torture_suite_add_1smb2_test(suite, "listdir", test_twrp_listdir);
    3321             : 
    3322        2358 :         suite->description = talloc_strdup(suite, "SMB2-TWRP tests");
    3323             : 
    3324        2358 :         return suite;
    3325             : }
    3326             : 
    3327             : /*
    3328             :    basic testing of SMB2 File-IDs
    3329             : */
    3330        2358 : struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx)
    3331             : {
    3332        2358 :         struct torture_suite *suite = torture_suite_create(ctx, "fileid");
    3333             : 
    3334        2358 :         torture_suite_add_1smb2_test(suite, "fileid", test_fileid);
    3335        2358 :         torture_suite_add_1smb2_test(suite, "fileid-dir", test_fileid_dir);
    3336        2358 :         torture_suite_add_1smb2_test(suite, "unique", test_fileid_unique);
    3337        2358 :         torture_suite_add_1smb2_test(suite, "unique-dir", test_fileid_unique_dir);
    3338             : 
    3339        2358 :         suite->description = talloc_strdup(suite, "SMB2-FILEID tests");
    3340             : 
    3341        2358 :         return suite;
    3342             : }
    3343             : 
    3344           2 : static bool test_no_stream(struct torture_context *tctx,
    3345             :                            struct smb2_tree *tree)
    3346             : {
    3347           0 :         struct smb2_create c;
    3348           0 :         NTSTATUS status;
    3349           2 :         bool ret = true;
    3350           2 :         const char *names[] = {
    3351             :                 "test_no_stream::$DATA",
    3352             :                 "test_no_stream::foooooooooooo",
    3353             :                 "test_no_stream:stream",
    3354             :                 "test_no_stream:stream:$DATA",
    3355             :                 NULL
    3356             :         };
    3357           0 :         int i;
    3358             : 
    3359          10 :         for (i = 0; names[i] != NULL; i++) {
    3360           8 :                 c = (struct smb2_create) {
    3361             :                         .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED,
    3362             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3363             :                         .in.create_disposition = NTCREATEX_DISP_OPEN,
    3364             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3365           8 :                         .in.fname = names[i],
    3366             :                 };
    3367             : 
    3368           8 :                 status = smb2_create(tree, tctx, &c);
    3369           8 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
    3370           0 :                         torture_comment(
    3371             :                                 tctx, "Expected NT_STATUS_OBJECT_NAME_INVALID, "
    3372             :                                 "got %s, name: '%s'\n",
    3373             :                                 nt_errstr(status), names[i]);
    3374           0 :                         torture_fail_goto(tctx, done, "Bad create result\n");
    3375             :                 }
    3376             :         }
    3377           2 : done:
    3378           2 :         return ret;
    3379             : }
    3380             : 
    3381        2358 : struct torture_suite *torture_smb2_create_no_streams_init(TALLOC_CTX *ctx)
    3382             : {
    3383        2358 :         struct torture_suite *suite = torture_suite_create(ctx, "create_no_streams");
    3384             : 
    3385        2358 :         torture_suite_add_1smb2_test(suite, "no_stream", test_no_stream);
    3386             : 
    3387        2358 :         suite->description = talloc_strdup(suite, "SMB2-CREATE stream test on share without streams support");
    3388             : 
    3389        2358 :         return suite;
    3390             : }

Generated by: LCOV version 1.14