LCOV - code coverage report
Current view: top level - source4/torture/smb2 - create.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 1483 1736 85.4 %
Date: 2024-02-28 12:06:22 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         104 :                 for (i=0; i<num_files; i++) {
    1036          98 :                         if (requests[i] == NULL) {
    1037           8 :                                 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          82 :                 for (i=0; i<num_files; i++) {
    1614          76 :                         if (requests[i] == NULL) {
    1615          16 :                                 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           0 :         uint32_t expected_access;
    1757           0 :         union smb_fileinfo getinfo;
    1758           0 :         union smb_setfileinfo setinfo;
    1759           2 :         struct security_descriptor *sd = NULL, *sd_orig = NULL;
    1760           2 :         const char *owner_sid = NULL;
    1761           0 :         struct create_disps_tests {
    1762             :                 const char *file;
    1763             :                 uint32_t create_disposition;
    1764             :                 uint32_t create_options;
    1765             :                 NTSTATUS expected_status;
    1766             :         };
    1767           2 :         struct create_disps_tests *cd_test = NULL;
    1768             : 
    1769           2 :         file = torture_setting_string(tctx, "twrp_file", NULL);
    1770           2 :         if (file == NULL) {
    1771           0 :                 torture_skip(tctx, "missing 'twrp_file' option\n");
    1772             :         }
    1773             : 
    1774           2 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    1775           2 :         if (snapshot == NULL) {
    1776           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    1777             :         }
    1778             : 
    1779           2 :         torture_comment(tctx, "Testing timewarp (%s) (%s)\n", file, snapshot);
    1780             : 
    1781           2 :         setenv("TZ", "GMT", 1);
    1782             : 
    1783             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    1784             :          * effect if it is greater than 1. */
    1785           2 :         ZERO_STRUCT(tm);
    1786             : 
    1787           2 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    1788           2 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    1789           2 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    1790             : 
    1791           2 :         t = mktime(&tm);
    1792           2 :         unix_to_nt_time(&nttime, t);
    1793             : 
    1794           2 :         io = (struct smb2_create) {
    1795             :                 .in.desired_access = SEC_FILE_READ_DATA,
    1796             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    1797             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    1798             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1799             :                 .in.fname = file,
    1800             :                 .in.query_maximal_access = true,
    1801             :                 .in.timewarp = nttime,
    1802             :         };
    1803             : 
    1804           2 :         status = smb2_create(tree, tctx, &io);
    1805           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1806             :                                         "smb2_create\n");
    1807           2 :         smb2_util_close(tree, io.out.file.handle);
    1808             : 
    1809           2 :         expected_access = SEC_RIGHTS_FILE_ALL &
    1810             :                                 ~(SEC_FILE_EXECUTE | SEC_DIR_DELETE_CHILD);
    1811             : 
    1812           2 :         torture_assert_int_equal_goto(tctx,
    1813             :                                       io.out.maximal_access & expected_access,
    1814             :                                       expected_access,
    1815             :                                       ret, done, "Bad access\n");
    1816             : 
    1817             :         {
    1818             :                 /*
    1819             :                  * Test create dispositions
    1820             :                  */
    1821           2 :                 struct create_disps_tests cd_tests[] = {
    1822             :                         {
    1823             :                                 .file = file,
    1824             :                                 .create_disposition = NTCREATEX_DISP_OPEN,
    1825             :                                 .expected_status = NT_STATUS_OK,
    1826             :                         },
    1827             :                         {
    1828             :                                 .file = file,
    1829             :                                 .create_disposition = NTCREATEX_DISP_OPEN_IF,
    1830             :                                 .expected_status = NT_STATUS_OK,
    1831             :                         },
    1832             :                         {
    1833             :                                 .file = file,
    1834             :                                 .create_disposition = NTCREATEX_DISP_OVERWRITE,
    1835             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1836             :                         },
    1837             :                         {
    1838             :                                 .file = file,
    1839             :                                 .create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
    1840             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1841             :                         },
    1842             :                         {
    1843             :                                 .file = file,
    1844             :                                 .create_disposition = NTCREATEX_DISP_SUPERSEDE,
    1845             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1846             :                         },
    1847             :                         {
    1848             :                                 .file = "newfile",
    1849             :                                 .create_disposition = NTCREATEX_DISP_OPEN_IF,
    1850             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1851             :                         },
    1852             :                         {
    1853             :                                 .file = "newfile",
    1854             :                                 .create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
    1855             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1856             :                         },
    1857             :                         {
    1858             :                                 .file = "newfile",
    1859             :                                 .create_disposition = NTCREATEX_DISP_CREATE,
    1860             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1861             :                         },
    1862             :                         {
    1863             :                                 .file = "newfile",
    1864             :                                 .create_disposition = NTCREATEX_DISP_SUPERSEDE,
    1865             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1866             :                         },
    1867             :                         {
    1868             :                                 .file = "newdir",
    1869             :                                 .create_disposition = NTCREATEX_DISP_OPEN_IF,
    1870             :                                 .create_options = NTCREATEX_OPTIONS_DIRECTORY,
    1871             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1872             :                         },
    1873             :                         {
    1874             :                                 .file = "newdir",
    1875             :                                 .create_disposition = NTCREATEX_DISP_CREATE,
    1876             :                                 .create_options = NTCREATEX_OPTIONS_DIRECTORY,
    1877             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    1878             :                         },
    1879             :                         {
    1880             :                                 .file = NULL,
    1881             :                         },
    1882             :                 };
    1883             : 
    1884          24 :                 for (cd_test = &cd_tests[0]; cd_test->file != NULL; cd_test++) {
    1885          22 :                         io = (struct smb2_create) {
    1886          22 :                                 .in.fname = cd_test->file,
    1887          22 :                                 .in.create_disposition = cd_test->create_disposition,
    1888          22 :                                 .in.create_options = cd_test->create_options,
    1889             : 
    1890             :                                 .in.desired_access = SEC_FILE_READ_DATA,
    1891             :                                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    1892             :                                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1893             :                                 .in.timewarp = nttime,
    1894             :                         };
    1895             : 
    1896          22 :                         status = smb2_create(tree, tctx, &io);
    1897          22 :                         torture_assert_ntstatus_equal_goto(
    1898             :                                 tctx, status, cd_test->expected_status, ret, done,
    1899             :                                 "Bad status\n");
    1900             :                 }
    1901             :         }
    1902             : 
    1903           2 :         io = (struct smb2_create) {
    1904             :                 .in.desired_access = expected_access,
    1905             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    1906             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    1907             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    1908             :                 .in.fname = file,
    1909             :                 .in.timewarp = nttime,
    1910             :         };
    1911             : 
    1912           2 :         status = smb2_create(tree, tctx, &io);
    1913           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1914             :                                         "smb2_create\n");
    1915           2 :         h1 = io.out.file.handle;
    1916             : 
    1917           2 :         status = smb2_util_write(tree, h1, "123", 0, 3);
    1918           2 :         torture_assert_ntstatus_equal_goto(tctx, status,
    1919             :                                            NT_STATUS_MEDIA_WRITE_PROTECTED,
    1920             :                                            ret, done, "smb2_create\n");
    1921             : 
    1922             :         /*
    1923             :          * Verify access mask
    1924             :          */
    1925             : 
    1926           2 :         ZERO_STRUCT(getinfo);
    1927           2 :         getinfo.generic.level = RAW_FILEINFO_ACCESS_INFORMATION;
    1928           2 :         getinfo.generic.in.file.handle = h1;
    1929             : 
    1930           2 :         status = smb2_getinfo_file(tree, tree, &getinfo);
    1931           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1932             :                                         "smb2_getinfo_file\n");
    1933             : 
    1934           2 :         torture_assert_int_equal_goto(
    1935             :                 tctx,
    1936             :                 getinfo.access_information.out.access_flags,
    1937             :                 expected_access,
    1938             :                 ret, done,
    1939             :                 "Bad access mask\n");
    1940             : 
    1941             :         /*
    1942             :          * Check we can't set various things
    1943             :          */
    1944             : 
    1945           2 :         ZERO_STRUCT(getinfo);
    1946           2 :         getinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1947           2 :         getinfo.query_secdesc.in.file.handle = h1;
    1948           2 :         getinfo.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
    1949             : 
    1950           2 :         status = smb2_getinfo_file(tree, tctx, &getinfo);
    1951           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1952             :                                         "smb2_getinfo_file\n");
    1953             : 
    1954           2 :         sd_orig = getinfo.query_secdesc.out.sd;
    1955           2 :         owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
    1956             : 
    1957           2 :         sd = security_descriptor_dacl_create(tctx,
    1958             :                                              0, NULL, NULL,
    1959             :                                              owner_sid,
    1960             :                                              SEC_ACE_TYPE_ACCESS_ALLOWED,
    1961             :                                              SEC_FILE_WRITE_DATA,
    1962             :                                              0,
    1963             :                                              NULL);
    1964             : 
    1965             :         /* Try to set ACL */
    1966             : 
    1967           2 :         ZERO_STRUCT(setinfo);
    1968           2 :         setinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1969           2 :         setinfo.set_secdesc.in.file.handle = h1;
    1970           2 :         setinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1971           2 :         setinfo.set_secdesc.in.sd = sd;
    1972             : 
    1973           2 :         status = smb2_setinfo_file(tree, &setinfo);
    1974           2 :         torture_assert_ntstatus_equal_goto(
    1975             :                 tctx,
    1976             :                 status,
    1977             :                 NT_STATUS_MEDIA_WRITE_PROTECTED,
    1978             :                 ret, done,
    1979             :                 "smb2_setinfo_file\n");
    1980             : 
    1981             :         /* Try to delete */
    1982             : 
    1983           2 :         ZERO_STRUCT(setinfo);
    1984           2 :         setinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
    1985           2 :         setinfo.disposition_info.in.delete_on_close = 1;
    1986           2 :         setinfo.generic.in.file.handle = h1;
    1987             : 
    1988           2 :         status = smb2_setinfo_file(tree, &setinfo);
    1989           2 :         torture_assert_ntstatus_equal_goto(
    1990             :                 tctx,
    1991             :                 status,
    1992             :                 NT_STATUS_MEDIA_WRITE_PROTECTED,
    1993             :                 ret, done,
    1994             :                 "smb2_setinfo_file\n");
    1995             : 
    1996           2 :         ZERO_STRUCT(setinfo);
    1997           2 :         setinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN;
    1998           2 :         setinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
    1999           2 :         setinfo.generic.in.file.handle = h1;
    2000             : 
    2001           2 :         status = smb2_setinfo_file(tree, &setinfo);
    2002           2 :         torture_assert_ntstatus_equal_goto(
    2003             :                 tctx,
    2004             :                 status,
    2005             :                 NT_STATUS_MEDIA_WRITE_PROTECTED,
    2006             :                 ret, done,
    2007             :                 "smb2_setinfo_file\n");
    2008             : 
    2009             :         /* Try to truncate */
    2010             : 
    2011           2 :         ZERO_STRUCT(setinfo);
    2012           2 :         setinfo.generic.level = SMB_SFILEINFO_END_OF_FILE_INFORMATION;
    2013           2 :         setinfo.generic.in.file.handle = h1;
    2014           2 :         setinfo.end_of_file_info.in.size = 0x100000;
    2015             : 
    2016           2 :         status = smb2_setinfo_file(tree, &setinfo);
    2017           2 :         torture_assert_ntstatus_equal_goto(
    2018             :                 tctx,
    2019             :                 status,
    2020             :                 NT_STATUS_MEDIA_WRITE_PROTECTED,
    2021             :                 ret, done,
    2022             :                 "smb2_setinfo_file\n");
    2023             : 
    2024             :         /* Try to set a hardlink */
    2025             : 
    2026           2 :         ZERO_STRUCT(setinfo);
    2027           2 :         setinfo.generic.level = RAW_SFILEINFO_LINK_INFORMATION;
    2028           2 :         setinfo.generic.in.file.handle = h1;
    2029           2 :         setinfo.link_information.in.new_name = "hardlink";
    2030             : 
    2031           2 :         status = smb2_setinfo_file(tree, &setinfo);
    2032           2 :         torture_assert_ntstatus_equal_goto(
    2033             :                 tctx,
    2034             :                 status,
    2035             :                 NT_STATUS_NOT_SAME_DEVICE,
    2036             :                 ret, done,
    2037             :                 "smb2_setinfo_file\n");
    2038             : 
    2039             :         /* Try to rename */
    2040             : 
    2041           2 :         ZERO_STRUCT(setinfo);
    2042           2 :         setinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2043           2 :         setinfo.rename_information.in.file.handle = h1;
    2044           2 :         setinfo.rename_information.in.new_name = "renamed";
    2045             : 
    2046           2 :         status = smb2_setinfo_file(tree, &setinfo);
    2047           2 :         torture_assert_ntstatus_equal_goto(
    2048             :                 tctx,
    2049             :                 status,
    2050             :                 NT_STATUS_NOT_SAME_DEVICE,
    2051             :                 ret, done,
    2052             :                 "smb2_setinfo_file\n");
    2053             : 
    2054           2 :         smb2_util_close(tree, h1);
    2055           2 :         ZERO_STRUCT(h1);
    2056             : 
    2057           2 : done:
    2058           2 :         if (!smb2_util_handle_empty(h1)) {
    2059           0 :                 smb2_util_close(tree, h1);
    2060             :         }
    2061           2 :         return ret;
    2062             : }
    2063             : 
    2064           2 : static bool test_twrp_stream(struct torture_context *tctx,
    2065             :                              struct smb2_tree *tree)
    2066             : {
    2067           0 :         struct smb2_create io;
    2068           0 :         NTSTATUS status;
    2069           2 :         bool ret = true;
    2070           2 :         char *p = NULL;
    2071           0 :         struct tm tm;
    2072           0 :         time_t t;
    2073           0 :         uint64_t nttime;
    2074           2 :         const char *file = NULL;
    2075           2 :         const char *stream = NULL;
    2076           2 :         const char *snapshot = NULL;
    2077           0 :         int stream_size;
    2078           2 :         char *path = NULL;
    2079           2 :         uint8_t *buf = NULL;
    2080           2 :         struct smb2_handle h1 = {{0}};
    2081           0 :         struct smb2_read r;
    2082             : 
    2083           2 :         file = torture_setting_string(tctx, "twrp_file", NULL);
    2084           2 :         if (file == NULL) {
    2085           0 :                 torture_skip(tctx, "missing 'twrp_file' option\n");
    2086             :         }
    2087             : 
    2088           2 :         stream = torture_setting_string(tctx, "twrp_stream", NULL);
    2089           2 :         if (stream == NULL) {
    2090           0 :                 torture_skip(tctx, "missing 'twrp_stream' option\n");
    2091             :         }
    2092             : 
    2093           2 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2094           2 :         if (snapshot == NULL) {
    2095           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    2096             :         }
    2097             : 
    2098           2 :         stream_size = torture_setting_int(tctx, "twrp_stream_size", 0);
    2099           2 :         if (stream_size == 0) {
    2100           0 :                 torture_skip(tctx, "missing 'twrp_stream_size' option\n");
    2101             :         }
    2102             : 
    2103           2 :         torture_comment(tctx, "Testing timewarp on stream (%s) (%s)\n",
    2104             :                         file, snapshot);
    2105             : 
    2106           2 :         path = talloc_asprintf(tree, "%s:%s", file, stream);
    2107           2 :         torture_assert_not_null_goto(tctx, path, ret, done, "path\n");
    2108             : 
    2109           2 :         buf = talloc_zero_array(tree, uint8_t, stream_size);
    2110           2 :         torture_assert_not_null_goto(tctx, buf, ret, done, "buf\n");
    2111             : 
    2112           2 :         setenv("TZ", "GMT", 1);
    2113             : 
    2114             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2115             :          * effect if it is greater than 1. */
    2116           2 :         ZERO_STRUCT(tm);
    2117             : 
    2118           2 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2119           2 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2120           2 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2121             : 
    2122           2 :         t = mktime(&tm);
    2123           2 :         unix_to_nt_time(&nttime, t);
    2124             : 
    2125           2 :         io = (struct smb2_create) {
    2126             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2127             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2128             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2129             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2130             :                 .in.fname = path,
    2131             :                 .in.timewarp = nttime,
    2132             :         };
    2133             : 
    2134           2 :         status = smb2_create(tree, tctx, &io);
    2135           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2136             :                                         "smb2_create\n");
    2137           2 :         h1 = io.out.file.handle;
    2138             : 
    2139           2 :         r = (struct smb2_read) {
    2140             :                 .in.file.handle = h1,
    2141             :                 .in.length = stream_size,
    2142             :                 .in.offset = 0,
    2143             :         };
    2144             : 
    2145           2 :         status = smb2_read(tree, tree, &r);
    2146           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2147             :                                         "smb2_create\n");
    2148             : 
    2149           2 :         smb2_util_close(tree, h1);
    2150             : 
    2151           2 : done:
    2152           2 :         return ret;
    2153             : }
    2154             : 
    2155           2 : static bool test_twrp_openroot(struct torture_context *tctx, struct smb2_tree *tree)
    2156             : {
    2157           0 :         struct smb2_create io;
    2158           0 :         NTSTATUS status;
    2159           2 :         bool ret = true;
    2160           2 :         char *p = NULL;
    2161           0 :         struct tm tm;
    2162           0 :         time_t t;
    2163           0 :         uint64_t nttime;
    2164           2 :         const char *snapshot = NULL;
    2165             : 
    2166           2 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2167           2 :         if (snapshot == NULL) {
    2168           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    2169             :         }
    2170             : 
    2171           2 :         torture_comment(tctx, "Testing open of root of "
    2172             :                 "share with timewarp (%s)\n",
    2173             :                 snapshot);
    2174             : 
    2175           2 :         setenv("TZ", "GMT", 1);
    2176             : 
    2177             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2178             :          * effect if it is greater than 1. */
    2179           2 :         ZERO_STRUCT(tm);
    2180             : 
    2181           2 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2182           2 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2183           2 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2184             : 
    2185           2 :         t = mktime(&tm);
    2186           2 :         unix_to_nt_time(&nttime, t);
    2187             : 
    2188           2 :         io = (struct smb2_create) {
    2189             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2190             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2191             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2192             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2193             :                 .in.fname = "",
    2194             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2195             :                 .in.timewarp = nttime,
    2196             :         };
    2197             : 
    2198           2 :         status = smb2_create(tree, tctx, &io);
    2199           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2200             :                                         "smb2_create\n");
    2201           2 :         smb2_util_close(tree, io.out.file.handle);
    2202             : 
    2203           2 : done:
    2204           2 :         return ret;
    2205             : }
    2206             : 
    2207           2 : static bool test_twrp_listdir(struct torture_context *tctx,
    2208             :                               struct smb2_tree *tree)
    2209             : {
    2210           0 :         struct smb2_create create;
    2211           2 :         struct smb2_handle h = {{0}};
    2212           0 :         struct smb2_find find;
    2213           0 :         unsigned int count;
    2214           0 :         union smb_search_data *d;
    2215           2 :         char *p = NULL;
    2216           0 :         struct tm tm;
    2217           0 :         time_t t;
    2218           0 :         uint64_t nttime;
    2219           2 :         const char *snapshot = NULL;
    2220           0 :         uint64_t normal_fileid;
    2221           0 :         uint64_t snapshot_fileid;
    2222           0 :         NTSTATUS status;
    2223           2 :         bool ret = true;
    2224             : 
    2225           2 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2226           2 :         if (snapshot == NULL) {
    2227           0 :                 torture_fail(tctx, "missing 'twrp_snapshot' option\n");
    2228             :         }
    2229             : 
    2230           2 :         torture_comment(tctx, "Testing File-Ids of directory listing "
    2231             :                         "with timewarp (%s)\n",
    2232             :                         snapshot);
    2233             : 
    2234           2 :         setenv("TZ", "GMT", 1);
    2235             : 
    2236             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2237             :          * effect if it is greater than 1. */
    2238           2 :         ZERO_STRUCT(tm);
    2239             : 
    2240           2 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2241           2 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2242           2 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2243             : 
    2244           2 :         t = mktime(&tm);
    2245           2 :         unix_to_nt_time(&nttime, t);
    2246             : 
    2247             :         /*
    2248             :          * 1: Query the file's File-Id
    2249             :          */
    2250           2 :         create = (struct smb2_create) {
    2251             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2252             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2253             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2254             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2255             :                 .in.fname = "subdir/hardlink",
    2256             :                 .in.query_on_disk_id = true,
    2257             :         };
    2258             : 
    2259           2 :         status = smb2_create(tree, tctx, &create);
    2260           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2261             :                                         "test file could not be created\n");
    2262           2 :         smb2_util_close(tree, create.out.file.handle);
    2263           2 :         normal_fileid = BVAL(&create.out.on_disk_id, 0);
    2264             : 
    2265             :         /*
    2266             :          * 2: check directory listing of the file returns same File-Id
    2267             :          */
    2268             : 
    2269           2 :         create = (struct smb2_create) {
    2270             :                 .in.desired_access = SEC_DIR_LIST,
    2271             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2272             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2273             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2274             :                 .in.fname = "subdir",
    2275             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2276             :         };
    2277             : 
    2278           2 :         status = smb2_create(tree, tctx, &create);
    2279           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2280             :                                         "smb2_create\n");
    2281           2 :         h = create.out.file.handle;
    2282             : 
    2283           2 :         find = (struct smb2_find) {
    2284             :                 .in.file.handle = h,
    2285             :                 .in.pattern = "*",
    2286             :                 .in.max_response_size = 0x1000,
    2287             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2288             :         };
    2289             : 
    2290           2 :         status = smb2_find_level(tree, tree, &find, &count, &d);
    2291           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2292             :                                         "smb2_find_level failed\n");
    2293             : 
    2294           2 :         smb2_util_close(tree, h);
    2295             : 
    2296           2 :         torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
    2297           2 :         torture_assert_str_equal_goto(tctx,
    2298             :                                       d[2].id_both_directory_info.name.s,
    2299             :                                       "hardlink",
    2300             :                                       ret, done, "bad name");
    2301           2 :         torture_assert_u64_equal_goto(tctx,
    2302             :                                       d[2].id_both_directory_info.file_id,
    2303             :                                       normal_fileid,
    2304             :                                       ret, done, "bad fileid\n");
    2305             : 
    2306             :         /*
    2307             :          * 3: Query File-Id of snapshot of the file and check the File-Id is
    2308             :          * different compared to the basefile
    2309             :          */
    2310             : 
    2311           2 :         create = (struct smb2_create) {
    2312             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2313             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2314             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2315             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2316             :                 .in.fname = "subdir/hardlink",
    2317             :                 .in.query_on_disk_id = true,
    2318             :                 .in.timewarp = nttime,
    2319             :         };
    2320             : 
    2321           2 :         status = smb2_create(tree, tctx, &create);
    2322           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2323             :                                         "test file could not be created\n");
    2324           2 :         smb2_util_close(tree, create.out.file.handle);
    2325             : 
    2326           2 :         snapshot_fileid = BVAL(&create.out.on_disk_id, 0);
    2327             : 
    2328             :         /*
    2329             :          * 4: List directory of the snapshot and check the File-Id returned here
    2330             :          * is the same as in 3.
    2331             :          */
    2332             : 
    2333           2 :         create = (struct smb2_create) {
    2334             :                 .in.desired_access = SEC_DIR_LIST,
    2335             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2336             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2337             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2338             :                 .in.fname = "subdir",
    2339             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2340             :                 .in.timewarp = nttime,
    2341             :         };
    2342             : 
    2343           2 :         status = smb2_create(tree, tctx, &create);
    2344           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2345             :                                         "smb2_create\n");
    2346           2 :         h = create.out.file.handle;
    2347             : 
    2348           2 :         find = (struct smb2_find) {
    2349             :                 .in.file.handle = h,
    2350             :                 .in.pattern = "*",
    2351             :                 .in.max_response_size = 0x1000,
    2352             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2353             :         };
    2354             : 
    2355           2 :         status = smb2_find_level(tree, tree, &find, &count, &d);
    2356           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2357             :                                         "smb2_find_level failed\n");
    2358           2 :         smb2_util_close(tree, h);
    2359             : 
    2360           2 :         torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
    2361           2 :         torture_assert_str_equal_goto(tctx,
    2362             :                                       d[2].id_both_directory_info.name.s,
    2363             :                                       "hardlink",
    2364             :                                       ret, done, "bad name");
    2365           2 :         torture_assert_u64_equal_goto(tctx,
    2366             :                                       snapshot_fileid,
    2367             :                                       d[2].id_both_directory_info.file_id,
    2368             :                                       ret, done, "bad fileid\n");
    2369             : 
    2370           2 : done:
    2371           2 :         return ret;
    2372             : }
    2373             : 
    2374           2 : static bool test_fileid(struct torture_context *tctx,
    2375             :                         struct smb2_tree *tree)
    2376             : {
    2377           2 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2378           2 :         const char *fname = DNAME "\\foo";
    2379           2 :         const char *sname = DNAME "\\foo:bar";
    2380           0 :         struct smb2_handle testdirh;
    2381           0 :         struct smb2_handle h1;
    2382           0 :         struct smb2_create create;
    2383           0 :         union smb_fileinfo finfo;
    2384           0 :         union smb_setfileinfo sinfo;
    2385           0 :         struct smb2_find f;
    2386           0 :         unsigned int count;
    2387           0 :         union smb_search_data *d;
    2388           0 :         uint64_t expected_fileid;
    2389           0 :         uint64_t returned_fileid;
    2390           0 :         NTSTATUS status;
    2391           2 :         bool ret = true;
    2392             : 
    2393           2 :         smb2_deltree(tree, DNAME);
    2394             : 
    2395           2 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    2396           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2397             :                                         "torture_smb2_testdir failed\n");
    2398             : 
    2399             :         /*
    2400             :          * Initial create with QFID
    2401             :          */
    2402           2 :         create = (struct smb2_create) {
    2403             :                 .in.desired_access = SEC_FILE_ALL,
    2404             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2405             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2406             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    2407             :                 .in.fname = fname,
    2408             :                 .in.query_on_disk_id = true,
    2409             :         };
    2410             : 
    2411           2 :         status = smb2_create(tree, tctx, &create);
    2412           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2413             :                                         "test file could not be created\n");
    2414           2 :         h1 = create.out.file.handle;
    2415           2 :         expected_fileid = BVAL(&create.out.on_disk_id, 0);
    2416             : 
    2417             :         /*
    2418             :          * Getinfo the File-ID on the just opened handle
    2419             :          */
    2420           2 :         finfo = (union smb_fileinfo) {
    2421             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2422             :                 .generic.in.file.handle = h1,
    2423             :         };
    2424             : 
    2425           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2426           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2427             :                                         "torture_smb2_testdir\n");
    2428           2 :         smb2_util_close(tree, h1);
    2429           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2430             :                                       expected_fileid,
    2431             :                                       ret, done, "bad fileid\n");
    2432             : 
    2433             :         /*
    2434             :          * Open existing with QFID
    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 = fname,
    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           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2450           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2451             :                                       ret, done, "bad fileid\n");
    2452             : 
    2453             :         /*
    2454             :          * Getinfo the File-ID on the just opened handle
    2455             :          */
    2456           2 :         finfo = (union smb_fileinfo) {
    2457             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2458             :                 .generic.in.file.handle = h1,
    2459             :         };
    2460             : 
    2461           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2462           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2463             :                                         "torture_smb2_testdir\n");
    2464           2 :         smb2_util_close(tree, h1);
    2465           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2466             :                                       expected_fileid,
    2467             :                                       ret, done, "bad fileid\n");
    2468             : 
    2469             :         /*
    2470             :          * Overwrite with QFID
    2471             :          */
    2472           2 :         create = (struct smb2_create) {
    2473             :                 .in.desired_access = SEC_FILE_ALL,
    2474             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2475             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2476             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2477             :                 .in.fname = fname,
    2478             :                 .in.query_on_disk_id = true,
    2479             :         };
    2480             : 
    2481           2 :         status = smb2_create(tree, tctx, &create);
    2482           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2483             :                                         "test file could not be created\n");
    2484           2 :         h1 = create.out.file.handle;
    2485           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2486           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2487             :                                       ret, done, "bad fileid\n");
    2488             : 
    2489             :         /*
    2490             :          * Getinfo the File-ID on the open with overwrite handle
    2491             :          */
    2492           2 :         finfo = (union smb_fileinfo) {
    2493             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2494             :                 .generic.in.file.handle = h1,
    2495             :         };
    2496             : 
    2497           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2498           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2499             :                                         "torture_smb2_testdir\n");
    2500           2 :         smb2_util_close(tree, h1);
    2501           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2502             :                                       expected_fileid,
    2503             :                                       ret, done, "bad fileid\n");
    2504             : 
    2505             :         /*
    2506             :          * Do some modifications on the basefile (IO, setinfo), verifying
    2507             :          * File-ID after each step.
    2508             :          */
    2509           2 :         create = (struct smb2_create) {
    2510             :                 .in.desired_access = SEC_FILE_ALL,
    2511             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2512             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2513             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2514             :                 .in.fname = fname,
    2515             :                 .in.query_on_disk_id = true,
    2516             :         };
    2517             : 
    2518           2 :         status = smb2_create(tree, tctx, &create);
    2519           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2520             :                                         "test file could not be created\n");
    2521           2 :         h1 = create.out.file.handle;
    2522             : 
    2523           2 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    2524           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2525             :                                         "smb2_util_write failed\n");
    2526             : 
    2527           2 :         finfo = (union smb_fileinfo) {
    2528             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2529             :                 .generic.in.file.handle = h1,
    2530             :         };
    2531           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2532           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2533             :                                         "smb2_getinfo_file failed\n");
    2534           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2535             :                                       expected_fileid,
    2536             :                                       ret, done, "bad fileid\n");
    2537             : 
    2538           2 :         sinfo = (union smb_setfileinfo) {
    2539             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    2540             :                 .basic_info.in.file.handle = h1,
    2541             :         };
    2542           2 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    2543             : 
    2544           2 :         status = smb2_setinfo_file(tree, &sinfo);
    2545           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2546             :                                         "smb2_setinfo_file failed\n");
    2547             : 
    2548           2 :         finfo = (union smb_fileinfo) {
    2549             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2550             :                 .generic.in.file.handle = h1,
    2551             :         };
    2552           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2553           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2554             :                                         "smb2_getinfo_file failed\n");
    2555           2 :         smb2_util_close(tree, h1);
    2556           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2557             :                                       expected_fileid,
    2558             :                                       ret, done, "bad fileid\n");
    2559             : 
    2560             :         /*
    2561             :          * Create stream, check the stream's File-ID, should be the same as the
    2562             :          * base file (sic!, tested against Windows).
    2563             :          */
    2564           2 :         create = (struct smb2_create) {
    2565             :                 .in.desired_access = SEC_FILE_ALL,
    2566             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2567             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2568             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    2569             :                 .in.fname = sname,
    2570             :                 .in.query_on_disk_id = true,
    2571             :         };
    2572             : 
    2573           2 :         status = smb2_create(tree, tctx, &create);
    2574           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2575             :                                         "test file could not be created\n");
    2576           2 :         h1 = create.out.file.handle;
    2577           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2578           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2579             :                                       ret, done, "bad fileid\n");
    2580             : 
    2581             :         /*
    2582             :          * Getinfo the File-ID on the created stream
    2583             :          */
    2584           2 :         finfo = (union smb_fileinfo) {
    2585             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2586             :                 .generic.in.file.handle = h1,
    2587             :         };
    2588             : 
    2589           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2590           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2591             :                                         "smb2_getinfo_file failed\n");
    2592           2 :         smb2_util_close(tree, h1);
    2593           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2594             :                                       expected_fileid,
    2595             :                                       ret, done, "bad fileid\n");
    2596             : 
    2597             :         /*
    2598             :          * Open stream, check the stream's File-ID, should be the same as the
    2599             :          * base file (sic!, tested against Windows).
    2600             :          */
    2601           2 :         create = (struct smb2_create) {
    2602             :                 .in.desired_access = SEC_FILE_ALL,
    2603             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2604             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2605             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2606             :                 .in.fname = sname,
    2607             :                 .in.query_on_disk_id = true,
    2608             :         };
    2609             : 
    2610           2 :         status = smb2_create(tree, tctx, &create);
    2611           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2612             :                                         "test file could not be created\n");
    2613           2 :         h1 = create.out.file.handle;
    2614           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2615           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2616             :                                       ret, done, "bad fileid\n");
    2617             : 
    2618             :         /*
    2619             :          * Getinfo the File-ID on the opened stream
    2620             :          */
    2621           2 :         finfo = (union smb_fileinfo) {
    2622             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2623             :                 .generic.in.file.handle = h1,
    2624             :         };
    2625             : 
    2626           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2627           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2628             :                                         "smb2_getinfo_file failed\n");
    2629           2 :         smb2_util_close(tree, h1);
    2630           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2631             :                                       expected_fileid,
    2632             :                                       ret, done, "bad fileid\n");
    2633             : 
    2634             :         /*
    2635             :          * Overwrite stream, check the stream's File-ID, should be the same as
    2636             :          * the base file (sic!, tested against Windows).
    2637             :          */
    2638           2 :         create = (struct smb2_create) {
    2639             :                 .in.desired_access = SEC_FILE_ALL,
    2640             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2641             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2642             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2643             :                 .in.fname = sname,
    2644             :                 .in.query_on_disk_id = true,
    2645             :         };
    2646             : 
    2647           2 :         status = smb2_create(tree, tctx, &create);
    2648           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2649             :                                         "test file could not be created\n");
    2650           2 :         h1 = create.out.file.handle;
    2651           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2652           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2653             :                                       ret, done, "bad fileid\n");
    2654             : 
    2655             :         /*
    2656             :          * Getinfo the File-ID on the overwritten stream
    2657             :          */
    2658           2 :         finfo = (union smb_fileinfo) {
    2659             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2660             :                 .generic.in.file.handle = h1,
    2661             :         };
    2662             : 
    2663           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2664           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2665             :                                         "smb2_getinfo_file failed\n");
    2666           2 :         smb2_util_close(tree, h1);
    2667           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2668             :                                       expected_fileid,
    2669             :                                       ret, done, "bad fileid\n");
    2670             : 
    2671             :         /*
    2672             :          * Do some modifications on the stream (IO, setinfo), verifying File-ID
    2673             :          * after each step.
    2674             :          */
    2675           2 :         create = (struct smb2_create) {
    2676             :                 .in.desired_access = SEC_FILE_ALL,
    2677             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2678             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2679             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2680             :                 .in.fname = sname,
    2681             :                 .in.query_on_disk_id = true,
    2682             :         };
    2683             : 
    2684           2 :         status = smb2_create(tree, tctx, &create);
    2685           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2686             :                                         "test file could not be created\n");
    2687           2 :         h1 = create.out.file.handle;
    2688             : 
    2689           2 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    2690           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2691             :                                         "smb2_util_write failed\n");
    2692             : 
    2693           2 :         finfo = (union smb_fileinfo) {
    2694             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2695             :                 .generic.in.file.handle = h1,
    2696             :         };
    2697           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2698           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2699             :                                         "smb2_getinfo_file failed\n");
    2700           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2701             :                                       expected_fileid,
    2702             :                                       ret, done, "bad fileid\n");
    2703             : 
    2704           2 :         sinfo = (union smb_setfileinfo) {
    2705             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    2706             :                 .basic_info.in.file.handle = h1,
    2707             :         };
    2708           2 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    2709             : 
    2710           2 :         status = smb2_setinfo_file(tree, &sinfo);
    2711           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2712             :                                         "smb2_setinfo_file failed\n");
    2713             : 
    2714           2 :         finfo = (union smb_fileinfo) {
    2715             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2716             :                 .generic.in.file.handle = h1,
    2717             :         };
    2718           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2719           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2720             :                                         "smb2_getinfo_file failed\n");
    2721           2 :         smb2_util_close(tree, h1);
    2722           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2723             :                                       expected_fileid,
    2724             :                                       ret, done, "bad fileid\n");
    2725             : 
    2726             :         /*
    2727             :          * Final open of the basefile with QFID
    2728             :          */
    2729           2 :         create = (struct smb2_create) {
    2730             :                 .in.desired_access = SEC_FILE_ALL,
    2731             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2732             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2733             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2734             :                 .in.fname = fname,
    2735             :                 .in.query_on_disk_id = true,
    2736             :         };
    2737             : 
    2738           2 :         status = smb2_create(tree, tctx, &create);
    2739           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2740             :                                         "test file could not be created\n");
    2741           2 :         h1 = create.out.file.handle;
    2742           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2743           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2744             :                                       ret, done, "bad fileid\n");
    2745             : 
    2746             :         /*
    2747             :          * Final Getinfo checking File-ID
    2748             :          */
    2749           2 :         finfo = (union smb_fileinfo) {
    2750             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2751             :                 .generic.in.file.handle = h1,
    2752             :         };
    2753             : 
    2754           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2755           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2756             :                                         "torture_smb2_testdir\n");
    2757           2 :         smb2_util_close(tree, h1);
    2758           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2759             :                                       expected_fileid,
    2760             :                                       ret, done, "bad fileid\n");
    2761             : 
    2762             :         /*
    2763             :          * Final list directory, verifying the operations on basefile and stream
    2764             :          * didn't modify the base file metadata.
    2765             :          */
    2766           2 :         f = (struct smb2_find) {
    2767             :                 .in.file.handle = testdirh,
    2768             :                 .in.pattern = "foo",
    2769             :                 .in.max_response_size = 0x1000,
    2770             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2771             :                 .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
    2772             :         };
    2773             : 
    2774           2 :         status = smb2_find_level(tree, tree, &f, &count, &d);
    2775           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2776             :                                         "smb2_find_level failed\n");
    2777           2 :         torture_assert_u64_equal_goto(tctx,
    2778             :                                       d->id_both_directory_info.file_id,
    2779             :                                       expected_fileid,
    2780             :                                       ret, done, "bad fileid\n");
    2781             : 
    2782           2 : done:
    2783           2 :         smb2_util_close(tree, testdirh);
    2784           2 :         smb2_deltree(tree, DNAME);
    2785           2 :         talloc_free(mem_ctx);
    2786           2 :         return ret;
    2787             : }
    2788             : 
    2789           2 : static bool test_fileid_dir(struct torture_context *tctx,
    2790             :                             struct smb2_tree *tree)
    2791             : {
    2792           2 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2793           2 :         const char *dname = DNAME "\\foo";
    2794           2 :         const char *sname = DNAME "\\foo:bar";
    2795           0 :         struct smb2_handle testdirh;
    2796           0 :         struct smb2_handle h1;
    2797           0 :         struct smb2_create create;
    2798           0 :         union smb_fileinfo finfo;
    2799           0 :         union smb_setfileinfo sinfo;
    2800           0 :         struct smb2_find f;
    2801           0 :         unsigned int count;
    2802           0 :         union smb_search_data *d;
    2803           0 :         uint64_t expected_fileid;
    2804           0 :         uint64_t returned_fileid;
    2805           0 :         NTSTATUS status;
    2806           2 :         bool ret = true;
    2807             : 
    2808           2 :         smb2_deltree(tree, DNAME);
    2809             : 
    2810           2 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    2811           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2812             :                                         "torture_smb2_testdir failed\n");
    2813             : 
    2814             :         /*
    2815             :          * Initial directory create with QFID
    2816             :          */
    2817           2 :         create = (struct smb2_create) {
    2818             :                 .in.desired_access = SEC_FILE_ALL,
    2819             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2820             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    2821             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2822             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2823             :                 .in.fname = dname,
    2824             :                 .in.query_on_disk_id = true,
    2825             :         };
    2826             : 
    2827           2 :         status = smb2_create(tree, tctx, &create);
    2828           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2829             :                                         "test file could not be created\n");
    2830           2 :         h1 = create.out.file.handle;
    2831           2 :         expected_fileid = BVAL(&create.out.on_disk_id, 0);
    2832             : 
    2833             :         /*
    2834             :          * Getinfo the File-ID on the just opened handle
    2835             :          */
    2836           2 :         finfo = (union smb_fileinfo) {
    2837             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2838             :                 .generic.in.file.handle = h1,
    2839             :         };
    2840             : 
    2841           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2842           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2843             :                                         "torture_smb2_testdir\n");
    2844           2 :         smb2_util_close(tree, h1);
    2845           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2846             :                                       expected_fileid,
    2847             :                                       ret, done, "bad fileid\n");
    2848             : 
    2849             :         /*
    2850             :          * Open existing directory with QFID
    2851             :          */
    2852           2 :         create = (struct smb2_create) {
    2853             :                 .in.desired_access = SEC_FILE_ALL,
    2854             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2855             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2856             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2857             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2858             :                 .in.fname = dname,
    2859             :                 .in.query_on_disk_id = true,
    2860             :         };
    2861             : 
    2862           2 :         status = smb2_create(tree, tctx, &create);
    2863           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2864             :                                         "test file could not be created\n");
    2865           2 :         h1 = create.out.file.handle;
    2866           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2867           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2868             :                                       ret, done, "bad fileid\n");
    2869             : 
    2870             :         /*
    2871             :          * Getinfo the File-ID on the just opened handle
    2872             :          */
    2873           2 :         finfo = (union smb_fileinfo) {
    2874             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2875             :                 .generic.in.file.handle = h1,
    2876             :         };
    2877             : 
    2878           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2879           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2880             :                                         "torture_smb2_testdir\n");
    2881           2 :         smb2_util_close(tree, h1);
    2882           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2883             :                                       expected_fileid,
    2884             :                                       ret, done, "bad fileid\n");
    2885             : 
    2886             :         /*
    2887             :          * Create stream, check the stream's File-ID, should be the same as the
    2888             :          * base file (sic!, tested against Windows).
    2889             :          */
    2890           2 :         create = (struct smb2_create) {
    2891             :                 .in.desired_access = SEC_FILE_ALL,
    2892             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2893             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2894             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    2895             :                 .in.fname = sname,
    2896             :                 .in.query_on_disk_id = true,
    2897             :         };
    2898             : 
    2899           2 :         status = smb2_create(tree, tctx, &create);
    2900           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2901             :                                         "test file could not be created\n");
    2902           2 :         h1 = create.out.file.handle;
    2903           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2904           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2905             :                                       ret, done, "bad fileid\n");
    2906             : 
    2907             :         /*
    2908             :          * Getinfo the File-ID on the created stream
    2909             :          */
    2910           2 :         finfo = (union smb_fileinfo) {
    2911             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2912             :                 .generic.in.file.handle = h1,
    2913             :         };
    2914             : 
    2915           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2916           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2917             :                                         "smb2_getinfo_file failed\n");
    2918           2 :         smb2_util_close(tree, h1);
    2919           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2920             :                                       expected_fileid,
    2921             :                                       ret, done, "bad fileid\n");
    2922             : 
    2923             :         /*
    2924             :          * Open stream, check the stream's File-ID, should be the same as the
    2925             :          * base file (sic!, tested against Windows).
    2926             :          */
    2927           2 :         create = (struct smb2_create) {
    2928             :                 .in.desired_access = SEC_FILE_ALL,
    2929             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2930             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2931             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2932             :                 .in.fname = sname,
    2933             :                 .in.query_on_disk_id = true,
    2934             :         };
    2935             : 
    2936           2 :         status = smb2_create(tree, tctx, &create);
    2937           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2938             :                                         "test file could not be created\n");
    2939           2 :         h1 = create.out.file.handle;
    2940           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2941           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2942             :                                       ret, done, "bad fileid\n");
    2943             : 
    2944             :         /*
    2945             :          * Getinfo the File-ID on the opened stream
    2946             :          */
    2947           2 :         finfo = (union smb_fileinfo) {
    2948             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2949             :                 .generic.in.file.handle = h1,
    2950             :         };
    2951             : 
    2952           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2953           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2954             :                                         "smb2_getinfo_file failed\n");
    2955           2 :         smb2_util_close(tree, h1);
    2956           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2957             :                                       expected_fileid,
    2958             :                                       ret, done, "bad fileid\n");
    2959             : 
    2960             :         /*
    2961             :          * Overwrite stream, check the stream's File-ID, should be the same as
    2962             :          * the base file (sic!, tested against Windows).
    2963             :          */
    2964           2 :         create = (struct smb2_create) {
    2965             :                 .in.desired_access = SEC_FILE_ALL,
    2966             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2967             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2968             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2969             :                 .in.fname = sname,
    2970             :                 .in.query_on_disk_id = true,
    2971             :         };
    2972             : 
    2973           2 :         status = smb2_create(tree, tctx, &create);
    2974           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2975             :                                         "test file could not be created\n");
    2976           2 :         h1 = create.out.file.handle;
    2977           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2978           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2979             :                                       ret, done, "bad fileid\n");
    2980             : 
    2981             :         /*
    2982             :          * Getinfo the File-ID on the overwritten stream
    2983             :          */
    2984           2 :         finfo = (union smb_fileinfo) {
    2985             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2986             :                 .generic.in.file.handle = h1,
    2987             :         };
    2988             : 
    2989           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2990           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2991             :                                         "smb2_getinfo_file failed\n");
    2992           2 :         smb2_util_close(tree, h1);
    2993           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2994             :                                       expected_fileid,
    2995             :                                       ret, done, "bad fileid\n");
    2996             : 
    2997             :         /*
    2998             :          * Do some modifications on the stream (IO, setinfo), verifying File-ID
    2999             :          * after each step.
    3000             :          */
    3001           2 :         create = (struct smb2_create) {
    3002             :                 .in.desired_access = SEC_FILE_ALL,
    3003             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3004             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3005             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3006             :                 .in.fname = sname,
    3007             :                 .in.query_on_disk_id = true,
    3008             :         };
    3009             : 
    3010           2 :         status = smb2_create(tree, tctx, &create);
    3011           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3012             :                                         "test file could not be created\n");
    3013           2 :         h1 = create.out.file.handle;
    3014             : 
    3015           2 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    3016           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3017             :                                         "smb2_util_write failed\n");
    3018             : 
    3019           2 :         finfo = (union smb_fileinfo) {
    3020             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3021             :                 .generic.in.file.handle = h1,
    3022             :         };
    3023           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3024           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3025             :                                         "smb2_getinfo_file failed\n");
    3026           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3027             :                                       expected_fileid,
    3028             :                                       ret, done, "bad fileid\n");
    3029             : 
    3030           2 :         sinfo = (union smb_setfileinfo) {
    3031             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    3032             :                 .basic_info.in.file.handle = h1,
    3033             :         };
    3034           2 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    3035             : 
    3036           2 :         status = smb2_setinfo_file(tree, &sinfo);
    3037           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3038             :                                         "smb2_setinfo_file failed\n");
    3039             : 
    3040           2 :         finfo = (union smb_fileinfo) {
    3041             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3042             :                 .generic.in.file.handle = h1,
    3043             :         };
    3044           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3045           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3046             :                                         "smb2_getinfo_file failed\n");
    3047           2 :         smb2_util_close(tree, h1);
    3048           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3049             :                                       expected_fileid,
    3050             :                                       ret, done, "bad fileid\n");
    3051             : 
    3052             :         /*
    3053             :          * Final open of the directory with QFID
    3054             :          */
    3055           2 :         create = (struct smb2_create) {
    3056             :                 .in.desired_access = SEC_FILE_ALL,
    3057             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3058             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    3059             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3060             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3061             :                 .in.fname = dname,
    3062             :                 .in.query_on_disk_id = true,
    3063             :         };
    3064             : 
    3065           2 :         status = smb2_create(tree, tctx, &create);
    3066           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3067             :                                         "test file could not be created\n");
    3068           2 :         h1 = create.out.file.handle;
    3069           2 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3070           2 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3071             :                                       ret, done, "bad fileid\n");
    3072             : 
    3073             :         /*
    3074             :          * Final Getinfo checking File-ID
    3075             :          */
    3076           2 :         finfo = (union smb_fileinfo) {
    3077             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3078             :                 .generic.in.file.handle = h1,
    3079             :         };
    3080             : 
    3081           2 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3082           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3083             :                                         "torture_smb2_testdir\n");
    3084           2 :         smb2_util_close(tree, h1);
    3085           2 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3086             :                                       expected_fileid,
    3087             :                                       ret, done, "bad fileid\n");
    3088             : 
    3089             :         /*
    3090             :          * Final list directory, verifying the operations on basefile and stream
    3091             :          * didn't modify the base file metadata.
    3092             :          */
    3093           2 :         f = (struct smb2_find) {
    3094             :                 .in.file.handle = testdirh,
    3095             :                 .in.pattern = "foo",
    3096             :                 .in.max_response_size = 0x1000,
    3097             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    3098             :                 .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
    3099             :         };
    3100             : 
    3101           2 :         status = smb2_find_level(tree, tree, &f, &count, &d);
    3102           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3103             :                                         "smb2_find_level failed\n");
    3104           2 :         torture_assert_u64_equal_goto(tctx,
    3105             :                                       d->id_both_directory_info.file_id,
    3106             :                                       expected_fileid,
    3107             :                                       ret, done, "bad fileid\n");
    3108             : 
    3109           2 : done:
    3110           2 :         smb2_util_close(tree, testdirh);
    3111           2 :         smb2_deltree(tree, DNAME);
    3112           2 :         talloc_free(mem_ctx);
    3113           2 :         return ret;
    3114             : }
    3115             : 
    3116           4 : static bool test_fileid_unique_object(
    3117             :                         struct torture_context *tctx,
    3118             :                         struct smb2_tree *tree,
    3119             :                         unsigned int num_objs,
    3120             :                         bool create_dirs)
    3121           4 : {
    3122           4 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    3123           4 :         char *fname = NULL;
    3124           0 :         struct smb2_handle testdirh;
    3125           0 :         struct smb2_handle h1;
    3126           0 :         struct smb2_create create;
    3127           0 :         unsigned int i;
    3128           4 :         uint64_t fileid_array[num_objs];
    3129           0 :         NTSTATUS status;
    3130           4 :         bool ret = true;
    3131             : 
    3132           4 :         smb2_deltree(tree, DNAME);
    3133             : 
    3134           4 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    3135           4 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3136             :                                         "test_fileid_unique failed\n");
    3137           4 :         smb2_util_close(tree, testdirh);
    3138             : 
    3139             :         /* Create num_obj files as rapidly as we can. */
    3140         404 :         for (i = 0; i < num_objs; i++) {
    3141         400 :                 fname = talloc_asprintf(mem_ctx,
    3142             :                                         "%s\\testfile.%u",
    3143             :                                         DNAME,
    3144             :                                         i);
    3145         400 :                 torture_assert_goto(tctx,
    3146             :                                 fname != NULL,
    3147             :                                 ret,
    3148             :                                 done,
    3149             :                                 "talloc failed\n");
    3150             : 
    3151         400 :                 create = (struct smb2_create) {
    3152             :                         .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
    3153             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3154             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3155             :                         .in.create_disposition = NTCREATEX_DISP_CREATE,
    3156             :                         .in.fname = fname,
    3157             :                 };
    3158             : 
    3159         400 :                 if (create_dirs) {
    3160         200 :                         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    3161         200 :                         create.in.create_options = FILE_DIRECTORY_FILE;
    3162             :                 }
    3163             : 
    3164         400 :                 status = smb2_create(tree, tctx, &create);
    3165         400 :                 if (!NT_STATUS_IS_OK(status)) {
    3166           0 :                         torture_fail(tctx,
    3167             :                                 talloc_asprintf(tctx,
    3168             :                                         "test file %s could not be created\n",
    3169             :                                         fname));
    3170             :                         TALLOC_FREE(fname);
    3171             :                         ret = false;
    3172             :                         goto done;
    3173             :                 }
    3174             : 
    3175         400 :                 h1 = create.out.file.handle;
    3176         400 :                 smb2_util_close(tree, h1);
    3177         400 :                 TALLOC_FREE(fname);
    3178             :         }
    3179             : 
    3180             :         /*
    3181             :          * Get the file ids.
    3182             :          */
    3183         404 :         for (i = 0; i < num_objs; i++) {
    3184           0 :                 union smb_fileinfo finfo;
    3185             : 
    3186         400 :                 fname = talloc_asprintf(mem_ctx,
    3187             :                                         "%s\\testfile.%u",
    3188             :                                         DNAME,
    3189             :                                         i);
    3190         400 :                 torture_assert_goto(tctx,
    3191             :                                 fname != NULL,
    3192             :                                 ret,
    3193             :                                 done,
    3194             :                                 "talloc failed\n");
    3195             : 
    3196         400 :                 create = (struct smb2_create) {
    3197             :                         .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
    3198             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3199             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3200             :                         .in.create_disposition = NTCREATEX_DISP_OPEN,
    3201             :                         .in.fname = fname,
    3202             :                 };
    3203             : 
    3204         400 :                 if (create_dirs) {
    3205         200 :                         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    3206         200 :                         create.in.create_options = FILE_DIRECTORY_FILE;
    3207             :                 }
    3208             : 
    3209         400 :                 status = smb2_create(tree, tctx, &create);
    3210         400 :                 if (!NT_STATUS_IS_OK(status)) {
    3211           0 :                         torture_fail(tctx,
    3212             :                                 talloc_asprintf(tctx,
    3213             :                                         "test file %s could not "
    3214             :                                         "be opened: %s\n",
    3215             :                                         fname,
    3216             :                                         nt_errstr(status)));
    3217             :                         TALLOC_FREE(fname);
    3218             :                         ret = false;
    3219             :                         goto done;
    3220             :                 }
    3221             : 
    3222         400 :                 h1 = create.out.file.handle;
    3223             : 
    3224         400 :                 finfo = (union smb_fileinfo) {
    3225             :                         .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3226             :                         .generic.in.file.handle = h1,
    3227             :                 };
    3228             : 
    3229         400 :                 status = smb2_getinfo_file(tree, tctx, &finfo);
    3230         400 :                 if (!NT_STATUS_IS_OK(status)) {
    3231           0 :                         torture_fail(tctx,
    3232             :                                 talloc_asprintf(tctx,
    3233             :                                         "failed to get fileid for "
    3234             :                                         "test file %s: %s\n",
    3235             :                                         fname,
    3236             :                                         nt_errstr(status)));
    3237             :                         TALLOC_FREE(fname);
    3238             :                         ret = false;
    3239             :                         goto done;
    3240             :                 }
    3241         400 :                 smb2_util_close(tree, h1);
    3242             : 
    3243         400 :                 fileid_array[i] = finfo.all_info2.out.file_id;
    3244         400 :                 TALLOC_FREE(fname);
    3245             :         }
    3246             : 
    3247             :         /* All returned fileids must be unique. 100 is small so brute force. */
    3248         400 :         for (i = 0; i < num_objs - 1; i++) {
    3249           0 :                 unsigned int j;
    3250       20196 :                 for (j = i + 1; j < num_objs; j++) {
    3251       19800 :                         if (fileid_array[i] == fileid_array[j]) {
    3252           0 :                                 torture_fail(tctx,
    3253             :                                         talloc_asprintf(tctx,
    3254             :                                                 "fileid %u == fileid %u (0x%"PRIu64")\n",
    3255             :                                                 i,
    3256             :                                                 j,
    3257             :                                                 fileid_array[i]));
    3258             :                                 ret = false;
    3259             :                                 goto done;
    3260             :                         }
    3261             :                 }
    3262             :         }
    3263             : 
    3264           4 : done:
    3265             : 
    3266           4 :         smb2_util_close(tree, testdirh);
    3267           4 :         smb2_deltree(tree, DNAME);
    3268           4 :         talloc_free(mem_ctx);
    3269           4 :         return ret;
    3270             : }
    3271             : 
    3272           2 : static bool test_fileid_unique(
    3273             :                         struct torture_context *tctx,
    3274             :                         struct smb2_tree *tree)
    3275             : {
    3276           2 :         return test_fileid_unique_object(tctx, tree, 100, false);
    3277             : }
    3278             : 
    3279           2 : static bool test_fileid_unique_dir(
    3280             :                         struct torture_context *tctx,
    3281             :                         struct smb2_tree *tree)
    3282             : {
    3283           2 :         return test_fileid_unique_object(tctx, tree, 100, true);
    3284             : }
    3285             : 
    3286           6 : static bool test_dosattr_tmp_dir(struct torture_context *tctx,
    3287             :                                  struct smb2_tree *tree)
    3288             : {
    3289           6 :         bool ret = true;
    3290           0 :         NTSTATUS status;
    3291           0 :         struct smb2_create c;
    3292           6 :         struct smb2_handle h1 = {{0}};
    3293           6 :         const char *fname = DNAME;
    3294             : 
    3295           6 :         smb2_deltree(tree, fname);
    3296           6 :         smb2_util_rmdir(tree, fname);
    3297             : 
    3298           6 :         c = (struct smb2_create) {
    3299             :                 .in.desired_access = SEC_RIGHTS_DIR_ALL,
    3300             :                 .in.file_attributes  = FILE_ATTRIBUTE_DIRECTORY,
    3301             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    3302             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3303             :                         NTCREATEX_SHARE_ACCESS_WRITE |
    3304             :                         NTCREATEX_SHARE_ACCESS_DELETE,
    3305             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3306             :                 .in.fname = DNAME,
    3307             :         };
    3308             : 
    3309           6 :         status = smb2_create(tree, tctx, &c);
    3310           6 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3311             :                                         "smb2_create\n");
    3312           6 :         h1 = c.out.file.handle;
    3313             : 
    3314             :         /* Try to set temporary attribute on directory */
    3315           6 :         SET_ATTRIB(FILE_ATTRIBUTE_TEMPORARY);
    3316             : 
    3317           6 :         torture_assert_ntstatus_equal_goto(tctx, status,
    3318             :                                            NT_STATUS_INVALID_PARAMETER,
    3319             :                                            ret, done,
    3320             :                                            "Unexpected setinfo result\n");
    3321             : 
    3322           6 : done:
    3323           6 :         if (!smb2_util_handle_empty(h1)) {
    3324           6 :                 smb2_util_close(tree, h1);
    3325             :         }
    3326           6 :         smb2_util_unlink(tree, fname);
    3327           6 :         smb2_deltree(tree, fname);
    3328             : 
    3329           6 :         return ret;
    3330             : }
    3331             : 
    3332             : /*
    3333             :   test opening quota fakefile handle and returned attributes
    3334             : */
    3335           6 : static bool test_smb2_open_quota_fake_file(struct torture_context *tctx,
    3336             :                                            struct smb2_tree *tree)
    3337             : {
    3338           6 :         const char *fname = "$Extend\\$Quota:$Q:$INDEX_ALLOCATION";
    3339           0 :         struct smb2_create create;
    3340           6 :         struct smb2_handle h = {{0}};
    3341           0 :         NTSTATUS status;
    3342           6 :         bool ret = true;
    3343             : 
    3344           6 :         create = (struct smb2_create) {
    3345             :                 .in.desired_access = SEC_RIGHTS_FILE_READ,
    3346             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3347             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3348             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3349             :                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
    3350             :                 .in.fname = fname,
    3351             :         };
    3352             : 
    3353           6 :         status = smb2_create(tree, tree, &create);
    3354           6 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3355             :                                         "smb2_create failed\n");
    3356           5 :         h = create.out.file.handle;
    3357             : 
    3358           5 :         torture_assert_u64_equal_goto(tctx,
    3359             :                                       create.out.file_attr,
    3360             :                                       FILE_ATTRIBUTE_HIDDEN
    3361             :                                       | FILE_ATTRIBUTE_SYSTEM
    3362             :                                       | FILE_ATTRIBUTE_DIRECTORY
    3363             :                                       | FILE_ATTRIBUTE_ARCHIVE,
    3364             :                                       ret,
    3365             :                                       done,
    3366             :                                       "Wrong attributes\n");
    3367             : 
    3368           5 :         torture_assert_u64_equal_goto(tctx,
    3369             :                                       create.out.create_time, 0,
    3370             :                                       ret,
    3371             :                                       done,
    3372             :                                       "create_time is not 0\n");
    3373           5 :         torture_assert_u64_equal_goto(tctx,
    3374             :                                       create.out.access_time, 0,
    3375             :                                       ret,
    3376             :                                       done,
    3377             :                                       "access_time is not 0\n");
    3378           5 :         torture_assert_u64_equal_goto(tctx,
    3379             :                                       create.out.write_time, 0,
    3380             :                                       ret,
    3381             :                                       done,
    3382             :                                       "write_time is not 0\n");
    3383           5 :         torture_assert_u64_equal_goto(tctx,
    3384             :                                       create.out.change_time, 0,
    3385             :                                       ret,
    3386             :                                       done,
    3387             :                                       "change_time is not 0\n");
    3388             : 
    3389           5 : done:
    3390           6 :         smb2_util_close(tree, h);
    3391           6 :         return ret;
    3392             : }
    3393             : 
    3394             : /**
    3395             :   Find Maximum Path Length
    3396             :  */
    3397           0 : static bool generate_path(const size_t len,
    3398             :                           char *buffer,
    3399             :                           const size_t buf_len)
    3400             : {
    3401             :         size_t i;
    3402             : 
    3403           0 :         if (len >= buf_len) {
    3404           0 :                 return false;
    3405             :         }
    3406             : 
    3407           0 :         for (i = 0; i < len ; i++) {
    3408           0 :                 buffer[i] = (char)(i % 10) + 48;
    3409             :         }
    3410           0 :         buffer[i] = '\0';
    3411           0 :         return true;
    3412             : }
    3413             : 
    3414           6 : static bool test_path_length_test(struct torture_context *tctx,
    3415             :                                   struct smb2_tree *tree)
    3416             : {
    3417           6 :         const size_t max_name = 2048;
    3418           6 :         char *name = talloc_array(tctx, char, max_name);
    3419           6 :         struct smb2_handle fh = {{0}};
    3420           6 :         size_t length = 128;
    3421           6 :         size_t max_file_name = 0;
    3422           6 :         size_t max_path_length = 0;
    3423           6 :         char *path_ok = NULL;
    3424           6 :         char *path_next = NULL;
    3425           6 :         char *topdir = NULL;
    3426           6 :         bool is_interactive = torture_setting_bool(tctx, "interactive", false);
    3427           0 :         NTSTATUS status;
    3428           6 :         bool ret = true;
    3429             : 
    3430           6 :         if (!is_interactive) {
    3431           6 :                 torture_result(tctx, TORTURE_SKIP,
    3432             :                                "Interactive Test: Skipping... "
    3433             :                                "(enable with --interactive)\n");
    3434           6 :                 return ret;
    3435             :         }
    3436             : 
    3437           0 :         torture_comment(tctx, "Testing filename and path lengths\n");
    3438             : 
    3439             :         /* Find Longest File Name */
    3440           0 :         for (length = 128; length < max_name; length++) {
    3441           0 :                 if (!generate_path(length, name, max_name))  {
    3442           0 :                         torture_result(tctx, TORTURE_FAIL,
    3443             :                                        "Failed to generate path.");
    3444           0 :                         return false;
    3445             :                 }
    3446             : 
    3447           0 :                 status = torture_smb2_testfile(tree, name, &fh);
    3448           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3449           0 :                         break;
    3450             :                 }
    3451             : 
    3452           0 :                 smb2_util_close(tree, fh);
    3453           0 :                 smb2_util_unlink(tree, name);
    3454             : 
    3455           0 :                 max_file_name = length;
    3456             :         }
    3457             : 
    3458           0 :         torture_assert_int_not_equal_goto(tctx, length, max_name, ret, done,
    3459             :                                           "Name too big\n");
    3460             : 
    3461           0 :         torture_comment(tctx, "Max file name length: %zu\n", max_file_name);
    3462             : 
    3463             :         /* Remove one char that caused the failure above */
    3464           0 :         name[max_file_name] = '\0';
    3465             : 
    3466           0 :         path_ok = talloc_strdup(tree, name);
    3467           0 :         torture_assert_not_null_goto(tctx, path_ok, ret, done,
    3468             :                                      "talloc_strdup failed\n");
    3469             : 
    3470           0 :         topdir = talloc_strdup(tree, name);
    3471           0 :         torture_assert_not_null_goto(tctx, topdir, ret, done,
    3472             :                                      "talloc_strdup failed\n");
    3473             : 
    3474           0 :         status = smb2_util_mkdir(tree, path_ok);
    3475           0 :         if (!NT_STATUS_IS_OK(status)) {
    3476           0 :                 torture_comment(tctx, "mkdir [%s] failed: %s\n",
    3477             :                                 path_ok, nt_errstr(status));
    3478           0 :                 torture_result(tctx, TORTURE_FAIL, "Initial mkdir failed");
    3479           0 :                 return false;
    3480             :         }
    3481             : 
    3482           0 :         while (true) {
    3483           0 :                 path_next = talloc_asprintf(tctx, "%s\\%s", path_ok, name);
    3484           0 :                 torture_assert_not_null_goto(tctx, path_next, ret, done,
    3485             :                                              "talloc_asprintf failed\n");
    3486             : 
    3487           0 :                 status = smb2_util_mkdir(tree, path_next);
    3488           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3489           0 :                         break;
    3490             :                 }
    3491             : 
    3492           0 :                 path_ok = path_next;
    3493             :         }
    3494             : 
    3495           0 :         for (length = 1; length < max_name; length++) {
    3496           0 :                 if (!generate_path(length, name, max_name))  {
    3497           0 :                         torture_result(tctx, TORTURE_FAIL,
    3498             :                                        "Failed to generate path.");
    3499           0 :                         return false;
    3500             :                 }
    3501             : 
    3502           0 :                 path_next = talloc_asprintf(tctx, "%s\\%s", path_ok, name);
    3503           0 :                 torture_assert_not_null_goto(tctx, path_next, ret, done,
    3504             :                                              "talloc_asprintf failed\n");
    3505             : 
    3506           0 :                 status = torture_smb2_testfile(tree, path_next, &fh);
    3507           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3508           0 :                         break;
    3509             :                 }
    3510           0 :                 smb2_util_close(tree, fh);
    3511           0 :                 path_ok = path_next;
    3512             :         }
    3513             : 
    3514           0 :         max_path_length = talloc_array_length(path_ok);
    3515             : 
    3516           0 :         torture_comment(tctx, "Max path name length: %zu\n", max_path_length);
    3517             : 
    3518           0 : done:
    3519           0 :         return ret;
    3520             : }
    3521             : 
    3522             : /*
    3523             :    basic testing of SMB2 read
    3524             : */
    3525        2379 : struct torture_suite *torture_smb2_create_init(TALLOC_CTX *ctx)
    3526             : {
    3527        2379 :         struct torture_suite *suite = torture_suite_create(ctx, "create");
    3528             : 
    3529        2379 :         torture_suite_add_1smb2_test(suite, "gentest", test_create_gentest);
    3530        2379 :         torture_suite_add_1smb2_test(suite, "blob", test_create_blob);
    3531        2379 :         torture_suite_add_1smb2_test(suite, "open", test_smb2_open);
    3532        2379 :         torture_suite_add_1smb2_test(suite, "brlocked", test_smb2_open_brlocked);
    3533        2379 :         torture_suite_add_1smb2_test(suite, "multi", test_smb2_open_multi);
    3534        2379 :         torture_suite_add_1smb2_test(suite, "delete", test_smb2_open_for_delete);
    3535        2379 :         torture_suite_add_1smb2_test(suite, "leading-slash", test_smb2_leading_slash);
    3536        2379 :         torture_suite_add_1smb2_test(suite, "impersonation", test_smb2_impersonation_level);
    3537        2379 :         torture_suite_add_1smb2_test(suite, "aclfile", test_create_acl_file);
    3538        2379 :         torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir);
    3539        2379 :         torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl);
    3540        2379 :         torture_suite_add_1smb2_test(suite, "mkdir-dup", test_mkdir_dup);
    3541        2379 :         torture_suite_add_1smb2_test(suite, "dir-alloc-size", test_dir_alloc_size);
    3542        2379 :         torture_suite_add_1smb2_test(suite, "dosattr_tmp_dir", test_dosattr_tmp_dir);
    3543        2379 :         torture_suite_add_1smb2_test(suite, "quota-fake-file", test_smb2_open_quota_fake_file);
    3544        2379 :         torture_suite_add_1smb2_test(suite, "path-length", test_path_length_test);
    3545        2379 :         torture_suite_add_1smb2_test(suite, "bench-path-contention-shared", test_smb2_bench_path_contention_shared);
    3546             : 
    3547        2379 :         suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
    3548             : 
    3549        2379 :         return suite;
    3550             : }
    3551             : 
    3552        2379 : struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx)
    3553             : {
    3554        2379 :         struct torture_suite *suite = torture_suite_create(ctx, "twrp");
    3555             : 
    3556        2379 :         torture_suite_add_1smb2_test(suite, "write", test_twrp_write);
    3557        2379 :         torture_suite_add_1smb2_test(suite, "stream", test_twrp_stream);
    3558        2379 :         torture_suite_add_1smb2_test(suite, "openroot", test_twrp_openroot);
    3559        2379 :         torture_suite_add_1smb2_test(suite, "listdir", test_twrp_listdir);
    3560             : 
    3561        2379 :         suite->description = talloc_strdup(suite, "SMB2-TWRP tests");
    3562             : 
    3563        2379 :         return suite;
    3564             : }
    3565             : 
    3566             : /*
    3567             :    basic testing of SMB2 File-IDs
    3568             : */
    3569        2379 : struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx)
    3570             : {
    3571        2379 :         struct torture_suite *suite = torture_suite_create(ctx, "fileid");
    3572             : 
    3573        2379 :         torture_suite_add_1smb2_test(suite, "fileid", test_fileid);
    3574        2379 :         torture_suite_add_1smb2_test(suite, "fileid-dir", test_fileid_dir);
    3575        2379 :         torture_suite_add_1smb2_test(suite, "unique", test_fileid_unique);
    3576        2379 :         torture_suite_add_1smb2_test(suite, "unique-dir", test_fileid_unique_dir);
    3577             : 
    3578        2379 :         suite->description = talloc_strdup(suite, "SMB2-FILEID tests");
    3579             : 
    3580        2379 :         return suite;
    3581             : }
    3582             : 
    3583           3 : static bool test_no_stream(struct torture_context *tctx,
    3584             :                            struct smb2_tree *tree)
    3585             : {
    3586           0 :         struct smb2_create c;
    3587           0 :         NTSTATUS status;
    3588           3 :         bool ret = true;
    3589           3 :         const char *names[] = {
    3590             :                 "test_no_stream::$DATA",
    3591             :                 "test_no_stream::foooooooooooo",
    3592             :                 "test_no_stream:stream",
    3593             :                 "test_no_stream:stream:$DATA",
    3594             :                 NULL
    3595             :         };
    3596           0 :         int i;
    3597             : 
    3598          15 :         for (i = 0; names[i] != NULL; i++) {
    3599          12 :                 c = (struct smb2_create) {
    3600             :                         .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED,
    3601             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3602             :                         .in.create_disposition = NTCREATEX_DISP_OPEN,
    3603             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3604          12 :                         .in.fname = names[i],
    3605             :                 };
    3606             : 
    3607          12 :                 status = smb2_create(tree, tctx, &c);
    3608          12 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
    3609           0 :                         torture_comment(
    3610             :                                 tctx, "Expected NT_STATUS_OBJECT_NAME_INVALID, "
    3611             :                                 "got %s, name: '%s'\n",
    3612             :                                 nt_errstr(status), names[i]);
    3613           0 :                         torture_fail_goto(tctx, done, "Bad create result\n");
    3614             :                 }
    3615             :         }
    3616           3 : done:
    3617           3 :         return ret;
    3618             : }
    3619             : 
    3620        2379 : struct torture_suite *torture_smb2_create_no_streams_init(TALLOC_CTX *ctx)
    3621             : {
    3622        2379 :         struct torture_suite *suite = torture_suite_create(ctx, "create_no_streams");
    3623             : 
    3624        2379 :         torture_suite_add_1smb2_test(suite, "no_stream", test_no_stream);
    3625             : 
    3626        2379 :         suite->description = talloc_strdup(suite, "SMB2-CREATE stream test on share without streams support");
    3627             : 
    3628        2379 :         return suite;
    3629             : }

Generated by: LCOV version 1.14