LCOV - code coverage report
Current view: top level - source4/torture/smb2 - create.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 1188 1985 59.8 %
Date: 2024-02-14 10:14:15 Functions: 29 45 64.4 %

          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             :    stress testing keepalive iops
     132             :  */
     133             : 
     134             : struct test_smb2_bench_echo_conn;
     135             : struct test_smb2_bench_echo_loop;
     136             : 
     137             : struct test_smb2_bench_echo_state {
     138             :         struct torture_context *tctx;
     139             :         size_t num_conns;
     140             :         struct test_smb2_bench_echo_conn *conns;
     141             :         size_t num_loops;
     142             :         struct test_smb2_bench_echo_loop *loops;
     143             :         struct timeval starttime;
     144             :         int timecount;
     145             :         int timelimit;
     146             :         uint64_t num_finished;
     147             :         double total_latency;
     148             :         double min_latency;
     149             :         double max_latency;
     150             :         bool ok;
     151             :         bool stop;
     152             : };
     153             : 
     154             : struct test_smb2_bench_echo_conn {
     155             :         struct test_smb2_bench_echo_state *state;
     156             :         int idx;
     157             :         struct smb2_tree *tree;
     158             : };
     159             : 
     160             : struct test_smb2_bench_echo_loop {
     161             :         struct test_smb2_bench_echo_state *state;
     162             :         struct test_smb2_bench_echo_conn *conn;
     163             :         int idx;
     164             :         struct tevent_immediate *im;
     165             :         struct tevent_req *req;
     166             :         struct timeval starttime;
     167             :         uint64_t num_started;
     168             :         uint64_t num_finished;
     169             :         double total_latency;
     170             :         double min_latency;
     171             :         double max_latency;
     172             :         NTSTATUS error;
     173             : };
     174             : 
     175             : static void test_smb2_bench_echo_loop_do(
     176             :         struct test_smb2_bench_echo_loop *loop);
     177             : 
     178           0 : static void test_smb2_bench_echo_loop_start(struct tevent_context *ctx,
     179             :                                                        struct tevent_immediate *im,
     180             :                                                        void *private_data)
     181             : {
     182           0 :         struct test_smb2_bench_echo_loop *loop =
     183             :                 (struct test_smb2_bench_echo_loop *)
     184             :                 private_data;
     185             : 
     186           0 :         test_smb2_bench_echo_loop_do(loop);
     187           0 : }
     188             : 
     189             : static void test_smb2_bench_echo_loop_done(struct tevent_req *req);
     190             : 
     191           0 : static void test_smb2_bench_echo_loop_do(
     192             :         struct test_smb2_bench_echo_loop *loop)
     193             : {
     194           0 :         struct test_smb2_bench_echo_state *state = loop->state;
     195             : 
     196           0 :         loop->num_started += 1;
     197           0 :         loop->starttime = timeval_current();
     198           0 :         loop->req = smb2cli_echo_send(state->loops,
     199           0 :                                       state->tctx->ev,
     200           0 :                                       loop->conn->tree->session->transport->conn,
     201             :                                       1000);
     202           0 :         torture_assert_goto(state->tctx, loop->req != NULL,
     203             :                             state->ok, asserted, "smb2_create_send");
     204             : 
     205           0 :         tevent_req_set_callback(loop->req,
     206             :                                 test_smb2_bench_echo_loop_done,
     207             :                                 loop);
     208           0 :         return;
     209           0 : asserted:
     210           0 :         state->stop = true;
     211             : }
     212             : 
     213           0 : static void test_smb2_bench_echo_loop_done(struct tevent_req *req)
     214             : {
     215             :         struct test_smb2_bench_echo_loop *loop =
     216             :                 (struct test_smb2_bench_echo_loop *)
     217           0 :                 _tevent_req_callback_data(req);
     218           0 :         struct test_smb2_bench_echo_state *state = loop->state;
     219           0 :         double latency = timeval_elapsed(&loop->starttime);
     220           0 :         TALLOC_CTX *frame = talloc_stackframe();
     221             : 
     222           0 :         torture_assert_goto(state->tctx, loop->req == req,
     223             :                             state->ok, asserted, __location__);
     224           0 :         loop->error = smb2cli_echo_recv(req);
     225           0 :         torture_assert_ntstatus_ok_goto(state->tctx, loop->error,
     226             :                                         state->ok, asserted, __location__);
     227           0 :         SMB_ASSERT(latency >= 0.000001);
     228             : 
     229           0 :         if (loop->num_finished == 0) {
     230             :                 /* first round */
     231           0 :                 loop->min_latency = latency;
     232           0 :                 loop->max_latency = latency;
     233             :         }
     234             : 
     235           0 :         loop->num_finished += 1;
     236           0 :         loop->total_latency += latency;
     237             : 
     238           0 :         if (latency < loop->min_latency) {
     239           0 :                 loop->min_latency = latency;
     240             :         }
     241             : 
     242           0 :         if (latency > loop->max_latency) {
     243           0 :                 loop->max_latency = latency;
     244             :         }
     245             : 
     246           0 :         TALLOC_FREE(frame);
     247           0 :         test_smb2_bench_echo_loop_do(loop);
     248           0 :         return;
     249           0 : asserted:
     250           0 :         state->stop = true;
     251           0 :         TALLOC_FREE(frame);
     252             : }
     253             : 
     254           0 : static void test_smb2_bench_echo_progress(struct tevent_context *ev,
     255             :                                           struct tevent_timer *te,
     256             :                                           struct timeval current_time,
     257             :                                           void *private_data)
     258             : {
     259           0 :         struct test_smb2_bench_echo_state *state =
     260             :                 (struct test_smb2_bench_echo_state *)private_data;
     261           0 :         uint64_t num_echos = 0;
     262           0 :         double total_echo_latency = 0;
     263           0 :         double min_echo_latency = 0;
     264           0 :         double max_echo_latency = 0;
     265           0 :         double avs_echo_latency = 0;
     266             :         size_t i;
     267             : 
     268           0 :         state->timecount += 1;
     269             : 
     270           0 :         for (i=0;i<state->num_loops;i++) {
     271           0 :                 struct test_smb2_bench_echo_loop *loop =
     272           0 :                         &state->loops[i];
     273             : 
     274           0 :                 num_echos += loop->num_finished;
     275           0 :                 total_echo_latency += loop->total_latency;
     276           0 :                 if (min_echo_latency == 0.0 && loop->min_latency != 0.0) {
     277           0 :                         min_echo_latency = loop->min_latency;
     278             :                 }
     279           0 :                 if (loop->min_latency < min_echo_latency) {
     280           0 :                         min_echo_latency = loop->min_latency;
     281             :                 }
     282           0 :                 if (max_echo_latency == 0.0) {
     283           0 :                         max_echo_latency = loop->max_latency;
     284             :                 }
     285           0 :                 if (loop->max_latency > max_echo_latency) {
     286           0 :                         max_echo_latency = loop->max_latency;
     287             :                 }
     288           0 :                 loop->num_finished = 0;
     289           0 :                 loop->total_latency = 0.0;
     290             :         }
     291             : 
     292           0 :         state->num_finished += num_echos;
     293           0 :         state->total_latency += total_echo_latency;
     294           0 :         if (state->min_latency == 0.0 && min_echo_latency != 0.0) {
     295           0 :                 state->min_latency = min_echo_latency;
     296             :         }
     297           0 :         if (min_echo_latency < state->min_latency) {
     298           0 :                 state->min_latency = min_echo_latency;
     299             :         }
     300           0 :         if (state->max_latency == 0.0) {
     301           0 :                 state->max_latency = max_echo_latency;
     302             :         }
     303           0 :         if (max_echo_latency > state->max_latency) {
     304           0 :                 state->max_latency = max_echo_latency;
     305             :         }
     306             : 
     307           0 :         if (state->timecount < state->timelimit) {
     308           0 :                 te = tevent_add_timer(state->tctx->ev,
     309             :                                       state,
     310             :                                       timeval_current_ofs(1, 0),
     311             :                                       test_smb2_bench_echo_progress,
     312             :                                       state);
     313           0 :                 torture_assert_goto(state->tctx, te != NULL,
     314             :                                     state->ok, asserted, "tevent_add_timer");
     315             : 
     316           0 :                 if (!torture_setting_bool(state->tctx, "progress", true)) {
     317           0 :                         return;
     318             :                 }
     319             : 
     320           0 :                 avs_echo_latency = total_echo_latency / num_echos;
     321             : 
     322           0 :                 torture_comment(state->tctx,
     323             :                                 "%.2f second: "
     324             :                                 "echo[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]      \r",
     325           0 :                                 timeval_elapsed(&state->starttime),
     326             :                                 (unsigned long long)num_echos,
     327             :                                 avs_echo_latency,
     328             :                                 min_echo_latency,
     329             :                                 max_echo_latency);
     330           0 :                 return;
     331             :         }
     332             : 
     333           0 :         avs_echo_latency = state->total_latency / state->num_finished;
     334           0 :         num_echos = state->num_finished / state->timelimit;
     335             : 
     336           0 :         torture_comment(state->tctx,
     337             :                         "%.2f second: "
     338             :                         "echo[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]\n",
     339           0 :                         timeval_elapsed(&state->starttime),
     340             :                         (unsigned long long)num_echos,
     341             :                         avs_echo_latency,
     342             :                         state->min_latency,
     343             :                         state->max_latency);
     344             : 
     345           0 : asserted:
     346           0 :         state->stop = true;
     347             : }
     348             : 
     349           0 : static bool test_smb2_bench_echo(struct torture_context *tctx,
     350             :                                  struct smb2_tree *tree)
     351             : {
     352           0 :         struct test_smb2_bench_echo_state *state = NULL;
     353           0 :         bool ret = true;
     354           0 :         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
     355           0 :         int torture_qdepth = torture_setting_int(tctx, "qdepth", 1);
     356             :         size_t i;
     357           0 :         size_t li = 0;
     358           0 :         int timelimit = torture_setting_int(tctx, "timelimit", 10);
     359           0 :         struct tevent_timer *te = NULL;
     360             :         uint32_t timeout_msec;
     361             : 
     362           0 :         state = talloc_zero(tctx, struct test_smb2_bench_echo_state);
     363           0 :         torture_assert(tctx, state != NULL, __location__);
     364           0 :         state->tctx = tctx;
     365           0 :         state->num_conns = torture_nprocs;
     366           0 :         state->conns = talloc_zero_array(state,
     367             :                         struct test_smb2_bench_echo_conn,
     368             :                         state->num_conns);
     369           0 :         torture_assert(tctx, state->conns != NULL, __location__);
     370           0 :         state->num_loops = torture_nprocs * torture_qdepth;
     371           0 :         state->loops = talloc_zero_array(state,
     372             :                         struct test_smb2_bench_echo_loop,
     373             :                         state->num_loops);
     374           0 :         torture_assert(tctx, state->loops != NULL, __location__);
     375           0 :         state->ok = true;
     376           0 :         state->timelimit = MAX(timelimit, 1);
     377             : 
     378           0 :         timeout_msec = tree->session->transport->options.request_timeout * 1000;
     379             : 
     380           0 :         torture_comment(tctx, "Opening %zu connections\n", state->num_conns);
     381             : 
     382           0 :         for (i=0;i<state->num_conns;i++) {
     383           0 :                 struct smb2_tree *ct = NULL;
     384           0 :                 DATA_BLOB out_input_buffer = data_blob_null;
     385           0 :                 DATA_BLOB out_output_buffer = data_blob_null;
     386             :                 size_t pcli;
     387             : 
     388           0 :                 state->conns[i].state = state;
     389           0 :                 state->conns[i].idx = i;
     390             : 
     391           0 :                 if (!torture_smb2_connection(tctx, &ct)) {
     392           0 :                         torture_comment(tctx, "Failed opening %zu/%zu connections\n", i, state->num_conns);
     393           0 :                         return false;
     394             :                 }
     395           0 :                 state->conns[i].tree = talloc_steal(state->conns, ct);
     396             : 
     397           0 :                 smb2cli_conn_set_max_credits(ct->session->transport->conn, 8192);
     398           0 :                 smb2cli_ioctl(ct->session->transport->conn,
     399             :                               timeout_msec,
     400           0 :                               ct->session->smbXcli,
     401           0 :                               ct->smbXcli,
     402             :                               UINT64_MAX, /* in_fid_persistent */
     403             :                               UINT64_MAX, /* in_fid_volatile */
     404             :                               UINT32_MAX,
     405             :                               0, /* in_max_input_length */
     406             :                               NULL, /* in_input_buffer */
     407             :                               1, /* in_max_output_length */
     408             :                               NULL, /* in_output_buffer */
     409             :                               SMB2_IOCTL_FLAG_IS_FSCTL,
     410             :                               ct,
     411             :                               &out_input_buffer,
     412             :                               &out_output_buffer);
     413           0 :                 torture_assert(tctx,
     414             :                        smbXcli_conn_is_connected(ct->session->transport->conn),
     415             :                        "smbXcli_conn_is_connected");
     416             : 
     417           0 :                 for (pcli = 0; pcli < torture_qdepth; pcli++) {
     418           0 :                         struct test_smb2_bench_echo_loop *loop = &state->loops[li];
     419             : 
     420           0 :                         loop->idx = li++;
     421           0 :                         loop->state = state;
     422           0 :                         loop->conn = &state->conns[i];
     423           0 :                         loop->im = tevent_create_immediate(state->loops);
     424           0 :                         torture_assert(tctx, loop->im != NULL, __location__);
     425             : 
     426           0 :                         tevent_schedule_immediate(loop->im,
     427             :                                                   tctx->ev,
     428             :                                                   test_smb2_bench_echo_loop_start,
     429             :                                                   loop);
     430             :                 }
     431             :         }
     432             : 
     433           0 :         torture_comment(tctx, "Opened %zu connections with qdepth=%d => %zu loops\n",
     434             :                         state->num_conns, torture_qdepth, state->num_loops);
     435             : 
     436           0 :         torture_comment(tctx, "Running for %d seconds\n", state->timelimit);
     437             : 
     438           0 :         state->starttime = timeval_current();
     439             : 
     440           0 :         te = tevent_add_timer(tctx->ev,
     441             :                               state,
     442             :                               timeval_current_ofs(1, 0),
     443             :                               test_smb2_bench_echo_progress,
     444             :                               state);
     445           0 :         torture_assert(tctx, te != NULL, __location__);
     446             : 
     447           0 :         while (!state->stop) {
     448           0 :                 int rc = tevent_loop_once(tctx->ev);
     449           0 :                 torture_assert_int_equal(tctx, rc, 0, "tevent_loop_once");
     450             :         }
     451             : 
     452           0 :         torture_comment(tctx, "%.2f seconds\n", timeval_elapsed(&state->starttime));
     453           0 :         TALLOC_FREE(state);
     454           0 :         return ret;
     455             : }
     456             : 
     457             : /*
     458             :   test some interesting combinations found by gentest
     459             :  */
     460           2 : static bool test_create_gentest(struct torture_context *tctx, struct smb2_tree *tree)
     461             : {
     462             :         struct smb2_create io;
     463             :         NTSTATUS status;
     464             :         uint32_t access_mask, file_attributes_set;
     465             :         uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
     466             :         uint32_t not_a_directory_mask, unexpected_mask;
     467             :         union smb_fileinfo q;
     468             : 
     469           2 :         ZERO_STRUCT(io);
     470           2 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     471           2 :         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
     472           2 :         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     473           2 :         io.in.share_access = 
     474             :                 NTCREATEX_SHARE_ACCESS_DELETE|
     475             :                 NTCREATEX_SHARE_ACCESS_READ|
     476             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     477           2 :         io.in.create_options = 0;
     478           2 :         io.in.fname = FNAME;
     479             : 
     480           2 :         status = smb2_create(tree, tctx, &io);
     481           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     482             : 
     483           2 :         status = smb2_util_close(tree, io.out.file.handle);
     484           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     485             : 
     486           2 :         io.in.create_options = 0xF0000000;
     487           2 :         status = smb2_create(tree, tctx, &io);
     488           2 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     489             : 
     490           2 :         io.in.create_options = 0;
     491             : 
     492           2 :         io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
     493           2 :         status = smb2_create(tree, tctx, &io);
     494           2 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     495             : 
     496           1 :         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
     497           1 :         status = smb2_create(tree, tctx, &io);
     498           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     499             : 
     500           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
     501           1 :         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
     502           1 :         status = smb2_create(tree, tctx, &io);
     503           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     504             :         
     505           1 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
     506           1 :         io.in.desired_access = 0x08000000;
     507           1 :         status = smb2_create(tree, tctx, &io);
     508           1 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
     509             : 
     510           1 :         io.in.desired_access = 0x04000000;
     511           1 :         status = smb2_create(tree, tctx, &io);
     512           1 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
     513             : 
     514           1 :         io.in.file_attributes = 0;
     515           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     516           1 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     517           1 :         ok_mask = 0;
     518           1 :         not_supported_mask = 0;
     519           1 :         invalid_parameter_mask = 0;
     520           1 :         not_a_directory_mask = 0;
     521           1 :         unexpected_mask = 0;
     522             :         {
     523             :                 int i;
     524          33 :                 for (i=0;i<32;i++) {
     525          32 :                         io.in.create_options = (uint32_t)1<<i;
     526          32 :                         if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
     527           1 :                                 continue;
     528             :                         }
     529          31 :                         status = smb2_create(tree, tctx, &io);
     530          31 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
     531           3 :                                 not_supported_mask |= 1<<i;
     532          28 :                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
     533           8 :                                 invalid_parameter_mask |= 1<<i;
     534          20 :                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
     535           1 :                                 not_a_directory_mask |= 1<<i;
     536          19 :                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
     537          19 :                                 ok_mask |= 1<<i;
     538          19 :                                 status = smb2_util_close(tree, io.out.file.handle);
     539          19 :                                 CHECK_STATUS(status, NT_STATUS_OK);
     540             :                         } else {
     541           0 :                                 unexpected_mask |= 1<<i;
     542           0 :                                 torture_comment(tctx,
     543             :                                     "create option 0x%08x returned %s\n",
     544             :                                     1<<i, nt_errstr(status));
     545             :                         }
     546             :                 }
     547             :         }
     548           1 :         io.in.create_options = 0;
     549             : 
     550           1 :         CHECK_EQUAL(ok_mask,                0x00efcf7e);
     551           1 :         CHECK_EQUAL(not_a_directory_mask,   0x00000001);
     552           1 :         CHECK_EQUAL(not_supported_mask,     0x00102080);
     553           1 :         CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
     554           1 :         CHECK_EQUAL(unexpected_mask,        0x00000000);
     555             : 
     556           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     557           1 :         io.in.file_attributes = 0;
     558           1 :         access_mask = 0;
     559             :         {
     560             :                 int i;
     561          33 :                 for (i=0;i<32;i++) {
     562          32 :                         io.in.desired_access = (uint32_t)1<<i;
     563          32 :                         status = smb2_create(tree, tctx, &io);
     564          32 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
     565          19 :                             NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
     566          13 :                                 access_mask |= io.in.desired_access;
     567             :                         } else {
     568          19 :                                 CHECK_STATUS(status, NT_STATUS_OK);
     569          19 :                                 status = smb2_util_close(tree, io.out.file.handle);
     570          19 :                                 CHECK_STATUS(status, NT_STATUS_OK);
     571             :                         }
     572             :                 }
     573             :         }
     574             : 
     575           1 :         if (TARGET_IS_WIN7(tctx)) {
     576           0 :                 CHECK_EQUAL(access_mask, 0x0de0fe00);
     577           1 :         } else if (torture_setting_bool(tctx, "samba4", false)) {
     578           1 :                 CHECK_EQUAL(access_mask, 0x0cf0fe00);
     579             :         } else {
     580           0 :                 CHECK_EQUAL(access_mask, 0x0df0fe00);
     581             :         }
     582             : 
     583           1 :         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     584           1 :         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
     585           1 :         io.in.file_attributes = 0;
     586           1 :         ok_mask = 0;
     587           1 :         invalid_parameter_mask = 0;
     588           1 :         unexpected_mask = 0;
     589           1 :         file_attributes_set = 0;
     590             :         {
     591             :                 int i;
     592          33 :                 for (i=0;i<32;i++) {
     593          32 :                         io.in.file_attributes = (uint32_t)1<<i;
     594          32 :                         if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
     595           1 :                                 continue;
     596             :                         }
     597          31 :                         smb2_deltree(tree, FNAME);
     598          31 :                         status = smb2_create(tree, tctx, &io);
     599          31 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
     600          19 :                                 invalid_parameter_mask |= 1<<i;
     601          12 :                         } else if (NT_STATUS_IS_OK(status)) {
     602             :                                 uint32_t expected;
     603          12 :                                 ok_mask |= 1<<i;
     604             : 
     605          12 :                                 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
     606          12 :                                 io.out.file_attr &= ~FILE_ATTRIBUTE_NONINDEXED;
     607          12 :                                 CHECK_EQUAL(io.out.file_attr, expected);
     608          12 :                                 file_attributes_set |= io.out.file_attr;
     609             : 
     610          12 :                                 status = smb2_util_close(tree, io.out.file.handle);
     611          12 :                                 CHECK_STATUS(status, NT_STATUS_OK);
     612             :                         } else {
     613           0 :                                 unexpected_mask |= 1<<i;
     614           0 :                                 torture_comment(tctx,
     615             :                                     "file attribute 0x%08x returned %s\n",
     616             :                                     1<<i, nt_errstr(status));
     617             :                         }
     618             :                 }
     619             :         }
     620             : 
     621           1 :         CHECK_EQUAL(ok_mask,                0x00003fb7);
     622           1 :         CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
     623           1 :         CHECK_EQUAL(unexpected_mask,        0x00000000);
     624           1 :         CHECK_EQUAL(file_attributes_set,    0x00001127);
     625             : 
     626           1 :         smb2_deltree(tree, FNAME);
     627             : 
     628             :         /*
     629             :          * Standalone servers doesn't support encryption
     630             :          */
     631           1 :         io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
     632           1 :         status = smb2_create(tree, tctx, &io);
     633           1 :         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
     634           1 :                 torture_comment(tctx,
     635             :                     "FILE_ATTRIBUTE_ENCRYPTED returned %s\n",
     636             :                     nt_errstr(status));
     637             :         } else {
     638           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     639           0 :                 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
     640           0 :                 status = smb2_util_close(tree, io.out.file.handle);
     641           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     642             :         }
     643             : 
     644           1 :         smb2_deltree(tree, FNAME);
     645             : 
     646           1 :         ZERO_STRUCT(io);
     647           1 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     648           1 :         io.in.file_attributes    = 0;
     649           1 :         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     650           1 :         io.in.share_access = 
     651             :                 NTCREATEX_SHARE_ACCESS_READ|
     652             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     653           1 :         io.in.create_options = 0;
     654           1 :         io.in.fname = FNAME ":stream1";
     655           1 :         status = smb2_create(tree, tctx, &io);
     656           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     657             : 
     658           1 :         status = smb2_util_close(tree, io.out.file.handle);
     659           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     660             : 
     661           1 :         io.in.fname = FNAME;
     662           1 :         io.in.file_attributes = 0x8040;
     663           1 :         io.in.share_access = 
     664             :                 NTCREATEX_SHARE_ACCESS_READ;
     665           1 :         status = smb2_create(tree, tctx, &io);
     666           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     667             : 
     668           1 :         io.in.fname = FNAME;
     669           1 :         io.in.file_attributes = 0;
     670           1 :         io.in.desired_access  = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
     671           1 :         io.in.query_maximal_access = true;
     672           1 :         status = smb2_create(tree, tctx, &io);
     673           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     674           1 :         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
     675             : 
     676           1 :         q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
     677           1 :         q.access_information.in.file.handle = io.out.file.handle;
     678           1 :         status = smb2_getinfo_file(tree, tctx, &q);
     679           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     680           1 :         CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
     681             : 
     682           1 :         io.in.file_attributes = 0;
     683           1 :         io.in.desired_access  = 0;
     684           1 :         io.in.query_maximal_access = false;
     685           1 :         io.in.share_access = 0;
     686           1 :         status = smb2_create(tree, tctx, &io);
     687           1 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
     688             :         
     689           1 :         smb2_deltree(tree, FNAME);
     690             : 
     691           1 :         return true;
     692             : }
     693             : 
     694             : 
     695             : /*
     696             :   try the various request blobs
     697             :  */
     698           2 : static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tree)
     699             : {
     700             :         struct smb2_create io;
     701             :         NTSTATUS status;
     702             : 
     703           2 :         smb2_deltree(tree, FNAME);
     704             : 
     705           2 :         ZERO_STRUCT(io);
     706           2 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     707           2 :         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
     708           2 :         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     709           2 :         io.in.share_access = 
     710             :                 NTCREATEX_SHARE_ACCESS_DELETE|
     711             :                 NTCREATEX_SHARE_ACCESS_READ|
     712             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     713           2 :         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
     714             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
     715             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
     716             :                                           0x00200000;
     717           2 :         io.in.fname = FNAME;
     718             : 
     719           2 :         status = smb2_create(tree, tctx, &io);
     720           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     721             : 
     722           2 :         status = smb2_util_close(tree, io.out.file.handle);
     723           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     724             : 
     725           2 :         torture_comment(tctx, "Testing alloc size\n");
     726             :         /* FIXME We use 1M cause that's the rounded size of Samba.
     727             :          * We should ask the server for the cluser size and calulate it
     728             :          * correctly. */
     729           2 :         io.in.alloc_size = 0x00100000;
     730           2 :         status = smb2_create(tree, tctx, &io);
     731           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     732           2 :         CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
     733             : 
     734           2 :         status = smb2_util_close(tree, io.out.file.handle);
     735           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     736             : 
     737           2 :         torture_comment(tctx, "Testing durable open\n");
     738           2 :         io.in.durable_open = true;
     739           2 :         status = smb2_create(tree, tctx, &io);
     740           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     741             : 
     742           2 :         status = smb2_util_close(tree, io.out.file.handle);
     743           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     744             : 
     745           2 :         torture_comment(tctx, "Testing query maximal access\n");
     746           2 :         io.in.query_maximal_access = true;
     747           2 :         status = smb2_create(tree, tctx, &io);
     748           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     749           2 :         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
     750             : 
     751           2 :         status = smb2_util_close(tree, io.out.file.handle);
     752           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     753             : 
     754           2 :         torture_comment(tctx, "Testing timewarp\n");
     755           2 :         io.in.timewarp = 10000;
     756           2 :         status = smb2_create(tree, tctx, &io);
     757           2 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     758           1 :         io.in.timewarp = 0;
     759             : 
     760           1 :         torture_comment(tctx, "Testing query_on_disk\n");
     761           1 :         io.in.query_on_disk_id = true;
     762           1 :         status = smb2_create(tree, tctx, &io);
     763           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     764             : 
     765           1 :         status = smb2_util_close(tree, io.out.file.handle);
     766           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     767             : 
     768           1 :         torture_comment(tctx, "Testing unknown tag\n");
     769           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     770             :                                       "FooO", data_blob(NULL, 0));
     771           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     772             : 
     773           1 :         status = smb2_create(tree, tctx, &io);
     774           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     775             : 
     776           1 :         status = smb2_util_close(tree, io.out.file.handle);
     777           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     778             : 
     779           1 :         torture_comment(tctx, "Testing bad tag length 0\n");
     780           1 :         ZERO_STRUCT(io.in.blobs);
     781           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     782             :                                       "x", data_blob(NULL, 0));
     783           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     784           1 :         status = smb2_create(tree, tctx, &io);
     785           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     786             : 
     787           1 :         torture_comment(tctx, "Testing bad tag length 1\n");
     788           1 :         ZERO_STRUCT(io.in.blobs);
     789           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     790             :                                       "x", data_blob(NULL, 0));
     791           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     792           1 :         status = smb2_create(tree, tctx, &io);
     793           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     794             : 
     795           1 :         torture_comment(tctx, "Testing bad tag length 2\n");
     796           1 :         ZERO_STRUCT(io.in.blobs);
     797           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     798             :                                       "xx", data_blob(NULL, 0));
     799           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     800           1 :         status = smb2_create(tree, tctx, &io);
     801           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     802             : 
     803           1 :         torture_comment(tctx, "Testing bad tag length 3\n");
     804           1 :         ZERO_STRUCT(io.in.blobs);
     805           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     806             :                                       "xxx", data_blob(NULL, 0));
     807           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     808           1 :         status = smb2_create(tree, tctx, &io);
     809           1 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     810             : 
     811           1 :         torture_comment(tctx, "Testing tag length 4\n");
     812           1 :         ZERO_STRUCT(io.in.blobs);
     813           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     814             :                                       "xxxx", data_blob(NULL, 0));
     815           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     816           1 :         status = smb2_create(tree, tctx, &io);
     817           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     818             : 
     819           1 :         torture_comment(tctx, "Testing tag length 5\n");
     820           1 :         ZERO_STRUCT(io.in.blobs);
     821           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     822             :                                       "xxxxx", data_blob(NULL, 0));
     823           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     824           1 :         status = smb2_create(tree, tctx, &io);
     825           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     826             : 
     827           1 :         torture_comment(tctx, "Testing tag length 6\n");
     828           1 :         ZERO_STRUCT(io.in.blobs);
     829           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     830             :                                       "xxxxxx", data_blob(NULL, 0));
     831           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     832           1 :         status = smb2_create(tree, tctx, &io);
     833           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     834             : 
     835           1 :         torture_comment(tctx, "Testing tag length 7\n");
     836           1 :         ZERO_STRUCT(io.in.blobs);
     837           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     838             :                                       "xxxxxxx", data_blob(NULL, 0));
     839           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     840           1 :         status = smb2_create(tree, tctx, &io);
     841           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     842             : 
     843           1 :         torture_comment(tctx, "Testing tag length 8\n");
     844           1 :         ZERO_STRUCT(io.in.blobs);
     845           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     846             :                                       "xxxxxxxx", data_blob(NULL, 0));
     847           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     848           1 :         status = smb2_create(tree, tctx, &io);
     849           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     850             : 
     851           1 :         torture_comment(tctx, "Testing tag length 16\n");
     852           1 :         ZERO_STRUCT(io.in.blobs);
     853           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     854             :                                       "xxxxxxxxxxxxxxxx", data_blob(NULL, 0));
     855           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     856           1 :         status = smb2_create(tree, tctx, &io);
     857           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     858             : 
     859           1 :         torture_comment(tctx, "Testing tag length 17\n");
     860           1 :         ZERO_STRUCT(io.in.blobs);
     861           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     862             :                                       "xxxxxxxxxxxxxxxxx", data_blob(NULL, 0));
     863           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     864           1 :         status = smb2_create(tree, tctx, &io);
     865           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     866             : 
     867           1 :         torture_comment(tctx, "Testing tag length 34\n");
     868           1 :         ZERO_STRUCT(io.in.blobs);
     869           1 :         status = smb2_create_blob_add(tctx, &io.in.blobs,
     870             :                                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     871             :                                       data_blob(NULL, 0));
     872           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     873           1 :         status = smb2_create(tree, tctx, &io);
     874           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     875             : 
     876           1 :         smb2_deltree(tree, FNAME);
     877             :         
     878           1 :         return true;
     879             : }
     880             : 
     881             : #define FAIL_UNLESS(__cond)                                     \
     882             :         do {                                                    \
     883             :                 if (__cond) {} else {                           \
     884             :                         torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n",    \
     885             :                                __location__, #__cond);          \
     886             :                         ret = false; goto done;                 \
     887             :                 }                                               \
     888             :         } while(0)
     889             : 
     890             : /*
     891             :   try creating with acls
     892             :  */
     893           4 : static bool test_create_acl_ext(struct torture_context *tctx, struct smb2_tree *tree, bool test_dir)
     894             : {
     895           4 :         bool ret = true;
     896             :         struct smb2_create io;
     897             :         NTSTATUS status;
     898             :         struct security_ace ace;
     899             :         struct security_descriptor *sd;
     900             :         struct dom_sid *test_sid;
     901           4 :         union smb_fileinfo q = {};
     902           4 :         uint32_t attrib =
     903             :             FILE_ATTRIBUTE_HIDDEN |
     904             :             FILE_ATTRIBUTE_SYSTEM |
     905             :             (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
     906           4 :         NTSTATUS (*delete_func)(struct smb2_tree *, const char *) =
     907           4 :             test_dir ? smb2_util_rmdir : smb2_util_unlink;
     908             : 
     909           4 :         ZERO_STRUCT(ace);
     910             : 
     911           4 :         smb2_deltree(tree, FNAME);
     912             : 
     913           4 :         ZERO_STRUCT(io);
     914           4 :         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     915           4 :         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
     916           4 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
     917           4 :         io.in.share_access = 
     918             :                 NTCREATEX_SHARE_ACCESS_DELETE |
     919             :                 NTCREATEX_SHARE_ACCESS_READ |
     920             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     921           4 :         io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT | 0x00200000 |
     922             :             (test_dir ?  NTCREATEX_OPTIONS_DIRECTORY :
     923             :                 (NTCREATEX_OPTIONS_NON_DIRECTORY_FILE));
     924             : 
     925           4 :         io.in.fname = FNAME;
     926             : 
     927           4 :         torture_comment(tctx, "basic create\n");
     928             : 
     929           4 :         status = smb2_create(tree, tctx, &io);
     930           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     931             : 
     932           4 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
     933           4 :         q.query_secdesc.in.file.handle = io.out.file.handle;
     934           4 :         q.query_secdesc.in.secinfo_flags = 
     935             :                 SECINFO_OWNER |
     936             :                 SECINFO_GROUP |
     937             :                 SECINFO_DACL;
     938           4 :         status = smb2_getinfo_file(tree, tctx, &q);
     939           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     940           4 :         sd = q.query_secdesc.out.sd;
     941             : 
     942           4 :         status = smb2_util_close(tree, io.out.file.handle);
     943           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     944           4 :         status = delete_func(tree, FNAME);
     945           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     946             : 
     947           4 :         torture_comment(tctx, "adding a new ACE\n");
     948           4 :         test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS);
     949             : 
     950           4 :         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
     951           4 :         ace.flags = 0;
     952           4 :         ace.access_mask = SEC_STD_ALL;
     953           4 :         ace.trustee = *test_sid;
     954             : 
     955           4 :         status = security_descriptor_dacl_add(sd, &ace);
     956           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     957             : 
     958           4 :         torture_comment(tctx, "creating a file with an initial ACL\n");
     959             : 
     960           4 :         io.in.sec_desc = sd;
     961           4 :         status = smb2_create(tree, tctx, &io);
     962           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     963             : 
     964           4 :         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
     965             : 
     966           4 :         status = smb2_util_close(tree, io.out.file.handle);
     967           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     968           4 :         status = delete_func(tree, FNAME);
     969           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     970             : 
     971           4 :         torture_comment(tctx, "creating with attributes\n");
     972             : 
     973           4 :         io.in.sec_desc = NULL;
     974           4 :         io.in.file_attributes = attrib;
     975           4 :         status = smb2_create(tree, tctx, &io);
     976           4 :         CHECK_STATUS(status, NT_STATUS_OK);
     977             : 
     978           4 :         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
     979             : 
     980           3 :         status = smb2_util_close(tree, io.out.file.handle);
     981           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     982           3 :         status = delete_func(tree, FNAME);
     983           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     984             : 
     985           3 :         torture_comment(tctx, "creating with attributes and ACL\n");
     986             : 
     987           3 :         io.in.sec_desc = sd;
     988           3 :         io.in.file_attributes = attrib;
     989           3 :         status = smb2_create(tree, tctx, &io);
     990           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     991             : 
     992           3 :         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
     993           3 :         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
     994             :         
     995           3 :         status = smb2_util_close(tree, io.out.file.handle);
     996           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     997           3 :         status = delete_func(tree, FNAME);
     998           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     999             : 
    1000           3 :         torture_comment(tctx, "creating with attributes, ACL and owner\n");
    1001           3 :         sd = security_descriptor_dacl_create(tctx,
    1002             :                                         0, SID_WORLD, SID_BUILTIN_USERS,
    1003             :                                         SID_WORLD,
    1004             :                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
    1005             :                                         SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
    1006             :                                         0,
    1007             :                                         NULL);
    1008             : 
    1009           3 :         io.in.sec_desc = sd;
    1010           3 :         io.in.file_attributes = attrib;
    1011           3 :         status = smb2_create(tree, tctx, &io);
    1012           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1013             : 
    1014           3 :         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
    1015           3 :         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
    1016             : 
    1017           4 :  done:
    1018           4 :         status = smb2_util_close(tree, io.out.file.handle);
    1019           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1020           4 :         status = delete_func(tree, FNAME);
    1021           4 :         CHECK_STATUS(status, NT_STATUS_OK);
    1022             : 
    1023           4 :         return ret;
    1024             : }
    1025             : 
    1026             : /*
    1027             :   test SMB2 open
    1028             : */
    1029           2 : static bool test_smb2_open(struct torture_context *tctx,
    1030             :                            struct smb2_tree *tree)
    1031             : {
    1032             :         union smb_open io;
    1033             :         union smb_fileinfo finfo;
    1034           2 :         const char *fname = DNAME "\\torture_ntcreatex.txt";
    1035           2 :         const char *dname = DNAME "\\torture_ntcreatex.dir";
    1036             :         NTSTATUS status;
    1037           2 :         struct smb2_handle h = {{0}};
    1038           2 :         struct smb2_handle h1 = {{0}};
    1039           2 :         bool ret = true;
    1040             :         size_t i;
    1041             :         struct {
    1042             :                 uint32_t create_disp;
    1043             :                 bool with_file;
    1044             :                 NTSTATUS correct_status;
    1045           2 :         } open_funcs[] = {
    1046             :                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_OK },
    1047             :                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_OK },
    1048             :                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
    1049             :                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
    1050             :                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
    1051             :                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
    1052             :                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
    1053             :                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
    1054             :                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_OK },
    1055             :                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
    1056             :                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_OK },
    1057             :                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_OK },
    1058             :                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
    1059             :                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
    1060             :         };
    1061             : 
    1062           2 :         torture_comment(tctx, "Checking SMB2 Open\n");
    1063             : 
    1064           2 :         smb2_util_unlink(tree, fname);
    1065           2 :         smb2_util_rmdir(tree, dname);
    1066             : 
    1067           2 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1068           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1069             : 
    1070           2 :         ZERO_STRUCT(io.smb2);
    1071             :         /* reasonable default parameters */
    1072           2 :         io.generic.level = RAW_OPEN_SMB2;
    1073           2 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1074           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1075           2 :         io.smb2.in.alloc_size = 1024*1024;
    1076           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1077           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1078           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1079           2 :         io.smb2.in.create_options = 0;
    1080           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1081           2 :         io.smb2.in.security_flags = 0;
    1082           2 :         io.smb2.in.fname = fname;
    1083             : 
    1084             :         /* test the create disposition */
    1085          30 :         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
    1086          28 :                 if (open_funcs[i].with_file) {
    1087          14 :                         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1088          14 :                         status= smb2_create(tree, tctx, &(io.smb2));
    1089          14 :                         if (!NT_STATUS_IS_OK(status)) {
    1090           0 :                                 torture_comment(tctx,
    1091             :                                     "Failed to create file %s status %s %zu\n",
    1092             :                                     fname, nt_errstr(status), i);
    1093             : 
    1094           0 :                                 ret = false;
    1095           0 :                                 goto done;
    1096             :                         }
    1097          14 :                         smb2_util_close(tree, io.smb2.out.file.handle);
    1098             :                 }
    1099          28 :                 io.smb2.in.create_disposition = open_funcs[i].create_disp;
    1100          28 :                 status = smb2_create(tree, tctx, &(io.smb2));
    1101          28 :                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
    1102           0 :                         torture_comment(tctx,
    1103             :                             "(%s) incorrect status %s should be %s (i=%zu "
    1104             :                             "with_file=%d open_disp=%d)\n",
    1105             :                          __location__, nt_errstr(status),
    1106             :                         nt_errstr(open_funcs[i].correct_status),
    1107           0 :                         i, (int)open_funcs[i].with_file,
    1108           0 :                         (int)open_funcs[i].create_disp);
    1109             : 
    1110           0 :                         ret = false;
    1111           0 :                         goto done;
    1112             :                 }
    1113          28 :                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
    1114          22 :                         smb2_util_close(tree, io.smb2.out.file.handle);
    1115          22 :                         smb2_util_unlink(tree, fname);
    1116             :                 }
    1117             :         }
    1118             : 
    1119             :         /* basic field testing */
    1120           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1121             : 
    1122           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1123           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1124           2 :         h1 = io.smb2.out.file.handle;
    1125             : 
    1126           2 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
    1127           2 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
    1128           2 :         CHECK_NTTIME(io.smb2.out.create_time, create_time);
    1129           2 :         CHECK_NTTIME(io.smb2.out.access_time, access_time);
    1130           2 :         CHECK_NTTIME(io.smb2.out.write_time, write_time);
    1131           2 :         CHECK_NTTIME(io.smb2.out.change_time, change_time);
    1132           2 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    1133           2 :         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
    1134           2 :         CHECK_ALL_INFO(io.smb2.out.size, size);
    1135             : 
    1136             :         /* check fields when the file already existed */
    1137           2 :         smb2_util_close(tree, h1);
    1138           2 :         smb2_util_unlink(tree, fname);
    1139             : 
    1140           2 :         status = smb2_create_complex_file(tctx, tree, fname, &h1);
    1141           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1142             : 
    1143           1 :         smb2_util_close(tree, h1);
    1144             : 
    1145           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1146           1 :         status = smb2_create(tree, tctx, &(io.smb2));
    1147           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1148           1 :         h1 = io.smb2.out.file.handle;
    1149             : 
    1150           1 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
    1151           1 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_EXISTED);
    1152           1 :         CHECK_NTTIME(io.smb2.out.create_time, create_time);
    1153           1 :         CHECK_NTTIME(io.smb2.out.access_time, access_time);
    1154           1 :         CHECK_NTTIME(io.smb2.out.write_time, write_time);
    1155           1 :         CHECK_NTTIME(io.smb2.out.change_time, change_time);
    1156           1 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    1157           1 :         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
    1158           1 :         CHECK_ALL_INFO(io.smb2.out.size, size);
    1159           1 :         smb2_util_close(tree, h1);
    1160           1 :         smb2_util_unlink(tree, fname);
    1161             : 
    1162             :         /* create a directory */
    1163           1 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1164           1 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1165           1 :         io.smb2.in.alloc_size = 0;
    1166           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    1167           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1168           1 :         io.smb2.in.create_options = 0;
    1169           1 :         io.smb2.in.fname = dname;
    1170           1 :         fname = dname;
    1171             : 
    1172           1 :         smb2_util_rmdir(tree, fname);
    1173           1 :         smb2_util_unlink(tree, fname);
    1174             : 
    1175           1 :         io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    1176           1 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1177           1 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1178           1 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1179             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1180           1 :         status = smb2_create(tree, tctx, &(io.smb2));
    1181           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1182           1 :         h1 = io.smb2.out.file.handle;
    1183             : 
    1184           1 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
    1185           1 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
    1186           1 :         CHECK_NTTIME(io.smb2.out.create_time, create_time);
    1187           1 :         CHECK_NTTIME(io.smb2.out.access_time, access_time);
    1188           1 :         CHECK_NTTIME(io.smb2.out.write_time, write_time);
    1189           1 :         CHECK_NTTIME(io.smb2.out.change_time, change_time);
    1190           1 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    1191           1 :         CHECK_VAL(io.smb2.out.file_attr & ~FILE_ATTRIBUTE_NONINDEXED,
    1192             :                   FILE_ATTRIBUTE_DIRECTORY);
    1193           1 :         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
    1194           1 :         CHECK_ALL_INFO(io.smb2.out.size, size);
    1195           1 :         CHECK_VAL(io.smb2.out.size, 0);
    1196           1 :         smb2_util_unlink(tree, fname);
    1197             : 
    1198           1 : done:
    1199           1 :         smb2_util_close(tree, h1);
    1200           1 :         smb2_util_unlink(tree, fname);
    1201           1 :         smb2_deltree(tree, DNAME);
    1202           1 :         return ret;
    1203             : }
    1204             : 
    1205             : /*
    1206             :   test with an already opened and byte range locked file
    1207             : */
    1208             : 
    1209           2 : static bool test_smb2_open_brlocked(struct torture_context *tctx,
    1210             :                                     struct smb2_tree *tree)
    1211             : {
    1212             :         union smb_open io, io1;
    1213             :         union smb_lock io2;
    1214             :         struct smb2_lock_element lock[1];
    1215           2 :         const char *fname = DNAME "\\torture_ntcreatex.txt";
    1216             :         NTSTATUS status;
    1217           2 :         bool ret = true;
    1218             :         struct smb2_handle h;
    1219           2 :         char b = 42;
    1220             : 
    1221           2 :         torture_comment(tctx,
    1222             :                 "Testing SMB2 open with a byte range locked file\n");
    1223             : 
    1224           2 :         smb2_util_unlink(tree, fname);
    1225             : 
    1226           2 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1227           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1228             : 
    1229           2 :         ZERO_STRUCT(io.smb2);
    1230           2 :         io.generic.level = RAW_OPEN_SMB2;
    1231           2 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1232           2 :         io.smb2.in.desired_access = 0x2019f;
    1233           2 :         io.smb2.in.alloc_size = 0;
    1234           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1235           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1236             :                 NTCREATEX_SHARE_ACCESS_WRITE;
    1237           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1238           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
    1239           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
    1240           2 :         io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
    1241           2 :         io.smb2.in.fname = fname;
    1242             : 
    1243           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1244           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1245             : 
    1246           2 :         status = smb2_util_write(tree, io.smb2.out.file.handle, &b, 0, 1);
    1247           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1248             : 
    1249           2 :         ZERO_STRUCT(io2.smb2);
    1250           2 :         io2.smb2.level = RAW_LOCK_SMB2;
    1251           2 :         io2.smb2.in.file.handle = io.smb2.out.file.handle;
    1252           2 :         io2.smb2.in.lock_count = 1;
    1253             : 
    1254           2 :         ZERO_STRUCT(lock);
    1255           2 :         lock[0].offset = 0;
    1256           2 :         lock[0].length = 1;
    1257           2 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
    1258             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1259           2 :         io2.smb2.in.locks = &lock[0];
    1260           2 :         status = smb2_lock(tree, &(io2.smb2));
    1261           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1262             : 
    1263           2 :         ZERO_STRUCT(io1.smb2);
    1264           2 :         io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1265           2 :         io1.smb2.in.desired_access = 0x20196;
    1266           2 :         io1.smb2.in.alloc_size = 0;
    1267           2 :         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1268           2 :         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1269             :                 NTCREATEX_SHARE_ACCESS_WRITE;
    1270           2 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    1271           2 :         io1.smb2.in.create_options = 0;
    1272           2 :         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
    1273           2 :         io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
    1274           2 :         io1.smb2.in.fname = fname;
    1275             : 
    1276           2 :         status = smb2_create(tree, tctx, &(io1.smb2));
    1277           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1278             : 
    1279           2 :         smb2_util_close(tree, io.smb2.out.file.handle);
    1280           2 :         smb2_util_close(tree, io1.smb2.out.file.handle);
    1281           2 :         smb2_util_unlink(tree, fname);
    1282           2 :         smb2_deltree(tree, DNAME);
    1283             : 
    1284           2 :         return ret;
    1285             : }
    1286             : 
    1287             : /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
    1288             : 
    1289           2 : static bool test_smb2_open_multi(struct torture_context *tctx,
    1290             :                                 struct smb2_tree *tree)
    1291             : {
    1292           2 :         const char *fname = "test_oplock.dat";
    1293             :         NTSTATUS status;
    1294           2 :         bool ret = true;
    1295             :         union smb_open io;
    1296             :         struct smb2_tree **trees;
    1297             :         struct smb2_request **requests;
    1298             :         union smb_open *ios;
    1299           2 :         int i, num_files = 3;
    1300           2 :         int num_ok = 0;
    1301           2 :         int num_collision = 0;
    1302             : 
    1303           2 :         torture_comment(tctx,
    1304             :                 "Testing SMB2 Open with multiple connections\n");
    1305           2 :         trees = talloc_array(tctx, struct smb2_tree *, num_files);
    1306           2 :         requests = talloc_array(tctx, struct smb2_request *, num_files);
    1307           2 :         ios = talloc_array(tctx, union smb_open, num_files);
    1308           2 :         if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
    1309             :             (ios == NULL)) {
    1310           0 :                 torture_comment(tctx, ("talloc failed\n"));
    1311           0 :                 ret = false;
    1312           0 :                 goto done;
    1313             :         }
    1314             : 
    1315           2 :         tree->session->transport->options.request_timeout = 60;
    1316             : 
    1317           8 :         for (i=0; i<num_files; i++) {
    1318           6 :                 if (!torture_smb2_connection(tctx, &(trees[i]))) {
    1319           0 :                         torture_comment(tctx,
    1320             :                                 "Could not open %d'th connection\n", i);
    1321           0 :                         ret = false;
    1322           0 :                         goto done;
    1323             :                 }
    1324           6 :                 trees[i]->session->transport->options.request_timeout = 60;
    1325             :         }
    1326             : 
    1327             :         /* cleanup */
    1328           2 :         smb2_util_unlink(tree, fname);
    1329             : 
    1330             :         /*
    1331             :           base ntcreatex parms
    1332             :         */
    1333           2 :         ZERO_STRUCT(io.smb2);
    1334           2 :         io.generic.level = RAW_OPEN_SMB2;
    1335           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1336           2 :         io.smb2.in.alloc_size = 0;
    1337           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1338           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1339             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1340             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1341           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1342           2 :         io.smb2.in.create_options = 0;
    1343           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1344           2 :         io.smb2.in.security_flags = 0;
    1345           2 :         io.smb2.in.fname = fname;
    1346           2 :         io.smb2.in.create_flags = 0;
    1347             : 
    1348           8 :         for (i=0; i<num_files; i++) {
    1349           6 :                 ios[i] = io;
    1350           6 :                 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
    1351           6 :                 if (requests[i] == NULL) {
    1352           0 :                         torture_comment(tctx,
    1353             :                                 "could not send %d'th request\n", i);
    1354           0 :                         ret = false;
    1355           0 :                         goto done;
    1356             :                 }
    1357             :         }
    1358             : 
    1359           2 :         torture_comment(tctx, "waiting for replies\n");
    1360          24 :         while (1) {
    1361          26 :                 bool unreplied = false;
    1362          43 :                 for (i=0; i<num_files; i++) {
    1363          41 :                         if (requests[i] == NULL) {
    1364          11 :                                 continue;
    1365             :                         }
    1366          30 :                         if (requests[i]->state < SMB2_REQUEST_DONE) {
    1367          24 :                                 unreplied = true;
    1368          24 :                                 break;
    1369             :                         }
    1370           6 :                         status = smb2_create_recv(requests[i], tctx,
    1371           6 :                                                   &(ios[i].smb2));
    1372             : 
    1373           6 :                         torture_comment(tctx,
    1374             :                                 "File %d returned status %s\n", i,
    1375             :                                 nt_errstr(status));
    1376             : 
    1377           6 :                         if (NT_STATUS_IS_OK(status)) {
    1378           2 :                                 num_ok += 1;
    1379             :                         }
    1380             : 
    1381           6 :                         if (NT_STATUS_EQUAL(status,
    1382             :                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
    1383           4 :                                 num_collision += 1;
    1384             :                         }
    1385             : 
    1386           6 :                         requests[i] = NULL;
    1387             :                 }
    1388          26 :                 if (!unreplied) {
    1389           2 :                         break;
    1390             :                 }
    1391             : 
    1392          24 :                 if (tevent_loop_once(tctx->ev) != 0) {
    1393           0 :                         torture_comment(tctx, "tevent_loop_once failed\n");
    1394           0 :                         ret = false;
    1395           0 :                         goto done;
    1396             :                 }
    1397             :         }
    1398             : 
    1399           2 :         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
    1400           0 :                 ret = false;
    1401             :         }
    1402           2 : done:
    1403           2 :         smb2_deltree(tree, fname);
    1404             : 
    1405           2 :         return ret;
    1406             : }
    1407             : 
    1408             : /*
    1409             :   test opening for delete on a read-only attribute file.
    1410             : */
    1411             : 
    1412           2 : static bool test_smb2_open_for_delete(struct torture_context *tctx,
    1413             :                                       struct smb2_tree *tree)
    1414             : {
    1415             :         union smb_open io;
    1416             :         union smb_fileinfo finfo;
    1417           2 :         const char *fname = DNAME "\\torture_open_for_delete.txt";
    1418             :         NTSTATUS status;
    1419             :         struct smb2_handle h, h1;
    1420           2 :         bool ret = true;
    1421             : 
    1422           2 :         torture_comment(tctx,
    1423             :                 "Checking SMB2_OPEN for delete on a readonly file.\n");
    1424           2 :         smb2_util_unlink(tree, fname);
    1425           2 :         smb2_deltree(tree, fname);
    1426             : 
    1427           2 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1428           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1429             : 
    1430             :         /* reasonable default parameters */
    1431           2 :         ZERO_STRUCT(io.smb2);
    1432           2 :         io.generic.level = RAW_OPEN_SMB2;
    1433           2 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1434           2 :         io.smb2.in.alloc_size = 0;
    1435           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1436           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY;
    1437           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1438           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1439           2 :         io.smb2.in.create_options = 0;
    1440           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1441           2 :         io.smb2.in.security_flags = 0;
    1442           2 :         io.smb2.in.fname = fname;
    1443             : 
    1444             :         /* Create the readonly file. */
    1445             : 
    1446           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1447           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1448           2 :         h1 = io.smb2.out.file.handle;
    1449             : 
    1450           2 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
    1451           2 :         io.smb2.in.create_options = 0;
    1452           2 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
    1453           2 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    1454           2 :         smb2_util_close(tree, h1);
    1455             : 
    1456             :         /* Now try and open for delete only - should succeed. */
    1457           2 :         io.smb2.in.desired_access = SEC_STD_DELETE;
    1458           2 :         io.smb2.in.file_attributes = 0;
    1459           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1460             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1461             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1462           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1463           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1464           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1465           2 :         smb2_util_close(tree, io.smb2.out.file.handle);
    1466             : 
    1467             :         /* Clear readonly flag to allow file deletion */
    1468           2 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1469             :                                 SEC_FILE_WRITE_ATTRIBUTE;
    1470           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1471           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1472           2 :         h1 = io.smb2.out.file.handle;
    1473           2 :         SET_ATTRIB(FILE_ATTRIBUTE_ARCHIVE);
    1474           2 :         smb2_util_close(tree, h1);
    1475             : 
    1476           2 :         smb2_util_close(tree, h);
    1477           2 :         smb2_util_unlink(tree, fname);
    1478           2 :         smb2_deltree(tree, DNAME);
    1479             : 
    1480           2 :         return ret;
    1481             : }
    1482             : 
    1483             : /*
    1484             :   test SMB2 open with a leading slash on the path.
    1485             :   Trying to create a directory with a leading slash
    1486             :   should give NT_STATUS_INVALID_PARAMETER error
    1487             : */
    1488           2 : static bool test_smb2_leading_slash(struct torture_context *tctx,
    1489             :                                     struct smb2_tree *tree)
    1490             : {
    1491             :         union smb_open io;
    1492           2 :         const char *dnameslash = "\\"DNAME;
    1493             :         NTSTATUS status;
    1494           2 :         bool ret = true;
    1495             : 
    1496           2 :         torture_comment(tctx,
    1497             :                 "Trying to create a directory with leading slash on path\n");
    1498           2 :         smb2_deltree(tree, dnameslash);
    1499             : 
    1500           2 :         ZERO_STRUCT(io.smb2);
    1501           2 :         io.generic.level = RAW_OPEN_SMB2;
    1502           2 :         io.smb2.in.oplock_level = 0;
    1503           2 :         io.smb2.in.desired_access = SEC_RIGHTS_DIR_ALL;
    1504           2 :         io.smb2.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
    1505           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1506           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1507             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1508             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1509           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1510           2 :         io.smb2.in.fname = dnameslash;
    1511             : 
    1512           2 :         status = smb2_create(tree, tree, &(io.smb2));
    1513           2 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1514             : 
    1515           2 :         smb2_deltree(tree, dnameslash);
    1516           2 :         return ret;
    1517             : }
    1518             : 
    1519             : /*
    1520             :   test SMB2 open with an invalid impersonation level.
    1521             :   Should give NT_STATUS_BAD_IMPERSONATION_LEVEL error
    1522             : */
    1523           2 : static bool test_smb2_impersonation_level(struct torture_context *tctx,
    1524             :                                     struct smb2_tree *tree)
    1525             : {
    1526             :         union smb_open io;
    1527           2 :         const char *fname = DNAME "\\torture_invalid_impersonation_level.txt";
    1528             :         NTSTATUS status;
    1529             :         struct smb2_handle h;
    1530           2 :         bool ret = true;
    1531             : 
    1532           2 :         torture_comment(tctx,
    1533             :                 "Testing SMB2 open with an invalid impersonation level.\n");
    1534             : 
    1535           2 :         smb2_util_unlink(tree, fname);
    1536           2 :         smb2_util_rmdir(tree, DNAME);
    1537             : 
    1538           2 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1539           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1540             : 
    1541           2 :         ZERO_STRUCT(io.smb2);
    1542           2 :         io.generic.level = RAW_OPEN_SMB2;
    1543           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1544           2 :         io.smb2.in.alloc_size = 0;
    1545           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1546           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1547             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1548             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1549           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1550           2 :         io.smb2.in.create_options = 0;
    1551           2 :         io.smb2.in.impersonation_level = 0x12345678;
    1552           2 :         io.smb2.in.security_flags = 0;
    1553           2 :         io.smb2.in.fname = fname;
    1554           2 :         io.smb2.in.create_flags = 0;
    1555             : 
    1556           2 :         status = smb2_create(tree, tree, &(io.smb2));
    1557           2 :         CHECK_STATUS(status, NT_STATUS_BAD_IMPERSONATION_LEVEL);
    1558             : 
    1559           1 :         smb2_util_close(tree, h);
    1560           1 :         smb2_util_unlink(tree, fname);
    1561           1 :         smb2_deltree(tree, DNAME);
    1562           1 :         return ret;
    1563             : }
    1564             : 
    1565           2 : static bool test_create_acl_file(struct torture_context *tctx,
    1566             :     struct smb2_tree *tree)
    1567             : {
    1568           2 :         torture_comment(tctx, "Testing nttrans create with sec_desc on files\n");
    1569             : 
    1570           2 :         return test_create_acl_ext(tctx, tree, false);
    1571             : }
    1572             : 
    1573           2 : static bool test_create_acl_dir(struct torture_context *tctx,
    1574             :     struct smb2_tree *tree)
    1575             : {
    1576           2 :         torture_comment(tctx, "Testing nttrans create with sec_desc on directories\n");
    1577             : 
    1578           2 :         return test_create_acl_ext(tctx, tree, true);
    1579             : }
    1580             : 
    1581             : #define CHECK_ACCESS_FLAGS(_fh, flags) do { \
    1582             :         union smb_fileinfo _q; \
    1583             :         _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
    1584             :         _q.access_information.in.file.handle = (_fh); \
    1585             :         status = smb2_getinfo_file(tree, tctx, &_q); \
    1586             :         CHECK_STATUS(status, NT_STATUS_OK); \
    1587             :         if (_q.access_information.out.access_flags != (flags)) { \
    1588             :                 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
    1589             :                        __location__, _q.access_information.out.access_flags, (flags)); \
    1590             :                 ret = false; \
    1591             :                 goto done; \
    1592             :         } \
    1593             : } while (0)
    1594             : 
    1595             : /*
    1596             :  * Test creating a file with a NULL DACL.
    1597             :  */
    1598           2 : static bool test_create_null_dacl(struct torture_context *tctx,
    1599             :     struct smb2_tree *tree)
    1600             : {
    1601             :         NTSTATUS status;
    1602             :         struct smb2_create io;
    1603           2 :         const char *fname = "nulldacl.txt";
    1604           2 :         bool ret = true;
    1605             :         struct smb2_handle handle;
    1606             :         union smb_fileinfo q;
    1607             :         union smb_setfileinfo s;
    1608           2 :         struct security_descriptor *sd = security_descriptor_initialise(tctx);
    1609             :         struct security_acl dacl;
    1610             : 
    1611           2 :         torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n");
    1612             : 
    1613           2 :         smb2_util_unlink(tree, fname);
    1614             : 
    1615           2 :         ZERO_STRUCT(io);
    1616           2 :         io.level = RAW_OPEN_SMB2;
    1617           2 :         io.in.create_flags = 0;
    1618           2 :         io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC
    1619             :                 | SEC_STD_WRITE_OWNER;
    1620           2 :         io.in.create_options = 0;
    1621           2 :         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1622           2 :         io.in.share_access =
    1623             :                 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
    1624           2 :         io.in.alloc_size = 0;
    1625           2 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
    1626           2 :         io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
    1627           2 :         io.in.security_flags = 0;
    1628           2 :         io.in.fname = fname;
    1629           2 :         io.in.sec_desc = sd;
    1630             :         /* XXX create_options ? */
    1631           2 :         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1632             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
    1633             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1634             :                                           0x00200000;
    1635             : 
    1636           2 :         torture_comment(tctx, "creating a file with a empty sd\n");
    1637           2 :         status = smb2_create(tree, tctx, &io);
    1638           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1639           2 :         handle = io.out.file.handle;
    1640             : 
    1641           2 :         torture_comment(tctx, "get the original sd\n");
    1642           2 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1643           2 :         q.query_secdesc.in.file.handle = handle;
    1644           2 :         q.query_secdesc.in.secinfo_flags =
    1645             :                 SECINFO_OWNER |
    1646             :                 SECINFO_GROUP |
    1647             :                 SECINFO_DACL;
    1648           2 :         status = smb2_getinfo_file(tree, tctx, &q);
    1649           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1650             : 
    1651             :         /*
    1652             :          * Testing the created DACL,
    1653             :          * the server should add the inherited DACL
    1654             :          * when SEC_DESC_DACL_PRESENT isn't specified
    1655             :          */
    1656           2 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1657           0 :                 ret = false;
    1658           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1659             :         }
    1660           2 :         if (q.query_secdesc.out.sd->dacl == NULL) {
    1661           0 :                 ret = false;
    1662           0 :                 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
    1663             :         }
    1664             : 
    1665           2 :         torture_comment(tctx, "set NULL DACL\n");
    1666           2 :         sd->type |= SEC_DESC_DACL_PRESENT;
    1667             : 
    1668           2 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1669           2 :         s.set_secdesc.in.file.handle = handle;
    1670           2 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1671           2 :         s.set_secdesc.in.sd = sd;
    1672           2 :         status = smb2_setinfo_file(tree, &s);
    1673           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1674             : 
    1675           2 :         torture_comment(tctx, "get the sd\n");
    1676           2 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1677           2 :         q.query_secdesc.in.file.handle = handle;
    1678           2 :         q.query_secdesc.in.secinfo_flags =
    1679             :                 SECINFO_OWNER |
    1680             :                 SECINFO_GROUP |
    1681             :                 SECINFO_DACL;
    1682           2 :         status = smb2_getinfo_file(tree, tctx, &q);
    1683           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1684             : 
    1685             :         /* Testing the modified DACL */
    1686           2 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1687           0 :                 ret = false;
    1688           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1689             :         }
    1690           2 :         if (q.query_secdesc.out.sd->dacl != NULL) {
    1691           0 :                 ret = false;
    1692           0 :                 torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
    1693             :         }
    1694             : 
    1695           2 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    1696             : 
    1697           2 :         torture_comment(tctx, "try open for read control\n");
    1698           2 :         io.in.desired_access = SEC_STD_READ_CONTROL;
    1699           2 :         status = smb2_create(tree, tctx, &io);
    1700           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1701           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1702             :                 SEC_STD_READ_CONTROL);
    1703           2 :         smb2_util_close(tree, io.out.file.handle);
    1704             : 
    1705           2 :         torture_comment(tctx, "try open for write\n");
    1706           2 :         io.in.desired_access = SEC_FILE_WRITE_DATA;
    1707           2 :         status = smb2_create(tree, tctx, &io);
    1708           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1709           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1710             :                 SEC_FILE_WRITE_DATA);
    1711           2 :         smb2_util_close(tree, io.out.file.handle);
    1712             : 
    1713           2 :         torture_comment(tctx, "try open for read\n");
    1714           2 :         io.in.desired_access = SEC_FILE_READ_DATA;
    1715           2 :         status = smb2_create(tree, tctx, &io);
    1716           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1717           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1718             :                 SEC_FILE_READ_DATA);
    1719           2 :         smb2_util_close(tree, io.out.file.handle);
    1720             : 
    1721           2 :         torture_comment(tctx, "try open for generic write\n");
    1722           2 :         io.in.desired_access = SEC_GENERIC_WRITE;
    1723           2 :         status = smb2_create(tree, tctx, &io);
    1724           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1725           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1726             :                 SEC_RIGHTS_FILE_WRITE);
    1727           2 :         smb2_util_close(tree, io.out.file.handle);
    1728             : 
    1729           2 :         torture_comment(tctx, "try open for generic read\n");
    1730           2 :         io.in.desired_access = SEC_GENERIC_READ;
    1731           2 :         status = smb2_create(tree, tctx, &io);
    1732           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1733           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1734             :                 SEC_RIGHTS_FILE_READ);
    1735           2 :         smb2_util_close(tree, io.out.file.handle);
    1736             : 
    1737           2 :         torture_comment(tctx, "set DACL with 0 aces\n");
    1738           2 :         ZERO_STRUCT(dacl);
    1739           2 :         dacl.revision = SECURITY_ACL_REVISION_NT4;
    1740           2 :         dacl.num_aces = 0;
    1741           2 :         sd->dacl = &dacl;
    1742             : 
    1743           2 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1744           2 :         s.set_secdesc.in.file.handle = handle;
    1745           2 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1746           2 :         s.set_secdesc.in.sd = sd;
    1747           2 :         status = smb2_setinfo_file(tree, &s);
    1748           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1749             : 
    1750           2 :         torture_comment(tctx, "get the sd\n");
    1751           2 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1752           2 :         q.query_secdesc.in.file.handle = handle;
    1753           2 :         q.query_secdesc.in.secinfo_flags =
    1754             :                 SECINFO_OWNER |
    1755             :                 SECINFO_GROUP |
    1756             :                 SECINFO_DACL;
    1757           2 :         status = smb2_getinfo_file(tree, tctx, &q);
    1758           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1759             : 
    1760             :         /* Testing the modified DACL */
    1761           2 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1762           0 :                 ret = false;
    1763           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1764             :         }
    1765           2 :         if (q.query_secdesc.out.sd->dacl == NULL) {
    1766           0 :                 ret = false;
    1767           0 :                 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
    1768             :         }
    1769           2 :         if (q.query_secdesc.out.sd->dacl->num_aces != 0) {
    1770           0 :                 torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n",
    1771           0 :                        q.query_secdesc.out.sd->dacl->num_aces);
    1772           0 :                 ret = false;
    1773           0 :                 goto done;
    1774             :         }
    1775             : 
    1776           2 :         torture_comment(tctx, "try open for read control\n");
    1777           2 :         io.in.desired_access = SEC_STD_READ_CONTROL;
    1778           2 :         status = smb2_create(tree, tctx, &io);
    1779           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1780           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1781             :                 SEC_STD_READ_CONTROL);
    1782           2 :         smb2_util_close(tree, io.out.file.handle);
    1783             : 
    1784           2 :         torture_comment(tctx, "try open for write => access_denied\n");
    1785           2 :         io.in.desired_access = SEC_FILE_WRITE_DATA;
    1786           2 :         status = smb2_create(tree, tctx, &io);
    1787           2 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1788           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1789             :         } else {
    1790           2 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1791             :         }
    1792             : 
    1793           2 :         torture_comment(tctx, "try open for read => access_denied\n");
    1794           2 :         io.in.desired_access = SEC_FILE_READ_DATA;
    1795           2 :         status = smb2_create(tree, tctx, &io);
    1796           2 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1797           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1798             :         } else {
    1799           2 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1800             :         }
    1801             : 
    1802           2 :         torture_comment(tctx, "try open for generic write => access_denied\n");
    1803           2 :         io.in.desired_access = SEC_GENERIC_WRITE;
    1804           2 :         status = smb2_create(tree, tctx, &io);
    1805           2 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1806           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1807             :         } else {
    1808           2 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1809             :         }
    1810             : 
    1811           2 :         torture_comment(tctx, "try open for generic read => access_denied\n");
    1812           2 :         io.in.desired_access = SEC_GENERIC_READ;
    1813           2 :         status = smb2_create(tree, tctx, &io);
    1814           2 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1815           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1816             :         } else {
    1817           2 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1818             :         }
    1819             : 
    1820           2 :         torture_comment(tctx, "set empty sd\n");
    1821           2 :         sd->type &= ~SEC_DESC_DACL_PRESENT;
    1822           2 :         sd->dacl = NULL;
    1823             : 
    1824           2 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1825           2 :         s.set_secdesc.in.file.handle = handle;
    1826           2 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1827           2 :         s.set_secdesc.in.sd = sd;
    1828           2 :         status = smb2_setinfo_file(tree, &s);
    1829           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1830             : 
    1831           2 :         torture_comment(tctx, "get the sd\n");
    1832           2 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1833           2 :         q.query_secdesc.in.file.handle = handle;
    1834           2 :         q.query_secdesc.in.secinfo_flags =
    1835             :                 SECINFO_OWNER |
    1836             :                 SECINFO_GROUP |
    1837             :                 SECINFO_DACL;
    1838           2 :         status = smb2_getinfo_file(tree, tctx, &q);
    1839           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1840             : 
    1841             :         /* Testing the modified DACL */
    1842           2 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1843           0 :                 ret = false;
    1844           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1845             :         }
    1846           2 :         if (q.query_secdesc.out.sd->dacl != NULL) {
    1847           0 :                 ret = false;
    1848           0 :                 torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
    1849             :         }
    1850           2 : done:
    1851           2 :         smb2_util_close(tree, handle);
    1852           2 :         smb2_util_unlink(tree, fname);
    1853           2 :         smb2_tdis(tree);
    1854           2 :         smb2_logoff(tree->session);
    1855           2 :         return ret;
    1856             : }
    1857             : 
    1858             : /*
    1859             :   test SMB2 mkdir with OPEN_IF on the same name twice.
    1860             :   Must use 2 connections to hit the race.
    1861             : */
    1862             : 
    1863           2 : static bool test_mkdir_dup(struct torture_context *tctx,
    1864             :                                 struct smb2_tree *tree)
    1865             : {
    1866           2 :         const char *fname = "mkdir_dup";
    1867             :         NTSTATUS status;
    1868           2 :         bool ret = true;
    1869             :         union smb_open io;
    1870             :         struct smb2_tree **trees;
    1871             :         struct smb2_request **requests;
    1872             :         union smb_open *ios;
    1873           2 :         int i, num_files = 2;
    1874           2 :         int num_ok = 0;
    1875           2 :         int num_created = 0;
    1876           2 :         int num_existed = 0;
    1877             : 
    1878           2 :         torture_comment(tctx,
    1879             :                 "Testing SMB2 Create Directory with multiple connections\n");
    1880           2 :         trees = talloc_array(tctx, struct smb2_tree *, num_files);
    1881           2 :         requests = talloc_array(tctx, struct smb2_request *, num_files);
    1882           2 :         ios = talloc_array(tctx, union smb_open, num_files);
    1883           2 :         if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
    1884             :             (ios == NULL)) {
    1885           0 :                 torture_fail(tctx, ("talloc failed\n"));
    1886             :                 ret = false;
    1887             :                 goto done;
    1888             :         }
    1889             : 
    1890           2 :         tree->session->transport->options.request_timeout = 60;
    1891             : 
    1892           6 :         for (i=0; i<num_files; i++) {
    1893           4 :                 if (!torture_smb2_connection(tctx, &(trees[i]))) {
    1894           0 :                         torture_fail(tctx,
    1895             :                                 talloc_asprintf(tctx,
    1896             :                                         "Could not open %d'th connection\n", i));
    1897             :                         ret = false;
    1898             :                         goto done;
    1899             :                 }
    1900           4 :                 trees[i]->session->transport->options.request_timeout = 60;
    1901             :         }
    1902             : 
    1903             :         /* cleanup */
    1904           2 :         smb2_util_unlink(tree, fname);
    1905           2 :         smb2_util_rmdir(tree, fname);
    1906             : 
    1907             :         /*
    1908             :           base ntcreatex parms
    1909             :         */
    1910           2 :         ZERO_STRUCT(io.smb2);
    1911           2 :         io.generic.level = RAW_OPEN_SMB2;
    1912           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1913           2 :         io.smb2.in.alloc_size = 0;
    1914           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1915           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1916             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1917             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1918           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1919           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1920           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1921           2 :         io.smb2.in.security_flags = 0;
    1922           2 :         io.smb2.in.fname = fname;
    1923           2 :         io.smb2.in.create_flags = 0;
    1924             : 
    1925           6 :         for (i=0; i<num_files; i++) {
    1926           4 :                 ios[i] = io;
    1927           4 :                 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
    1928           4 :                 if (requests[i] == NULL) {
    1929           0 :                         torture_fail(tctx,
    1930             :                                 talloc_asprintf(tctx,
    1931             :                                 "could not send %d'th request\n", i));
    1932             :                         ret = false;
    1933             :                         goto done;
    1934             :                 }
    1935             :         }
    1936             : 
    1937           2 :         torture_comment(tctx, "waiting for replies\n");
    1938          16 :         while (1) {
    1939          18 :                 bool unreplied = false;
    1940          28 :                 for (i=0; i<num_files; i++) {
    1941          26 :                         if (requests[i] == NULL) {
    1942           6 :                                 continue;
    1943             :                         }
    1944          20 :                         if (requests[i]->state < SMB2_REQUEST_DONE) {
    1945          16 :                                 unreplied = true;
    1946          16 :                                 break;
    1947             :                         }
    1948           4 :                         status = smb2_create_recv(requests[i], tctx,
    1949           4 :                                                   &(ios[i].smb2));
    1950             : 
    1951           4 :                         if (NT_STATUS_IS_OK(status)) {
    1952           4 :                                 num_ok += 1;
    1953             : 
    1954           4 :                                 if (ios[i].smb2.out.create_action ==
    1955             :                                                 NTCREATEX_ACTION_CREATED) {
    1956           2 :                                         num_created++;
    1957             :                                 }
    1958           4 :                                 if (ios[i].smb2.out.create_action ==
    1959             :                                                 NTCREATEX_ACTION_EXISTED) {
    1960           2 :                                         num_existed++;
    1961             :                                 }
    1962             :                         } else {
    1963           0 :                                 torture_fail(tctx,
    1964             :                                         talloc_asprintf(tctx,
    1965             :                                         "File %d returned status %s\n", i,
    1966             :                                         nt_errstr(status)));
    1967             :                         }
    1968             : 
    1969             : 
    1970           4 :                         requests[i] = NULL;
    1971             :                 }
    1972          18 :                 if (!unreplied) {
    1973           2 :                         break;
    1974             :                 }
    1975             : 
    1976          16 :                 if (tevent_loop_once(tctx->ev) != 0) {
    1977           0 :                         torture_fail(tctx, "tevent_loop_once failed\n");
    1978             :                         ret = false;
    1979             :                         goto done;
    1980             :                 }
    1981             :         }
    1982             : 
    1983           2 :         if (num_ok != 2) {
    1984           0 :                 torture_fail(tctx,
    1985             :                         talloc_asprintf(tctx,
    1986             :                         "num_ok == %d\n", num_ok));
    1987             :                 ret = false;
    1988             :         }
    1989           2 :         if (num_created != 1) {
    1990           0 :                 torture_fail(tctx,
    1991             :                         talloc_asprintf(tctx,
    1992             :                         "num_created == %d\n", num_created));
    1993             :                 ret = false;
    1994             :         }
    1995           2 :         if (num_existed != 1) {
    1996           0 :                 torture_fail(tctx,
    1997             :                         talloc_asprintf(tctx,
    1998             :                         "num_existed == %d\n", num_existed));
    1999             :                 ret = false;
    2000             :         }
    2001           2 : done:
    2002           2 :         smb2_deltree(tree, fname);
    2003             : 
    2004           2 :         return ret;
    2005             : }
    2006             : 
    2007             : /*
    2008             :   test directory creation with an initial allocation size > 0
    2009             : */
    2010           2 : static bool test_dir_alloc_size(struct torture_context *tctx,
    2011             :                                 struct smb2_tree *tree)
    2012             : {
    2013           2 :         bool ret = true;
    2014           2 :         const char *dname = DNAME "\\torture_alloc_size.dir";
    2015             :         NTSTATUS status;
    2016             :         struct smb2_create c;
    2017           2 :         struct smb2_handle h1 = {{0}}, h2;
    2018             : 
    2019           2 :         torture_comment(tctx, "Checking initial allocation size on directories\n");
    2020             : 
    2021           2 :         smb2_deltree(tree, dname);
    2022             : 
    2023           2 :         status = torture_smb2_testdir(tree, DNAME, &h1);
    2024           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
    2025             : 
    2026           2 :         ZERO_STRUCT(c);
    2027           2 :         c.in.create_disposition = NTCREATEX_DISP_CREATE;
    2028           2 :         c.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    2029           2 :         c.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    2030           2 :         c.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2031           2 :         c.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2032           2 :         c.in.fname = dname;
    2033             :         /*
    2034             :          * An insanely large value so we can check the value is
    2035             :          * ignored: Samba either returns 0 (current behaviour), or,
    2036             :          * once vfswrap_get_alloc_size() is fixed to allow retrieving
    2037             :          * the allocated size for directories, returns
    2038             :          * smb_roundup(..., stat.st_size) which would be 1 MB by
    2039             :          * default.
    2040             :          *
    2041             :          * Windows returns 0 for empty directories, once directories
    2042             :          * have a few entries it starts replying with values > 0.
    2043             :          */
    2044           2 :         c.in.alloc_size = 1024*1024*1024;
    2045             : 
    2046           2 :         status = smb2_create(tree, tctx, &c);
    2047           2 :         h2 = c.out.file.handle;
    2048           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2049             :                                         "dir create with initial alloc size failed");
    2050             : 
    2051           2 :         smb2_util_close(tree, h2);
    2052             : 
    2053           2 :         torture_comment(tctx, "Got directory alloc size: %ju\n", (uintmax_t)c.out.alloc_size);
    2054             : 
    2055             :         /*
    2056             :          * See above for the rational for this test
    2057             :          */
    2058           2 :         if (c.out.alloc_size > 1024*1024) {
    2059           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "bad alloc size: %ju",
    2060             :                                                               (uintmax_t)c.out.alloc_size));
    2061             :         }
    2062             : 
    2063           2 : done:
    2064           2 :         if (!smb2_util_handle_empty(h1)) {
    2065           2 :                 smb2_util_close(tree, h1);
    2066             :         }
    2067           2 :         smb2_deltree(tree, DNAME);
    2068           2 :         return ret;
    2069             : }
    2070             : 
    2071           0 : static bool test_twrp_write(struct torture_context *tctx, struct smb2_tree *tree)
    2072             : {
    2073             :         struct smb2_create io;
    2074           0 :         struct smb2_handle h1 = {{0}};
    2075             :         NTSTATUS status;
    2076           0 :         bool ret = true;
    2077           0 :         char *p = NULL;
    2078             :         struct tm tm;
    2079             :         time_t t;
    2080             :         uint64_t nttime;
    2081           0 :         const char *file = NULL;
    2082           0 :         const char *snapshot = NULL;
    2083             :         uint32_t expected_access;
    2084             :         union smb_fileinfo getinfo;
    2085             :         union smb_setfileinfo setinfo;
    2086           0 :         struct security_descriptor *sd = NULL, *sd_orig = NULL;
    2087           0 :         const char *owner_sid = NULL;
    2088             :         struct create_disps_tests {
    2089             :                 const char *file;
    2090             :                 uint32_t create_disposition;
    2091             :                 uint32_t create_options;
    2092             :                 NTSTATUS expected_status;
    2093             :         };
    2094           0 :         struct create_disps_tests *cd_test = NULL;
    2095             : 
    2096           0 :         file = torture_setting_string(tctx, "twrp_file", NULL);
    2097           0 :         if (file == NULL) {
    2098           0 :                 torture_skip(tctx, "missing 'twrp_file' option\n");
    2099             :         }
    2100             : 
    2101           0 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2102           0 :         if (snapshot == NULL) {
    2103           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    2104             :         }
    2105             : 
    2106           0 :         torture_comment(tctx, "Testing timewarp (%s) (%s)\n", file, snapshot);
    2107             : 
    2108           0 :         setenv("TZ", "GMT", 1);
    2109             : 
    2110             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2111             :          * effect if it is greather than 1. */
    2112           0 :         ZERO_STRUCT(tm);
    2113             : 
    2114           0 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2115           0 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2116           0 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2117             : 
    2118           0 :         t = mktime(&tm);
    2119           0 :         unix_to_nt_time(&nttime, t);
    2120             : 
    2121           0 :         io = (struct smb2_create) {
    2122             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2123             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2124             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2125             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2126             :                 .in.fname = file,
    2127             :                 .in.query_maximal_access = true,
    2128             :                 .in.timewarp = nttime,
    2129             :         };
    2130             : 
    2131           0 :         status = smb2_create(tree, tctx, &io);
    2132           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2133             :                                         "smb2_create\n");
    2134           0 :         smb2_util_close(tree, io.out.file.handle);
    2135             : 
    2136           0 :         expected_access = SEC_RIGHTS_FILE_ALL &
    2137             :                                 ~(SEC_FILE_EXECUTE | SEC_DIR_DELETE_CHILD);
    2138             : 
    2139           0 :         torture_assert_int_equal_goto(tctx,
    2140             :                                       io.out.maximal_access & expected_access,
    2141             :                                       expected_access,
    2142             :                                       ret, done, "Bad access\n");
    2143             : 
    2144             :         {
    2145             :                 /*
    2146             :                  * Test create dispositions
    2147             :                  */
    2148           0 :                 struct create_disps_tests cd_tests[] = {
    2149             :                         {
    2150             :                                 .file = file,
    2151             :                                 .create_disposition = NTCREATEX_DISP_OPEN,
    2152             :                                 .expected_status = NT_STATUS_OK,
    2153             :                         },
    2154             :                         {
    2155             :                                 .file = file,
    2156             :                                 .create_disposition = NTCREATEX_DISP_OPEN_IF,
    2157             :                                 .expected_status = NT_STATUS_OK,
    2158             :                         },
    2159             :                         {
    2160             :                                 .file = file,
    2161             :                                 .create_disposition = NTCREATEX_DISP_OVERWRITE,
    2162             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2163             :                         },
    2164             :                         {
    2165             :                                 .file = file,
    2166             :                                 .create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
    2167             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2168             :                         },
    2169             :                         {
    2170             :                                 .file = file,
    2171             :                                 .create_disposition = NTCREATEX_DISP_SUPERSEDE,
    2172             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2173             :                         },
    2174             :                         {
    2175             :                                 .file = "newfile",
    2176             :                                 .create_disposition = NTCREATEX_DISP_OPEN_IF,
    2177             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2178             :                         },
    2179             :                         {
    2180             :                                 .file = "newfile",
    2181             :                                 .create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
    2182             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2183             :                         },
    2184             :                         {
    2185             :                                 .file = "newfile",
    2186             :                                 .create_disposition = NTCREATEX_DISP_CREATE,
    2187             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2188             :                         },
    2189             :                         {
    2190             :                                 .file = "newfile",
    2191             :                                 .create_disposition = NTCREATEX_DISP_SUPERSEDE,
    2192             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2193             :                         },
    2194             :                         {
    2195             :                                 .file = "newdir",
    2196             :                                 .create_disposition = NTCREATEX_DISP_OPEN_IF,
    2197             :                                 .create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2198             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2199             :                         },
    2200             :                         {
    2201             :                                 .file = "newdir",
    2202             :                                 .create_disposition = NTCREATEX_DISP_CREATE,
    2203             :                                 .create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2204             :                                 .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
    2205             :                         },
    2206             :                         {
    2207             :                                 .file = NULL,
    2208             :                         },
    2209             :                 };
    2210             : 
    2211           0 :                 for (cd_test = &cd_tests[0]; cd_test->file != NULL; cd_test++) {
    2212           0 :                         io = (struct smb2_create) {
    2213           0 :                                 .in.fname = cd_test->file,
    2214           0 :                                 .in.create_disposition = cd_test->create_disposition,
    2215           0 :                                 .in.create_options = cd_test->create_options,
    2216             : 
    2217             :                                 .in.desired_access = SEC_FILE_READ_DATA,
    2218             :                                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2219             :                                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2220             :                                 .in.timewarp = nttime,
    2221             :                         };
    2222             : 
    2223           0 :                         status = smb2_create(tree, tctx, &io);
    2224           0 :                         torture_assert_ntstatus_equal_goto(
    2225             :                                 tctx, status, cd_test->expected_status, ret, done,
    2226             :                                 "Bad status\n");
    2227             :                 }
    2228             :         }
    2229             : 
    2230           0 :         io = (struct smb2_create) {
    2231             :                 .in.desired_access = expected_access,
    2232             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2233             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2234             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2235             :                 .in.fname = file,
    2236             :                 .in.timewarp = nttime,
    2237             :         };
    2238             : 
    2239           0 :         status = smb2_create(tree, tctx, &io);
    2240           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2241             :                                         "smb2_create\n");
    2242           0 :         h1 = io.out.file.handle;
    2243             : 
    2244           0 :         status = smb2_util_write(tree, h1, "123", 0, 3);
    2245           0 :         torture_assert_ntstatus_equal_goto(tctx, status,
    2246             :                                            NT_STATUS_MEDIA_WRITE_PROTECTED,
    2247             :                                            ret, done, "smb2_create\n");
    2248             : 
    2249             :         /*
    2250             :          * Verify access mask
    2251             :          */
    2252             : 
    2253           0 :         ZERO_STRUCT(getinfo);
    2254           0 :         getinfo.generic.level = RAW_FILEINFO_ACCESS_INFORMATION;
    2255           0 :         getinfo.generic.in.file.handle = h1;
    2256             : 
    2257           0 :         status = smb2_getinfo_file(tree, tree, &getinfo);
    2258           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2259             :                                         "smb2_getinfo_file\n");
    2260             : 
    2261           0 :         torture_assert_int_equal_goto(
    2262             :                 tctx,
    2263             :                 getinfo.access_information.out.access_flags,
    2264             :                 expected_access,
    2265             :                 ret, done,
    2266             :                 "Bad access mask\n");
    2267             : 
    2268             :         /*
    2269             :          * Check we can't set various things
    2270             :          */
    2271             : 
    2272           0 :         ZERO_STRUCT(getinfo);
    2273           0 :         getinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    2274           0 :         getinfo.query_secdesc.in.file.handle = h1;
    2275           0 :         getinfo.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
    2276             : 
    2277           0 :         status = smb2_getinfo_file(tree, tctx, &getinfo);
    2278           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2279             :                                         "smb2_getinfo_file\n");
    2280             : 
    2281           0 :         sd_orig = getinfo.query_secdesc.out.sd;
    2282           0 :         owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
    2283             : 
    2284           0 :         sd = security_descriptor_dacl_create(tctx,
    2285             :                                              0, NULL, NULL,
    2286             :                                              owner_sid,
    2287             :                                              SEC_ACE_TYPE_ACCESS_ALLOWED,
    2288             :                                              SEC_FILE_WRITE_DATA,
    2289             :                                              0,
    2290             :                                              NULL);
    2291             : 
    2292             :         /* Try to set ACL */
    2293             : 
    2294           0 :         ZERO_STRUCT(setinfo);
    2295           0 :         setinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    2296           0 :         setinfo.set_secdesc.in.file.handle = h1;
    2297           0 :         setinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    2298           0 :         setinfo.set_secdesc.in.sd = sd;
    2299             : 
    2300           0 :         status = smb2_setinfo_file(tree, &setinfo);
    2301           0 :         torture_assert_ntstatus_equal_goto(
    2302             :                 tctx,
    2303             :                 status,
    2304             :                 NT_STATUS_MEDIA_WRITE_PROTECTED,
    2305             :                 ret, done,
    2306             :                 "smb2_setinfo_file\n");
    2307             : 
    2308             :         /* Try to delete */
    2309             : 
    2310           0 :         ZERO_STRUCT(setinfo);
    2311           0 :         setinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
    2312           0 :         setinfo.disposition_info.in.delete_on_close = 1;
    2313           0 :         setinfo.generic.in.file.handle = h1;
    2314             : 
    2315           0 :         status = smb2_setinfo_file(tree, &setinfo);
    2316           0 :         torture_assert_ntstatus_equal_goto(
    2317             :                 tctx,
    2318             :                 status,
    2319             :                 NT_STATUS_MEDIA_WRITE_PROTECTED,
    2320             :                 ret, done,
    2321             :                 "smb2_setinfo_file\n");
    2322             : 
    2323           0 :         ZERO_STRUCT(setinfo);
    2324           0 :         setinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN;
    2325           0 :         setinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
    2326           0 :         setinfo.generic.in.file.handle = h1;
    2327             : 
    2328           0 :         status = smb2_setinfo_file(tree, &setinfo);
    2329           0 :         torture_assert_ntstatus_equal_goto(
    2330             :                 tctx,
    2331             :                 status,
    2332             :                 NT_STATUS_MEDIA_WRITE_PROTECTED,
    2333             :                 ret, done,
    2334             :                 "smb2_setinfo_file\n");
    2335             : 
    2336             :         /* Try to truncate */
    2337             : 
    2338           0 :         ZERO_STRUCT(setinfo);
    2339           0 :         setinfo.generic.level = SMB_SFILEINFO_END_OF_FILE_INFORMATION;
    2340           0 :         setinfo.generic.in.file.handle = h1;
    2341           0 :         setinfo.end_of_file_info.in.size = 0x100000;
    2342             : 
    2343           0 :         status = smb2_setinfo_file(tree, &setinfo);
    2344           0 :         torture_assert_ntstatus_equal_goto(
    2345             :                 tctx,
    2346             :                 status,
    2347             :                 NT_STATUS_MEDIA_WRITE_PROTECTED,
    2348             :                 ret, done,
    2349             :                 "smb2_setinfo_file\n");
    2350             : 
    2351             :         /* Try to set a hardlink */
    2352             : 
    2353           0 :         ZERO_STRUCT(setinfo);
    2354           0 :         setinfo.generic.level = RAW_SFILEINFO_LINK_INFORMATION;
    2355           0 :         setinfo.generic.in.file.handle = h1;
    2356           0 :         setinfo.link_information.in.new_name = "hardlink";
    2357             : 
    2358           0 :         status = smb2_setinfo_file(tree, &setinfo);
    2359           0 :         torture_assert_ntstatus_equal_goto(
    2360             :                 tctx,
    2361             :                 status,
    2362             :                 NT_STATUS_NOT_SAME_DEVICE,
    2363             :                 ret, done,
    2364             :                 "smb2_setinfo_file\n");
    2365             : 
    2366             :         /* Try to rename */
    2367             : 
    2368           0 :         ZERO_STRUCT(setinfo);
    2369           0 :         setinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2370           0 :         setinfo.rename_information.in.file.handle = h1;
    2371           0 :         setinfo.rename_information.in.new_name = "renamed";
    2372             : 
    2373           0 :         status = smb2_setinfo_file(tree, &setinfo);
    2374           0 :         torture_assert_ntstatus_equal_goto(
    2375             :                 tctx,
    2376             :                 status,
    2377             :                 NT_STATUS_NOT_SAME_DEVICE,
    2378             :                 ret, done,
    2379             :                 "smb2_setinfo_file\n");
    2380             : 
    2381           0 :         smb2_util_close(tree, h1);
    2382           0 :         ZERO_STRUCT(h1);
    2383             : 
    2384           0 : done:
    2385           0 :         if (!smb2_util_handle_empty(h1)) {
    2386           0 :                 smb2_util_close(tree, h1);
    2387             :         }
    2388           0 :         return ret;
    2389             : }
    2390             : 
    2391           0 : static bool test_twrp_stream(struct torture_context *tctx,
    2392             :                              struct smb2_tree *tree)
    2393             : {
    2394             :         struct smb2_create io;
    2395             :         NTSTATUS status;
    2396           0 :         bool ret = true;
    2397           0 :         char *p = NULL;
    2398             :         struct tm tm;
    2399             :         time_t t;
    2400             :         uint64_t nttime;
    2401           0 :         const char *file = NULL;
    2402           0 :         const char *stream = NULL;
    2403           0 :         const char *snapshot = NULL;
    2404             :         int stream_size;
    2405           0 :         char *path = NULL;
    2406           0 :         uint8_t *buf = NULL;
    2407           0 :         struct smb2_handle h1 = {{0}};
    2408             :         struct smb2_read r;
    2409             : 
    2410           0 :         file = torture_setting_string(tctx, "twrp_file", NULL);
    2411           0 :         if (file == NULL) {
    2412           0 :                 torture_skip(tctx, "missing 'twrp_file' option\n");
    2413             :         }
    2414             : 
    2415           0 :         stream = torture_setting_string(tctx, "twrp_stream", NULL);
    2416           0 :         if (stream == NULL) {
    2417           0 :                 torture_skip(tctx, "missing 'twrp_stream' option\n");
    2418             :         }
    2419             : 
    2420           0 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2421           0 :         if (snapshot == NULL) {
    2422           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    2423             :         }
    2424             : 
    2425           0 :         stream_size = torture_setting_int(tctx, "twrp_stream_size", 0);
    2426           0 :         if (stream_size == 0) {
    2427           0 :                 torture_skip(tctx, "missing 'twrp_stream_size' option\n");
    2428             :         }
    2429             : 
    2430           0 :         torture_comment(tctx, "Testing timewarp on stream (%s) (%s)\n",
    2431             :                         file, snapshot);
    2432             : 
    2433           0 :         path = talloc_asprintf(tree, "%s:%s", file, stream);
    2434           0 :         torture_assert_not_null_goto(tctx, path, ret, done, "path\n");
    2435             : 
    2436           0 :         buf = talloc_zero_array(tree, uint8_t, stream_size);
    2437           0 :         torture_assert_not_null_goto(tctx, buf, ret, done, "buf\n");
    2438             : 
    2439           0 :         setenv("TZ", "GMT", 1);
    2440             : 
    2441             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2442             :          * effect if it is greather than 1. */
    2443           0 :         ZERO_STRUCT(tm);
    2444             : 
    2445           0 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2446           0 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2447           0 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2448             : 
    2449           0 :         t = mktime(&tm);
    2450           0 :         unix_to_nt_time(&nttime, t);
    2451             : 
    2452           0 :         io = (struct smb2_create) {
    2453             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2454             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2455             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2456             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2457             :                 .in.fname = path,
    2458             :                 .in.timewarp = nttime,
    2459             :         };
    2460             : 
    2461           0 :         status = smb2_create(tree, tctx, &io);
    2462           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2463             :                                         "smb2_create\n");
    2464           0 :         h1 = io.out.file.handle;
    2465             : 
    2466           0 :         r = (struct smb2_read) {
    2467             :                 .in.file.handle = h1,
    2468             :                 .in.length = stream_size,
    2469             :                 .in.offset = 0,
    2470             :         };
    2471             : 
    2472           0 :         status = smb2_read(tree, tree, &r);
    2473           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2474             :                                         "smb2_create\n");
    2475             : 
    2476           0 :         smb2_util_close(tree, h1);
    2477             : 
    2478           0 : done:
    2479           0 :         return ret;
    2480             : }
    2481             : 
    2482           0 : static bool test_twrp_openroot(struct torture_context *tctx, struct smb2_tree *tree)
    2483             : {
    2484             :         struct smb2_create io;
    2485             :         NTSTATUS status;
    2486           0 :         bool ret = true;
    2487           0 :         char *p = NULL;
    2488             :         struct tm tm;
    2489             :         time_t t;
    2490             :         uint64_t nttime;
    2491           0 :         const char *snapshot = NULL;
    2492             : 
    2493           0 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2494           0 :         if (snapshot == NULL) {
    2495           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    2496             :         }
    2497             : 
    2498           0 :         torture_comment(tctx, "Testing open of root of "
    2499             :                 "share with timewarp (%s)\n",
    2500             :                 snapshot);
    2501             : 
    2502           0 :         setenv("TZ", "GMT", 1);
    2503             : 
    2504             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2505             :          * effect if it is greather than 1. */
    2506           0 :         ZERO_STRUCT(tm);
    2507             : 
    2508           0 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2509           0 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2510           0 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2511             : 
    2512           0 :         t = mktime(&tm);
    2513           0 :         unix_to_nt_time(&nttime, t);
    2514             : 
    2515           0 :         io = (struct smb2_create) {
    2516             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2517             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2518             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2519             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2520             :                 .in.fname = "",
    2521             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2522             :                 .in.timewarp = nttime,
    2523             :         };
    2524             : 
    2525           0 :         status = smb2_create(tree, tctx, &io);
    2526           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2527             :                                         "smb2_create\n");
    2528           0 :         smb2_util_close(tree, io.out.file.handle);
    2529             : 
    2530           0 : done:
    2531           0 :         return ret;
    2532             : }
    2533             : 
    2534           0 : static bool test_twrp_listdir(struct torture_context *tctx,
    2535             :                               struct smb2_tree *tree)
    2536             : {
    2537             :         struct smb2_create create;
    2538           0 :         struct smb2_handle h = {{0}};
    2539             :         struct smb2_find find;
    2540             :         unsigned int count;
    2541             :         union smb_search_data *d;
    2542           0 :         char *p = NULL;
    2543             :         struct tm tm;
    2544             :         time_t t;
    2545             :         uint64_t nttime;
    2546           0 :         const char *snapshot = NULL;
    2547             :         uint64_t normal_fileid;
    2548             :         uint64_t snapshot_fileid;
    2549             :         NTSTATUS status;
    2550           0 :         bool ret = true;
    2551             : 
    2552           0 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2553           0 :         if (snapshot == NULL) {
    2554           0 :                 torture_fail(tctx, "missing 'twrp_snapshot' option\n");
    2555             :         }
    2556             : 
    2557           0 :         torture_comment(tctx, "Testing File-Ids of directory listing "
    2558             :                         "with timewarp (%s)\n",
    2559             :                         snapshot);
    2560             : 
    2561           0 :         setenv("TZ", "GMT", 1);
    2562             : 
    2563             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2564             :          * effect if it is greather than 1. */
    2565           0 :         ZERO_STRUCT(tm);
    2566             : 
    2567           0 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2568           0 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2569           0 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2570             : 
    2571           0 :         t = mktime(&tm);
    2572           0 :         unix_to_nt_time(&nttime, t);
    2573             : 
    2574             :         /*
    2575             :          * 1: Query the file's File-Id
    2576             :          */
    2577           0 :         create = (struct smb2_create) {
    2578             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2579             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2580             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2581             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2582             :                 .in.fname = "subdir/hardlink",
    2583             :                 .in.query_on_disk_id = true,
    2584             :         };
    2585             : 
    2586           0 :         status = smb2_create(tree, tctx, &create);
    2587           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2588             :                                         "test file could not be created\n");
    2589           0 :         smb2_util_close(tree, create.out.file.handle);
    2590           0 :         normal_fileid = BVAL(&create.out.on_disk_id, 0);
    2591             : 
    2592             :         /*
    2593             :          * 2: check directory listing of the file returns same File-Id
    2594             :          */
    2595             : 
    2596           0 :         create = (struct smb2_create) {
    2597             :                 .in.desired_access = SEC_DIR_LIST,
    2598             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2599             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2600             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2601             :                 .in.fname = "subdir",
    2602             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2603             :         };
    2604             : 
    2605           0 :         status = smb2_create(tree, tctx, &create);
    2606           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2607             :                                         "smb2_create\n");
    2608           0 :         h = create.out.file.handle;
    2609             : 
    2610           0 :         find = (struct smb2_find) {
    2611             :                 .in.file.handle = h,
    2612             :                 .in.pattern = "*",
    2613             :                 .in.max_response_size = 0x1000,
    2614             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2615             :         };
    2616             : 
    2617           0 :         status = smb2_find_level(tree, tree, &find, &count, &d);
    2618           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2619             :                                         "smb2_find_level failed\n");
    2620             : 
    2621           0 :         smb2_util_close(tree, h);
    2622             : 
    2623           0 :         torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
    2624           0 :         torture_assert_str_equal_goto(tctx,
    2625             :                                       d[2].id_both_directory_info.name.s,
    2626             :                                       "hardlink",
    2627             :                                       ret, done, "bad name");
    2628           0 :         torture_assert_u64_equal_goto(tctx,
    2629             :                                       d[2].id_both_directory_info.file_id,
    2630             :                                       normal_fileid,
    2631             :                                       ret, done, "bad fileid\n");
    2632             : 
    2633             :         /*
    2634             :          * 3: Query File-Id of snapshot of the file and check the File-Id is
    2635             :          * different compared to the basefile
    2636             :          */
    2637             : 
    2638           0 :         create = (struct smb2_create) {
    2639             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2640             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2641             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2642             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2643             :                 .in.fname = "subdir/hardlink",
    2644             :                 .in.query_on_disk_id = true,
    2645             :                 .in.timewarp = nttime,
    2646             :         };
    2647             : 
    2648           0 :         status = smb2_create(tree, tctx, &create);
    2649           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2650             :                                         "test file could not be created\n");
    2651           0 :         smb2_util_close(tree, create.out.file.handle);
    2652             : 
    2653           0 :         snapshot_fileid = BVAL(&create.out.on_disk_id, 0);
    2654             : 
    2655             :         /*
    2656             :          * 4: List directory of the snapshot and check the File-Id returned here
    2657             :          * is the same as in 3.
    2658             :          */
    2659             : 
    2660           0 :         create = (struct smb2_create) {
    2661             :                 .in.desired_access = SEC_DIR_LIST,
    2662             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2663             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2664             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2665             :                 .in.fname = "subdir",
    2666             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2667             :                 .in.timewarp = nttime,
    2668             :         };
    2669             : 
    2670           0 :         status = smb2_create(tree, tctx, &create);
    2671           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2672             :                                         "smb2_create\n");
    2673           0 :         h = create.out.file.handle;
    2674             : 
    2675           0 :         find = (struct smb2_find) {
    2676             :                 .in.file.handle = h,
    2677             :                 .in.pattern = "*",
    2678             :                 .in.max_response_size = 0x1000,
    2679             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2680             :         };
    2681             : 
    2682           0 :         status = smb2_find_level(tree, tree, &find, &count, &d);
    2683           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2684             :                                         "smb2_find_level failed\n");
    2685           0 :         smb2_util_close(tree, h);
    2686             : 
    2687           0 :         torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
    2688           0 :         torture_assert_str_equal_goto(tctx,
    2689             :                                       d[2].id_both_directory_info.name.s,
    2690             :                                       "hardlink",
    2691             :                                       ret, done, "bad name");
    2692           0 :         torture_assert_u64_equal_goto(tctx,
    2693             :                                       snapshot_fileid,
    2694             :                                       d[2].id_both_directory_info.file_id,
    2695             :                                       ret, done, "bad fileid\n");
    2696             : 
    2697           0 : done:
    2698           0 :         return ret;
    2699             : }
    2700             : 
    2701           0 : static bool test_fileid(struct torture_context *tctx,
    2702             :                         struct smb2_tree *tree)
    2703             : {
    2704           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2705           0 :         const char *fname = DNAME "\\foo";
    2706           0 :         const char *sname = DNAME "\\foo:bar";
    2707             :         struct smb2_handle testdirh;
    2708             :         struct smb2_handle h1;
    2709             :         struct smb2_create create;
    2710             :         union smb_fileinfo finfo;
    2711             :         union smb_setfileinfo sinfo;
    2712             :         struct smb2_find f;
    2713             :         unsigned int count;
    2714             :         union smb_search_data *d;
    2715             :         uint64_t expected_fileid;
    2716             :         uint64_t returned_fileid;
    2717             :         NTSTATUS status;
    2718           0 :         bool ret = true;
    2719             : 
    2720           0 :         smb2_deltree(tree, DNAME);
    2721             : 
    2722           0 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    2723           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2724             :                                         "torture_smb2_testdir failed\n");
    2725             : 
    2726             :         /*
    2727             :          * Initial create with QFID
    2728             :          */
    2729           0 :         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_IF,
    2734             :                 .in.fname = fname,
    2735             :                 .in.query_on_disk_id = true,
    2736             :         };
    2737             : 
    2738           0 :         status = smb2_create(tree, tctx, &create);
    2739           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2740             :                                         "test file could not be created\n");
    2741           0 :         h1 = create.out.file.handle;
    2742           0 :         expected_fileid = BVAL(&create.out.on_disk_id, 0);
    2743             : 
    2744             :         /*
    2745             :          * Getinfo the File-ID on the just opened handle
    2746             :          */
    2747           0 :         finfo = (union smb_fileinfo) {
    2748             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2749             :                 .generic.in.file.handle = h1,
    2750             :         };
    2751             : 
    2752           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2753           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2754             :                                         "torture_smb2_testdir\n");
    2755           0 :         smb2_util_close(tree, h1);
    2756           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2757             :                                       expected_fileid,
    2758             :                                       ret, done, "bad fileid\n");
    2759             : 
    2760             :         /*
    2761             :          * Open existing with QFID
    2762             :          */
    2763           0 :         create = (struct smb2_create) {
    2764             :                 .in.desired_access = SEC_FILE_ALL,
    2765             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2766             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2767             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2768             :                 .in.fname = fname,
    2769             :                 .in.query_on_disk_id = true,
    2770             :         };
    2771             : 
    2772           0 :         status = smb2_create(tree, tctx, &create);
    2773           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2774             :                                         "test file could not be created\n");
    2775           0 :         h1 = create.out.file.handle;
    2776           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2777           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2778             :                                       ret, done, "bad fileid\n");
    2779             : 
    2780             :         /*
    2781             :          * Getinfo the File-ID on the just opened handle
    2782             :          */
    2783           0 :         finfo = (union smb_fileinfo) {
    2784             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2785             :                 .generic.in.file.handle = h1,
    2786             :         };
    2787             : 
    2788           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2789           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2790             :                                         "torture_smb2_testdir\n");
    2791           0 :         smb2_util_close(tree, h1);
    2792           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2793             :                                       expected_fileid,
    2794             :                                       ret, done, "bad fileid\n");
    2795             : 
    2796             :         /*
    2797             :          * Overwrite with QFID
    2798             :          */
    2799           0 :         create = (struct smb2_create) {
    2800             :                 .in.desired_access = SEC_FILE_ALL,
    2801             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2802             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2803             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2804             :                 .in.fname = fname,
    2805             :                 .in.query_on_disk_id = true,
    2806             :         };
    2807             : 
    2808           0 :         status = smb2_create(tree, tctx, &create);
    2809           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2810             :                                         "test file could not be created\n");
    2811           0 :         h1 = create.out.file.handle;
    2812           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2813           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2814             :                                       ret, done, "bad fileid\n");
    2815             : 
    2816             :         /*
    2817             :          * Getinfo the File-ID on the open with overwrite handle
    2818             :          */
    2819           0 :         finfo = (union smb_fileinfo) {
    2820             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2821             :                 .generic.in.file.handle = h1,
    2822             :         };
    2823             : 
    2824           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2825           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2826             :                                         "torture_smb2_testdir\n");
    2827           0 :         smb2_util_close(tree, h1);
    2828           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2829             :                                       expected_fileid,
    2830             :                                       ret, done, "bad fileid\n");
    2831             : 
    2832             :         /*
    2833             :          * Do some modifications on the basefile (IO, setinfo), verifying
    2834             :          * File-ID after each step.
    2835             :          */
    2836           0 :         create = (struct smb2_create) {
    2837             :                 .in.desired_access = SEC_FILE_ALL,
    2838             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2839             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2840             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2841             :                 .in.fname = fname,
    2842             :                 .in.query_on_disk_id = true,
    2843             :         };
    2844             : 
    2845           0 :         status = smb2_create(tree, tctx, &create);
    2846           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2847             :                                         "test file could not be created\n");
    2848           0 :         h1 = create.out.file.handle;
    2849             : 
    2850           0 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    2851           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2852             :                                         "smb2_util_write failed\n");
    2853             : 
    2854           0 :         finfo = (union smb_fileinfo) {
    2855             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2856             :                 .generic.in.file.handle = h1,
    2857             :         };
    2858           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2859           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2860             :                                         "smb2_getinfo_file failed\n");
    2861           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2862             :                                       expected_fileid,
    2863             :                                       ret, done, "bad fileid\n");
    2864             : 
    2865           0 :         sinfo = (union smb_setfileinfo) {
    2866             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    2867             :                 .basic_info.in.file.handle = h1,
    2868             :         };
    2869           0 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    2870             : 
    2871           0 :         status = smb2_setinfo_file(tree, &sinfo);
    2872           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2873             :                                         "smb2_setinfo_file failed\n");
    2874             : 
    2875           0 :         finfo = (union smb_fileinfo) {
    2876             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2877             :                 .generic.in.file.handle = h1,
    2878             :         };
    2879           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2880           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2881             :                                         "smb2_getinfo_file failed\n");
    2882           0 :         smb2_util_close(tree, h1);
    2883           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2884             :                                       expected_fileid,
    2885             :                                       ret, done, "bad fileid\n");
    2886             : 
    2887             :         /*
    2888             :          * Create stream, check the stream's File-ID, should be the same as the
    2889             :          * base file (sic!, tested against Windows).
    2890             :          */
    2891           0 :         create = (struct smb2_create) {
    2892             :                 .in.desired_access = SEC_FILE_ALL,
    2893             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2894             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2895             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    2896             :                 .in.fname = sname,
    2897             :                 .in.query_on_disk_id = true,
    2898             :         };
    2899             : 
    2900           0 :         status = smb2_create(tree, tctx, &create);
    2901           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2902             :                                         "test file could not be created\n");
    2903           0 :         h1 = create.out.file.handle;
    2904           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2905           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2906             :                                       ret, done, "bad fileid\n");
    2907             : 
    2908             :         /*
    2909             :          * Getinfo the File-ID on the created stream
    2910             :          */
    2911           0 :         finfo = (union smb_fileinfo) {
    2912             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2913             :                 .generic.in.file.handle = h1,
    2914             :         };
    2915             : 
    2916           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2917           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2918             :                                         "smb2_getinfo_file failed\n");
    2919           0 :         smb2_util_close(tree, h1);
    2920           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2921             :                                       expected_fileid,
    2922             :                                       ret, done, "bad fileid\n");
    2923             : 
    2924             :         /*
    2925             :          * Open stream, check the stream's File-ID, should be the same as the
    2926             :          * base file (sic!, tested against Windows).
    2927             :          */
    2928           0 :         create = (struct smb2_create) {
    2929             :                 .in.desired_access = SEC_FILE_ALL,
    2930             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2931             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2932             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2933             :                 .in.fname = sname,
    2934             :                 .in.query_on_disk_id = true,
    2935             :         };
    2936             : 
    2937           0 :         status = smb2_create(tree, tctx, &create);
    2938           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2939             :                                         "test file could not be created\n");
    2940           0 :         h1 = create.out.file.handle;
    2941           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2942           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2943             :                                       ret, done, "bad fileid\n");
    2944             : 
    2945             :         /*
    2946             :          * Getinfo the File-ID on the opened stream
    2947             :          */
    2948           0 :         finfo = (union smb_fileinfo) {
    2949             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2950             :                 .generic.in.file.handle = h1,
    2951             :         };
    2952             : 
    2953           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2954           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2955             :                                         "smb2_getinfo_file failed\n");
    2956           0 :         smb2_util_close(tree, h1);
    2957           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2958             :                                       expected_fileid,
    2959             :                                       ret, done, "bad fileid\n");
    2960             : 
    2961             :         /*
    2962             :          * Overwrite stream, check the stream's File-ID, should be the same as
    2963             :          * the base file (sic!, tested against Windows).
    2964             :          */
    2965           0 :         create = (struct smb2_create) {
    2966             :                 .in.desired_access = SEC_FILE_ALL,
    2967             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2968             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2969             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2970             :                 .in.fname = sname,
    2971             :                 .in.query_on_disk_id = true,
    2972             :         };
    2973             : 
    2974           0 :         status = smb2_create(tree, tctx, &create);
    2975           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2976             :                                         "test file could not be created\n");
    2977           0 :         h1 = create.out.file.handle;
    2978           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2979           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2980             :                                       ret, done, "bad fileid\n");
    2981             : 
    2982             :         /*
    2983             :          * Getinfo the File-ID on the overwritten stream
    2984             :          */
    2985           0 :         finfo = (union smb_fileinfo) {
    2986             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2987             :                 .generic.in.file.handle = h1,
    2988             :         };
    2989             : 
    2990           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2991           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2992             :                                         "smb2_getinfo_file failed\n");
    2993           0 :         smb2_util_close(tree, h1);
    2994           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2995             :                                       expected_fileid,
    2996             :                                       ret, done, "bad fileid\n");
    2997             : 
    2998             :         /*
    2999             :          * Do some modifications on the stream (IO, setinfo), verifying File-ID
    3000             :          * after earch step.
    3001             :          */
    3002           0 :         create = (struct smb2_create) {
    3003             :                 .in.desired_access = SEC_FILE_ALL,
    3004             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3005             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3006             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3007             :                 .in.fname = sname,
    3008             :                 .in.query_on_disk_id = true,
    3009             :         };
    3010             : 
    3011           0 :         status = smb2_create(tree, tctx, &create);
    3012           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3013             :                                         "test file could not be created\n");
    3014           0 :         h1 = create.out.file.handle;
    3015             : 
    3016           0 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    3017           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3018             :                                         "smb2_util_write failed\n");
    3019             : 
    3020           0 :         finfo = (union smb_fileinfo) {
    3021             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3022             :                 .generic.in.file.handle = h1,
    3023             :         };
    3024           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3025           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3026             :                                         "smb2_getinfo_file failed\n");
    3027           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3028             :                                       expected_fileid,
    3029             :                                       ret, done, "bad fileid\n");
    3030             : 
    3031           0 :         sinfo = (union smb_setfileinfo) {
    3032             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    3033             :                 .basic_info.in.file.handle = h1,
    3034             :         };
    3035           0 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    3036             : 
    3037           0 :         status = smb2_setinfo_file(tree, &sinfo);
    3038           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3039             :                                         "smb2_setinfo_file failed\n");
    3040             : 
    3041           0 :         finfo = (union smb_fileinfo) {
    3042             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3043             :                 .generic.in.file.handle = h1,
    3044             :         };
    3045           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3046           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3047             :                                         "smb2_getinfo_file failed\n");
    3048           0 :         smb2_util_close(tree, h1);
    3049           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3050             :                                       expected_fileid,
    3051             :                                       ret, done, "bad fileid\n");
    3052             : 
    3053             :         /*
    3054             :          * Final open of the basefile with QFID
    3055             :          */
    3056           0 :         create = (struct smb2_create) {
    3057             :                 .in.desired_access = SEC_FILE_ALL,
    3058             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3059             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3060             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3061             :                 .in.fname = fname,
    3062             :                 .in.query_on_disk_id = true,
    3063             :         };
    3064             : 
    3065           0 :         status = smb2_create(tree, tctx, &create);
    3066           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3067             :                                         "test file could not be created\n");
    3068           0 :         h1 = create.out.file.handle;
    3069           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3070           0 :         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           0 :         finfo = (union smb_fileinfo) {
    3077             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3078             :                 .generic.in.file.handle = h1,
    3079             :         };
    3080             : 
    3081           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3082           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3083             :                                         "torture_smb2_testdir\n");
    3084           0 :         smb2_util_close(tree, h1);
    3085           0 :         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           0 :         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           0 :         status = smb2_find_level(tree, tree, &f, &count, &d);
    3102           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3103             :                                         "smb2_find_level failed\n");
    3104           0 :         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           0 : done:
    3110           0 :         smb2_util_close(tree, testdirh);
    3111           0 :         smb2_deltree(tree, DNAME);
    3112           0 :         talloc_free(mem_ctx);
    3113           0 :         return ret;
    3114             : }
    3115             : 
    3116           0 : static bool test_fileid_dir(struct torture_context *tctx,
    3117             :                             struct smb2_tree *tree)
    3118             : {
    3119           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    3120           0 :         const char *dname = DNAME "\\foo";
    3121           0 :         const char *sname = DNAME "\\foo:bar";
    3122             :         struct smb2_handle testdirh;
    3123             :         struct smb2_handle h1;
    3124             :         struct smb2_create create;
    3125             :         union smb_fileinfo finfo;
    3126             :         union smb_setfileinfo sinfo;
    3127             :         struct smb2_find f;
    3128             :         unsigned int count;
    3129             :         union smb_search_data *d;
    3130             :         uint64_t expected_fileid;
    3131             :         uint64_t returned_fileid;
    3132             :         NTSTATUS status;
    3133           0 :         bool ret = true;
    3134             : 
    3135           0 :         smb2_deltree(tree, DNAME);
    3136             : 
    3137           0 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    3138           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3139             :                                         "torture_smb2_testdir failed\n");
    3140             : 
    3141             :         /*
    3142             :          * Initial directory create with QFID
    3143             :          */
    3144           0 :         create = (struct smb2_create) {
    3145             :                 .in.desired_access = SEC_FILE_ALL,
    3146             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3147             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    3148             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    3149             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3150             :                 .in.fname = dname,
    3151             :                 .in.query_on_disk_id = true,
    3152             :         };
    3153             : 
    3154           0 :         status = smb2_create(tree, tctx, &create);
    3155           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3156             :                                         "test file could not be created\n");
    3157           0 :         h1 = create.out.file.handle;
    3158           0 :         expected_fileid = BVAL(&create.out.on_disk_id, 0);
    3159             : 
    3160             :         /*
    3161             :          * Getinfo the File-ID on the just opened handle
    3162             :          */
    3163           0 :         finfo = (union smb_fileinfo) {
    3164             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3165             :                 .generic.in.file.handle = h1,
    3166             :         };
    3167             : 
    3168           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3169           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3170             :                                         "torture_smb2_testdir\n");
    3171           0 :         smb2_util_close(tree, h1);
    3172           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3173             :                                       expected_fileid,
    3174             :                                       ret, done, "bad fileid\n");
    3175             : 
    3176             :         /*
    3177             :          * Open existing directory with QFID
    3178             :          */
    3179           0 :         create = (struct smb2_create) {
    3180             :                 .in.desired_access = SEC_FILE_ALL,
    3181             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3182             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3183             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    3184             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3185             :                 .in.fname = dname,
    3186             :                 .in.query_on_disk_id = true,
    3187             :         };
    3188             : 
    3189           0 :         status = smb2_create(tree, tctx, &create);
    3190           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3191             :                                         "test file could not be created\n");
    3192           0 :         h1 = create.out.file.handle;
    3193           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3194           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3195             :                                       ret, done, "bad fileid\n");
    3196             : 
    3197             :         /*
    3198             :          * Getinfo the File-ID on the just opened handle
    3199             :          */
    3200           0 :         finfo = (union smb_fileinfo) {
    3201             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3202             :                 .generic.in.file.handle = h1,
    3203             :         };
    3204             : 
    3205           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3206           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3207             :                                         "torture_smb2_testdir\n");
    3208           0 :         smb2_util_close(tree, h1);
    3209           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3210             :                                       expected_fileid,
    3211             :                                       ret, done, "bad fileid\n");
    3212             : 
    3213             :         /*
    3214             :          * Create stream, check the stream's File-ID, should be the same as the
    3215             :          * base file (sic!, tested against Windows).
    3216             :          */
    3217           0 :         create = (struct smb2_create) {
    3218             :                 .in.desired_access = SEC_FILE_ALL,
    3219             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3220             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3221             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    3222             :                 .in.fname = sname,
    3223             :                 .in.query_on_disk_id = true,
    3224             :         };
    3225             : 
    3226           0 :         status = smb2_create(tree, tctx, &create);
    3227           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3228             :                                         "test file could not be created\n");
    3229           0 :         h1 = create.out.file.handle;
    3230           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3231           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3232             :                                       ret, done, "bad fileid\n");
    3233             : 
    3234             :         /*
    3235             :          * Getinfo the File-ID on the created stream
    3236             :          */
    3237           0 :         finfo = (union smb_fileinfo) {
    3238             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3239             :                 .generic.in.file.handle = h1,
    3240             :         };
    3241             : 
    3242           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3243           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3244             :                                         "smb2_getinfo_file failed\n");
    3245           0 :         smb2_util_close(tree, h1);
    3246           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3247             :                                       expected_fileid,
    3248             :                                       ret, done, "bad fileid\n");
    3249             : 
    3250             :         /*
    3251             :          * Open stream, check the stream's File-ID, should be the same as the
    3252             :          * base file (sic!, tested against Windows).
    3253             :          */
    3254           0 :         create = (struct smb2_create) {
    3255             :                 .in.desired_access = SEC_FILE_ALL,
    3256             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3257             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3258             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3259             :                 .in.fname = sname,
    3260             :                 .in.query_on_disk_id = true,
    3261             :         };
    3262             : 
    3263           0 :         status = smb2_create(tree, tctx, &create);
    3264           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3265             :                                         "test file could not be created\n");
    3266           0 :         h1 = create.out.file.handle;
    3267           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3268           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3269             :                                       ret, done, "bad fileid\n");
    3270             : 
    3271             :         /*
    3272             :          * Getinfo the File-ID on the opened stream
    3273             :          */
    3274           0 :         finfo = (union smb_fileinfo) {
    3275             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3276             :                 .generic.in.file.handle = h1,
    3277             :         };
    3278             : 
    3279           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3280           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3281             :                                         "smb2_getinfo_file failed\n");
    3282           0 :         smb2_util_close(tree, h1);
    3283           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3284             :                                       expected_fileid,
    3285             :                                       ret, done, "bad fileid\n");
    3286             : 
    3287             :         /*
    3288             :          * Overwrite stream, check the stream's File-ID, should be the same as
    3289             :          * the base file (sic!, tested against Windows).
    3290             :          */
    3291           0 :         create = (struct smb2_create) {
    3292             :                 .in.desired_access = SEC_FILE_ALL,
    3293             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3294             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3295             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    3296             :                 .in.fname = sname,
    3297             :                 .in.query_on_disk_id = true,
    3298             :         };
    3299             : 
    3300           0 :         status = smb2_create(tree, tctx, &create);
    3301           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3302             :                                         "test file could not be created\n");
    3303           0 :         h1 = create.out.file.handle;
    3304           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3305           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3306             :                                       ret, done, "bad fileid\n");
    3307             : 
    3308             :         /*
    3309             :          * Getinfo the File-ID on the overwritten stream
    3310             :          */
    3311           0 :         finfo = (union smb_fileinfo) {
    3312             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3313             :                 .generic.in.file.handle = h1,
    3314             :         };
    3315             : 
    3316           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3317           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3318             :                                         "smb2_getinfo_file failed\n");
    3319           0 :         smb2_util_close(tree, h1);
    3320           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3321             :                                       expected_fileid,
    3322             :                                       ret, done, "bad fileid\n");
    3323             : 
    3324             :         /*
    3325             :          * Do some modifications on the stream (IO, setinfo), verifying File-ID
    3326             :          * after earch step.
    3327             :          */
    3328           0 :         create = (struct smb2_create) {
    3329             :                 .in.desired_access = SEC_FILE_ALL,
    3330             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3331             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3332             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3333             :                 .in.fname = sname,
    3334             :                 .in.query_on_disk_id = true,
    3335             :         };
    3336             : 
    3337           0 :         status = smb2_create(tree, tctx, &create);
    3338           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3339             :                                         "test file could not be created\n");
    3340           0 :         h1 = create.out.file.handle;
    3341             : 
    3342           0 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    3343           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3344             :                                         "smb2_util_write failed\n");
    3345             : 
    3346           0 :         finfo = (union smb_fileinfo) {
    3347             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3348             :                 .generic.in.file.handle = h1,
    3349             :         };
    3350           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3351           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3352             :                                         "smb2_getinfo_file failed\n");
    3353           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3354             :                                       expected_fileid,
    3355             :                                       ret, done, "bad fileid\n");
    3356             : 
    3357           0 :         sinfo = (union smb_setfileinfo) {
    3358             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    3359             :                 .basic_info.in.file.handle = h1,
    3360             :         };
    3361           0 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    3362             : 
    3363           0 :         status = smb2_setinfo_file(tree, &sinfo);
    3364           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3365             :                                         "smb2_setinfo_file failed\n");
    3366             : 
    3367           0 :         finfo = (union smb_fileinfo) {
    3368             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3369             :                 .generic.in.file.handle = h1,
    3370             :         };
    3371           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3372           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3373             :                                         "smb2_getinfo_file failed\n");
    3374           0 :         smb2_util_close(tree, h1);
    3375           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3376             :                                       expected_fileid,
    3377             :                                       ret, done, "bad fileid\n");
    3378             : 
    3379             :         /*
    3380             :          * Final open of the directory with QFID
    3381             :          */
    3382           0 :         create = (struct smb2_create) {
    3383             :                 .in.desired_access = SEC_FILE_ALL,
    3384             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3385             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    3386             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3387             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3388             :                 .in.fname = dname,
    3389             :                 .in.query_on_disk_id = true,
    3390             :         };
    3391             : 
    3392           0 :         status = smb2_create(tree, tctx, &create);
    3393           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3394             :                                         "test file could not be created\n");
    3395           0 :         h1 = create.out.file.handle;
    3396           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3397           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3398             :                                       ret, done, "bad fileid\n");
    3399             : 
    3400             :         /*
    3401             :          * Final Getinfo checking File-ID
    3402             :          */
    3403           0 :         finfo = (union smb_fileinfo) {
    3404             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3405             :                 .generic.in.file.handle = h1,
    3406             :         };
    3407             : 
    3408           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3409           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3410             :                                         "torture_smb2_testdir\n");
    3411           0 :         smb2_util_close(tree, h1);
    3412           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3413             :                                       expected_fileid,
    3414             :                                       ret, done, "bad fileid\n");
    3415             : 
    3416             :         /*
    3417             :          * Final list directory, verifying the operations on basefile and stream
    3418             :          * didn't modify the base file metadata.
    3419             :          */
    3420           0 :         f = (struct smb2_find) {
    3421             :                 .in.file.handle = testdirh,
    3422             :                 .in.pattern = "foo",
    3423             :                 .in.max_response_size = 0x1000,
    3424             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    3425             :                 .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
    3426             :         };
    3427             : 
    3428           0 :         status = smb2_find_level(tree, tree, &f, &count, &d);
    3429           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3430             :                                         "smb2_find_level failed\n");
    3431           0 :         torture_assert_u64_equal_goto(tctx,
    3432             :                                       d->id_both_directory_info.file_id,
    3433             :                                       expected_fileid,
    3434             :                                       ret, done, "bad fileid\n");
    3435             : 
    3436           0 : done:
    3437           0 :         smb2_util_close(tree, testdirh);
    3438           0 :         smb2_deltree(tree, DNAME);
    3439           0 :         talloc_free(mem_ctx);
    3440           0 :         return ret;
    3441             : }
    3442             : 
    3443           0 : static bool test_fileid_unique_object(
    3444             :                         struct torture_context *tctx,
    3445             :                         struct smb2_tree *tree,
    3446             :                         unsigned int num_objs,
    3447             :                         bool create_dirs)
    3448           0 : {
    3449           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    3450           0 :         char *fname = NULL;
    3451             :         struct smb2_handle testdirh;
    3452             :         struct smb2_handle h1;
    3453             :         struct smb2_create create;
    3454             :         unsigned int i;
    3455           0 :         uint64_t fileid_array[num_objs];
    3456             :         NTSTATUS status;
    3457           0 :         bool ret = true;
    3458             : 
    3459           0 :         smb2_deltree(tree, DNAME);
    3460             : 
    3461           0 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    3462           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3463             :                                         "test_fileid_unique failed\n");
    3464           0 :         smb2_util_close(tree, testdirh);
    3465             : 
    3466             :         /* Create num_obj files as rapidly as we can. */
    3467           0 :         for (i = 0; i < num_objs; i++) {
    3468           0 :                 fname = talloc_asprintf(mem_ctx,
    3469             :                                         "%s\\testfile.%u",
    3470             :                                         DNAME,
    3471             :                                         i);
    3472           0 :                 torture_assert_goto(tctx,
    3473             :                                 fname != NULL,
    3474             :                                 ret,
    3475             :                                 done,
    3476             :                                 "talloc failed\n");
    3477             : 
    3478           0 :                 create = (struct smb2_create) {
    3479             :                         .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
    3480             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3481             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3482             :                         .in.create_disposition = NTCREATEX_DISP_CREATE,
    3483             :                         .in.fname = fname,
    3484             :                 };
    3485             : 
    3486           0 :                 if (create_dirs) {
    3487           0 :                         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    3488           0 :                         create.in.create_options = FILE_DIRECTORY_FILE;
    3489             :                 }
    3490             : 
    3491           0 :                 status = smb2_create(tree, tctx, &create);
    3492           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3493           0 :                         torture_fail(tctx,
    3494             :                                 talloc_asprintf(tctx,
    3495             :                                         "test file %s could not be created\n",
    3496             :                                         fname));
    3497             :                         TALLOC_FREE(fname);
    3498             :                         ret = false;
    3499             :                         goto done;
    3500             :                 }
    3501             : 
    3502           0 :                 h1 = create.out.file.handle;
    3503           0 :                 smb2_util_close(tree, h1);
    3504           0 :                 TALLOC_FREE(fname);
    3505             :         }
    3506             : 
    3507             :         /*
    3508             :          * Get the file ids.
    3509             :          */
    3510           0 :         for (i = 0; i < num_objs; i++) {
    3511             :                 union smb_fileinfo finfo;
    3512             : 
    3513           0 :                 fname = talloc_asprintf(mem_ctx,
    3514             :                                         "%s\\testfile.%u",
    3515             :                                         DNAME,
    3516             :                                         i);
    3517           0 :                 torture_assert_goto(tctx,
    3518             :                                 fname != NULL,
    3519             :                                 ret,
    3520             :                                 done,
    3521             :                                 "talloc failed\n");
    3522             : 
    3523           0 :                 create = (struct smb2_create) {
    3524             :                         .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
    3525             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3526             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3527             :                         .in.create_disposition = NTCREATEX_DISP_OPEN,
    3528             :                         .in.fname = fname,
    3529             :                 };
    3530             : 
    3531           0 :                 if (create_dirs) {
    3532           0 :                         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    3533           0 :                         create.in.create_options = FILE_DIRECTORY_FILE;
    3534             :                 }
    3535             : 
    3536           0 :                 status = smb2_create(tree, tctx, &create);
    3537           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3538           0 :                         torture_fail(tctx,
    3539             :                                 talloc_asprintf(tctx,
    3540             :                                         "test file %s could not "
    3541             :                                         "be opened: %s\n",
    3542             :                                         fname,
    3543             :                                         nt_errstr(status)));
    3544             :                         TALLOC_FREE(fname);
    3545             :                         ret = false;
    3546             :                         goto done;
    3547             :                 }
    3548             : 
    3549           0 :                 h1 = create.out.file.handle;
    3550             : 
    3551           0 :                 finfo = (union smb_fileinfo) {
    3552             :                         .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3553             :                         .generic.in.file.handle = h1,
    3554             :                 };
    3555             : 
    3556           0 :                 status = smb2_getinfo_file(tree, tctx, &finfo);
    3557           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3558           0 :                         torture_fail(tctx,
    3559             :                                 talloc_asprintf(tctx,
    3560             :                                         "failed to get fileid for "
    3561             :                                         "test file %s: %s\n",
    3562             :                                         fname,
    3563             :                                         nt_errstr(status)));
    3564             :                         TALLOC_FREE(fname);
    3565             :                         ret = false;
    3566             :                         goto done;
    3567             :                 }
    3568           0 :                 smb2_util_close(tree, h1);
    3569             : 
    3570           0 :                 fileid_array[i] = finfo.all_info2.out.file_id;
    3571           0 :                 TALLOC_FREE(fname);
    3572             :         }
    3573             : 
    3574             :         /* All returned fileids must be unique. 100 is small so brute force. */
    3575           0 :         for (i = 0; i < num_objs - 1; i++) {
    3576             :                 unsigned int j;
    3577           0 :                 for (j = i + 1; j < num_objs; j++) {
    3578           0 :                         if (fileid_array[i] == fileid_array[j]) {
    3579           0 :                                 torture_fail(tctx,
    3580             :                                         talloc_asprintf(tctx,
    3581             :                                                 "fileid %u == fileid %u (0x%"PRIu64")\n",
    3582             :                                                 i,
    3583             :                                                 j,
    3584             :                                                 fileid_array[i]));
    3585             :                                 ret = false;
    3586             :                                 goto done;
    3587             :                         }
    3588             :                 }
    3589             :         }
    3590             : 
    3591           0 : done:
    3592             : 
    3593           0 :         smb2_util_close(tree, testdirh);
    3594           0 :         smb2_deltree(tree, DNAME);
    3595           0 :         talloc_free(mem_ctx);
    3596           0 :         return ret;
    3597             : }
    3598             : 
    3599           0 : static bool test_fileid_unique(
    3600             :                         struct torture_context *tctx,
    3601             :                         struct smb2_tree *tree)
    3602             : {
    3603           0 :         return test_fileid_unique_object(tctx, tree, 100, false);
    3604             : }
    3605             : 
    3606           0 : static bool test_fileid_unique_dir(
    3607             :                         struct torture_context *tctx,
    3608             :                         struct smb2_tree *tree)
    3609             : {
    3610           0 :         return test_fileid_unique_object(tctx, tree, 100, true);
    3611             : }
    3612             : 
    3613           2 : static bool test_dosattr_tmp_dir(struct torture_context *tctx,
    3614             :                                  struct smb2_tree *tree)
    3615             : {
    3616           2 :         bool ret = true;
    3617             :         NTSTATUS status;
    3618             :         struct smb2_create c;
    3619           2 :         struct smb2_handle h1 = {{0}};
    3620           2 :         const char *fname = DNAME;
    3621             : 
    3622           2 :         smb2_deltree(tree, fname);
    3623           2 :         smb2_util_rmdir(tree, fname);
    3624             : 
    3625           2 :         c = (struct smb2_create) {
    3626             :                 .in.desired_access = SEC_RIGHTS_DIR_ALL,
    3627             :                 .in.file_attributes  = FILE_ATTRIBUTE_DIRECTORY,
    3628             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    3629             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3630             :                         NTCREATEX_SHARE_ACCESS_WRITE |
    3631             :                         NTCREATEX_SHARE_ACCESS_DELETE,
    3632             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3633             :                 .in.fname = DNAME,
    3634             :         };
    3635             : 
    3636           2 :         status = smb2_create(tree, tctx, &c);
    3637           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3638             :                                         "smb2_create\n");
    3639           2 :         h1 = c.out.file.handle;
    3640             : 
    3641             :         /* Try to set temporary attribute on directory */
    3642           2 :         SET_ATTRIB(FILE_ATTRIBUTE_TEMPORARY);
    3643             : 
    3644           2 :         torture_assert_ntstatus_equal_goto(tctx, status,
    3645             :                                            NT_STATUS_INVALID_PARAMETER,
    3646             :                                            ret, done,
    3647             :                                            "Unexpected setinfo result\n");
    3648             : 
    3649           2 : done:
    3650           2 :         if (!smb2_util_handle_empty(h1)) {
    3651           2 :                 smb2_util_close(tree, h1);
    3652             :         }
    3653           2 :         smb2_util_unlink(tree, fname);
    3654           2 :         smb2_deltree(tree, fname);
    3655             : 
    3656           2 :         return ret;
    3657             : }
    3658             : 
    3659             : /*
    3660             :   test opening quota fakefile handle and returned attributes
    3661             : */
    3662           2 : static bool test_smb2_open_quota_fake_file(struct torture_context *tctx,
    3663             :                                            struct smb2_tree *tree)
    3664             : {
    3665           2 :         const char *fname = "$Extend\\$Quota:$Q:$INDEX_ALLOCATION";
    3666             :         struct smb2_create create;
    3667           2 :         struct smb2_handle h = {{0}};
    3668             :         NTSTATUS status;
    3669           2 :         bool ret = true;
    3670             : 
    3671           2 :         create = (struct smb2_create) {
    3672             :                 .in.desired_access = SEC_RIGHTS_FILE_READ,
    3673             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3674             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3675             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3676             :                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
    3677             :                 .in.fname = fname,
    3678             :         };
    3679             : 
    3680           2 :         status = smb2_create(tree, tree, &create);
    3681           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3682             :                                         "smb2_create failed\n");
    3683           1 :         h = create.out.file.handle;
    3684             : 
    3685           1 :         torture_assert_u64_equal_goto(tctx,
    3686             :                                       create.out.file_attr,
    3687             :                                       FILE_ATTRIBUTE_HIDDEN
    3688             :                                       | FILE_ATTRIBUTE_SYSTEM
    3689             :                                       | FILE_ATTRIBUTE_DIRECTORY
    3690             :                                       | FILE_ATTRIBUTE_ARCHIVE,
    3691             :                                       ret,
    3692             :                                       done,
    3693             :                                       "Wrong attributes\n");
    3694             : 
    3695           1 :         torture_assert_u64_equal_goto(tctx,
    3696             :                                       create.out.create_time, 0,
    3697             :                                       ret,
    3698             :                                       done,
    3699             :                                       "create_time is not 0\n");
    3700           1 :         torture_assert_u64_equal_goto(tctx,
    3701             :                                       create.out.access_time, 0,
    3702             :                                       ret,
    3703             :                                       done,
    3704             :                                       "access_time is not 0\n");
    3705           1 :         torture_assert_u64_equal_goto(tctx,
    3706             :                                       create.out.write_time, 0,
    3707             :                                       ret,
    3708             :                                       done,
    3709             :                                       "write_time is not 0\n");
    3710           1 :         torture_assert_u64_equal_goto(tctx,
    3711             :                                       create.out.change_time, 0,
    3712             :                                       ret,
    3713             :                                       done,
    3714             :                                       "change_time is not 0\n");
    3715             : 
    3716           1 : done:
    3717           2 :         smb2_util_close(tree, h);
    3718           2 :         return ret;
    3719             : }
    3720             : 
    3721             : /*
    3722             :    stress testing path base operations
    3723             :    e.g. contention on lockting.tdb records
    3724             :  */
    3725             : 
    3726             : struct test_smb2_bench_path_contention_shared_conn;
    3727             : struct test_smb2_bench_path_contention_shared_loop;
    3728             : 
    3729             : struct test_smb2_bench_path_contention_shared_state {
    3730             :         struct torture_context *tctx;
    3731             :         size_t num_conns;
    3732             :         struct test_smb2_bench_path_contention_shared_conn *conns;
    3733             :         size_t num_loops;
    3734             :         struct test_smb2_bench_path_contention_shared_loop *loops;
    3735             :         struct timeval starttime;
    3736             :         int timecount;
    3737             :         int timelimit;
    3738             :         struct {
    3739             :                 uint64_t num_finished;
    3740             :                 double total_latency;
    3741             :                 double min_latency;
    3742             :                 double max_latency;
    3743             :         } opens;
    3744             :         struct {
    3745             :                 uint64_t num_finished;
    3746             :                 double total_latency;
    3747             :                 double min_latency;
    3748             :                 double max_latency;
    3749             :         } closes;
    3750             :         bool ok;
    3751             :         bool stop;
    3752             : };
    3753             : 
    3754             : struct test_smb2_bench_path_contention_shared_conn {
    3755             :         struct test_smb2_bench_path_contention_shared_state *state;
    3756             :         int idx;
    3757             :         struct smb2_tree *tree;
    3758             : };
    3759             : 
    3760             : struct test_smb2_bench_path_contention_shared_loop {
    3761             :         struct test_smb2_bench_path_contention_shared_state *state;
    3762             :         struct test_smb2_bench_path_contention_shared_conn *conn;
    3763             :         int idx;
    3764             :         struct tevent_immediate *im;
    3765             :         struct {
    3766             :                 struct smb2_create io;
    3767             :                 struct smb2_request *req;
    3768             :                 struct timeval starttime;
    3769             :                 uint64_t num_started;
    3770             :                 uint64_t num_finished;
    3771             :                 double total_latency;
    3772             :                 double min_latency;
    3773             :                 double max_latency;
    3774             :         } opens;
    3775             :         struct {
    3776             :                 struct smb2_close io;
    3777             :                 struct smb2_request *req;
    3778             :                 struct timeval starttime;
    3779             :                 uint64_t num_started;
    3780             :                 uint64_t num_finished;
    3781             :                 double total_latency;
    3782             :                 double min_latency;
    3783             :                 double max_latency;
    3784             :         } closes;
    3785             :         NTSTATUS error;
    3786             : };
    3787             : 
    3788             : static void test_smb2_bench_path_contention_loop_open(
    3789             :         struct test_smb2_bench_path_contention_shared_loop *loop);
    3790             : 
    3791           8 : static void test_smb2_bench_path_contention_loop_start(struct tevent_context *ctx,
    3792             :                                                        struct tevent_immediate *im,
    3793             :                                                        void *private_data)
    3794             : {
    3795           8 :         struct test_smb2_bench_path_contention_shared_loop *loop =
    3796             :                 (struct test_smb2_bench_path_contention_shared_loop *)
    3797             :                 private_data;
    3798             : 
    3799           8 :         test_smb2_bench_path_contention_loop_open(loop);
    3800           8 : }
    3801             : 
    3802             : static void test_smb2_bench_path_contention_loop_opened(struct smb2_request *req);
    3803             : 
    3804       10752 : static void test_smb2_bench_path_contention_loop_open(
    3805             :         struct test_smb2_bench_path_contention_shared_loop *loop)
    3806             : {
    3807       10752 :         struct test_smb2_bench_path_contention_shared_state *state = loop->state;
    3808             : 
    3809       10752 :         loop->opens.num_started += 1;
    3810       10752 :         loop->opens.starttime = timeval_current();
    3811       10752 :         loop->opens.req = smb2_create_send(loop->conn->tree, &loop->opens.io);
    3812       10752 :         torture_assert_goto(state->tctx, loop->opens.req != NULL,
    3813             :                             state->ok, asserted, "smb2_create_send");
    3814             : 
    3815       10752 :         loop->opens.req->async.fn = test_smb2_bench_path_contention_loop_opened;
    3816       10752 :         loop->opens.req->async.private_data = loop;
    3817       10752 :         return;
    3818           0 : asserted:
    3819           0 :         state->stop = true;
    3820             : }
    3821             : 
    3822             : static void test_smb2_bench_path_contention_loop_close(
    3823             :         struct test_smb2_bench_path_contention_shared_loop *loop);
    3824             : 
    3825       10746 : static void test_smb2_bench_path_contention_loop_opened(struct smb2_request *req)
    3826             : {
    3827       10746 :         struct test_smb2_bench_path_contention_shared_loop *loop =
    3828             :                 (struct test_smb2_bench_path_contention_shared_loop *)
    3829             :                 req->async.private_data;
    3830       10746 :         struct test_smb2_bench_path_contention_shared_state *state = loop->state;
    3831       10746 :         double latency = timeval_elapsed(&loop->opens.starttime);
    3832       10746 :         TALLOC_CTX *frame = talloc_stackframe();
    3833             : 
    3834       10746 :         torture_assert_goto(state->tctx, loop->opens.req == req,
    3835             :                             state->ok, asserted, __location__);
    3836       10746 :         loop->error = smb2_create_recv(req, frame, &loop->opens.io);
    3837       10746 :         torture_assert_ntstatus_ok_goto(state->tctx, loop->error,
    3838             :                                         state->ok, asserted, __location__);
    3839       10746 :         ZERO_STRUCT(loop->opens.io.out.blobs);
    3840       10746 :         SMB_ASSERT(latency >= 0.000001);
    3841             : 
    3842       10746 :         if (loop->opens.num_finished == 0) {
    3843             :                 /* first round */
    3844           8 :                 loop->opens.min_latency = latency;
    3845           8 :                 loop->opens.max_latency = latency;
    3846             :         }
    3847             : 
    3848       10746 :         loop->opens.num_finished += 1;
    3849       10746 :         loop->opens.total_latency += latency;
    3850             : 
    3851       10746 :         if (latency < loop->opens.min_latency) {
    3852          59 :                 loop->opens.min_latency = latency;
    3853             :         }
    3854             : 
    3855       10746 :         if (latency > loop->opens.max_latency) {
    3856          25 :                 loop->opens.max_latency = latency;
    3857             :         }
    3858             : 
    3859       10746 :         TALLOC_FREE(frame);
    3860       10746 :         test_smb2_bench_path_contention_loop_close(loop);
    3861       10746 :         return;
    3862           0 : asserted:
    3863           0 :         state->stop = true;
    3864           0 :         TALLOC_FREE(frame);
    3865             : }
    3866             : 
    3867             : static void test_smb2_bench_path_contention_loop_closed(struct smb2_request *req);
    3868             : 
    3869       10746 : static void test_smb2_bench_path_contention_loop_close(
    3870             :         struct test_smb2_bench_path_contention_shared_loop *loop)
    3871             : {
    3872       10746 :         struct test_smb2_bench_path_contention_shared_state *state = loop->state;
    3873             : 
    3874       10746 :         loop->closes.num_started += 1;
    3875       10746 :         loop->closes.starttime = timeval_current();
    3876       10746 :         loop->closes.io.in.file = loop->opens.io.out.file;
    3877       10746 :         loop->closes.req = smb2_close_send(loop->conn->tree, &loop->closes.io);
    3878       10746 :         torture_assert_goto(state->tctx, loop->closes.req != NULL,
    3879             :                             state->ok, asserted, "smb2_close_send");
    3880             : 
    3881       10746 :         loop->closes.req->async.fn = test_smb2_bench_path_contention_loop_closed;
    3882       10746 :         loop->closes.req->async.private_data = loop;
    3883       10746 :         return;
    3884           0 : asserted:
    3885           0 :         state->stop = true;
    3886             : }
    3887             : 
    3888       10744 : static void test_smb2_bench_path_contention_loop_closed(struct smb2_request *req)
    3889             : {
    3890       10744 :         struct test_smb2_bench_path_contention_shared_loop *loop =
    3891             :                 (struct test_smb2_bench_path_contention_shared_loop *)
    3892             :                 req->async.private_data;
    3893       10744 :         struct test_smb2_bench_path_contention_shared_state *state = loop->state;
    3894       10744 :         double latency = timeval_elapsed(&loop->closes.starttime);
    3895             : 
    3896       10744 :         torture_assert_goto(state->tctx, loop->closes.req == req,
    3897             :                             state->ok, asserted, __location__);
    3898       10744 :         loop->error = smb2_close_recv(req, &loop->closes.io);
    3899       10744 :         torture_assert_ntstatus_ok_goto(state->tctx, loop->error,
    3900             :                                         state->ok, asserted, __location__);
    3901       10744 :         SMB_ASSERT(latency >= 0.000001);
    3902       10744 :         if (loop->closes.num_finished == 0) {
    3903             :                 /* first round */
    3904           8 :                 loop->closes.min_latency = latency;
    3905           8 :                 loop->closes.max_latency = latency;
    3906             :         }
    3907       10744 :         loop->closes.num_finished += 1;
    3908             : 
    3909       10744 :         loop->closes.total_latency += latency;
    3910             : 
    3911       10744 :         if (latency < loop->closes.min_latency) {
    3912          47 :                 loop->closes.min_latency = latency;
    3913             :         }
    3914             : 
    3915       10744 :         if (latency > loop->closes.max_latency) {
    3916          39 :                 loop->closes.max_latency = latency;
    3917             :         }
    3918             : 
    3919       10744 :         test_smb2_bench_path_contention_loop_open(loop);
    3920       10744 :         return;
    3921           0 : asserted:
    3922           0 :         state->stop = true;
    3923             : }
    3924             : 
    3925           2 : static void test_smb2_bench_path_contention_progress(struct tevent_context *ev,
    3926             :                                                      struct tevent_timer *te,
    3927             :                                                      struct timeval current_time,
    3928             :                                                      void *private_data)
    3929             : {
    3930           2 :         struct test_smb2_bench_path_contention_shared_state *state =
    3931             :                 (struct test_smb2_bench_path_contention_shared_state *)private_data;
    3932           2 :         uint64_t num_opens = 0;
    3933           2 :         double total_open_latency = 0;
    3934           2 :         double min_open_latency = 0;
    3935           2 :         double max_open_latency = 0;
    3936           2 :         double avs_open_latency = 0;
    3937           2 :         uint64_t num_closes = 0;
    3938           2 :         double total_close_latency = 0;
    3939           2 :         double min_close_latency = 0;
    3940           2 :         double max_close_latency = 0;
    3941           2 :         double avs_close_latency = 0;
    3942             :         size_t i;
    3943             : 
    3944           2 :         state->timecount += 1;
    3945             : 
    3946          10 :         for (i=0;i<state->num_loops;i++) {
    3947           8 :                 struct test_smb2_bench_path_contention_shared_loop *loop =
    3948           8 :                         &state->loops[i];
    3949             : 
    3950           8 :                 num_opens += loop->opens.num_finished;
    3951           8 :                 total_open_latency += loop->opens.total_latency;
    3952           8 :                 if (min_open_latency == 0.0 && loop->opens.min_latency != 0.0) {
    3953           2 :                         min_open_latency = loop->opens.min_latency;
    3954             :                 }
    3955           8 :                 if (loop->opens.min_latency < min_open_latency) {
    3956           0 :                         min_open_latency = loop->opens.min_latency;
    3957             :                 }
    3958           8 :                 if (max_open_latency == 0.0) {
    3959           2 :                         max_open_latency = loop->opens.max_latency;
    3960             :                 }
    3961           8 :                 if (loop->opens.max_latency > max_open_latency) {
    3962           3 :                         max_open_latency = loop->opens.max_latency;
    3963             :                 }
    3964           8 :                 loop->opens.num_finished = 0;
    3965           8 :                 loop->opens.total_latency = 0.0;
    3966             : 
    3967           8 :                 num_closes += loop->closes.num_finished;
    3968           8 :                 total_close_latency += loop->closes.total_latency;
    3969           8 :                 if (min_close_latency == 0.0 && loop->closes.min_latency != 0.0) {
    3970           2 :                         min_close_latency = loop->closes.min_latency;
    3971             :                 }
    3972           8 :                 if (loop->closes.min_latency < min_close_latency) {
    3973           0 :                         min_close_latency = loop->closes.min_latency;
    3974             :                 }
    3975           8 :                 if (max_close_latency == 0.0) {
    3976           2 :                         max_close_latency = loop->closes.max_latency;
    3977             :                 }
    3978           8 :                 if (loop->closes.max_latency > max_close_latency) {
    3979           2 :                         max_close_latency = loop->closes.max_latency;
    3980             :                 }
    3981           8 :                 loop->closes.num_finished = 0;
    3982           8 :                 loop->closes.total_latency = 0.0;
    3983             :         }
    3984             : 
    3985           2 :         state->opens.num_finished += num_opens;
    3986           2 :         state->opens.total_latency += total_open_latency;
    3987           2 :         if (state->opens.min_latency == 0.0 && min_open_latency != 0.0) {
    3988           2 :                 state->opens.min_latency = min_open_latency;
    3989             :         }
    3990           2 :         if (min_open_latency < state->opens.min_latency) {
    3991           0 :                 state->opens.min_latency = min_open_latency;
    3992             :         }
    3993           2 :         if (state->opens.max_latency == 0.0) {
    3994           2 :                 state->opens.max_latency = max_open_latency;
    3995             :         }
    3996           2 :         if (max_open_latency > state->opens.max_latency) {
    3997           0 :                 state->opens.max_latency = max_open_latency;
    3998             :         }
    3999             : 
    4000           2 :         state->closes.num_finished += num_closes;
    4001           2 :         state->closes.total_latency += total_close_latency;
    4002           2 :         if (state->closes.min_latency == 0.0 && min_close_latency != 0.0) {
    4003           2 :                 state->closes.min_latency = min_close_latency;
    4004             :         }
    4005           2 :         if (min_close_latency < state->closes.min_latency) {
    4006           0 :                 state->closes.min_latency = min_close_latency;
    4007             :         }
    4008           2 :         if (state->closes.max_latency == 0.0) {
    4009           2 :                 state->closes.max_latency = max_close_latency;
    4010             :         }
    4011           2 :         if (max_close_latency > state->closes.max_latency) {
    4012           0 :                 state->closes.max_latency = max_close_latency;
    4013             :         }
    4014             : 
    4015           2 :         if (state->timecount < state->timelimit) {
    4016           0 :                 te = tevent_add_timer(state->tctx->ev,
    4017             :                                       state,
    4018             :                                       timeval_current_ofs(1, 0),
    4019             :                                       test_smb2_bench_path_contention_progress,
    4020             :                                       state);
    4021           0 :                 torture_assert_goto(state->tctx, te != NULL,
    4022             :                                     state->ok, asserted, "tevent_add_timer");
    4023             : 
    4024           0 :                 if (!torture_setting_bool(state->tctx, "progress", true)) {
    4025           0 :                         return;
    4026             :                 }
    4027             : 
    4028           0 :                 avs_open_latency = total_open_latency / num_opens;
    4029           0 :                 avs_close_latency = total_close_latency / num_closes;
    4030             : 
    4031           0 :                 torture_comment(state->tctx,
    4032             :                                 "%.2f second: "
    4033             :                                 "open[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] "
    4034             :                                 "close[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]     \r",
    4035           0 :                                 timeval_elapsed(&state->starttime),
    4036             :                                 (unsigned long long)num_opens,
    4037             :                                 avs_open_latency,
    4038             :                                 min_open_latency,
    4039             :                                 max_open_latency,
    4040             :                                 (unsigned long long)num_closes,
    4041             :                                 avs_close_latency,
    4042             :                                 min_close_latency,
    4043             :                                 max_close_latency);
    4044           0 :                 return;
    4045             :         }
    4046             : 
    4047           2 :         avs_open_latency = state->opens.total_latency / state->opens.num_finished;
    4048           2 :         avs_close_latency = state->closes.total_latency / state->closes.num_finished;
    4049           2 :         num_opens = state->opens.num_finished / state->timelimit;
    4050           2 :         num_closes = state->closes.num_finished / state->timelimit;
    4051             : 
    4052           2 :         torture_comment(state->tctx,
    4053             :                         "%.2f second: "
    4054             :                         "open[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] "
    4055             :                         "close[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]\n",
    4056           2 :                         timeval_elapsed(&state->starttime),
    4057             :                         (unsigned long long)num_opens,
    4058             :                         avs_open_latency,
    4059             :                         state->opens.min_latency,
    4060             :                         state->opens.max_latency,
    4061             :                         (unsigned long long)num_closes,
    4062             :                         avs_close_latency,
    4063             :                         state->closes.min_latency,
    4064             :                         state->closes.max_latency);
    4065             : 
    4066           2 : asserted:
    4067           2 :         state->stop = true;
    4068             : }
    4069             : 
    4070           2 : static bool test_smb2_bench_path_contention_shared(struct torture_context *tctx,
    4071             :                                                    struct smb2_tree *tree)
    4072             : {
    4073           2 :         struct test_smb2_bench_path_contention_shared_state *state = NULL;
    4074           2 :         bool ret = true;
    4075           2 :         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
    4076           2 :         int torture_qdepth = torture_setting_int(tctx, "qdepth", 1);
    4077             :         size_t i;
    4078           2 :         size_t li = 0;
    4079           2 :         int timelimit = torture_setting_int(tctx, "timelimit", 10);
    4080           2 :         const char *path = torture_setting_string(tctx, "bench_path", "");
    4081           2 :         struct smb2_create open_io = { .level = RAW_OPEN_SMB2, };
    4082           2 :         struct smb2_close close_io = { .level = RAW_CLOSE_SMB2, };
    4083           2 :         struct tevent_timer *te = NULL;
    4084             :         uint32_t timeout_msec;
    4085             : 
    4086           2 :         state = talloc_zero(tctx, struct test_smb2_bench_path_contention_shared_state);
    4087           2 :         torture_assert(tctx, state != NULL, __location__);
    4088           2 :         state->tctx = tctx;
    4089           2 :         state->num_conns = torture_nprocs;
    4090           2 :         state->conns = talloc_zero_array(state,
    4091             :                         struct test_smb2_bench_path_contention_shared_conn,
    4092             :                         state->num_conns);
    4093           2 :         torture_assert(tctx, state->conns != NULL, __location__);
    4094           2 :         state->num_loops = torture_nprocs * torture_qdepth;
    4095           2 :         state->loops = talloc_zero_array(state,
    4096             :                         struct test_smb2_bench_path_contention_shared_loop,
    4097             :                         state->num_loops);
    4098           2 :         torture_assert(tctx, state->loops != NULL, __location__);
    4099           2 :         state->ok = true;
    4100           2 :         state->timelimit = MAX(timelimit, 1);
    4101             : 
    4102           2 :         open_io.in.desired_access = SEC_DIR_READ_ATTRIBUTE;
    4103           2 :         open_io.in.alloc_size = 0;
    4104           2 :         open_io.in.file_attributes = 0;
    4105           2 :         open_io.in.share_access = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
    4106           2 :         open_io.in.create_disposition = FILE_OPEN;
    4107           2 :         open_io.in.create_options = FILE_OPEN_REPARSE_POINT;
    4108           2 :         open_io.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    4109           2 :         open_io.in.security_flags = 0;
    4110           2 :         open_io.in.fname = path;
    4111           2 :         open_io.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    4112           2 :         open_io.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
    4113             : 
    4114           2 :         timeout_msec = tree->session->transport->options.request_timeout * 1000;
    4115             : 
    4116           2 :         torture_comment(tctx, "Opening %zd connections\n", state->num_conns);
    4117             : 
    4118          10 :         for (i=0;i<state->num_conns;i++) {
    4119           8 :                 struct smb2_tree *ct = NULL;
    4120           8 :                 DATA_BLOB out_input_buffer = data_blob_null;
    4121           8 :                 DATA_BLOB out_output_buffer = data_blob_null;
    4122             :                 size_t pcli;
    4123             : 
    4124           8 :                 state->conns[i].state = state;
    4125           8 :                 state->conns[i].idx = i;
    4126             : 
    4127           8 :                 if (!torture_smb2_connection(tctx, &ct)) {
    4128           0 :                         torture_comment(tctx, "Failed opening %zd/%zd connections\n", i, state->num_conns);
    4129           0 :                         return false;
    4130             :                 }
    4131           8 :                 state->conns[i].tree = talloc_steal(state->conns, ct);
    4132             : 
    4133           8 :                 smb2cli_conn_set_max_credits(ct->session->transport->conn, 8192);
    4134           8 :                 smb2cli_ioctl(ct->session->transport->conn,
    4135             :                               timeout_msec,
    4136           8 :                               ct->session->smbXcli,
    4137           8 :                               ct->smbXcli,
    4138             :                               UINT64_MAX, /* in_fid_persistent */
    4139             :                               UINT64_MAX, /* in_fid_volatile */
    4140             :                               UINT32_MAX,
    4141             :                               0, /* in_max_input_length */
    4142             :                               NULL, /* in_input_buffer */
    4143             :                               1, /* in_max_output_length */
    4144             :                               NULL, /* in_output_buffer */
    4145             :                               SMB2_IOCTL_FLAG_IS_FSCTL,
    4146             :                               ct,
    4147             :                               &out_input_buffer,
    4148             :                               &out_output_buffer);
    4149           8 :                 torture_assert(tctx,
    4150             :                        smbXcli_conn_is_connected(ct->session->transport->conn),
    4151             :                        "smbXcli_conn_is_connected");
    4152          16 :                 for (pcli = 0; pcli < torture_qdepth; pcli++) {
    4153           8 :                         struct test_smb2_bench_path_contention_shared_loop *loop = &state->loops[li];
    4154             : 
    4155           8 :                         loop->idx = li++;
    4156           8 :                         loop->state = state;
    4157           8 :                         loop->conn = &state->conns[i];
    4158           8 :                         loop->im = tevent_create_immediate(state->loops);
    4159           8 :                         torture_assert(tctx, loop->im != NULL, __location__);
    4160           8 :                         loop->opens.io = open_io;
    4161           8 :                         loop->closes.io = close_io;
    4162             : 
    4163           8 :                         tevent_schedule_immediate(loop->im,
    4164             :                                                   tctx->ev,
    4165             :                                                   test_smb2_bench_path_contention_loop_start,
    4166             :                                                   loop);
    4167             :                 }
    4168             :         }
    4169             : 
    4170           2 :         torture_comment(tctx, "Opened %zu connections with qdepth=%d => %zu loops\n",
    4171             :                         state->num_conns, torture_qdepth, state->num_loops);
    4172             : 
    4173           2 :         torture_comment(tctx, "Running for %d seconds\n", state->timelimit);
    4174             : 
    4175           2 :         state->starttime = timeval_current();
    4176             : 
    4177           2 :         te = tevent_add_timer(tctx->ev,
    4178             :                               state,
    4179             :                               timeval_current_ofs(1, 0),
    4180             :                               test_smb2_bench_path_contention_progress,
    4181             :                               state);
    4182           2 :         torture_assert(tctx, te != NULL, __location__);
    4183             : 
    4184       80143 :         while (!state->stop) {
    4185       80141 :                 int rc = tevent_loop_once(tctx->ev);
    4186       80141 :                 torture_assert_int_equal(tctx, rc, 0, "tevent_loop_once");
    4187             :         }
    4188             : 
    4189           2 :         torture_comment(tctx, "%.2f seconds\n", timeval_elapsed(&state->starttime));
    4190           2 :         TALLOC_FREE(state);
    4191           2 :         return ret;
    4192             : }
    4193             : 
    4194             : /**
    4195             :   Find Maximum Path Length
    4196             :  */
    4197           0 : static bool generate_path(const size_t len,
    4198             :                           char *buffer,
    4199             :                           const size_t buf_len)
    4200             : {
    4201             :         size_t i;
    4202             : 
    4203           0 :         if (len >= buf_len) {
    4204           0 :                 return false;
    4205             :         }
    4206             : 
    4207           0 :         for (i = 0; i < len ; i++) {
    4208           0 :                 buffer[i] = (char)(i % 10) + 48;
    4209             :         }
    4210           0 :         buffer[i] = '\0';
    4211           0 :         return true;
    4212             : }
    4213             : 
    4214           2 : static bool test_path_length_test(struct torture_context *tctx,
    4215             :                                   struct smb2_tree *tree)
    4216             : {
    4217           2 :         const size_t max_name = 2048;
    4218           2 :         char *name = talloc_array(tctx, char, max_name);
    4219           2 :         struct smb2_handle fh = {{0}};
    4220           2 :         size_t length = 128;
    4221           2 :         size_t max_file_name = 0;
    4222           2 :         size_t max_path_length = 0;
    4223           2 :         char *path_ok = NULL;
    4224           2 :         char *path_next = NULL;
    4225           2 :         char *topdir = NULL;
    4226           2 :         bool is_interactive = torture_setting_bool(tctx, "interactive", false);
    4227             :         NTSTATUS status;
    4228           2 :         bool ret = true;
    4229             : 
    4230           2 :         if (!is_interactive) {
    4231           2 :                 torture_result(tctx, TORTURE_SKIP,
    4232             :                                "Interactive Test: Skipping... "
    4233             :                                "(enable with --interactive)\n");
    4234           2 :                 return ret;
    4235             :         }
    4236             : 
    4237           0 :         torture_comment(tctx, "Testing filename and path lengths\n");
    4238             : 
    4239             :         /* Find Longest File Name */
    4240           0 :         for (length = 128; length < max_name; length++) {
    4241           0 :                 if (!generate_path(length, name, max_name))  {
    4242           0 :                         torture_result(tctx, TORTURE_FAIL,
    4243             :                                        "Failed to generate path.");
    4244           0 :                         return false;
    4245             :                 }
    4246             : 
    4247           0 :                 status = torture_smb2_testfile(tree, name, &fh);
    4248           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4249           0 :                         break;
    4250             :                 }
    4251             : 
    4252           0 :                 smb2_util_close(tree, fh);
    4253           0 :                 smb2_util_unlink(tree, name);
    4254             : 
    4255           0 :                 max_file_name = length;
    4256             :         }
    4257             : 
    4258           0 :         torture_assert_int_not_equal_goto(tctx, length, max_name, ret, done,
    4259             :                                           "Name too big\n");
    4260             : 
    4261           0 :         torture_comment(tctx, "Max file name length: %zu\n", max_file_name);
    4262             : 
    4263             :         /* Remove one char that caused the failure above */
    4264           0 :         name[max_file_name] = '\0';
    4265             : 
    4266           0 :         path_ok = talloc_strdup(tree, name);
    4267           0 :         torture_assert_not_null_goto(tctx, path_ok, ret, done,
    4268             :                                      "talloc_strdup failed\n");
    4269             : 
    4270           0 :         topdir = talloc_strdup(tree, name);
    4271           0 :         torture_assert_not_null_goto(tctx, topdir, ret, done,
    4272             :                                      "talloc_strdup failed\n");
    4273             : 
    4274           0 :         status = smb2_util_mkdir(tree, path_ok);
    4275           0 :         if (!NT_STATUS_IS_OK(status)) {
    4276           0 :                 torture_comment(tctx, "mkdir [%s] failed: %s\n",
    4277             :                                 path_ok, nt_errstr(status));
    4278           0 :                 torture_result(tctx, TORTURE_FAIL, "Initial mkdir failed");
    4279           0 :                 return false;
    4280             :         }
    4281             : 
    4282             :         while (true) {
    4283           0 :                 path_next = talloc_asprintf(tctx, "%s\\%s", path_ok, name);
    4284           0 :                 torture_assert_not_null_goto(tctx, path_next, ret, done,
    4285             :                                              "talloc_asprintf failed\n");
    4286             : 
    4287           0 :                 status = smb2_util_mkdir(tree, path_next);
    4288           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4289           0 :                         break;
    4290             :                 }
    4291             : 
    4292           0 :                 path_ok = path_next;
    4293             :         }
    4294             : 
    4295           0 :         for (length = 1; length < max_name; length++) {
    4296           0 :                 if (!generate_path(length, name, max_name))  {
    4297           0 :                         torture_result(tctx, TORTURE_FAIL,
    4298             :                                        "Failed to generate path.");
    4299           0 :                         return false;
    4300             :                 }
    4301             : 
    4302           0 :                 path_next = talloc_asprintf(tctx, "%s\\%s", path_ok, name);
    4303           0 :                 torture_assert_not_null_goto(tctx, path_next, ret, done,
    4304             :                                              "talloc_asprintf failed\n");
    4305             : 
    4306           0 :                 status = torture_smb2_testfile(tree, path_next, &fh);
    4307           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4308           0 :                         break;
    4309             :                 }
    4310           0 :                 smb2_util_close(tree, fh);
    4311           0 :                 path_ok = path_next;
    4312             :         }
    4313             : 
    4314           0 :         max_path_length = talloc_array_length(path_ok);
    4315             : 
    4316           0 :         torture_comment(tctx, "Max path name length: %zu\n", max_path_length);
    4317             : 
    4318           0 : done:
    4319           0 :         return ret;
    4320             : }
    4321             : 
    4322             : /*
    4323             :    basic testing of SMB2 read
    4324             : */
    4325         966 : struct torture_suite *torture_smb2_create_init(TALLOC_CTX *ctx)
    4326             : {
    4327         966 :         struct torture_suite *suite = torture_suite_create(ctx, "create");
    4328             : 
    4329         966 :         torture_suite_add_1smb2_test(suite, "gentest", test_create_gentest);
    4330         966 :         torture_suite_add_1smb2_test(suite, "blob", test_create_blob);
    4331         966 :         torture_suite_add_1smb2_test(suite, "open", test_smb2_open);
    4332         966 :         torture_suite_add_1smb2_test(suite, "brlocked", test_smb2_open_brlocked);
    4333         966 :         torture_suite_add_1smb2_test(suite, "multi", test_smb2_open_multi);
    4334         966 :         torture_suite_add_1smb2_test(suite, "delete", test_smb2_open_for_delete);
    4335         966 :         torture_suite_add_1smb2_test(suite, "leading-slash", test_smb2_leading_slash);
    4336         966 :         torture_suite_add_1smb2_test(suite, "impersonation", test_smb2_impersonation_level);
    4337         966 :         torture_suite_add_1smb2_test(suite, "aclfile", test_create_acl_file);
    4338         966 :         torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir);
    4339         966 :         torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl);
    4340         966 :         torture_suite_add_1smb2_test(suite, "mkdir-dup", test_mkdir_dup);
    4341         966 :         torture_suite_add_1smb2_test(suite, "dir-alloc-size", test_dir_alloc_size);
    4342         966 :         torture_suite_add_1smb2_test(suite, "dosattr_tmp_dir", test_dosattr_tmp_dir);
    4343         966 :         torture_suite_add_1smb2_test(suite, "quota-fake-file", test_smb2_open_quota_fake_file);
    4344         966 :         torture_suite_add_1smb2_test(suite, "path-length", test_path_length_test);
    4345         966 :         torture_suite_add_1smb2_test(suite, "bench-path-contention-shared", test_smb2_bench_path_contention_shared);
    4346             : 
    4347         966 :         suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
    4348             : 
    4349         966 :         return suite;
    4350             : }
    4351             : 
    4352         966 : struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx)
    4353             : {
    4354         966 :         struct torture_suite *suite = torture_suite_create(ctx, "twrp");
    4355             : 
    4356         966 :         torture_suite_add_1smb2_test(suite, "write", test_twrp_write);
    4357         966 :         torture_suite_add_1smb2_test(suite, "stream", test_twrp_stream);
    4358         966 :         torture_suite_add_1smb2_test(suite, "openroot", test_twrp_openroot);
    4359         966 :         torture_suite_add_1smb2_test(suite, "listdir", test_twrp_listdir);
    4360             : 
    4361         966 :         suite->description = talloc_strdup(suite, "SMB2-TWRP tests");
    4362             : 
    4363         966 :         return suite;
    4364             : }
    4365             : 
    4366             : /*
    4367             :    basic testing of SMB2 File-IDs
    4368             : */
    4369         966 : struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx)
    4370             : {
    4371         966 :         struct torture_suite *suite = torture_suite_create(ctx, "fileid");
    4372             : 
    4373         966 :         torture_suite_add_1smb2_test(suite, "fileid", test_fileid);
    4374         966 :         torture_suite_add_1smb2_test(suite, "fileid-dir", test_fileid_dir);
    4375         966 :         torture_suite_add_1smb2_test(suite, "unique", test_fileid_unique);
    4376         966 :         torture_suite_add_1smb2_test(suite, "unique-dir", test_fileid_unique_dir);
    4377             : 
    4378         966 :         suite->description = talloc_strdup(suite, "SMB2-FILEID tests");
    4379             : 
    4380         966 :         return suite;
    4381             : }
    4382             : 
    4383         966 : struct torture_suite *torture_smb2_bench_init(TALLOC_CTX *ctx)
    4384             : {
    4385         966 :         struct torture_suite *suite = torture_suite_create(ctx, "bench");
    4386             : 
    4387         966 :         torture_suite_add_1smb2_test(suite, "oplock1", test_smb2_bench_oplock);
    4388         966 :         torture_suite_add_1smb2_test(suite, "path-contention-shared", test_smb2_bench_path_contention_shared);
    4389         966 :         torture_suite_add_1smb2_test(suite, "echo", test_smb2_bench_echo);
    4390             : 
    4391         966 :         suite->description = talloc_strdup(suite, "SMB2-BENCH tests");
    4392             : 
    4393         966 :         return suite;
    4394             : }
    4395             : 
    4396           0 : static bool test_no_stream(struct torture_context *tctx,
    4397             :                            struct smb2_tree *tree)
    4398             : {
    4399             :         struct smb2_create c;
    4400             :         NTSTATUS status;
    4401           0 :         bool ret = true;
    4402           0 :         const char *names[] = {
    4403             :                 "test_no_stream::$DATA",
    4404             :                 "test_no_stream::foooooooooooo",
    4405             :                 "test_no_stream:stream",
    4406             :                 "test_no_stream:stream:$DATA",
    4407             :                 NULL
    4408             :         };
    4409             :         int i;
    4410             : 
    4411           0 :         for (i = 0; names[i] != NULL; i++) {
    4412           0 :                 c = (struct smb2_create) {
    4413             :                         .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED,
    4414             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    4415             :                         .in.create_disposition = NTCREATEX_DISP_OPEN,
    4416             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    4417           0 :                         .in.fname = names[i],
    4418             :                 };
    4419             : 
    4420           0 :                 status = smb2_create(tree, tctx, &c);
    4421           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
    4422           0 :                         torture_comment(
    4423             :                                 tctx, "Expected NT_STATUS_OBJECT_NAME_INVALID, "
    4424             :                                 "got %s, name: '%s'\n",
    4425             :                                 nt_errstr(status), names[i]);
    4426           0 :                         torture_fail_goto(tctx, done, "Bad create result\n");
    4427             :                 }
    4428             :         }
    4429           0 : done:
    4430           0 :         return ret;
    4431             : }
    4432             : 
    4433         966 : struct torture_suite *torture_smb2_create_no_streams_init(TALLOC_CTX *ctx)
    4434             : {
    4435         966 :         struct torture_suite *suite = torture_suite_create(ctx, "create_no_streams");
    4436             : 
    4437         966 :         torture_suite_add_1smb2_test(suite, "no_stream", test_no_stream);
    4438             : 
    4439         966 :         suite->description = talloc_strdup(suite, "SMB2-CREATE stream test on share without streams support");
    4440             : 
    4441         966 :         return suite;
    4442             : }

Generated by: LCOV version 1.14