LCOV - code coverage report
Current view: top level - source4/torture/smb2 - create.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1174 1854 63.3 %
Date: 2024-06-13 04:01:37 Functions: 28 43 65.1 %

          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           0 :         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          51 :                         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 :         CHECK_VAL(io.smb2.out.alloc_size, 0);
    1197           1 :         smb2_util_unlink(tree, fname);
    1198             : 
    1199           1 : done:
    1200           1 :         smb2_util_close(tree, h1);
    1201           1 :         smb2_util_unlink(tree, fname);
    1202           1 :         smb2_deltree(tree, DNAME);
    1203           1 :         return ret;
    1204             : }
    1205             : 
    1206             : /*
    1207             :   test with an already opened and byte range locked file
    1208             : */
    1209             : 
    1210           2 : static bool test_smb2_open_brlocked(struct torture_context *tctx,
    1211             :                                     struct smb2_tree *tree)
    1212             : {
    1213             :         union smb_open io, io1;
    1214             :         union smb_lock io2;
    1215             :         struct smb2_lock_element lock[1];
    1216           2 :         const char *fname = DNAME "\\torture_ntcreatex.txt";
    1217             :         NTSTATUS status;
    1218           2 :         bool ret = true;
    1219             :         struct smb2_handle h;
    1220           2 :         char b = 42;
    1221             : 
    1222           2 :         torture_comment(tctx,
    1223             :                 "Testing SMB2 open with a byte range locked file\n");
    1224             : 
    1225           2 :         smb2_util_unlink(tree, fname);
    1226             : 
    1227           2 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1228           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1229             : 
    1230           2 :         ZERO_STRUCT(io.smb2);
    1231           2 :         io.generic.level = RAW_OPEN_SMB2;
    1232           2 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1233           2 :         io.smb2.in.desired_access = 0x2019f;
    1234           2 :         io.smb2.in.alloc_size = 0;
    1235           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1236           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1237             :                 NTCREATEX_SHARE_ACCESS_WRITE;
    1238           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1239           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
    1240           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
    1241           2 :         io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
    1242           2 :         io.smb2.in.fname = fname;
    1243             : 
    1244           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1245           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1246             : 
    1247           2 :         status = smb2_util_write(tree, io.smb2.out.file.handle, &b, 0, 1);
    1248           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1249             : 
    1250           2 :         ZERO_STRUCT(io2.smb2);
    1251           2 :         io2.smb2.level = RAW_LOCK_SMB2;
    1252           2 :         io2.smb2.in.file.handle = io.smb2.out.file.handle;
    1253           2 :         io2.smb2.in.lock_count = 1;
    1254             : 
    1255           2 :         ZERO_STRUCT(lock);
    1256           2 :         lock[0].offset = 0;
    1257           2 :         lock[0].length = 1;
    1258           2 :         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
    1259             :                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    1260           2 :         io2.smb2.in.locks = &lock[0];
    1261           2 :         status = smb2_lock(tree, &(io2.smb2));
    1262           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1263             : 
    1264           2 :         ZERO_STRUCT(io1.smb2);
    1265           2 :         io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1266           2 :         io1.smb2.in.desired_access = 0x20196;
    1267           2 :         io1.smb2.in.alloc_size = 0;
    1268           2 :         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1269           2 :         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1270             :                 NTCREATEX_SHARE_ACCESS_WRITE;
    1271           2 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    1272           2 :         io1.smb2.in.create_options = 0;
    1273           2 :         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
    1274           2 :         io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
    1275           2 :         io1.smb2.in.fname = fname;
    1276             : 
    1277           2 :         status = smb2_create(tree, tctx, &(io1.smb2));
    1278           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1279             : 
    1280           2 :         smb2_util_close(tree, io.smb2.out.file.handle);
    1281           2 :         smb2_util_close(tree, io1.smb2.out.file.handle);
    1282           2 :         smb2_util_unlink(tree, fname);
    1283           2 :         smb2_deltree(tree, DNAME);
    1284             : 
    1285           2 :         return ret;
    1286             : }
    1287             : 
    1288             : /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
    1289             : 
    1290           2 : static bool test_smb2_open_multi(struct torture_context *tctx,
    1291             :                                 struct smb2_tree *tree)
    1292             : {
    1293           2 :         const char *fname = "test_oplock.dat";
    1294             :         NTSTATUS status;
    1295           2 :         bool ret = true;
    1296             :         union smb_open io;
    1297             :         struct smb2_tree **trees;
    1298             :         struct smb2_request **requests;
    1299             :         union smb_open *ios;
    1300           2 :         int i, num_files = 3;
    1301           2 :         int num_ok = 0;
    1302           2 :         int num_collision = 0;
    1303             : 
    1304           2 :         torture_comment(tctx,
    1305             :                 "Testing SMB2 Open with multiple connections\n");
    1306           2 :         trees = talloc_array(tctx, struct smb2_tree *, num_files);
    1307           2 :         requests = talloc_array(tctx, struct smb2_request *, num_files);
    1308           2 :         ios = talloc_array(tctx, union smb_open, num_files);
    1309           2 :         if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
    1310             :             (ios == NULL)) {
    1311           0 :                 torture_comment(tctx, ("talloc failed\n"));
    1312           0 :                 ret = false;
    1313           0 :                 goto done;
    1314             :         }
    1315             : 
    1316           2 :         tree->session->transport->options.request_timeout = 60;
    1317             : 
    1318           8 :         for (i=0; i<num_files; i++) {
    1319           6 :                 if (!torture_smb2_connection(tctx, &(trees[i]))) {
    1320           0 :                         torture_comment(tctx,
    1321             :                                 "Could not open %d'th connection\n", i);
    1322           0 :                         ret = false;
    1323           0 :                         goto done;
    1324             :                 }
    1325           6 :                 trees[i]->session->transport->options.request_timeout = 60;
    1326             :         }
    1327             : 
    1328             :         /* cleanup */
    1329           2 :         smb2_util_unlink(tree, fname);
    1330             : 
    1331             :         /*
    1332             :           base ntcreatex parms
    1333             :         */
    1334           2 :         ZERO_STRUCT(io.smb2);
    1335           2 :         io.generic.level = RAW_OPEN_SMB2;
    1336           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1337           2 :         io.smb2.in.alloc_size = 0;
    1338           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1339           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1340             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1341             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1342           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1343           2 :         io.smb2.in.create_options = 0;
    1344           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1345           2 :         io.smb2.in.security_flags = 0;
    1346           2 :         io.smb2.in.fname = fname;
    1347           2 :         io.smb2.in.create_flags = 0;
    1348             : 
    1349           8 :         for (i=0; i<num_files; i++) {
    1350           6 :                 ios[i] = io;
    1351           6 :                 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
    1352           6 :                 if (requests[i] == NULL) {
    1353           0 :                         torture_comment(tctx,
    1354             :                                 "could not send %d'th request\n", i);
    1355           0 :                         ret = false;
    1356           0 :                         goto done;
    1357             :                 }
    1358             :         }
    1359             : 
    1360           2 :         torture_comment(tctx, "waiting for replies\n");
    1361          24 :         while (1) {
    1362          26 :                 bool unreplied = false;
    1363          47 :                 for (i=0; i<num_files; i++) {
    1364          45 :                         if (requests[i] == NULL) {
    1365          15 :                                 continue;
    1366             :                         }
    1367          30 :                         if (requests[i]->state < SMB2_REQUEST_DONE) {
    1368          24 :                                 unreplied = true;
    1369          24 :                                 break;
    1370             :                         }
    1371           6 :                         status = smb2_create_recv(requests[i], tctx,
    1372           6 :                                                   &(ios[i].smb2));
    1373             : 
    1374           6 :                         torture_comment(tctx,
    1375             :                                 "File %d returned status %s\n", i,
    1376             :                                 nt_errstr(status));
    1377             : 
    1378           6 :                         if (NT_STATUS_IS_OK(status)) {
    1379           2 :                                 num_ok += 1;
    1380             :                         }
    1381             : 
    1382           6 :                         if (NT_STATUS_EQUAL(status,
    1383             :                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
    1384           4 :                                 num_collision += 1;
    1385             :                         }
    1386             : 
    1387           6 :                         requests[i] = NULL;
    1388             :                 }
    1389          26 :                 if (!unreplied) {
    1390           2 :                         break;
    1391             :                 }
    1392             : 
    1393          24 :                 if (tevent_loop_once(tctx->ev) != 0) {
    1394           0 :                         torture_comment(tctx, "tevent_loop_once failed\n");
    1395           0 :                         ret = false;
    1396           0 :                         goto done;
    1397             :                 }
    1398             :         }
    1399             : 
    1400           2 :         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
    1401           0 :                 ret = false;
    1402             :         }
    1403           4 : done:
    1404           2 :         smb2_deltree(tree, fname);
    1405             : 
    1406           2 :         return ret;
    1407             : }
    1408             : 
    1409             : /*
    1410             :   test opening for delete on a read-only attribute file.
    1411             : */
    1412             : 
    1413           2 : static bool test_smb2_open_for_delete(struct torture_context *tctx,
    1414             :                                       struct smb2_tree *tree)
    1415             : {
    1416             :         union smb_open io;
    1417             :         union smb_fileinfo finfo;
    1418           2 :         const char *fname = DNAME "\\torture_open_for_delete.txt";
    1419             :         NTSTATUS status;
    1420             :         struct smb2_handle h, h1;
    1421           2 :         bool ret = true;
    1422             : 
    1423           2 :         torture_comment(tctx,
    1424             :                 "Checking SMB2_OPEN for delete on a readonly file.\n");
    1425           2 :         smb2_util_unlink(tree, fname);
    1426           2 :         smb2_deltree(tree, fname);
    1427             : 
    1428           2 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1429           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1430             : 
    1431             :         /* reasonable default parameters */
    1432           2 :         ZERO_STRUCT(io.smb2);
    1433           2 :         io.generic.level = RAW_OPEN_SMB2;
    1434           2 :         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    1435           2 :         io.smb2.in.alloc_size = 0;
    1436           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1437           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY;
    1438           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    1439           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1440           2 :         io.smb2.in.create_options = 0;
    1441           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1442           2 :         io.smb2.in.security_flags = 0;
    1443           2 :         io.smb2.in.fname = fname;
    1444             : 
    1445             :         /* Create the readonly file. */
    1446             : 
    1447           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1448           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1449           2 :         h1 = io.smb2.out.file.handle;
    1450             : 
    1451           2 :         CHECK_VAL(io.smb2.out.oplock_level, 0);
    1452           2 :         io.smb2.in.create_options = 0;
    1453           2 :         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
    1454           2 :         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    1455           2 :         smb2_util_close(tree, h1);
    1456             : 
    1457             :         /* Now try and open for delete only - should succeed. */
    1458           2 :         io.smb2.in.desired_access = SEC_STD_DELETE;
    1459           2 :         io.smb2.in.file_attributes = 0;
    1460           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1461             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1462             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1463           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1464           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1465           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1466           2 :         smb2_util_close(tree, io.smb2.out.file.handle);
    1467             : 
    1468             :         /* Clear readonly flag to allow file deletion */
    1469           2 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
    1470             :                                 SEC_FILE_WRITE_ATTRIBUTE;
    1471           2 :         status = smb2_create(tree, tctx, &(io.smb2));
    1472           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1473           2 :         h1 = io.smb2.out.file.handle;
    1474           2 :         SET_ATTRIB(FILE_ATTRIBUTE_ARCHIVE);
    1475           2 :         smb2_util_close(tree, h1);
    1476             : 
    1477           2 :         smb2_util_close(tree, h);
    1478           2 :         smb2_util_unlink(tree, fname);
    1479           2 :         smb2_deltree(tree, DNAME);
    1480             : 
    1481           2 :         return ret;
    1482             : }
    1483             : 
    1484             : /*
    1485             :   test SMB2 open with a leading slash on the path.
    1486             :   Trying to create a directory with a leading slash
    1487             :   should give NT_STATUS_INVALID_PARAMETER error
    1488             : */
    1489           2 : static bool test_smb2_leading_slash(struct torture_context *tctx,
    1490             :                                     struct smb2_tree *tree)
    1491             : {
    1492             :         union smb_open io;
    1493           2 :         const char *dnameslash = "\\"DNAME;
    1494             :         NTSTATUS status;
    1495           2 :         bool ret = true;
    1496             : 
    1497           2 :         torture_comment(tctx,
    1498             :                 "Trying to create a directory with leading slash on path\n");
    1499           2 :         smb2_deltree(tree, dnameslash);
    1500             : 
    1501           2 :         ZERO_STRUCT(io.smb2);
    1502           2 :         io.generic.level = RAW_OPEN_SMB2;
    1503           2 :         io.smb2.in.oplock_level = 0;
    1504           2 :         io.smb2.in.desired_access = SEC_RIGHTS_DIR_ALL;
    1505           2 :         io.smb2.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
    1506           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1507           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1508             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
    1509             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
    1510           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1511           2 :         io.smb2.in.fname = dnameslash;
    1512             : 
    1513           2 :         status = smb2_create(tree, tree, &(io.smb2));
    1514           2 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1515             : 
    1516           2 :         smb2_deltree(tree, dnameslash);
    1517           2 :         return ret;
    1518             : }
    1519             : 
    1520             : /*
    1521             :   test SMB2 open with an invalid impersonation level.
    1522             :   Should give NT_STATUS_BAD_IMPERSONATION_LEVEL error
    1523             : */
    1524           2 : static bool test_smb2_impersonation_level(struct torture_context *tctx,
    1525             :                                     struct smb2_tree *tree)
    1526             : {
    1527             :         union smb_open io;
    1528           2 :         const char *fname = DNAME "\\torture_invalid_impersonation_level.txt";
    1529             :         NTSTATUS status;
    1530             :         struct smb2_handle h;
    1531           2 :         bool ret = true;
    1532             : 
    1533           2 :         torture_comment(tctx,
    1534             :                 "Testing SMB2 open with an invalid impersonation level.\n");
    1535             : 
    1536           2 :         smb2_util_unlink(tree, fname);
    1537           2 :         smb2_util_rmdir(tree, DNAME);
    1538             : 
    1539           2 :         status = torture_smb2_testdir(tree, DNAME, &h);
    1540           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1541             : 
    1542           2 :         ZERO_STRUCT(io.smb2);
    1543           2 :         io.generic.level = RAW_OPEN_SMB2;
    1544           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1545           2 :         io.smb2.in.alloc_size = 0;
    1546           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1547           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1548             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1549             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1550           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1551           2 :         io.smb2.in.create_options = 0;
    1552           2 :         io.smb2.in.impersonation_level = 0x12345678;
    1553           2 :         io.smb2.in.security_flags = 0;
    1554           2 :         io.smb2.in.fname = fname;
    1555           2 :         io.smb2.in.create_flags = 0;
    1556             : 
    1557           2 :         status = smb2_create(tree, tree, &(io.smb2));
    1558           2 :         CHECK_STATUS(status, NT_STATUS_BAD_IMPERSONATION_LEVEL);
    1559             : 
    1560           1 :         smb2_util_close(tree, h);
    1561           1 :         smb2_util_unlink(tree, fname);
    1562           1 :         smb2_deltree(tree, DNAME);
    1563           1 :         return ret;
    1564             : }
    1565             : 
    1566           2 : static bool test_create_acl_file(struct torture_context *tctx,
    1567             :     struct smb2_tree *tree)
    1568             : {
    1569           2 :         torture_comment(tctx, "Testing nttrans create with sec_desc on files\n");
    1570             : 
    1571           2 :         return test_create_acl_ext(tctx, tree, false);
    1572             : }
    1573             : 
    1574           2 : static bool test_create_acl_dir(struct torture_context *tctx,
    1575             :     struct smb2_tree *tree)
    1576             : {
    1577           2 :         torture_comment(tctx, "Testing nttrans create with sec_desc on directories\n");
    1578             : 
    1579           2 :         return test_create_acl_ext(tctx, tree, true);
    1580             : }
    1581             : 
    1582             : #define CHECK_ACCESS_FLAGS(_fh, flags) do { \
    1583             :         union smb_fileinfo _q; \
    1584             :         _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
    1585             :         _q.access_information.in.file.handle = (_fh); \
    1586             :         status = smb2_getinfo_file(tree, tctx, &_q); \
    1587             :         CHECK_STATUS(status, NT_STATUS_OK); \
    1588             :         if (_q.access_information.out.access_flags != (flags)) { \
    1589             :                 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
    1590             :                        __location__, _q.access_information.out.access_flags, (flags)); \
    1591             :                 ret = false; \
    1592             :                 goto done; \
    1593             :         } \
    1594             : } while (0)
    1595             : 
    1596             : /*
    1597             :  * Test creating a file with a NULL DACL.
    1598             :  */
    1599           2 : static bool test_create_null_dacl(struct torture_context *tctx,
    1600             :     struct smb2_tree *tree)
    1601             : {
    1602             :         NTSTATUS status;
    1603             :         struct smb2_create io;
    1604           2 :         const char *fname = "nulldacl.txt";
    1605           2 :         bool ret = true;
    1606             :         struct smb2_handle handle;
    1607             :         union smb_fileinfo q;
    1608             :         union smb_setfileinfo s;
    1609           2 :         struct security_descriptor *sd = security_descriptor_initialise(tctx);
    1610             :         struct security_acl dacl;
    1611             : 
    1612           2 :         torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n");
    1613             : 
    1614           2 :         smb2_util_unlink(tree, fname);
    1615             : 
    1616           2 :         ZERO_STRUCT(io);
    1617           2 :         io.level = RAW_OPEN_SMB2;
    1618           2 :         io.in.create_flags = 0;
    1619           2 :         io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC
    1620             :                 | SEC_STD_WRITE_OWNER;
    1621           2 :         io.in.create_options = 0;
    1622           2 :         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1623           2 :         io.in.share_access =
    1624             :                 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
    1625           2 :         io.in.alloc_size = 0;
    1626           2 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
    1627           2 :         io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
    1628           2 :         io.in.security_flags = 0;
    1629           2 :         io.in.fname = fname;
    1630           2 :         io.in.sec_desc = sd;
    1631             :         /* XXX create_options ? */
    1632           2 :         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1633             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
    1634             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1635             :                                           0x00200000;
    1636             : 
    1637           2 :         torture_comment(tctx, "creating a file with a empty sd\n");
    1638           2 :         status = smb2_create(tree, tctx, &io);
    1639           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1640           2 :         handle = io.out.file.handle;
    1641             : 
    1642           2 :         torture_comment(tctx, "get the original sd\n");
    1643           2 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1644           2 :         q.query_secdesc.in.file.handle = handle;
    1645           2 :         q.query_secdesc.in.secinfo_flags =
    1646             :                 SECINFO_OWNER |
    1647             :                 SECINFO_GROUP |
    1648             :                 SECINFO_DACL;
    1649           2 :         status = smb2_getinfo_file(tree, tctx, &q);
    1650           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1651             : 
    1652             :         /*
    1653             :          * Testing the created DACL,
    1654             :          * the server should add the inherited DACL
    1655             :          * when SEC_DESC_DACL_PRESENT isn't specified
    1656             :          */
    1657           2 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1658           0 :                 ret = false;
    1659           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1660             :         }
    1661           2 :         if (q.query_secdesc.out.sd->dacl == NULL) {
    1662           0 :                 ret = false;
    1663           0 :                 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
    1664             :         }
    1665             : 
    1666           2 :         torture_comment(tctx, "set NULL DACL\n");
    1667           2 :         sd->type |= SEC_DESC_DACL_PRESENT;
    1668             : 
    1669           2 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1670           2 :         s.set_secdesc.in.file.handle = handle;
    1671           2 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1672           2 :         s.set_secdesc.in.sd = sd;
    1673           2 :         status = smb2_setinfo_file(tree, &s);
    1674           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1675             : 
    1676           2 :         torture_comment(tctx, "get the sd\n");
    1677           2 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1678           2 :         q.query_secdesc.in.file.handle = handle;
    1679           2 :         q.query_secdesc.in.secinfo_flags =
    1680             :                 SECINFO_OWNER |
    1681             :                 SECINFO_GROUP |
    1682             :                 SECINFO_DACL;
    1683           2 :         status = smb2_getinfo_file(tree, tctx, &q);
    1684           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1685             : 
    1686             :         /* Testing the modified DACL */
    1687           2 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1688           0 :                 ret = false;
    1689           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1690             :         }
    1691           2 :         if (q.query_secdesc.out.sd->dacl != NULL) {
    1692           0 :                 ret = false;
    1693           0 :                 torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
    1694             :         }
    1695             : 
    1696           2 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
    1697             : 
    1698           2 :         torture_comment(tctx, "try open for read control\n");
    1699           2 :         io.in.desired_access = SEC_STD_READ_CONTROL;
    1700           2 :         status = smb2_create(tree, tctx, &io);
    1701           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1702           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1703             :                 SEC_STD_READ_CONTROL);
    1704           2 :         smb2_util_close(tree, io.out.file.handle);
    1705             : 
    1706           2 :         torture_comment(tctx, "try open for write\n");
    1707           2 :         io.in.desired_access = SEC_FILE_WRITE_DATA;
    1708           2 :         status = smb2_create(tree, tctx, &io);
    1709           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1710           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1711             :                 SEC_FILE_WRITE_DATA);
    1712           2 :         smb2_util_close(tree, io.out.file.handle);
    1713             : 
    1714           2 :         torture_comment(tctx, "try open for read\n");
    1715           2 :         io.in.desired_access = SEC_FILE_READ_DATA;
    1716           2 :         status = smb2_create(tree, tctx, &io);
    1717           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1718           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1719             :                 SEC_FILE_READ_DATA);
    1720           2 :         smb2_util_close(tree, io.out.file.handle);
    1721             : 
    1722           2 :         torture_comment(tctx, "try open for generic write\n");
    1723           2 :         io.in.desired_access = SEC_GENERIC_WRITE;
    1724           2 :         status = smb2_create(tree, tctx, &io);
    1725           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1726           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1727             :                 SEC_RIGHTS_FILE_WRITE);
    1728           2 :         smb2_util_close(tree, io.out.file.handle);
    1729             : 
    1730           2 :         torture_comment(tctx, "try open for generic read\n");
    1731           2 :         io.in.desired_access = SEC_GENERIC_READ;
    1732           2 :         status = smb2_create(tree, tctx, &io);
    1733           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1734           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1735             :                 SEC_RIGHTS_FILE_READ);
    1736           2 :         smb2_util_close(tree, io.out.file.handle);
    1737             : 
    1738           2 :         torture_comment(tctx, "set DACL with 0 aces\n");
    1739           2 :         ZERO_STRUCT(dacl);
    1740           2 :         dacl.revision = SECURITY_ACL_REVISION_NT4;
    1741           2 :         dacl.num_aces = 0;
    1742           2 :         sd->dacl = &dacl;
    1743             : 
    1744           2 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1745           2 :         s.set_secdesc.in.file.handle = handle;
    1746           2 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1747           2 :         s.set_secdesc.in.sd = sd;
    1748           2 :         status = smb2_setinfo_file(tree, &s);
    1749           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1750             : 
    1751           2 :         torture_comment(tctx, "get the sd\n");
    1752           2 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1753           2 :         q.query_secdesc.in.file.handle = handle;
    1754           2 :         q.query_secdesc.in.secinfo_flags =
    1755             :                 SECINFO_OWNER |
    1756             :                 SECINFO_GROUP |
    1757             :                 SECINFO_DACL;
    1758           2 :         status = smb2_getinfo_file(tree, tctx, &q);
    1759           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1760             : 
    1761             :         /* Testing the modified DACL */
    1762           2 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1763           0 :                 ret = false;
    1764           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1765             :         }
    1766           2 :         if (q.query_secdesc.out.sd->dacl == NULL) {
    1767           0 :                 ret = false;
    1768           0 :                 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
    1769             :         }
    1770           2 :         if (q.query_secdesc.out.sd->dacl->num_aces != 0) {
    1771           0 :                 torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n",
    1772           0 :                        q.query_secdesc.out.sd->dacl->num_aces);
    1773           0 :                 ret = false;
    1774           0 :                 goto done;
    1775             :         }
    1776             : 
    1777           2 :         torture_comment(tctx, "try open for read control\n");
    1778           2 :         io.in.desired_access = SEC_STD_READ_CONTROL;
    1779           2 :         status = smb2_create(tree, tctx, &io);
    1780           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1781           2 :         CHECK_ACCESS_FLAGS(io.out.file.handle,
    1782             :                 SEC_STD_READ_CONTROL);
    1783           2 :         smb2_util_close(tree, io.out.file.handle);
    1784             : 
    1785           2 :         torture_comment(tctx, "try open for write => access_denied\n");
    1786           2 :         io.in.desired_access = SEC_FILE_WRITE_DATA;
    1787           2 :         status = smb2_create(tree, tctx, &io);
    1788           2 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1789           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1790             :         } else {
    1791           2 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1792             :         }
    1793             : 
    1794           2 :         torture_comment(tctx, "try open for read => access_denied\n");
    1795           2 :         io.in.desired_access = SEC_FILE_READ_DATA;
    1796           2 :         status = smb2_create(tree, tctx, &io);
    1797           2 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1798           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1799             :         } else {
    1800           2 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1801             :         }
    1802             : 
    1803           2 :         torture_comment(tctx, "try open for generic write => access_denied\n");
    1804           2 :         io.in.desired_access = SEC_GENERIC_WRITE;
    1805           2 :         status = smb2_create(tree, tctx, &io);
    1806           2 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1807           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1808             :         } else {
    1809           2 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1810             :         }
    1811             : 
    1812           2 :         torture_comment(tctx, "try open for generic read => access_denied\n");
    1813           2 :         io.in.desired_access = SEC_GENERIC_READ;
    1814           2 :         status = smb2_create(tree, tctx, &io);
    1815           2 :         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
    1816           0 :                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    1817             :         } else {
    1818           2 :                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    1819             :         }
    1820             : 
    1821           2 :         torture_comment(tctx, "set empty sd\n");
    1822           2 :         sd->type &= ~SEC_DESC_DACL_PRESENT;
    1823           2 :         sd->dacl = NULL;
    1824             : 
    1825           2 :         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1826           2 :         s.set_secdesc.in.file.handle = handle;
    1827           2 :         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1828           2 :         s.set_secdesc.in.sd = sd;
    1829           2 :         status = smb2_setinfo_file(tree, &s);
    1830           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1831             : 
    1832           2 :         torture_comment(tctx, "get the sd\n");
    1833           2 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    1834           2 :         q.query_secdesc.in.file.handle = handle;
    1835           2 :         q.query_secdesc.in.secinfo_flags =
    1836             :                 SECINFO_OWNER |
    1837             :                 SECINFO_GROUP |
    1838             :                 SECINFO_DACL;
    1839           2 :         status = smb2_getinfo_file(tree, tctx, &q);
    1840           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1841             : 
    1842             :         /* Testing the modified DACL */
    1843           2 :         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
    1844           0 :                 ret = false;
    1845           0 :                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    1846             :         }
    1847           2 :         if (q.query_secdesc.out.sd->dacl != NULL) {
    1848           0 :                 ret = false;
    1849           0 :                 torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
    1850             :         }
    1851           4 : done:
    1852           2 :         smb2_util_close(tree, handle);
    1853           2 :         smb2_util_unlink(tree, fname);
    1854           2 :         smb2_tdis(tree);
    1855           2 :         smb2_logoff(tree->session);
    1856           2 :         return ret;
    1857             : }
    1858             : 
    1859             : /*
    1860             :   test SMB2 mkdir with OPEN_IF on the same name twice.
    1861             :   Must use 2 connections to hit the race.
    1862             : */
    1863             : 
    1864           2 : static bool test_mkdir_dup(struct torture_context *tctx,
    1865             :                                 struct smb2_tree *tree)
    1866             : {
    1867           2 :         const char *fname = "mkdir_dup";
    1868             :         NTSTATUS status;
    1869           2 :         bool ret = true;
    1870             :         union smb_open io;
    1871             :         struct smb2_tree **trees;
    1872             :         struct smb2_request **requests;
    1873             :         union smb_open *ios;
    1874           2 :         int i, num_files = 2;
    1875           2 :         int num_ok = 0;
    1876           2 :         int num_created = 0;
    1877           2 :         int num_existed = 0;
    1878             : 
    1879           2 :         torture_comment(tctx,
    1880             :                 "Testing SMB2 Create Directory with multiple connections\n");
    1881           2 :         trees = talloc_array(tctx, struct smb2_tree *, num_files);
    1882           2 :         requests = talloc_array(tctx, struct smb2_request *, num_files);
    1883           2 :         ios = talloc_array(tctx, union smb_open, num_files);
    1884           2 :         if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
    1885             :             (ios == NULL)) {
    1886           0 :                 torture_fail(tctx, ("talloc failed\n"));
    1887             :                 ret = false;
    1888             :                 goto done;
    1889             :         }
    1890             : 
    1891           2 :         tree->session->transport->options.request_timeout = 60;
    1892             : 
    1893           6 :         for (i=0; i<num_files; i++) {
    1894           4 :                 if (!torture_smb2_connection(tctx, &(trees[i]))) {
    1895           0 :                         torture_fail(tctx,
    1896             :                                 talloc_asprintf(tctx,
    1897             :                                         "Could not open %d'th connection\n", i));
    1898             :                         ret = false;
    1899             :                         goto done;
    1900             :                 }
    1901           4 :                 trees[i]->session->transport->options.request_timeout = 60;
    1902             :         }
    1903             : 
    1904             :         /* cleanup */
    1905           2 :         smb2_util_unlink(tree, fname);
    1906           2 :         smb2_util_rmdir(tree, fname);
    1907             : 
    1908             :         /*
    1909             :           base ntcreatex parms
    1910             :         */
    1911           2 :         ZERO_STRUCT(io.smb2);
    1912           2 :         io.generic.level = RAW_OPEN_SMB2;
    1913           2 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1914           2 :         io.smb2.in.alloc_size = 0;
    1915           2 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1916           2 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1917             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1918             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1919           2 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1920           2 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1921           2 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1922           2 :         io.smb2.in.security_flags = 0;
    1923           2 :         io.smb2.in.fname = fname;
    1924           2 :         io.smb2.in.create_flags = 0;
    1925             : 
    1926           6 :         for (i=0; i<num_files; i++) {
    1927           4 :                 ios[i] = io;
    1928           4 :                 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
    1929           4 :                 if (requests[i] == NULL) {
    1930           0 :                         torture_fail(tctx,
    1931             :                                 talloc_asprintf(tctx,
    1932             :                                 "could not send %d'th request\n", i));
    1933             :                         ret = false;
    1934             :                         goto done;
    1935             :                 }
    1936             :         }
    1937             : 
    1938           2 :         torture_comment(tctx, "waiting for replies\n");
    1939          16 :         while (1) {
    1940          18 :                 bool unreplied = false;
    1941          24 :                 for (i=0; i<num_files; i++) {
    1942          22 :                         if (requests[i] == NULL) {
    1943           2 :                                 continue;
    1944             :                         }
    1945          20 :                         if (requests[i]->state < SMB2_REQUEST_DONE) {
    1946          16 :                                 unreplied = true;
    1947          16 :                                 break;
    1948             :                         }
    1949           4 :                         status = smb2_create_recv(requests[i], tctx,
    1950           4 :                                                   &(ios[i].smb2));
    1951             : 
    1952           4 :                         if (NT_STATUS_IS_OK(status)) {
    1953           4 :                                 num_ok += 1;
    1954             : 
    1955           4 :                                 if (ios[i].smb2.out.create_action ==
    1956             :                                                 NTCREATEX_ACTION_CREATED) {
    1957           2 :                                         num_created++;
    1958             :                                 }
    1959           4 :                                 if (ios[i].smb2.out.create_action ==
    1960             :                                                 NTCREATEX_ACTION_EXISTED) {
    1961           2 :                                         num_existed++;
    1962             :                                 }
    1963             :                         } else {
    1964           0 :                                 torture_fail(tctx,
    1965             :                                         talloc_asprintf(tctx,
    1966             :                                         "File %d returned status %s\n", i,
    1967             :                                         nt_errstr(status)));
    1968             :                         }
    1969             : 
    1970             : 
    1971           4 :                         requests[i] = NULL;
    1972             :                 }
    1973          18 :                 if (!unreplied) {
    1974           2 :                         break;
    1975             :                 }
    1976             : 
    1977          16 :                 if (tevent_loop_once(tctx->ev) != 0) {
    1978           0 :                         torture_fail(tctx, "tevent_loop_once failed\n");
    1979             :                         ret = false;
    1980             :                         goto done;
    1981             :                 }
    1982             :         }
    1983             : 
    1984           2 :         if (num_ok != 2) {
    1985           0 :                 torture_fail(tctx,
    1986             :                         talloc_asprintf(tctx,
    1987             :                         "num_ok == %d\n", num_ok));
    1988             :                 ret = false;
    1989             :         }
    1990           2 :         if (num_created != 1) {
    1991           0 :                 torture_fail(tctx,
    1992             :                         talloc_asprintf(tctx,
    1993             :                         "num_created == %d\n", num_created));
    1994             :                 ret = false;
    1995             :         }
    1996           2 :         if (num_existed != 1) {
    1997           0 :                 torture_fail(tctx,
    1998             :                         talloc_asprintf(tctx,
    1999             :                         "num_existed == %d\n", num_existed));
    2000             :                 ret = false;
    2001             :         }
    2002           2 : done:
    2003           2 :         smb2_deltree(tree, fname);
    2004             : 
    2005           2 :         return ret;
    2006             : }
    2007             : 
    2008             : /*
    2009             :   test directory creation with an initial allocation size > 0
    2010             : */
    2011           2 : static bool test_dir_alloc_size(struct torture_context *tctx,
    2012             :                                 struct smb2_tree *tree)
    2013             : {
    2014           2 :         bool ret = true;
    2015           2 :         const char *dname = DNAME "\\torture_alloc_size.dir";
    2016             :         NTSTATUS status;
    2017             :         struct smb2_create c;
    2018           2 :         struct smb2_handle h1 = {{0}}, h2;
    2019             : 
    2020           2 :         torture_comment(tctx, "Checking initial allocation size on directories\n");
    2021             : 
    2022           2 :         smb2_deltree(tree, dname);
    2023             : 
    2024           2 :         status = torture_smb2_testdir(tree, DNAME, &h1);
    2025           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
    2026             : 
    2027           2 :         ZERO_STRUCT(c);
    2028           2 :         c.in.create_disposition = NTCREATEX_DISP_CREATE;
    2029           2 :         c.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    2030           2 :         c.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    2031           2 :         c.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    2032           2 :         c.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2033           2 :         c.in.fname = dname;
    2034             :         /*
    2035             :          * An insanely large value so we can check the value is
    2036             :          * ignored: Samba either returns 0 (current behaviour), or,
    2037             :          * once vfswrap_get_alloc_size() is fixed to allow retrieving
    2038             :          * the allocated size for directories, returns
    2039             :          * smb_roundup(..., stat.st_size) which would be 1 MB by
    2040             :          * default.
    2041             :          *
    2042             :          * Windows returns 0 for empty directories, once directories
    2043             :          * have a few entries it starts replying with values > 0.
    2044             :          */
    2045           2 :         c.in.alloc_size = 1024*1024*1024;
    2046             : 
    2047           2 :         status = smb2_create(tree, tctx, &c);
    2048           2 :         h2 = c.out.file.handle;
    2049           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2050             :                                         "dir create with initial alloc size failed");
    2051             : 
    2052           2 :         smb2_util_close(tree, h2);
    2053             : 
    2054           2 :         torture_comment(tctx, "Got directory alloc size: %ju\n", (uintmax_t)c.out.alloc_size);
    2055             : 
    2056             :         /*
    2057             :          * See above for the rational for this test
    2058             :          */
    2059           2 :         if (c.out.alloc_size > 1024*1024) {
    2060           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "bad alloc size: %ju",
    2061             :                                                               (uintmax_t)c.out.alloc_size));
    2062             :         }
    2063             : 
    2064           4 : done:
    2065           2 :         if (!smb2_util_handle_empty(h1)) {
    2066           2 :                 smb2_util_close(tree, h1);
    2067             :         }
    2068           2 :         smb2_deltree(tree, DNAME);
    2069           2 :         return ret;
    2070             : }
    2071             : 
    2072           0 : static bool test_twrp_write(struct torture_context *tctx, struct smb2_tree *tree)
    2073             : {
    2074             :         struct smb2_create io;
    2075           0 :         struct smb2_handle h1 = {{0}};
    2076             :         NTSTATUS status;
    2077           0 :         bool ret = true;
    2078           0 :         char *p = NULL;
    2079             :         struct tm tm;
    2080             :         time_t t;
    2081             :         uint64_t nttime;
    2082           0 :         const char *file = NULL;
    2083           0 :         const char *snapshot = NULL;
    2084             : 
    2085           0 :         file = torture_setting_string(tctx, "twrp_file", NULL);
    2086           0 :         if (file == NULL) {
    2087           0 :                 torture_skip(tctx, "missing 'twrp_file' option\n");
    2088             :         }
    2089             : 
    2090           0 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2091           0 :         if (snapshot == NULL) {
    2092           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    2093             :         }
    2094             : 
    2095           0 :         torture_comment(tctx, "Testing timewarp (%s) (%s)\n", file, snapshot);
    2096             : 
    2097           0 :         setenv("TZ", "GMT", 1);
    2098             : 
    2099             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2100             :          * effect if it is greather than 1. */
    2101           0 :         ZERO_STRUCT(tm);
    2102             : 
    2103           0 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2104           0 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2105           0 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2106             : 
    2107           0 :         t = mktime(&tm);
    2108           0 :         unix_to_nt_time(&nttime, t);
    2109             : 
    2110           0 :         io = (struct smb2_create) {
    2111             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2112             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2113             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2114             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2115             :                 .in.fname = file,
    2116             :                 .in.query_maximal_access = true,
    2117             :                 .in.timewarp = nttime,
    2118             :         };
    2119             : 
    2120           0 :         status = smb2_create(tree, tctx, &io);
    2121           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2122             :                                         "smb2_create\n");
    2123           0 :         smb2_util_close(tree, io.out.file.handle);
    2124             : 
    2125           0 :         ret = io.out.maximal_access & (SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA);
    2126           0 :         torture_assert_goto(tctx, ret, ret, done, "Bad access\n");
    2127             : 
    2128           0 :         io = (struct smb2_create) {
    2129             :                 .in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
    2130             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2131             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2132             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2133             :                 .in.fname = file,
    2134             :                 .in.timewarp = nttime,
    2135             :         };
    2136             : 
    2137           0 :         status = smb2_create(tree, tctx, &io);
    2138           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2139             :                                         "smb2_create\n");
    2140           0 :         h1 = io.out.file.handle;
    2141             : 
    2142           0 :         status = smb2_util_write(tree, h1, "123", 0, 3);
    2143           0 :         torture_assert_ntstatus_equal_goto(tctx, status,
    2144             :                                            NT_STATUS_MEDIA_WRITE_PROTECTED,
    2145             :                                            ret, done, "smb2_create\n");
    2146             : 
    2147           0 :         smb2_util_close(tree, h1);
    2148             : 
    2149           0 : done:
    2150           0 :         return ret;
    2151             : }
    2152             : 
    2153           0 : static bool test_twrp_stream(struct torture_context *tctx,
    2154             :                              struct smb2_tree *tree)
    2155             : {
    2156             :         struct smb2_create io;
    2157             :         NTSTATUS status;
    2158           0 :         bool ret = true;
    2159           0 :         char *p = NULL;
    2160             :         struct tm tm;
    2161             :         time_t t;
    2162             :         uint64_t nttime;
    2163           0 :         const char *file = NULL;
    2164           0 :         const char *stream = NULL;
    2165           0 :         const char *snapshot = NULL;
    2166             :         int stream_size;
    2167           0 :         char *path = NULL;
    2168           0 :         uint8_t *buf = NULL;
    2169           0 :         struct smb2_handle h1 = {{0}};
    2170             :         struct smb2_read r;
    2171             : 
    2172           0 :         file = torture_setting_string(tctx, "twrp_file", NULL);
    2173           0 :         if (file == NULL) {
    2174           0 :                 torture_skip(tctx, "missing 'twrp_file' option\n");
    2175             :         }
    2176             : 
    2177           0 :         stream = torture_setting_string(tctx, "twrp_stream", NULL);
    2178           0 :         if (stream == NULL) {
    2179           0 :                 torture_skip(tctx, "missing 'twrp_stream' option\n");
    2180             :         }
    2181             : 
    2182           0 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2183           0 :         if (snapshot == NULL) {
    2184           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    2185             :         }
    2186             : 
    2187           0 :         stream_size = torture_setting_int(tctx, "twrp_stream_size", 0);
    2188           0 :         if (stream_size == 0) {
    2189           0 :                 torture_skip(tctx, "missing 'twrp_stream_size' option\n");
    2190             :         }
    2191             : 
    2192           0 :         torture_comment(tctx, "Testing timewarp on stream (%s) (%s)\n",
    2193             :                         file, snapshot);
    2194             : 
    2195           0 :         path = talloc_asprintf(tree, "%s:%s", file, stream);
    2196           0 :         torture_assert_not_null_goto(tctx, path, ret, done, "path\n");
    2197             : 
    2198           0 :         buf = talloc_zero_array(tree, uint8_t, stream_size);
    2199           0 :         torture_assert_not_null_goto(tctx, buf, ret, done, "buf\n");
    2200             : 
    2201           0 :         setenv("TZ", "GMT", 1);
    2202             : 
    2203             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2204             :          * effect if it is greather than 1. */
    2205           0 :         ZERO_STRUCT(tm);
    2206             : 
    2207           0 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2208           0 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2209           0 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2210             : 
    2211           0 :         t = mktime(&tm);
    2212           0 :         unix_to_nt_time(&nttime, t);
    2213             : 
    2214           0 :         io = (struct smb2_create) {
    2215             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2216             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2217             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2218             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2219             :                 .in.fname = path,
    2220             :                 .in.timewarp = nttime,
    2221             :         };
    2222             : 
    2223           0 :         status = smb2_create(tree, tctx, &io);
    2224           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2225             :                                         "smb2_create\n");
    2226           0 :         h1 = io.out.file.handle;
    2227             : 
    2228           0 :         r = (struct smb2_read) {
    2229             :                 .in.file.handle = h1,
    2230             :                 .in.length = stream_size,
    2231             :                 .in.offset = 0,
    2232             :         };
    2233             : 
    2234           0 :         status = smb2_read(tree, tree, &r);
    2235           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2236             :                                         "smb2_create\n");
    2237             : 
    2238           0 :         smb2_util_close(tree, h1);
    2239             : 
    2240           0 : done:
    2241           0 :         return ret;
    2242             : }
    2243             : 
    2244           0 : static bool test_twrp_openroot(struct torture_context *tctx, struct smb2_tree *tree)
    2245             : {
    2246             :         struct smb2_create io;
    2247             :         NTSTATUS status;
    2248           0 :         bool ret = true;
    2249           0 :         char *p = NULL;
    2250             :         struct tm tm;
    2251             :         time_t t;
    2252             :         uint64_t nttime;
    2253           0 :         const char *snapshot = NULL;
    2254             : 
    2255           0 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2256           0 :         if (snapshot == NULL) {
    2257           0 :                 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
    2258             :         }
    2259             : 
    2260           0 :         torture_comment(tctx, "Testing open of root of "
    2261             :                 "share with timewarp (%s)\n",
    2262             :                 snapshot);
    2263             : 
    2264           0 :         setenv("TZ", "GMT", 1);
    2265             : 
    2266             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2267             :          * effect if it is greather than 1. */
    2268           0 :         ZERO_STRUCT(tm);
    2269             : 
    2270           0 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2271           0 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2272           0 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2273             : 
    2274           0 :         t = mktime(&tm);
    2275           0 :         unix_to_nt_time(&nttime, t);
    2276             : 
    2277           0 :         io = (struct smb2_create) {
    2278             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2279             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2280             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2281             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2282             :                 .in.fname = "",
    2283             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2284             :                 .in.timewarp = nttime,
    2285             :         };
    2286             : 
    2287           0 :         status = smb2_create(tree, tctx, &io);
    2288           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2289             :                                         "smb2_create\n");
    2290           0 :         smb2_util_close(tree, io.out.file.handle);
    2291             : 
    2292           0 : done:
    2293           0 :         return ret;
    2294             : }
    2295             : 
    2296           0 : static bool test_twrp_listdir(struct torture_context *tctx,
    2297             :                               struct smb2_tree *tree)
    2298             : {
    2299             :         struct smb2_create create;
    2300           0 :         struct smb2_handle h = {{0}};
    2301             :         struct smb2_find find;
    2302             :         unsigned int count;
    2303             :         union smb_search_data *d;
    2304           0 :         char *p = NULL;
    2305             :         struct tm tm;
    2306             :         time_t t;
    2307             :         uint64_t nttime;
    2308           0 :         const char *snapshot = NULL;
    2309             :         uint64_t normal_fileid;
    2310             :         uint64_t snapshot_fileid;
    2311             :         NTSTATUS status;
    2312           0 :         bool ret = true;
    2313             : 
    2314           0 :         snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
    2315           0 :         if (snapshot == NULL) {
    2316           0 :                 torture_fail(tctx, "missing 'twrp_snapshot' option\n");
    2317             :         }
    2318             : 
    2319           0 :         torture_comment(tctx, "Testing File-Ids of directory listing "
    2320             :                         "with timewarp (%s)\n",
    2321             :                         snapshot);
    2322             : 
    2323           0 :         setenv("TZ", "GMT", 1);
    2324             : 
    2325             :         /* strptime does not set tm.tm_isdst but mktime assumes DST is in
    2326             :          * effect if it is greather than 1. */
    2327           0 :         ZERO_STRUCT(tm);
    2328             : 
    2329           0 :         p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
    2330           0 :         torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
    2331           0 :         torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
    2332             : 
    2333           0 :         t = mktime(&tm);
    2334           0 :         unix_to_nt_time(&nttime, t);
    2335             : 
    2336             :         /*
    2337             :          * 1: Query the file's File-Id
    2338             :          */
    2339           0 :         create = (struct smb2_create) {
    2340             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2341             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2342             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2343             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2344             :                 .in.fname = "subdir/hardlink",
    2345             :                 .in.query_on_disk_id = true,
    2346             :         };
    2347             : 
    2348           0 :         status = smb2_create(tree, tctx, &create);
    2349           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2350             :                                         "test file could not be created\n");
    2351           0 :         smb2_util_close(tree, create.out.file.handle);
    2352           0 :         normal_fileid = BVAL(&create.out.on_disk_id, 0);
    2353             : 
    2354             :         /*
    2355             :          * 2: check directory listing of the file returns same File-Id
    2356             :          */
    2357             : 
    2358           0 :         create = (struct smb2_create) {
    2359             :                 .in.desired_access = SEC_DIR_LIST,
    2360             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2361             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2362             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2363             :                 .in.fname = "subdir",
    2364             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2365             :         };
    2366             : 
    2367           0 :         status = smb2_create(tree, tctx, &create);
    2368           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2369             :                                         "smb2_create\n");
    2370           0 :         h = create.out.file.handle;
    2371             : 
    2372           0 :         find = (struct smb2_find) {
    2373             :                 .in.file.handle = h,
    2374             :                 .in.pattern = "*",
    2375             :                 .in.max_response_size = 0x1000,
    2376             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2377             :         };
    2378             : 
    2379           0 :         status = smb2_find_level(tree, tree, &find, &count, &d);
    2380           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2381             :                                         "smb2_find_level failed\n");
    2382             : 
    2383           0 :         smb2_util_close(tree, h);
    2384             : 
    2385           0 :         torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
    2386           0 :         torture_assert_str_equal_goto(tctx,
    2387             :                                       d[2].id_both_directory_info.name.s,
    2388             :                                       "hardlink",
    2389             :                                       ret, done, "bad name");
    2390           0 :         torture_assert_u64_equal_goto(tctx,
    2391             :                                       d[2].id_both_directory_info.file_id,
    2392             :                                       normal_fileid,
    2393             :                                       ret, done, "bad fileid\n");
    2394             : 
    2395             :         /*
    2396             :          * 3: Query File-Id of snapshot of the file and check the File-Id is
    2397             :          * different compared to the basefile
    2398             :          */
    2399             : 
    2400           0 :         create = (struct smb2_create) {
    2401             :                 .in.desired_access = SEC_FILE_READ_DATA,
    2402             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2403             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2404             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2405             :                 .in.fname = "subdir/hardlink",
    2406             :                 .in.query_on_disk_id = true,
    2407             :                 .in.timewarp = nttime,
    2408             :         };
    2409             : 
    2410           0 :         status = smb2_create(tree, tctx, &create);
    2411           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2412             :                                         "test file could not be created\n");
    2413           0 :         smb2_util_close(tree, create.out.file.handle);
    2414             : 
    2415           0 :         snapshot_fileid = BVAL(&create.out.on_disk_id, 0);
    2416             : 
    2417             :         /*
    2418             :          * 4: List directory of the snapshot and check the File-Id returned here
    2419             :          * is the same as in 3.
    2420             :          */
    2421             : 
    2422           0 :         create = (struct smb2_create) {
    2423             :                 .in.desired_access = SEC_DIR_LIST,
    2424             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2425             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2426             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2427             :                 .in.fname = "subdir",
    2428             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2429             :                 .in.timewarp = nttime,
    2430             :         };
    2431             : 
    2432           0 :         status = smb2_create(tree, tctx, &create);
    2433           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2434             :                                         "smb2_create\n");
    2435           0 :         h = create.out.file.handle;
    2436             : 
    2437           0 :         find = (struct smb2_find) {
    2438             :                 .in.file.handle = h,
    2439             :                 .in.pattern = "*",
    2440             :                 .in.max_response_size = 0x1000,
    2441             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2442             :         };
    2443             : 
    2444           0 :         status = smb2_find_level(tree, tree, &find, &count, &d);
    2445           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2446             :                                         "smb2_find_level failed\n");
    2447           0 :         smb2_util_close(tree, h);
    2448             : 
    2449           0 :         torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
    2450           0 :         torture_assert_str_equal_goto(tctx,
    2451             :                                       d[2].id_both_directory_info.name.s,
    2452             :                                       "hardlink",
    2453             :                                       ret, done, "bad name");
    2454           0 :         torture_assert_u64_equal_goto(tctx,
    2455             :                                       snapshot_fileid,
    2456             :                                       d[2].id_both_directory_info.file_id,
    2457             :                                       ret, done, "bad fileid\n");
    2458             : 
    2459           0 : done:
    2460           0 :         return ret;
    2461             : }
    2462             : 
    2463           0 : static bool test_fileid(struct torture_context *tctx,
    2464             :                         struct smb2_tree *tree)
    2465             : {
    2466           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2467           0 :         const char *fname = DNAME "\\foo";
    2468           0 :         const char *sname = DNAME "\\foo:bar";
    2469             :         struct smb2_handle testdirh;
    2470             :         struct smb2_handle h1;
    2471             :         struct smb2_create create;
    2472             :         union smb_fileinfo finfo;
    2473             :         union smb_setfileinfo sinfo;
    2474             :         struct smb2_find f;
    2475             :         unsigned int count;
    2476             :         union smb_search_data *d;
    2477             :         uint64_t expected_fileid;
    2478             :         uint64_t returned_fileid;
    2479             :         NTSTATUS status;
    2480           0 :         bool ret = true;
    2481             : 
    2482           0 :         smb2_deltree(tree, DNAME);
    2483             : 
    2484           0 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    2485           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2486             :                                         "torture_smb2_testdir failed\n");
    2487             : 
    2488             :         /*
    2489             :          * Initial create with QFID
    2490             :          */
    2491           0 :         create = (struct smb2_create) {
    2492             :                 .in.desired_access = SEC_FILE_ALL,
    2493             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2494             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2495             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    2496             :                 .in.fname = fname,
    2497             :                 .in.query_on_disk_id = true,
    2498             :         };
    2499             : 
    2500           0 :         status = smb2_create(tree, tctx, &create);
    2501           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2502             :                                         "test file could not be created\n");
    2503           0 :         h1 = create.out.file.handle;
    2504           0 :         expected_fileid = BVAL(&create.out.on_disk_id, 0);
    2505             : 
    2506             :         /*
    2507             :          * Getinfo the File-ID on the just opened handle
    2508             :          */
    2509           0 :         finfo = (union smb_fileinfo) {
    2510             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2511             :                 .generic.in.file.handle = h1,
    2512             :         };
    2513             : 
    2514           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2515           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2516             :                                         "torture_smb2_testdir\n");
    2517           0 :         smb2_util_close(tree, h1);
    2518           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2519             :                                       expected_fileid,
    2520             :                                       ret, done, "bad fileid\n");
    2521             : 
    2522             :         /*
    2523             :          * Open existing with QFID
    2524             :          */
    2525           0 :         create = (struct smb2_create) {
    2526             :                 .in.desired_access = SEC_FILE_ALL,
    2527             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2528             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2529             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2530             :                 .in.fname = fname,
    2531             :                 .in.query_on_disk_id = true,
    2532             :         };
    2533             : 
    2534           0 :         status = smb2_create(tree, tctx, &create);
    2535           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2536             :                                         "test file could not be created\n");
    2537           0 :         h1 = create.out.file.handle;
    2538           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2539           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2540             :                                       ret, done, "bad fileid\n");
    2541             : 
    2542             :         /*
    2543             :          * Getinfo the File-ID on the just opened handle
    2544             :          */
    2545           0 :         finfo = (union smb_fileinfo) {
    2546             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2547             :                 .generic.in.file.handle = h1,
    2548             :         };
    2549             : 
    2550           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2551           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2552             :                                         "torture_smb2_testdir\n");
    2553           0 :         smb2_util_close(tree, h1);
    2554           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2555             :                                       expected_fileid,
    2556             :                                       ret, done, "bad fileid\n");
    2557             : 
    2558             :         /*
    2559             :          * Overwrite with QFID
    2560             :          */
    2561           0 :         create = (struct smb2_create) {
    2562             :                 .in.desired_access = SEC_FILE_ALL,
    2563             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2564             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2565             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2566             :                 .in.fname = fname,
    2567             :                 .in.query_on_disk_id = true,
    2568             :         };
    2569             : 
    2570           0 :         status = smb2_create(tree, tctx, &create);
    2571           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2572             :                                         "test file could not be created\n");
    2573           0 :         h1 = create.out.file.handle;
    2574           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2575           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2576             :                                       ret, done, "bad fileid\n");
    2577             : 
    2578             :         /*
    2579             :          * Getinfo the File-ID on the open with overwrite handle
    2580             :          */
    2581           0 :         finfo = (union smb_fileinfo) {
    2582             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2583             :                 .generic.in.file.handle = h1,
    2584             :         };
    2585             : 
    2586           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2587           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2588             :                                         "torture_smb2_testdir\n");
    2589           0 :         smb2_util_close(tree, h1);
    2590           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2591             :                                       expected_fileid,
    2592             :                                       ret, done, "bad fileid\n");
    2593             : 
    2594             :         /*
    2595             :          * Do some modifications on the basefile (IO, setinfo), verifying
    2596             :          * File-ID after each step.
    2597             :          */
    2598           0 :         create = (struct smb2_create) {
    2599             :                 .in.desired_access = SEC_FILE_ALL,
    2600             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2601             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2602             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2603             :                 .in.fname = fname,
    2604             :                 .in.query_on_disk_id = true,
    2605             :         };
    2606             : 
    2607           0 :         status = smb2_create(tree, tctx, &create);
    2608           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2609             :                                         "test file could not be created\n");
    2610           0 :         h1 = create.out.file.handle;
    2611             : 
    2612           0 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    2613           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2614             :                                         "smb2_util_write failed\n");
    2615             : 
    2616           0 :         finfo = (union smb_fileinfo) {
    2617             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2618             :                 .generic.in.file.handle = h1,
    2619             :         };
    2620           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2621           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2622             :                                         "smb2_getinfo_file failed\n");
    2623           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2624             :                                       expected_fileid,
    2625             :                                       ret, done, "bad fileid\n");
    2626             : 
    2627           0 :         sinfo = (union smb_setfileinfo) {
    2628             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    2629             :                 .basic_info.in.file.handle = h1,
    2630             :         };
    2631           0 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    2632             : 
    2633           0 :         status = smb2_setinfo_file(tree, &sinfo);
    2634           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2635             :                                         "smb2_setinfo_file failed\n");
    2636             : 
    2637           0 :         finfo = (union smb_fileinfo) {
    2638             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2639             :                 .generic.in.file.handle = h1,
    2640             :         };
    2641           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2642           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2643             :                                         "smb2_getinfo_file failed\n");
    2644           0 :         smb2_util_close(tree, h1);
    2645           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2646             :                                       expected_fileid,
    2647             :                                       ret, done, "bad fileid\n");
    2648             : 
    2649             :         /*
    2650             :          * Create stream, check the stream's File-ID, should be the same as the
    2651             :          * base file (sic!, tested against Windows).
    2652             :          */
    2653           0 :         create = (struct smb2_create) {
    2654             :                 .in.desired_access = SEC_FILE_ALL,
    2655             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2656             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2657             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    2658             :                 .in.fname = sname,
    2659             :                 .in.query_on_disk_id = true,
    2660             :         };
    2661             : 
    2662           0 :         status = smb2_create(tree, tctx, &create);
    2663           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2664             :                                         "test file could not be created\n");
    2665           0 :         h1 = create.out.file.handle;
    2666           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2667           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2668             :                                       ret, done, "bad fileid\n");
    2669             : 
    2670             :         /*
    2671             :          * Getinfo the File-ID on the created stream
    2672             :          */
    2673           0 :         finfo = (union smb_fileinfo) {
    2674             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2675             :                 .generic.in.file.handle = h1,
    2676             :         };
    2677             : 
    2678           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2679           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2680             :                                         "smb2_getinfo_file failed\n");
    2681           0 :         smb2_util_close(tree, h1);
    2682           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2683             :                                       expected_fileid,
    2684             :                                       ret, done, "bad fileid\n");
    2685             : 
    2686             :         /*
    2687             :          * Open stream, check the stream's File-ID, should be the same as the
    2688             :          * base file (sic!, tested against Windows).
    2689             :          */
    2690           0 :         create = (struct smb2_create) {
    2691             :                 .in.desired_access = SEC_FILE_ALL,
    2692             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2693             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2694             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2695             :                 .in.fname = sname,
    2696             :                 .in.query_on_disk_id = true,
    2697             :         };
    2698             : 
    2699           0 :         status = smb2_create(tree, tctx, &create);
    2700           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2701             :                                         "test file could not be created\n");
    2702           0 :         h1 = create.out.file.handle;
    2703           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2704           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2705             :                                       ret, done, "bad fileid\n");
    2706             : 
    2707             :         /*
    2708             :          * Getinfo the File-ID on the opened stream
    2709             :          */
    2710           0 :         finfo = (union smb_fileinfo) {
    2711             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2712             :                 .generic.in.file.handle = h1,
    2713             :         };
    2714             : 
    2715           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2716           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2717             :                                         "smb2_getinfo_file failed\n");
    2718           0 :         smb2_util_close(tree, h1);
    2719           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2720             :                                       expected_fileid,
    2721             :                                       ret, done, "bad fileid\n");
    2722             : 
    2723             :         /*
    2724             :          * Overwrite stream, check the stream's File-ID, should be the same as
    2725             :          * the base file (sic!, tested against Windows).
    2726             :          */
    2727           0 :         create = (struct smb2_create) {
    2728             :                 .in.desired_access = SEC_FILE_ALL,
    2729             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2730             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2731             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    2732             :                 .in.fname = sname,
    2733             :                 .in.query_on_disk_id = true,
    2734             :         };
    2735             : 
    2736           0 :         status = smb2_create(tree, tctx, &create);
    2737           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2738             :                                         "test file could not be created\n");
    2739           0 :         h1 = create.out.file.handle;
    2740           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2741           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2742             :                                       ret, done, "bad fileid\n");
    2743             : 
    2744             :         /*
    2745             :          * Getinfo the File-ID on the overwritten stream
    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             :                                         "smb2_getinfo_file failed\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             :          * Do some modifications on the stream (IO, setinfo), verifying File-ID
    2762             :          * after earch step.
    2763             :          */
    2764           0 :         create = (struct smb2_create) {
    2765             :                 .in.desired_access = SEC_FILE_ALL,
    2766             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2767             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2768             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2769             :                 .in.fname = sname,
    2770             :                 .in.query_on_disk_id = true,
    2771             :         };
    2772             : 
    2773           0 :         status = smb2_create(tree, tctx, &create);
    2774           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2775             :                                         "test file could not be created\n");
    2776           0 :         h1 = create.out.file.handle;
    2777             : 
    2778           0 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    2779           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2780             :                                         "smb2_util_write failed\n");
    2781             : 
    2782           0 :         finfo = (union smb_fileinfo) {
    2783             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2784             :                 .generic.in.file.handle = h1,
    2785             :         };
    2786           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2787           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2788             :                                         "smb2_getinfo_file failed\n");
    2789           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2790             :                                       expected_fileid,
    2791             :                                       ret, done, "bad fileid\n");
    2792             : 
    2793           0 :         sinfo = (union smb_setfileinfo) {
    2794             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    2795             :                 .basic_info.in.file.handle = h1,
    2796             :         };
    2797           0 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    2798             : 
    2799           0 :         status = smb2_setinfo_file(tree, &sinfo);
    2800           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2801             :                                         "smb2_setinfo_file failed\n");
    2802             : 
    2803           0 :         finfo = (union smb_fileinfo) {
    2804             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2805             :                 .generic.in.file.handle = h1,
    2806             :         };
    2807           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2808           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2809             :                                         "smb2_getinfo_file failed\n");
    2810           0 :         smb2_util_close(tree, h1);
    2811           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2812             :                                       expected_fileid,
    2813             :                                       ret, done, "bad fileid\n");
    2814             : 
    2815             :         /*
    2816             :          * Final open of the basefile with QFID
    2817             :          */
    2818           0 :         create = (struct smb2_create) {
    2819             :                 .in.desired_access = SEC_FILE_ALL,
    2820             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2821             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2822             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2823             :                 .in.fname = fname,
    2824             :                 .in.query_on_disk_id = true,
    2825             :         };
    2826             : 
    2827           0 :         status = smb2_create(tree, tctx, &create);
    2828           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2829             :                                         "test file could not be created\n");
    2830           0 :         h1 = create.out.file.handle;
    2831           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2832           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2833             :                                       ret, done, "bad fileid\n");
    2834             : 
    2835             :         /*
    2836             :          * Final Getinfo checking File-ID
    2837             :          */
    2838           0 :         finfo = (union smb_fileinfo) {
    2839             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2840             :                 .generic.in.file.handle = h1,
    2841             :         };
    2842             : 
    2843           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2844           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2845             :                                         "torture_smb2_testdir\n");
    2846           0 :         smb2_util_close(tree, h1);
    2847           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2848             :                                       expected_fileid,
    2849             :                                       ret, done, "bad fileid\n");
    2850             : 
    2851             :         /*
    2852             :          * Final list directory, verifying the operations on basefile and stream
    2853             :          * didn't modify the base file metadata.
    2854             :          */
    2855           0 :         f = (struct smb2_find) {
    2856             :                 .in.file.handle = testdirh,
    2857             :                 .in.pattern = "foo",
    2858             :                 .in.max_response_size = 0x1000,
    2859             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    2860             :                 .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
    2861             :         };
    2862             : 
    2863           0 :         status = smb2_find_level(tree, tree, &f, &count, &d);
    2864           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2865             :                                         "smb2_find_level failed\n");
    2866           0 :         torture_assert_u64_equal_goto(tctx,
    2867             :                                       d->id_both_directory_info.file_id,
    2868             :                                       expected_fileid,
    2869             :                                       ret, done, "bad fileid\n");
    2870             : 
    2871           0 : done:
    2872           0 :         smb2_util_close(tree, testdirh);
    2873           0 :         smb2_deltree(tree, DNAME);
    2874           0 :         talloc_free(mem_ctx);
    2875           0 :         return ret;
    2876             : }
    2877             : 
    2878           0 : static bool test_fileid_dir(struct torture_context *tctx,
    2879             :                             struct smb2_tree *tree)
    2880             : {
    2881           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2882           0 :         const char *dname = DNAME "\\foo";
    2883           0 :         const char *sname = DNAME "\\foo:bar";
    2884             :         struct smb2_handle testdirh;
    2885             :         struct smb2_handle h1;
    2886             :         struct smb2_create create;
    2887             :         union smb_fileinfo finfo;
    2888             :         union smb_setfileinfo sinfo;
    2889             :         struct smb2_find f;
    2890             :         unsigned int count;
    2891             :         union smb_search_data *d;
    2892             :         uint64_t expected_fileid;
    2893             :         uint64_t returned_fileid;
    2894             :         NTSTATUS status;
    2895           0 :         bool ret = true;
    2896             : 
    2897           0 :         smb2_deltree(tree, DNAME);
    2898             : 
    2899           0 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    2900           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2901             :                                         "torture_smb2_testdir failed\n");
    2902             : 
    2903             :         /*
    2904             :          * Initial directory create with QFID
    2905             :          */
    2906           0 :         create = (struct smb2_create) {
    2907             :                 .in.desired_access = SEC_FILE_ALL,
    2908             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2909             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    2910             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2911             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2912             :                 .in.fname = dname,
    2913             :                 .in.query_on_disk_id = true,
    2914             :         };
    2915             : 
    2916           0 :         status = smb2_create(tree, tctx, &create);
    2917           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2918             :                                         "test file could not be created\n");
    2919           0 :         h1 = create.out.file.handle;
    2920           0 :         expected_fileid = BVAL(&create.out.on_disk_id, 0);
    2921             : 
    2922             :         /*
    2923             :          * Getinfo the File-ID on the just opened handle
    2924             :          */
    2925           0 :         finfo = (union smb_fileinfo) {
    2926             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2927             :                 .generic.in.file.handle = h1,
    2928             :         };
    2929             : 
    2930           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2931           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2932             :                                         "torture_smb2_testdir\n");
    2933           0 :         smb2_util_close(tree, h1);
    2934           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2935             :                                       expected_fileid,
    2936             :                                       ret, done, "bad fileid\n");
    2937             : 
    2938             :         /*
    2939             :          * Open existing directory with QFID
    2940             :          */
    2941           0 :         create = (struct smb2_create) {
    2942             :                 .in.desired_access = SEC_FILE_ALL,
    2943             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2944             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    2945             :                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    2946             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    2947             :                 .in.fname = dname,
    2948             :                 .in.query_on_disk_id = true,
    2949             :         };
    2950             : 
    2951           0 :         status = smb2_create(tree, tctx, &create);
    2952           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2953             :                                         "test file could not be created\n");
    2954           0 :         h1 = create.out.file.handle;
    2955           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2956           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2957             :                                       ret, done, "bad fileid\n");
    2958             : 
    2959             :         /*
    2960             :          * Getinfo the File-ID on the just opened handle
    2961             :          */
    2962           0 :         finfo = (union smb_fileinfo) {
    2963             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    2964             :                 .generic.in.file.handle = h1,
    2965             :         };
    2966             : 
    2967           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    2968           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2969             :                                         "torture_smb2_testdir\n");
    2970           0 :         smb2_util_close(tree, h1);
    2971           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    2972             :                                       expected_fileid,
    2973             :                                       ret, done, "bad fileid\n");
    2974             : 
    2975             :         /*
    2976             :          * Create stream, check the stream's File-ID, should be the same as the
    2977             :          * base file (sic!, tested against Windows).
    2978             :          */
    2979           0 :         create = (struct smb2_create) {
    2980             :                 .in.desired_access = SEC_FILE_ALL,
    2981             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    2982             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    2983             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
    2984             :                 .in.fname = sname,
    2985             :                 .in.query_on_disk_id = true,
    2986             :         };
    2987             : 
    2988           0 :         status = smb2_create(tree, tctx, &create);
    2989           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2990             :                                         "test file could not be created\n");
    2991           0 :         h1 = create.out.file.handle;
    2992           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    2993           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    2994             :                                       ret, done, "bad fileid\n");
    2995             : 
    2996             :         /*
    2997             :          * Getinfo the File-ID on the created stream
    2998             :          */
    2999           0 :         finfo = (union smb_fileinfo) {
    3000             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3001             :                 .generic.in.file.handle = h1,
    3002             :         };
    3003             : 
    3004           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3005           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3006             :                                         "smb2_getinfo_file failed\n");
    3007           0 :         smb2_util_close(tree, h1);
    3008           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3009             :                                       expected_fileid,
    3010             :                                       ret, done, "bad fileid\n");
    3011             : 
    3012             :         /*
    3013             :          * Open stream, check the stream's File-ID, should be the same as the
    3014             :          * base file (sic!, tested against Windows).
    3015             :          */
    3016           0 :         create = (struct smb2_create) {
    3017             :                 .in.desired_access = SEC_FILE_ALL,
    3018             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3019             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3020             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3021             :                 .in.fname = sname,
    3022             :                 .in.query_on_disk_id = true,
    3023             :         };
    3024             : 
    3025           0 :         status = smb2_create(tree, tctx, &create);
    3026           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3027             :                                         "test file could not be created\n");
    3028           0 :         h1 = create.out.file.handle;
    3029           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3030           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3031             :                                       ret, done, "bad fileid\n");
    3032             : 
    3033             :         /*
    3034             :          * Getinfo the File-ID on the opened stream
    3035             :          */
    3036           0 :         finfo = (union smb_fileinfo) {
    3037             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3038             :                 .generic.in.file.handle = h1,
    3039             :         };
    3040             : 
    3041           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3042           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3043             :                                         "smb2_getinfo_file failed\n");
    3044           0 :         smb2_util_close(tree, h1);
    3045           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3046             :                                       expected_fileid,
    3047             :                                       ret, done, "bad fileid\n");
    3048             : 
    3049             :         /*
    3050             :          * Overwrite stream, check the stream's File-ID, should be the same as
    3051             :          * the base file (sic!, tested against Windows).
    3052             :          */
    3053           0 :         create = (struct smb2_create) {
    3054             :                 .in.desired_access = SEC_FILE_ALL,
    3055             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3056             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3057             :                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
    3058             :                 .in.fname = sname,
    3059             :                 .in.query_on_disk_id = true,
    3060             :         };
    3061             : 
    3062           0 :         status = smb2_create(tree, tctx, &create);
    3063           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3064             :                                         "test file could not be created\n");
    3065           0 :         h1 = create.out.file.handle;
    3066           0 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3067           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3068             :                                       ret, done, "bad fileid\n");
    3069             : 
    3070             :         /*
    3071             :          * Getinfo the File-ID on the overwritten stream
    3072             :          */
    3073           0 :         finfo = (union smb_fileinfo) {
    3074             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3075             :                 .generic.in.file.handle = h1,
    3076             :         };
    3077             : 
    3078           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3079           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3080             :                                         "smb2_getinfo_file failed\n");
    3081           0 :         smb2_util_close(tree, h1);
    3082           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3083             :                                       expected_fileid,
    3084             :                                       ret, done, "bad fileid\n");
    3085             : 
    3086             :         /*
    3087             :          * Do some modifications on the stream (IO, setinfo), verifying File-ID
    3088             :          * after earch step.
    3089             :          */
    3090           0 :         create = (struct smb2_create) {
    3091             :                 .in.desired_access = SEC_FILE_ALL,
    3092             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3093             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3094             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3095             :                 .in.fname = sname,
    3096             :                 .in.query_on_disk_id = true,
    3097             :         };
    3098             : 
    3099           0 :         status = smb2_create(tree, tctx, &create);
    3100           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3101             :                                         "test file could not be created\n");
    3102           0 :         h1 = create.out.file.handle;
    3103             : 
    3104           0 :         status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
    3105           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3106             :                                         "smb2_util_write failed\n");
    3107             : 
    3108           0 :         finfo = (union smb_fileinfo) {
    3109             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3110             :                 .generic.in.file.handle = h1,
    3111             :         };
    3112           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3113           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3114             :                                         "smb2_getinfo_file failed\n");
    3115           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3116             :                                       expected_fileid,
    3117             :                                       ret, done, "bad fileid\n");
    3118             : 
    3119           0 :         sinfo = (union smb_setfileinfo) {
    3120             :                 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
    3121             :                 .basic_info.in.file.handle = h1,
    3122             :         };
    3123           0 :         unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
    3124             : 
    3125           0 :         status = smb2_setinfo_file(tree, &sinfo);
    3126           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3127             :                                         "smb2_setinfo_file failed\n");
    3128             : 
    3129           0 :         finfo = (union smb_fileinfo) {
    3130             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3131             :                 .generic.in.file.handle = h1,
    3132             :         };
    3133           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3134           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3135             :                                         "smb2_getinfo_file failed\n");
    3136           0 :         smb2_util_close(tree, h1);
    3137           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3138             :                                       expected_fileid,
    3139             :                                       ret, done, "bad fileid\n");
    3140             : 
    3141             :         /*
    3142             :          * Final open of the directory 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.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
    3148             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3149             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    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 :         returned_fileid = BVAL(&create.out.on_disk_id, 0);
    3159           0 :         torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
    3160             :                                       ret, done, "bad fileid\n");
    3161             : 
    3162             :         /*
    3163             :          * Final Getinfo checking File-ID
    3164             :          */
    3165           0 :         finfo = (union smb_fileinfo) {
    3166             :                 .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3167             :                 .generic.in.file.handle = h1,
    3168             :         };
    3169             : 
    3170           0 :         status = smb2_getinfo_file(tree, tctx, &finfo);
    3171           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3172             :                                         "torture_smb2_testdir\n");
    3173           0 :         smb2_util_close(tree, h1);
    3174           0 :         torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
    3175             :                                       expected_fileid,
    3176             :                                       ret, done, "bad fileid\n");
    3177             : 
    3178             :         /*
    3179             :          * Final list directory, verifying the operations on basefile and stream
    3180             :          * didn't modify the base file metadata.
    3181             :          */
    3182           0 :         f = (struct smb2_find) {
    3183             :                 .in.file.handle = testdirh,
    3184             :                 .in.pattern = "foo",
    3185             :                 .in.max_response_size = 0x1000,
    3186             :                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
    3187             :                 .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
    3188             :         };
    3189             : 
    3190           0 :         status = smb2_find_level(tree, tree, &f, &count, &d);
    3191           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3192             :                                         "smb2_find_level failed\n");
    3193           0 :         torture_assert_u64_equal_goto(tctx,
    3194             :                                       d->id_both_directory_info.file_id,
    3195             :                                       expected_fileid,
    3196             :                                       ret, done, "bad fileid\n");
    3197             : 
    3198           0 : done:
    3199           0 :         smb2_util_close(tree, testdirh);
    3200           0 :         smb2_deltree(tree, DNAME);
    3201           0 :         talloc_free(mem_ctx);
    3202           0 :         return ret;
    3203             : }
    3204             : 
    3205           0 : static bool test_fileid_unique_object(
    3206             :                         struct torture_context *tctx,
    3207             :                         struct smb2_tree *tree,
    3208             :                         unsigned int num_objs,
    3209             :                         bool create_dirs)
    3210           0 : {
    3211           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    3212           0 :         char *fname = NULL;
    3213             :         struct smb2_handle testdirh;
    3214             :         struct smb2_handle h1;
    3215             :         struct smb2_create create;
    3216             :         unsigned int i;
    3217           0 :         uint64_t fileid_array[num_objs];
    3218             :         NTSTATUS status;
    3219           0 :         bool ret = true;
    3220             : 
    3221           0 :         smb2_deltree(tree, DNAME);
    3222             : 
    3223           0 :         status = torture_smb2_testdir(tree, DNAME, &testdirh);
    3224           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3225             :                                         "test_fileid_unique failed\n");
    3226           0 :         smb2_util_close(tree, testdirh);
    3227             : 
    3228             :         /* Create num_obj files as rapidly as we can. */
    3229           0 :         for (i = 0; i < num_objs; i++) {
    3230           0 :                 fname = talloc_asprintf(mem_ctx,
    3231             :                                         "%s\\testfile.%u",
    3232             :                                         DNAME,
    3233             :                                         i);
    3234           0 :                 torture_assert_goto(tctx,
    3235             :                                 fname != NULL,
    3236             :                                 ret,
    3237             :                                 done,
    3238             :                                 "talloc failed\n");
    3239             : 
    3240           0 :                 create = (struct smb2_create) {
    3241             :                         .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
    3242             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3243             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3244             :                         .in.create_disposition = NTCREATEX_DISP_CREATE,
    3245             :                         .in.fname = fname,
    3246             :                 };
    3247             : 
    3248           0 :                 if (create_dirs) {
    3249           0 :                         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    3250           0 :                         create.in.create_options = FILE_DIRECTORY_FILE;
    3251             :                 }
    3252             : 
    3253           0 :                 status = smb2_create(tree, tctx, &create);
    3254           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3255           0 :                         torture_fail(tctx,
    3256             :                                 talloc_asprintf(tctx,
    3257             :                                         "test file %s could not be created\n",
    3258             :                                         fname));
    3259             :                         TALLOC_FREE(fname);
    3260             :                         ret = false;
    3261             :                         goto done;
    3262             :                 }
    3263             : 
    3264           0 :                 h1 = create.out.file.handle;
    3265           0 :                 smb2_util_close(tree, h1);
    3266           0 :                 TALLOC_FREE(fname);
    3267             :         }
    3268             : 
    3269             :         /*
    3270             :          * Get the file ids.
    3271             :          */
    3272           0 :         for (i = 0; i < num_objs; i++) {
    3273             :                 union smb_fileinfo finfo;
    3274             : 
    3275           0 :                 fname = talloc_asprintf(mem_ctx,
    3276             :                                         "%s\\testfile.%u",
    3277             :                                         DNAME,
    3278             :                                         i);
    3279           0 :                 torture_assert_goto(tctx,
    3280             :                                 fname != NULL,
    3281             :                                 ret,
    3282             :                                 done,
    3283             :                                 "talloc failed\n");
    3284             : 
    3285           0 :                 create = (struct smb2_create) {
    3286             :                         .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
    3287             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3288             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3289             :                         .in.create_disposition = NTCREATEX_DISP_OPEN,
    3290             :                         .in.fname = fname,
    3291             :                 };
    3292             : 
    3293           0 :                 if (create_dirs) {
    3294           0 :                         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    3295           0 :                         create.in.create_options = FILE_DIRECTORY_FILE;
    3296             :                 }
    3297             : 
    3298           0 :                 status = smb2_create(tree, tctx, &create);
    3299           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3300           0 :                         torture_fail(tctx,
    3301             :                                 talloc_asprintf(tctx,
    3302             :                                         "test file %s could not "
    3303             :                                         "be opened: %s\n",
    3304             :                                         fname,
    3305             :                                         nt_errstr(status)));
    3306             :                         TALLOC_FREE(fname);
    3307             :                         ret = false;
    3308             :                         goto done;
    3309             :                 }
    3310             : 
    3311           0 :                 h1 = create.out.file.handle;
    3312             : 
    3313           0 :                 finfo = (union smb_fileinfo) {
    3314             :                         .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
    3315             :                         .generic.in.file.handle = h1,
    3316             :                 };
    3317             : 
    3318           0 :                 status = smb2_getinfo_file(tree, tctx, &finfo);
    3319           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3320           0 :                         torture_fail(tctx,
    3321             :                                 talloc_asprintf(tctx,
    3322             :                                         "failed to get fileid for "
    3323             :                                         "test file %s: %s\n",
    3324             :                                         fname,
    3325             :                                         nt_errstr(status)));
    3326             :                         TALLOC_FREE(fname);
    3327             :                         ret = false;
    3328             :                         goto done;
    3329             :                 }
    3330           0 :                 smb2_util_close(tree, h1);
    3331             : 
    3332           0 :                 fileid_array[i] = finfo.all_info2.out.file_id;
    3333           0 :                 TALLOC_FREE(fname);
    3334             :         }
    3335             : 
    3336             :         /* All returned fileids must be unique. 100 is small so brute force. */
    3337           0 :         for (i = 0; i < num_objs - 1; i++) {
    3338             :                 unsigned int j;
    3339           0 :                 for (j = i + 1; j < num_objs; j++) {
    3340           0 :                         if (fileid_array[i] == fileid_array[j]) {
    3341           0 :                                 torture_fail(tctx,
    3342             :                                         talloc_asprintf(tctx,
    3343             :                                                 "fileid %u == fileid %u (0x%"PRIu64")\n",
    3344             :                                                 i,
    3345             :                                                 j,
    3346             :                                                 fileid_array[i]));
    3347             :                                 ret = false;
    3348             :                                 goto done;
    3349             :                         }
    3350             :                 }
    3351             :         }
    3352             : 
    3353           0 : done:
    3354             : 
    3355           0 :         smb2_util_close(tree, testdirh);
    3356           0 :         smb2_deltree(tree, DNAME);
    3357           0 :         talloc_free(mem_ctx);
    3358           0 :         return ret;
    3359             : }
    3360             : 
    3361           0 : static bool test_fileid_unique(
    3362             :                         struct torture_context *tctx,
    3363             :                         struct smb2_tree *tree)
    3364             : {
    3365           0 :         return test_fileid_unique_object(tctx, tree, 100, false);
    3366             : }
    3367             : 
    3368           0 : static bool test_fileid_unique_dir(
    3369             :                         struct torture_context *tctx,
    3370             :                         struct smb2_tree *tree)
    3371             : {
    3372           0 :         return test_fileid_unique_object(tctx, tree, 100, true);
    3373             : }
    3374             : 
    3375           2 : static bool test_dosattr_tmp_dir(struct torture_context *tctx,
    3376             :                                  struct smb2_tree *tree)
    3377             : {
    3378           2 :         bool ret = true;
    3379             :         NTSTATUS status;
    3380             :         struct smb2_create c;
    3381           2 :         struct smb2_handle h1 = {{0}};
    3382           2 :         const char *fname = DNAME;
    3383             : 
    3384           2 :         smb2_deltree(tree, fname);
    3385           2 :         smb2_util_rmdir(tree, fname);
    3386             : 
    3387           2 :         c = (struct smb2_create) {
    3388             :                 .in.desired_access = SEC_RIGHTS_DIR_ALL,
    3389             :                 .in.file_attributes  = FILE_ATTRIBUTE_DIRECTORY,
    3390             :                 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
    3391             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    3392             :                         NTCREATEX_SHARE_ACCESS_WRITE |
    3393             :                         NTCREATEX_SHARE_ACCESS_DELETE,
    3394             :                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
    3395             :                 .in.fname = DNAME,
    3396             :         };
    3397             : 
    3398           2 :         status = smb2_create(tree, tctx, &c);
    3399           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3400             :                                         "smb2_create\n");
    3401           2 :         h1 = c.out.file.handle;
    3402             : 
    3403             :         /* Try to set temporary attribute on directory */
    3404           2 :         SET_ATTRIB(FILE_ATTRIBUTE_TEMPORARY);
    3405             : 
    3406           2 :         torture_assert_ntstatus_equal_goto(tctx, status,
    3407             :                                            NT_STATUS_INVALID_PARAMETER,
    3408             :                                            ret, done,
    3409             :                                            "Unexpected setinfo result\n");
    3410             : 
    3411           2 : done:
    3412           2 :         if (!smb2_util_handle_empty(h1)) {
    3413           2 :                 smb2_util_close(tree, h1);
    3414             :         }
    3415           2 :         smb2_util_unlink(tree, fname);
    3416           2 :         smb2_deltree(tree, fname);
    3417             : 
    3418           2 :         return ret;
    3419             : }
    3420             : 
    3421             : /*
    3422             :   test opening quota fakefile handle and returned attributes
    3423             : */
    3424           2 : static bool test_smb2_open_quota_fake_file(struct torture_context *tctx,
    3425             :                                            struct smb2_tree *tree)
    3426             : {
    3427           2 :         const char *fname = "$Extend\\$Quota:$Q:$INDEX_ALLOCATION";
    3428             :         struct smb2_create create;
    3429           2 :         struct smb2_handle h = {{0}};
    3430             :         NTSTATUS status;
    3431           2 :         bool ret = true;
    3432             : 
    3433           2 :         create = (struct smb2_create) {
    3434             :                 .in.desired_access = SEC_RIGHTS_FILE_READ,
    3435             :                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    3436             :                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    3437             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
    3438             :                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
    3439             :                 .in.fname = fname,
    3440             :         };
    3441             : 
    3442           2 :         status = smb2_create(tree, tree, &create);
    3443           2 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    3444             :                                         "smb2_create failed\n");
    3445           1 :         h = create.out.file.handle;
    3446             : 
    3447           1 :         torture_assert_u64_equal_goto(tctx,
    3448             :                                       create.out.file_attr,
    3449             :                                       FILE_ATTRIBUTE_HIDDEN
    3450             :                                       | FILE_ATTRIBUTE_SYSTEM
    3451             :                                       | FILE_ATTRIBUTE_DIRECTORY
    3452             :                                       | FILE_ATTRIBUTE_ARCHIVE,
    3453             :                                       ret,
    3454             :                                       done,
    3455             :                                       "Wrong attributes\n");
    3456             : 
    3457           1 :         torture_assert_u64_equal_goto(tctx,
    3458             :                                       create.out.create_time, 0,
    3459             :                                       ret,
    3460             :                                       done,
    3461             :                                       "create_time is not 0\n");
    3462           1 :         torture_assert_u64_equal_goto(tctx,
    3463             :                                       create.out.access_time, 0,
    3464             :                                       ret,
    3465             :                                       done,
    3466             :                                       "access_time is not 0\n");
    3467           1 :         torture_assert_u64_equal_goto(tctx,
    3468             :                                       create.out.write_time, 0,
    3469             :                                       ret,
    3470             :                                       done,
    3471             :                                       "write_time is not 0\n");
    3472           1 :         torture_assert_u64_equal_goto(tctx,
    3473             :                                       create.out.change_time, 0,
    3474             :                                       ret,
    3475             :                                       done,
    3476             :                                       "change_time is not 0\n");
    3477             : 
    3478           3 : done:
    3479           2 :         smb2_util_close(tree, h);
    3480           2 :         return ret;
    3481             : }
    3482             : 
    3483             : /*
    3484             :    stress testing path base operations
    3485             :    e.g. contention on lockting.tdb records
    3486             :  */
    3487             : 
    3488             : struct test_smb2_bench_path_contention_shared_conn;
    3489             : struct test_smb2_bench_path_contention_shared_loop;
    3490             : 
    3491             : struct test_smb2_bench_path_contention_shared_state {
    3492             :         struct torture_context *tctx;
    3493             :         size_t num_conns;
    3494             :         struct test_smb2_bench_path_contention_shared_conn *conns;
    3495             :         size_t num_loops;
    3496             :         struct test_smb2_bench_path_contention_shared_loop *loops;
    3497             :         struct timeval starttime;
    3498             :         int timecount;
    3499             :         int timelimit;
    3500             :         struct {
    3501             :                 uint64_t num_finished;
    3502             :                 double total_latency;
    3503             :                 double min_latency;
    3504             :                 double max_latency;
    3505             :         } opens;
    3506             :         struct {
    3507             :                 uint64_t num_finished;
    3508             :                 double total_latency;
    3509             :                 double min_latency;
    3510             :                 double max_latency;
    3511             :         } closes;
    3512             :         bool ok;
    3513             :         bool stop;
    3514             : };
    3515             : 
    3516             : struct test_smb2_bench_path_contention_shared_conn {
    3517             :         struct test_smb2_bench_path_contention_shared_state *state;
    3518             :         int idx;
    3519             :         struct smb2_tree *tree;
    3520             : };
    3521             : 
    3522             : struct test_smb2_bench_path_contention_shared_loop {
    3523             :         struct test_smb2_bench_path_contention_shared_state *state;
    3524             :         struct test_smb2_bench_path_contention_shared_conn *conn;
    3525             :         int idx;
    3526             :         struct tevent_immediate *im;
    3527             :         struct {
    3528             :                 struct smb2_create io;
    3529             :                 struct smb2_request *req;
    3530             :                 struct timeval starttime;
    3531             :                 uint64_t num_started;
    3532             :                 uint64_t num_finished;
    3533             :                 double total_latency;
    3534             :                 double min_latency;
    3535             :                 double max_latency;
    3536             :         } opens;
    3537             :         struct {
    3538             :                 struct smb2_close io;
    3539             :                 struct smb2_request *req;
    3540             :                 struct timeval starttime;
    3541             :                 uint64_t num_started;
    3542             :                 uint64_t num_finished;
    3543             :                 double total_latency;
    3544             :                 double min_latency;
    3545             :                 double max_latency;
    3546             :         } closes;
    3547             :         NTSTATUS error;
    3548             : };
    3549             : 
    3550             : static void test_smb2_bench_path_contention_loop_open(
    3551             :         struct test_smb2_bench_path_contention_shared_loop *loop);
    3552             : 
    3553           8 : static void test_smb2_bench_path_contention_loop_start(struct tevent_context *ctx,
    3554             :                                                        struct tevent_immediate *im,
    3555             :                                                        void *private_data)
    3556             : {
    3557           8 :         struct test_smb2_bench_path_contention_shared_loop *loop =
    3558             :                 (struct test_smb2_bench_path_contention_shared_loop *)
    3559             :                 private_data;
    3560             : 
    3561           8 :         test_smb2_bench_path_contention_loop_open(loop);
    3562           8 : }
    3563             : 
    3564             : static void test_smb2_bench_path_contention_loop_opened(struct smb2_request *req);
    3565             : 
    3566        8653 : static void test_smb2_bench_path_contention_loop_open(
    3567             :         struct test_smb2_bench_path_contention_shared_loop *loop)
    3568             : {
    3569        8653 :         struct test_smb2_bench_path_contention_shared_state *state = loop->state;
    3570             : 
    3571        8653 :         loop->opens.num_started += 1;
    3572        8653 :         loop->opens.starttime = timeval_current();
    3573        8653 :         loop->opens.req = smb2_create_send(loop->conn->tree, &loop->opens.io);
    3574        8653 :         torture_assert_goto(state->tctx, loop->opens.req != NULL,
    3575             :                             state->ok, asserted, "smb2_create_send");
    3576             : 
    3577        8653 :         loop->opens.req->async.fn = test_smb2_bench_path_contention_loop_opened;
    3578        8653 :         loop->opens.req->async.private_data = loop;
    3579        8653 :         return;
    3580           0 : asserted:
    3581           0 :         state->stop = true;
    3582             : }
    3583             : 
    3584             : static void test_smb2_bench_path_contention_loop_close(
    3585             :         struct test_smb2_bench_path_contention_shared_loop *loop);
    3586             : 
    3587        8650 : static void test_smb2_bench_path_contention_loop_opened(struct smb2_request *req)
    3588             : {
    3589        8650 :         struct test_smb2_bench_path_contention_shared_loop *loop =
    3590             :                 (struct test_smb2_bench_path_contention_shared_loop *)
    3591             :                 req->async.private_data;
    3592        8650 :         struct test_smb2_bench_path_contention_shared_state *state = loop->state;
    3593        8650 :         double latency = timeval_elapsed(&loop->opens.starttime);
    3594        8650 :         TALLOC_CTX *frame = talloc_stackframe();
    3595             : 
    3596        8650 :         torture_assert_goto(state->tctx, loop->opens.req == req,
    3597             :                             state->ok, asserted, __location__);
    3598        8650 :         loop->error = smb2_create_recv(req, frame, &loop->opens.io);
    3599        8650 :         torture_assert_ntstatus_ok_goto(state->tctx, loop->error,
    3600             :                                         state->ok, asserted, __location__);
    3601        8650 :         ZERO_STRUCT(loop->opens.io.out.blobs);
    3602        8650 :         SMB_ASSERT(latency >= 0.000001);
    3603             : 
    3604        8650 :         if (loop->opens.num_finished == 0) {
    3605             :                 /* first round */
    3606           8 :                 loop->opens.min_latency = latency;
    3607           8 :                 loop->opens.max_latency = latency;
    3608             :         }
    3609             : 
    3610        8650 :         loop->opens.num_finished += 1;
    3611        8650 :         loop->opens.total_latency += latency;
    3612             : 
    3613        8650 :         if (latency < loop->opens.min_latency) {
    3614          45 :                 loop->opens.min_latency = latency;
    3615             :         }
    3616             : 
    3617        8650 :         if (latency > loop->opens.max_latency) {
    3618          21 :                 loop->opens.max_latency = latency;
    3619             :         }
    3620             : 
    3621        8650 :         TALLOC_FREE(frame);
    3622        8650 :         test_smb2_bench_path_contention_loop_close(loop);
    3623        8650 :         return;
    3624           0 : asserted:
    3625           0 :         state->stop = true;
    3626           0 :         TALLOC_FREE(frame);
    3627             : }
    3628             : 
    3629             : static void test_smb2_bench_path_contention_loop_closed(struct smb2_request *req);
    3630             : 
    3631        8650 : static void test_smb2_bench_path_contention_loop_close(
    3632             :         struct test_smb2_bench_path_contention_shared_loop *loop)
    3633             : {
    3634        8650 :         struct test_smb2_bench_path_contention_shared_state *state = loop->state;
    3635             : 
    3636        8650 :         loop->closes.num_started += 1;
    3637        8650 :         loop->closes.starttime = timeval_current();
    3638        8650 :         loop->closes.io.in.file = loop->opens.io.out.file;
    3639        8650 :         loop->closes.req = smb2_close_send(loop->conn->tree, &loop->closes.io);
    3640        8650 :         torture_assert_goto(state->tctx, loop->closes.req != NULL,
    3641             :                             state->ok, asserted, "smb2_close_send");
    3642             : 
    3643        8650 :         loop->closes.req->async.fn = test_smb2_bench_path_contention_loop_closed;
    3644        8650 :         loop->closes.req->async.private_data = loop;
    3645        8650 :         return;
    3646           0 : asserted:
    3647           0 :         state->stop = true;
    3648             : }
    3649             : 
    3650        8645 : static void test_smb2_bench_path_contention_loop_closed(struct smb2_request *req)
    3651             : {
    3652        8645 :         struct test_smb2_bench_path_contention_shared_loop *loop =
    3653             :                 (struct test_smb2_bench_path_contention_shared_loop *)
    3654             :                 req->async.private_data;
    3655        8645 :         struct test_smb2_bench_path_contention_shared_state *state = loop->state;
    3656        8645 :         double latency = timeval_elapsed(&loop->closes.starttime);
    3657             : 
    3658        8645 :         torture_assert_goto(state->tctx, loop->closes.req == req,
    3659             :                             state->ok, asserted, __location__);
    3660        8645 :         loop->error = smb2_close_recv(req, &loop->closes.io);
    3661        8645 :         torture_assert_ntstatus_ok_goto(state->tctx, loop->error,
    3662             :                                         state->ok, asserted, __location__);
    3663        8645 :         SMB_ASSERT(latency >= 0.000001);
    3664        8645 :         if (loop->closes.num_finished == 0) {
    3665             :                 /* first round */
    3666           8 :                 loop->closes.min_latency = latency;
    3667           8 :                 loop->closes.max_latency = latency;
    3668             :         }
    3669        8645 :         loop->closes.num_finished += 1;
    3670             : 
    3671        8645 :         loop->closes.total_latency += latency;
    3672             : 
    3673        8645 :         if (latency < loop->closes.min_latency) {
    3674          39 :                 loop->closes.min_latency = latency;
    3675             :         }
    3676             : 
    3677        8645 :         if (latency > loop->closes.max_latency) {
    3678          31 :                 loop->closes.max_latency = latency;
    3679             :         }
    3680             : 
    3681        8645 :         test_smb2_bench_path_contention_loop_open(loop);
    3682        8645 :         return;
    3683           0 : asserted:
    3684           0 :         state->stop = true;
    3685             : }
    3686             : 
    3687           2 : static void test_smb2_bench_path_contention_progress(struct tevent_context *ev,
    3688             :                                                      struct tevent_timer *te,
    3689             :                                                      struct timeval current_time,
    3690             :                                                      void *private_data)
    3691             : {
    3692           2 :         struct test_smb2_bench_path_contention_shared_state *state =
    3693             :                 (struct test_smb2_bench_path_contention_shared_state *)private_data;
    3694           2 :         uint64_t num_opens = 0;
    3695           2 :         double total_open_latency = 0;
    3696           2 :         double min_open_latency = 0;
    3697           2 :         double max_open_latency = 0;
    3698           2 :         double avs_open_latency = 0;
    3699           2 :         uint64_t num_closes = 0;
    3700           2 :         double total_close_latency = 0;
    3701           2 :         double min_close_latency = 0;
    3702           2 :         double max_close_latency = 0;
    3703           2 :         double avs_close_latency = 0;
    3704             :         size_t i;
    3705             : 
    3706           2 :         state->timecount += 1;
    3707             : 
    3708          10 :         for (i=0;i<state->num_loops;i++) {
    3709           8 :                 struct test_smb2_bench_path_contention_shared_loop *loop =
    3710           8 :                         &state->loops[i];
    3711             : 
    3712           8 :                 num_opens += loop->opens.num_finished;
    3713           8 :                 total_open_latency += loop->opens.total_latency;
    3714           8 :                 if (min_open_latency == 0.0 && loop->opens.min_latency != 0.0) {
    3715           2 :                         min_open_latency = loop->opens.min_latency;
    3716             :                 }
    3717           8 :                 if (loop->opens.min_latency < min_open_latency) {
    3718           1 :                         min_open_latency = loop->opens.min_latency;
    3719             :                 }
    3720           8 :                 if (max_open_latency == 0.0) {
    3721           2 :                         max_open_latency = loop->opens.max_latency;
    3722             :                 }
    3723           8 :                 if (loop->opens.max_latency > max_open_latency) {
    3724           2 :                         max_open_latency = loop->opens.max_latency;
    3725             :                 }
    3726           8 :                 loop->opens.num_finished = 0;
    3727           8 :                 loop->opens.total_latency = 0.0;
    3728             : 
    3729           8 :                 num_closes += loop->closes.num_finished;
    3730           8 :                 total_close_latency += loop->closes.total_latency;
    3731           8 :                 if (min_close_latency == 0.0 && loop->closes.min_latency != 0.0) {
    3732           2 :                         min_close_latency = loop->closes.min_latency;
    3733             :                 }
    3734           8 :                 if (loop->closes.min_latency < min_close_latency) {
    3735           0 :                         min_close_latency = loop->closes.min_latency;
    3736             :                 }
    3737           8 :                 if (max_close_latency == 0.0) {
    3738           2 :                         max_close_latency = loop->closes.max_latency;
    3739             :                 }
    3740           8 :                 if (loop->closes.max_latency > max_close_latency) {
    3741           3 :                         max_close_latency = loop->closes.max_latency;
    3742             :                 }
    3743           8 :                 loop->closes.num_finished = 0;
    3744           8 :                 loop->closes.total_latency = 0.0;
    3745             :         }
    3746             : 
    3747           2 :         state->opens.num_finished += num_opens;
    3748           2 :         state->opens.total_latency += total_open_latency;
    3749           2 :         if (state->opens.min_latency == 0.0 && min_open_latency != 0.0) {
    3750           2 :                 state->opens.min_latency = min_open_latency;
    3751             :         }
    3752           2 :         if (min_open_latency < state->opens.min_latency) {
    3753           0 :                 state->opens.min_latency = min_open_latency;
    3754             :         }
    3755           2 :         if (state->opens.max_latency == 0.0) {
    3756           2 :                 state->opens.max_latency = max_open_latency;
    3757             :         }
    3758           2 :         if (max_open_latency > state->opens.max_latency) {
    3759           0 :                 state->opens.max_latency = max_open_latency;
    3760             :         }
    3761             : 
    3762           2 :         state->closes.num_finished += num_closes;
    3763           2 :         state->closes.total_latency += total_close_latency;
    3764           2 :         if (state->closes.min_latency == 0.0 && min_close_latency != 0.0) {
    3765           2 :                 state->closes.min_latency = min_close_latency;
    3766             :         }
    3767           2 :         if (min_close_latency < state->closes.min_latency) {
    3768           0 :                 state->closes.min_latency = min_close_latency;
    3769             :         }
    3770           2 :         if (state->closes.max_latency == 0.0) {
    3771           2 :                 state->closes.max_latency = max_close_latency;
    3772             :         }
    3773           2 :         if (max_close_latency > state->closes.max_latency) {
    3774           0 :                 state->closes.max_latency = max_close_latency;
    3775             :         }
    3776             : 
    3777           2 :         if (state->timecount < state->timelimit) {
    3778           0 :                 te = tevent_add_timer(state->tctx->ev,
    3779             :                                       state,
    3780             :                                       timeval_current_ofs(1, 0),
    3781             :                                       test_smb2_bench_path_contention_progress,
    3782             :                                       state);
    3783           0 :                 torture_assert_goto(state->tctx, te != NULL,
    3784             :                                     state->ok, asserted, "tevent_add_timer");
    3785             : 
    3786           0 :                 if (!torture_setting_bool(state->tctx, "progress", true)) {
    3787           0 :                         return;
    3788             :                 }
    3789             : 
    3790           0 :                 avs_open_latency = total_open_latency / num_opens;
    3791           0 :                 avs_close_latency = total_close_latency / num_closes;
    3792             : 
    3793           0 :                 torture_comment(state->tctx,
    3794             :                                 "%.2f second: "
    3795             :                                 "open[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] "
    3796             :                                 "close[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]     \r",
    3797           0 :                                 timeval_elapsed(&state->starttime),
    3798             :                                 (unsigned long long)num_opens,
    3799             :                                 avs_open_latency,
    3800             :                                 min_open_latency,
    3801             :                                 max_open_latency,
    3802             :                                 (unsigned long long)num_closes,
    3803             :                                 avs_close_latency,
    3804             :                                 min_close_latency,
    3805             :                                 max_close_latency);
    3806           0 :                 return;
    3807             :         }
    3808             : 
    3809           2 :         avs_open_latency = state->opens.total_latency / state->opens.num_finished;
    3810           2 :         avs_close_latency = state->closes.total_latency / state->closes.num_finished;
    3811           2 :         num_opens = state->opens.num_finished / state->timelimit;
    3812           2 :         num_closes = state->closes.num_finished / state->timelimit;
    3813             : 
    3814           4 :         torture_comment(state->tctx,
    3815             :                         "%.2f second: "
    3816             :                         "open[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] "
    3817             :                         "close[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]\n",
    3818           2 :                         timeval_elapsed(&state->starttime),
    3819             :                         (unsigned long long)num_opens,
    3820             :                         avs_open_latency,
    3821             :                         state->opens.min_latency,
    3822             :                         state->opens.max_latency,
    3823             :                         (unsigned long long)num_closes,
    3824             :                         avs_close_latency,
    3825             :                         state->closes.min_latency,
    3826             :                         state->closes.max_latency);
    3827             : 
    3828           2 : asserted:
    3829           2 :         state->stop = true;
    3830             : }
    3831             : 
    3832           2 : static bool test_smb2_bench_path_contention_shared(struct torture_context *tctx,
    3833             :                                                    struct smb2_tree *tree)
    3834             : {
    3835           2 :         struct test_smb2_bench_path_contention_shared_state *state = NULL;
    3836           2 :         bool ret = true;
    3837           2 :         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
    3838           2 :         int torture_qdepth = torture_setting_int(tctx, "qdepth", 1);
    3839             :         size_t i;
    3840           2 :         size_t li = 0;
    3841           2 :         int timelimit = torture_setting_int(tctx, "timelimit", 10);
    3842           2 :         const char *path = torture_setting_string(tctx, "bench_path", "");
    3843           2 :         struct smb2_create open_io = { .level = RAW_OPEN_SMB2, };
    3844           2 :         struct smb2_close close_io = { .level = RAW_CLOSE_SMB2, };
    3845           2 :         struct tevent_timer *te = NULL;
    3846             :         uint32_t timeout_msec;
    3847             : 
    3848           2 :         state = talloc_zero(tctx, struct test_smb2_bench_path_contention_shared_state);
    3849           2 :         torture_assert(tctx, state != NULL, __location__);
    3850           2 :         state->tctx = tctx;
    3851           2 :         state->num_conns = torture_nprocs;
    3852           2 :         state->conns = talloc_zero_array(state,
    3853             :                         struct test_smb2_bench_path_contention_shared_conn,
    3854             :                         state->num_conns);
    3855           2 :         torture_assert(tctx, state->conns != NULL, __location__);
    3856           2 :         state->num_loops = torture_nprocs * torture_qdepth;
    3857           2 :         state->loops = talloc_zero_array(state,
    3858             :                         struct test_smb2_bench_path_contention_shared_loop,
    3859             :                         state->num_loops);
    3860           2 :         torture_assert(tctx, state->loops != NULL, __location__);
    3861           2 :         state->ok = true;
    3862           2 :         state->timelimit = MAX(timelimit, 1);
    3863             : 
    3864           2 :         open_io.in.desired_access = SEC_DIR_READ_ATTRIBUTE;
    3865           2 :         open_io.in.alloc_size = 0;
    3866           2 :         open_io.in.file_attributes = 0;
    3867           2 :         open_io.in.share_access = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
    3868           2 :         open_io.in.create_disposition = FILE_OPEN;
    3869           2 :         open_io.in.create_options = FILE_OPEN_REPARSE_POINT;
    3870           2 :         open_io.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    3871           2 :         open_io.in.security_flags = 0;
    3872           2 :         open_io.in.fname = path;
    3873           2 :         open_io.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    3874           2 :         open_io.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
    3875             : 
    3876           2 :         timeout_msec = tree->session->transport->options.request_timeout * 1000;
    3877             : 
    3878           2 :         torture_comment(tctx, "Opening %zd connections\n", state->num_conns);
    3879             : 
    3880          20 :         for (i=0;i<state->num_conns;i++) {
    3881           8 :                 struct smb2_tree *ct = NULL;
    3882           8 :                 DATA_BLOB out_input_buffer = data_blob_null;
    3883           8 :                 DATA_BLOB out_output_buffer = data_blob_null;
    3884             :                 size_t pcli;
    3885             : 
    3886           8 :                 state->conns[i].state = state;
    3887           8 :                 state->conns[i].idx = i;
    3888             : 
    3889           8 :                 if (!torture_smb2_connection(tctx, &ct)) {
    3890           0 :                         torture_comment(tctx, "Failed opening %zd/%zd connections\n", i, state->num_conns);
    3891           0 :                         return false;
    3892             :                 }
    3893           8 :                 state->conns[i].tree = talloc_steal(state->conns, ct);
    3894             : 
    3895           8 :                 smb2cli_conn_set_max_credits(ct->session->transport->conn, 8192);
    3896          24 :                 smb2cli_ioctl(ct->session->transport->conn,
    3897             :                               timeout_msec,
    3898           8 :                               ct->session->smbXcli,
    3899           8 :                               ct->smbXcli,
    3900             :                               UINT64_MAX, /* in_fid_persistent */
    3901             :                               UINT64_MAX, /* in_fid_volatile */
    3902             :                               UINT32_MAX,
    3903             :                               0, /* in_max_input_length */
    3904             :                               NULL, /* in_input_buffer */
    3905             :                               1, /* in_max_output_length */
    3906             :                               NULL, /* in_output_buffer */
    3907             :                               SMB2_IOCTL_FLAG_IS_FSCTL,
    3908             :                               ct,
    3909             :                               &out_input_buffer,
    3910             :                               &out_output_buffer);
    3911           8 :                 torture_assert(tctx,
    3912             :                        smbXcli_conn_is_connected(ct->session->transport->conn),
    3913             :                        "smbXcli_conn_is_connected");
    3914          16 :                 for (pcli = 0; pcli < torture_qdepth; pcli++) {
    3915           8 :                         struct test_smb2_bench_path_contention_shared_loop *loop = &state->loops[li];
    3916             : 
    3917           8 :                         loop->idx = li++;
    3918           8 :                         loop->state = state;
    3919           8 :                         loop->conn = &state->conns[i];
    3920           8 :                         loop->im = tevent_create_immediate(state->loops);
    3921           8 :                         torture_assert(tctx, loop->im != NULL, __location__);
    3922           8 :                         loop->opens.io = open_io;
    3923           8 :                         loop->closes.io = close_io;
    3924             : 
    3925           8 :                         tevent_schedule_immediate(loop->im,
    3926             :                                                   tctx->ev,
    3927             :                                                   test_smb2_bench_path_contention_loop_start,
    3928             :                                                   loop);
    3929             :                 }
    3930             :         }
    3931             : 
    3932           2 :         torture_comment(tctx, "Opened %zu connections with qdepth=%d => %zu loops\n",
    3933             :                         state->num_conns, torture_qdepth, state->num_loops);
    3934             : 
    3935           2 :         torture_comment(tctx, "Running for %d seconds\n", state->timelimit);
    3936             : 
    3937           2 :         state->starttime = timeval_current();
    3938             : 
    3939           2 :         te = tevent_add_timer(tctx->ev,
    3940             :                               state,
    3941             :                               timeval_current_ofs(1, 0),
    3942             :                               test_smb2_bench_path_contention_progress,
    3943             :                               state);
    3944           2 :         torture_assert(tctx, te != NULL, __location__);
    3945             : 
    3946       61759 :         while (!state->stop) {
    3947       61755 :                 int rc = tevent_loop_once(tctx->ev);
    3948       61755 :                 torture_assert_int_equal(tctx, rc, 0, "tevent_loop_once");
    3949             :         }
    3950             : 
    3951           2 :         torture_comment(tctx, "%.2f seconds\n", timeval_elapsed(&state->starttime));
    3952           2 :         TALLOC_FREE(state);
    3953           2 :         return ret;
    3954             : }
    3955             : 
    3956             : /*
    3957             :    basic testing of SMB2 read
    3958             : */
    3959         964 : struct torture_suite *torture_smb2_create_init(TALLOC_CTX *ctx)
    3960             : {
    3961         964 :         struct torture_suite *suite = torture_suite_create(ctx, "create");
    3962             : 
    3963         964 :         torture_suite_add_1smb2_test(suite, "gentest", test_create_gentest);
    3964         964 :         torture_suite_add_1smb2_test(suite, "blob", test_create_blob);
    3965         964 :         torture_suite_add_1smb2_test(suite, "open", test_smb2_open);
    3966         964 :         torture_suite_add_1smb2_test(suite, "brlocked", test_smb2_open_brlocked);
    3967         964 :         torture_suite_add_1smb2_test(suite, "multi", test_smb2_open_multi);
    3968         964 :         torture_suite_add_1smb2_test(suite, "delete", test_smb2_open_for_delete);
    3969         964 :         torture_suite_add_1smb2_test(suite, "leading-slash", test_smb2_leading_slash);
    3970         964 :         torture_suite_add_1smb2_test(suite, "impersonation", test_smb2_impersonation_level);
    3971         964 :         torture_suite_add_1smb2_test(suite, "aclfile", test_create_acl_file);
    3972         964 :         torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir);
    3973         964 :         torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl);
    3974         964 :         torture_suite_add_1smb2_test(suite, "mkdir-dup", test_mkdir_dup);
    3975         964 :         torture_suite_add_1smb2_test(suite, "dir-alloc-size", test_dir_alloc_size);
    3976         964 :         torture_suite_add_1smb2_test(suite, "dosattr_tmp_dir", test_dosattr_tmp_dir);
    3977         964 :         torture_suite_add_1smb2_test(suite, "quota-fake-file", test_smb2_open_quota_fake_file);
    3978             : 
    3979         964 :         torture_suite_add_1smb2_test(suite, "bench-path-contention-shared", test_smb2_bench_path_contention_shared);
    3980             : 
    3981         964 :         suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
    3982             : 
    3983         964 :         return suite;
    3984             : }
    3985             : 
    3986         964 : struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx)
    3987             : {
    3988         964 :         struct torture_suite *suite = torture_suite_create(ctx, "twrp");
    3989             : 
    3990         964 :         torture_suite_add_1smb2_test(suite, "write", test_twrp_write);
    3991         964 :         torture_suite_add_1smb2_test(suite, "stream", test_twrp_stream);
    3992         964 :         torture_suite_add_1smb2_test(suite, "openroot", test_twrp_openroot);
    3993         964 :         torture_suite_add_1smb2_test(suite, "listdir", test_twrp_listdir);
    3994             : 
    3995         964 :         suite->description = talloc_strdup(suite, "SMB2-TWRP tests");
    3996             : 
    3997         964 :         return suite;
    3998             : }
    3999             : 
    4000             : /*
    4001             :    basic testing of SMB2 File-IDs
    4002             : */
    4003         964 : struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx)
    4004             : {
    4005         964 :         struct torture_suite *suite = torture_suite_create(ctx, "fileid");
    4006             : 
    4007         964 :         torture_suite_add_1smb2_test(suite, "fileid", test_fileid);
    4008         964 :         torture_suite_add_1smb2_test(suite, "fileid-dir", test_fileid_dir);
    4009         964 :         torture_suite_add_1smb2_test(suite, "unique", test_fileid_unique);
    4010         964 :         torture_suite_add_1smb2_test(suite, "unique-dir", test_fileid_unique_dir);
    4011             : 
    4012         964 :         suite->description = talloc_strdup(suite, "SMB2-FILEID tests");
    4013             : 
    4014         964 :         return suite;
    4015             : }
    4016             : 
    4017         964 : struct torture_suite *torture_smb2_bench_init(TALLOC_CTX *ctx)
    4018             : {
    4019         964 :         struct torture_suite *suite = torture_suite_create(ctx, "bench");
    4020             : 
    4021         964 :         torture_suite_add_1smb2_test(suite, "oplock1", test_smb2_bench_oplock);
    4022         964 :         torture_suite_add_1smb2_test(suite, "path-contention-shared", test_smb2_bench_path_contention_shared);
    4023         964 :         torture_suite_add_1smb2_test(suite, "echo", test_smb2_bench_echo);
    4024             : 
    4025         964 :         suite->description = talloc_strdup(suite, "SMB2-BENCH tests");
    4026             : 
    4027         964 :         return suite;
    4028             : }
    4029             : 
    4030           0 : static bool test_no_stream(struct torture_context *tctx,
    4031             :                            struct smb2_tree *tree)
    4032             : {
    4033             :         struct smb2_create c;
    4034             :         NTSTATUS status;
    4035           0 :         bool ret = true;
    4036           0 :         const char *names[] = {
    4037             :                 "test_no_stream::$DATA",
    4038             :                 "test_no_stream::foooooooooooo",
    4039             :                 "test_no_stream:stream",
    4040             :                 "test_no_stream:stream:$DATA",
    4041             :                 NULL
    4042             :         };
    4043             :         int i;
    4044             : 
    4045           0 :         for (i = 0; names[i] != NULL; i++) {
    4046           0 :                 c = (struct smb2_create) {
    4047             :                         .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED,
    4048             :                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
    4049             :                         .in.create_disposition = NTCREATEX_DISP_OPEN,
    4050             :                         .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
    4051           0 :                         .in.fname = names[i],
    4052             :                 };
    4053             : 
    4054           0 :                 status = smb2_create(tree, tctx, &c);
    4055           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
    4056           0 :                         torture_comment(
    4057             :                                 tctx, "Expected NT_STATUS_OBJECT_NAME_INVALID, "
    4058             :                                 "got %s, name: '%s'\n",
    4059             :                                 nt_errstr(status), names[i]);
    4060           0 :                         torture_fail_goto(tctx, done, "Bad create result\n");
    4061             :                 }
    4062             :         }
    4063           0 : done:
    4064           0 :         return ret;
    4065             : }
    4066             : 
    4067         964 : struct torture_suite *torture_smb2_create_no_streams_init(TALLOC_CTX *ctx)
    4068             : {
    4069         964 :         struct torture_suite *suite = torture_suite_create(ctx, "create_no_streams");
    4070             : 
    4071         964 :         torture_suite_add_1smb2_test(suite, "no_stream", test_no_stream);
    4072             : 
    4073         964 :         suite->description = talloc_strdup(suite, "SMB2-CREATE stream test on share without streams support");
    4074             : 
    4075         964 :         return suite;
    4076             : }

Generated by: LCOV version 1.13