LCOV - code coverage report
Current view: top level - source4/torture/smb2 - compound.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 38 1343 2.8 %
Date: 2024-02-14 10:14:15 Functions: 3 31 9.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    test suite for SMB2 compounded requests
       5             : 
       6             :    Copyright (C) Stefan Metzmacher 2009
       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 "tevent.h"
      24             : #include "libcli/smb2/smb2.h"
      25             : #include "libcli/smb2/smb2_calls.h"
      26             : #include "torture/torture.h"
      27             : #include "torture/smb2/proto.h"
      28             : #include "libcli/security/security.h"
      29             : #include "librpc/gen_ndr/ndr_security.h"
      30             : #include "../libcli/smb/smbXcli_base.h"
      31             : 
      32             : #define CHECK_STATUS(status, correct) do { \
      33             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      34             :                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
      35             :                        nt_errstr(status), nt_errstr(correct)); \
      36             :                 ret = false; \
      37             :                 goto done; \
      38             :         }} while (0)
      39             : 
      40             : #define CHECK_VALUE(v, correct) do { \
      41             :         if ((v) != (correct)) { \
      42             :                 torture_result(tctx, TORTURE_FAIL, \
      43             :                     "(%s) Incorrect value %s=%d - should be %d\n", \
      44             :                     __location__, #v, (int)v, (int)correct); \
      45             :                 ret = false; \
      46             :         }} while (0)
      47             : 
      48             : #define WAIT_FOR_ASYNC_RESPONSE(req) \
      49             :         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \
      50             :                 if (tevent_loop_once(tctx->ev) != 0) { \
      51             :                         break; \
      52             :                 } \
      53             :         }
      54             : 
      55             : static struct {
      56             :         struct smb2_handle handle;
      57             :         uint8_t level;
      58             :         struct smb2_break br;
      59             :         int count;
      60             :         int failures;
      61             :         NTSTATUS failure_status;
      62             : } break_info;
      63             : 
      64           0 : static void torture_oplock_break_callback(struct smb2_request *req)
      65             : {
      66             :         NTSTATUS status;
      67             :         struct smb2_break br;
      68             : 
      69           0 :         ZERO_STRUCT(br);
      70           0 :         status = smb2_break_recv(req, &break_info.br);
      71           0 :         if (!NT_STATUS_IS_OK(status)) {
      72           0 :                 break_info.failures++;
      73           0 :                 break_info.failure_status = status;
      74             :         }
      75             : 
      76           0 :         return;
      77             : }
      78             : 
      79             : /* A general oplock break notification handler.  This should be used when a
      80             :  * test expects to break from batch or exclusive to a lower level. */
      81           0 : static bool torture_oplock_handler(struct smb2_transport *transport,
      82             :                                    const struct smb2_handle *handle,
      83             :                                    uint8_t level,
      84             :                                    void *private_data)
      85             : {
      86           0 :         struct smb2_tree *tree = private_data;
      87             :         const char *name;
      88             :         struct smb2_request *req;
      89           0 :         ZERO_STRUCT(break_info.br);
      90             : 
      91           0 :         break_info.handle       = *handle;
      92           0 :         break_info.level        = level;
      93           0 :         break_info.count++;
      94             : 
      95           0 :         switch (level) {
      96           0 :         case SMB2_OPLOCK_LEVEL_II:
      97           0 :                 name = "level II";
      98           0 :                 break;
      99           0 :         case SMB2_OPLOCK_LEVEL_NONE:
     100           0 :                 name = "none";
     101           0 :                 break;
     102           0 :         default:
     103           0 :                 name = "unknown";
     104           0 :                 break_info.failures++;
     105             :         }
     106           0 :         printf("Acking to %s [0x%02X] in oplock handler\n", name, level);
     107             : 
     108           0 :         break_info.br.in.file.handle    = *handle;
     109           0 :         break_info.br.in.oplock_level   = level;
     110           0 :         break_info.br.in.reserved       = 0;
     111           0 :         break_info.br.in.reserved2      = 0;
     112             : 
     113           0 :         req = smb2_break_send(tree, &break_info.br);
     114           0 :         req->async.fn = torture_oplock_break_callback;
     115           0 :         req->async.private_data = NULL;
     116           0 :         return true;
     117             : }
     118             : 
     119           0 : static bool test_compound_break(struct torture_context *tctx,
     120             :                                  struct smb2_tree *tree)
     121             : {
     122           0 :         const char *fname1 = "some-file.pptx";
     123             :         NTSTATUS status;
     124           0 :         bool ret = true;
     125             :         union smb_open io1;
     126             :         struct smb2_create io2;
     127             :         struct smb2_getinfo gf;
     128             :         struct smb2_request *req[2];
     129             :         struct smb2_handle h1;
     130             :         struct smb2_handle h;
     131             : 
     132           0 :         tree->session->transport->oplock.handler = torture_oplock_handler;
     133           0 :         tree->session->transport->oplock.private_data = tree;
     134             : 
     135           0 :         ZERO_STRUCT(break_info);
     136             : 
     137             :         /*
     138             :           base ntcreatex parms
     139             :         */
     140           0 :         ZERO_STRUCT(io1.smb2);
     141           0 :         io1.generic.level = RAW_OPEN_SMB2;
     142           0 :         io1.smb2.in.desired_access = (SEC_STD_SYNCHRONIZE|
     143             :                                         SEC_STD_READ_CONTROL|
     144             :                                         SEC_FILE_READ_ATTRIBUTE|
     145             :                                         SEC_FILE_READ_EA|
     146             :                                         SEC_FILE_READ_DATA);
     147           0 :         io1.smb2.in.alloc_size = 0;
     148           0 :         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     149           0 :         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
     150             :                         NTCREATEX_SHARE_ACCESS_WRITE|
     151             :                         NTCREATEX_SHARE_ACCESS_DELETE;
     152           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     153           0 :         io1.smb2.in.create_options = 0;
     154           0 :         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     155           0 :         io1.smb2.in.security_flags = 0;
     156           0 :         io1.smb2.in.fname = fname1;
     157             : 
     158           0 :         torture_comment(tctx, "TEST2: open a file with an batch "
     159             :                         "oplock (share mode: all)\n");
     160           0 :         io1.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
     161             : 
     162           0 :         status = smb2_create(tree, tctx, &(io1.smb2));
     163           0 :         torture_assert_ntstatus_ok(tctx, status, "Error opening the file");
     164             : 
     165           0 :         h1 = io1.smb2.out.file.handle;
     166             : 
     167           0 :         torture_comment(tctx, "TEST2: Opening second time with compound\n");
     168             : 
     169           0 :         ZERO_STRUCT(io2);
     170             : 
     171           0 :         io2.in.desired_access = (SEC_STD_SYNCHRONIZE|
     172             :                                 SEC_FILE_READ_ATTRIBUTE|
     173             :                                 SEC_FILE_READ_EA);
     174           0 :         io2.in.alloc_size = 0;
     175           0 :         io2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     176           0 :         io2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
     177             :                         NTCREATEX_SHARE_ACCESS_WRITE|
     178             :                         NTCREATEX_SHARE_ACCESS_DELETE;
     179           0 :         io2.in.create_disposition = NTCREATEX_DISP_OPEN;
     180           0 :         io2.in.create_options = 0;
     181           0 :         io2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     182           0 :         io2.in.security_flags = 0;
     183           0 :         io2.in.fname = fname1;
     184           0 :         io2.in.oplock_level = 0;
     185             : 
     186           0 :         smb2_transport_compound_start(tree->session->transport, 2);
     187             : 
     188           0 :         req[0] = smb2_create_send(tree, &io2);
     189             : 
     190           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     191             : 
     192           0 :         h.data[0] = UINT64_MAX;
     193           0 :         h.data[1] = UINT64_MAX;
     194             : 
     195           0 :         ZERO_STRUCT(gf);
     196           0 :         gf.in.file.handle = h;
     197           0 :         gf.in.info_type = SMB2_0_INFO_FILE;
     198           0 :         gf.in.info_class = 0x16;
     199           0 :         gf.in.output_buffer_length = 0x1000;
     200           0 :         gf.in.input_buffer = data_blob_null;
     201             : 
     202           0 :         req[1] = smb2_getinfo_send(tree, &gf);
     203             : 
     204           0 :         status = smb2_create_recv(req[0], tree, &io2);
     205           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     206             : 
     207           0 :         status = smb2_getinfo_recv(req[1], tree, &gf);
     208           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     209             : 
     210           0 : done:
     211             : 
     212           0 :         smb2_util_close(tree, h1);
     213           0 :         smb2_util_unlink(tree, fname1);
     214           0 :         return ret;
     215             : }
     216             : 
     217           0 : static bool test_compound_related1(struct torture_context *tctx,
     218             :                                    struct smb2_tree *tree)
     219             : {
     220             :         struct smb2_handle hd;
     221             :         struct smb2_create cr;
     222             :         NTSTATUS status;
     223           0 :         const char *fname = "compound_related1.dat";
     224             :         struct smb2_close cl;
     225           0 :         bool ret = true;
     226             :         struct smb2_request *req[2];
     227           0 :         struct smbXcli_tcon *saved_tcon = tree->smbXcli;
     228           0 :         struct smbXcli_session *saved_session = tree->session->smbXcli;
     229             : 
     230           0 :         smb2_transport_credits_ask_num(tree->session->transport, 2);
     231             : 
     232           0 :         smb2_util_unlink(tree, fname);
     233             : 
     234           0 :         smb2_transport_credits_ask_num(tree->session->transport, 1);
     235             : 
     236           0 :         ZERO_STRUCT(cr);
     237           0 :         cr.in.security_flags            = 0x00;
     238           0 :         cr.in.oplock_level              = 0;
     239           0 :         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
     240           0 :         cr.in.create_flags              = 0x00000000;
     241           0 :         cr.in.reserved                  = 0x00000000;
     242           0 :         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
     243           0 :         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
     244           0 :         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
     245             :                                           NTCREATEX_SHARE_ACCESS_WRITE |
     246             :                                           NTCREATEX_SHARE_ACCESS_DELETE;
     247           0 :         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
     248           0 :         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
     249             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
     250             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
     251             :                                           0x00200000;
     252           0 :         cr.in.fname                     = fname;
     253             : 
     254           0 :         smb2_transport_compound_start(tree->session->transport, 2);
     255             : 
     256           0 :         req[0] = smb2_create_send(tree, &cr);
     257             : 
     258           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     259             : 
     260           0 :         hd.data[0] = UINT64_MAX;
     261           0 :         hd.data[1] = UINT64_MAX;
     262             : 
     263           0 :         ZERO_STRUCT(cl);
     264           0 :         cl.in.file.handle = hd;
     265             : 
     266           0 :         tree->smbXcli = smbXcli_tcon_create(tree);
     267           0 :         smb2cli_tcon_set_values(tree->smbXcli,
     268             :                                 NULL, /* session */
     269             :                                 0xFFFFFFFF, /* tcon_id */
     270             :                                 0, /* type */
     271             :                                 0, /* flags */
     272             :                                 0, /* capabilities */
     273             :                                 0 /* maximal_access */);
     274             : 
     275           0 :         tree->session->smbXcli = smbXcli_session_shallow_copy(tree->session,
     276           0 :                                                         tree->session->smbXcli);
     277           0 :         smb2cli_session_set_id_and_flags(tree->session->smbXcli, UINT64_MAX, 0);
     278             : 
     279           0 :         req[1] = smb2_close_send(tree, &cl);
     280             : 
     281           0 :         status = smb2_create_recv(req[0], tree, &cr);
     282           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     283           0 :         status = smb2_close_recv(req[1], &cl);
     284           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     285             : 
     286           0 :         TALLOC_FREE(tree->smbXcli);
     287           0 :         tree->smbXcli = saved_tcon;
     288           0 :         TALLOC_FREE(tree->session->smbXcli);
     289           0 :         tree->session->smbXcli = saved_session;
     290             : 
     291           0 :         smb2_util_unlink(tree, fname);
     292           0 : done:
     293           0 :         return ret;
     294             : }
     295             : 
     296           0 : static bool test_compound_related2(struct torture_context *tctx,
     297             :                                    struct smb2_tree *tree)
     298             : {
     299             :         struct smb2_handle hd;
     300             :         struct smb2_create cr;
     301             :         NTSTATUS status;
     302           0 :         const char *fname = "compound_related2.dat";
     303             :         struct smb2_close cl;
     304           0 :         bool ret = true;
     305             :         struct smb2_request *req[5];
     306           0 :         struct smbXcli_tcon *saved_tcon = tree->smbXcli;
     307           0 :         struct smbXcli_session *saved_session = tree->session->smbXcli;
     308             : 
     309           0 :         smb2_transport_credits_ask_num(tree->session->transport, 5);
     310             : 
     311           0 :         smb2_util_unlink(tree, fname);
     312             : 
     313           0 :         smb2_transport_credits_ask_num(tree->session->transport, 1);
     314             : 
     315           0 :         ZERO_STRUCT(cr);
     316           0 :         cr.in.security_flags            = 0x00;
     317           0 :         cr.in.oplock_level              = 0;
     318           0 :         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
     319           0 :         cr.in.create_flags              = 0x00000000;
     320           0 :         cr.in.reserved                  = 0x00000000;
     321           0 :         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
     322           0 :         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
     323           0 :         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
     324             :                                           NTCREATEX_SHARE_ACCESS_WRITE |
     325             :                                           NTCREATEX_SHARE_ACCESS_DELETE;
     326           0 :         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
     327           0 :         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
     328             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
     329             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
     330             :                                           0x00200000;
     331           0 :         cr.in.fname                     = fname;
     332             : 
     333           0 :         smb2_transport_compound_start(tree->session->transport, 5);
     334             : 
     335           0 :         req[0] = smb2_create_send(tree, &cr);
     336             : 
     337           0 :         hd.data[0] = UINT64_MAX;
     338           0 :         hd.data[1] = UINT64_MAX;
     339             : 
     340           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     341             : 
     342           0 :         ZERO_STRUCT(cl);
     343           0 :         cl.in.file.handle = hd;
     344             : 
     345           0 :         tree->smbXcli = smbXcli_tcon_create(tree);
     346           0 :         smb2cli_tcon_set_values(tree->smbXcli,
     347             :                                 NULL, /* session */
     348             :                                 0xFFFFFFFF, /* tcon_id */
     349             :                                 0, /* type */
     350             :                                 0, /* flags */
     351             :                                 0, /* capabilities */
     352             :                                 0 /* maximal_access */);
     353             : 
     354           0 :         tree->session->smbXcli = smbXcli_session_shallow_copy(tree->session,
     355           0 :                                                         tree->session->smbXcli);
     356           0 :         smb2cli_session_set_id_and_flags(tree->session->smbXcli, UINT64_MAX, 0);
     357             : 
     358           0 :         req[1] = smb2_close_send(tree, &cl);
     359           0 :         req[2] = smb2_close_send(tree, &cl);
     360           0 :         req[3] = smb2_close_send(tree, &cl);
     361           0 :         req[4] = smb2_close_send(tree, &cl);
     362             : 
     363           0 :         status = smb2_create_recv(req[0], tree, &cr);
     364           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     365           0 :         status = smb2_close_recv(req[1], &cl);
     366           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     367           0 :         status = smb2_close_recv(req[2], &cl);
     368           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
     369           0 :         status = smb2_close_recv(req[3], &cl);
     370           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
     371           0 :         status = smb2_close_recv(req[4], &cl);
     372           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
     373             : 
     374           0 :         TALLOC_FREE(tree->smbXcli);
     375           0 :         tree->smbXcli = saved_tcon;
     376           0 :         TALLOC_FREE(tree->session->smbXcli);
     377           0 :         tree->session->smbXcli = saved_session;
     378             : 
     379           0 :         smb2_util_unlink(tree, fname);
     380           0 : done:
     381           0 :         return ret;
     382             : }
     383             : 
     384           0 : static bool test_compound_related3(struct torture_context *tctx,
     385             :                                    struct smb2_tree *tree)
     386             : {
     387             :         struct smb2_handle hd;
     388             :         struct smb2_ioctl io;
     389             :         struct smb2_create cr;
     390             :         struct smb2_close cl;
     391           0 :         const char *fname = "compound_related3.dat";
     392             :         struct smb2_request *req[3];
     393             :         NTSTATUS status;
     394           0 :         bool ret = false;
     395             : 
     396           0 :         smb2_util_unlink(tree, fname);
     397             : 
     398           0 :         ZERO_STRUCT(cr);
     399           0 :         cr.in.security_flags    = 0x00;
     400           0 :         cr.in.oplock_level      = 0;
     401           0 :         cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
     402           0 :         cr.in.create_flags      = 0x00000000;
     403           0 :         cr.in.reserved          = 0x00000000;
     404           0 :         cr.in.desired_access    = SEC_RIGHTS_FILE_ALL;
     405           0 :         cr.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
     406           0 :         cr.in.share_access      = NTCREATEX_SHARE_ACCESS_READ |
     407             :                                   NTCREATEX_SHARE_ACCESS_WRITE |
     408             :                                   NTCREATEX_SHARE_ACCESS_DELETE;
     409           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     410           0 :         cr.in.create_options    = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
     411             :                                   NTCREATEX_OPTIONS_ASYNC_ALERT |
     412             :                                   NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
     413             :                                   0x00200000;
     414           0 :         cr.in.fname             = fname;
     415             : 
     416           0 :         smb2_transport_compound_start(tree->session->transport, 3);
     417             : 
     418           0 :         req[0] = smb2_create_send(tree, &cr);
     419             : 
     420           0 :         hd.data[0] = UINT64_MAX;
     421           0 :         hd.data[1] = UINT64_MAX;
     422             : 
     423           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     424             : 
     425           0 :         ZERO_STRUCT(io);
     426           0 :         io.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID;
     427           0 :         io.in.file.handle = hd;
     428           0 :         io.in.reserved2 = 0;
     429           0 :         io.in.max_output_response = 64;
     430           0 :         io.in.flags = 1;
     431             : 
     432           0 :         req[1] = smb2_ioctl_send(tree, &io);
     433             : 
     434           0 :         ZERO_STRUCT(cl);
     435           0 :         cl.in.file.handle = hd;
     436             : 
     437           0 :         req[2] = smb2_close_send(tree, &cl);
     438             : 
     439           0 :         status = smb2_create_recv(req[0], tree, &cr);
     440           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     441           0 :         status = smb2_ioctl_recv(req[1], tree, &io);
     442           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     443           0 :         status = smb2_close_recv(req[2], &cl);
     444           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     445             : 
     446           0 :         status = smb2_util_unlink(tree, fname);
     447           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     448             : 
     449           0 :         ret = true;
     450           0 : done:
     451           0 :         return ret;
     452             : }
     453             : 
     454           0 : static bool test_compound_related4(struct torture_context *tctx,
     455             :                         struct smb2_tree *tree)
     456             : {
     457           0 :         const char *fname = "compound_related4.dat";
     458           0 :         struct security_descriptor *sd = NULL;
     459             :         struct smb2_handle hd;
     460             :         struct smb2_create cr;
     461             :         union smb_setfileinfo set;
     462             :         struct smb2_ioctl io;
     463             :         struct smb2_close cl;
     464             :         struct smb2_request *req[4];
     465             :         NTSTATUS status;
     466           0 :         bool ret = true;
     467             : 
     468           0 :         smb2_util_unlink(tree, fname);
     469             : 
     470           0 :         ZERO_STRUCT(cr);
     471           0 :         cr.level = RAW_OPEN_SMB2;
     472           0 :         cr.in.create_flags = 0;
     473           0 :         cr.in.desired_access = SEC_STD_READ_CONTROL |
     474             :                                 SEC_STD_WRITE_DAC |
     475             :                                 SEC_STD_WRITE_OWNER;
     476           0 :         cr.in.create_options = 0;
     477           0 :         cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     478           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
     479             :                                 NTCREATEX_SHARE_ACCESS_READ |
     480             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     481           0 :         cr.in.alloc_size = 0;
     482           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     483           0 :         cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
     484           0 :         cr.in.security_flags = 0;
     485           0 :         cr.in.fname = fname;
     486             : 
     487           0 :         status = smb2_create(tree, tctx, &cr);
     488           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
     489             : 
     490           0 :         hd = cr.out.file.handle;
     491           0 :         torture_comment(tctx, "set a sec desc allowing no write by CREATOR_OWNER\n");
     492             : 
     493           0 :         sd = security_descriptor_dacl_create(tctx,
     494             :                         0, NULL, NULL,
     495             :                         SID_CREATOR_OWNER,
     496             :                         SEC_ACE_TYPE_ACCESS_ALLOWED,
     497             :                         SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
     498             :                         0,
     499             :                         NULL);
     500           0 :         torture_assert_not_null_goto(tctx, sd, ret, done,
     501             :                                      "security_descriptor_dacl_create failed\n");
     502             : 
     503           0 :         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
     504           0 :         set.set_secdesc.in.file.handle = hd;
     505           0 :         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
     506           0 :         set.set_secdesc.in.sd = sd;
     507             : 
     508           0 :         status = smb2_setinfo_file(tree, &set);
     509           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     510             :                                         "smb2_setinfo_file failed\n");
     511             : 
     512           0 :         torture_comment(tctx, "try open for write\n");
     513           0 :         cr.in.desired_access = SEC_FILE_WRITE_DATA;
     514           0 :         smb2_transport_compound_start(tree->session->transport, 4);
     515             : 
     516           0 :         req[0] = smb2_create_send(tree, &cr);
     517           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
     518             :                                      "smb2_create_send failed\n");
     519             : 
     520           0 :         hd.data[0] = UINT64_MAX;
     521           0 :         hd.data[1] = UINT64_MAX;
     522             : 
     523           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     524           0 :         ZERO_STRUCT(io);
     525           0 :         io.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID;
     526           0 :         io.in.file.handle = hd;
     527           0 :         io.in.flags = 1;
     528             : 
     529           0 :         req[1] = smb2_ioctl_send(tree, &io);
     530           0 :         torture_assert_not_null_goto(tctx, req[1], ret, done,
     531             :                                      "smb2_ioctl_send failed\n");
     532             : 
     533           0 :         ZERO_STRUCT(cl);
     534           0 :         cl.in.file.handle = hd;
     535             : 
     536           0 :         req[2] = smb2_close_send(tree, &cl);
     537           0 :         torture_assert_not_null_goto(tctx, req[2], ret, done,
     538             :                                      "smb2_create_send failed\n");
     539             : 
     540           0 :         set.set_secdesc.in.file.handle = hd;
     541             : 
     542           0 :         req[3] = smb2_setinfo_file_send(tree, &set);
     543           0 :         torture_assert_not_null_goto(tctx, req[3], ret, done,
     544             :                                      "smb2_create_send failed\n");
     545             : 
     546           0 :         status = smb2_create_recv(req[0], tree, &cr);
     547           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     548             :                                            ret, done,
     549             :                                            "smb2_create_recv failed\n");
     550             : 
     551           0 :         status = smb2_ioctl_recv(req[1], tree, &io);
     552           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     553             :                                            ret, done,
     554             :                                            "smb2_ioctl_recv failed\n");
     555             : 
     556           0 :         status = smb2_close_recv(req[2], &cl);
     557           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     558             :                                            ret, done,
     559             :                                            "smb2_close_recv failed\n");
     560             : 
     561           0 :         status = smb2_setinfo_recv(req[3]);
     562           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     563             :                                            ret, done,
     564             :                                            "smb2_setinfo_recv failed\n");
     565             : 
     566           0 : done:
     567           0 :         smb2_util_unlink(tree, fname);
     568           0 :         smb2_tdis(tree);
     569           0 :         smb2_logoff(tree->session);
     570           0 :         return ret;
     571             : }
     572             : 
     573           0 : static bool test_compound_related5(struct torture_context *tctx,
     574             :                                    struct smb2_tree *tree)
     575             : {
     576             :         struct smb2_handle hd;
     577             :         struct smb2_ioctl io;
     578             :         struct smb2_close cl;
     579             :         struct smb2_request *req[2];
     580             :         NTSTATUS status;
     581           0 :         bool ret = false;
     582             : 
     583           0 :         smb2_transport_compound_start(tree->session->transport, 2);
     584             : 
     585           0 :         hd.data[0] = UINT64_MAX;
     586           0 :         hd.data[1] = UINT64_MAX;
     587             : 
     588           0 :         ZERO_STRUCT(io);
     589           0 :         io.in.function = FSCTL_CREATE_OR_GET_OBJECT_ID;
     590           0 :         io.in.file.handle = hd;
     591           0 :         io.in.flags = 1;
     592             : 
     593           0 :         req[0] = smb2_ioctl_send(tree, &io);
     594           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
     595             :                                      "smb2_ioctl_send failed\n");
     596             : 
     597           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     598             : 
     599           0 :         ZERO_STRUCT(cl);
     600           0 :         cl.in.file.handle = hd;
     601             : 
     602           0 :         req[1] = smb2_close_send(tree, &cl);
     603           0 :         torture_assert_not_null_goto(tctx, req[1], ret, done,
     604             :                                      "smb2_create_send failed\n");
     605             : 
     606           0 :         status = smb2_ioctl_recv(req[0], tree, &io);
     607           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_FILE_CLOSED,
     608             :                                            ret, done,
     609             :                                            "smb2_ioctl_recv failed\n");
     610             : 
     611           0 :         status = smb2_close_recv(req[1], &cl);
     612           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_FILE_CLOSED,
     613             :                                            ret, done,
     614             :                                            "smb2_close_recv failed\n");
     615             : 
     616           0 :         ret = true;
     617             : 
     618           0 : done:
     619           0 :         smb2_tdis(tree);
     620           0 :         smb2_logoff(tree->session);
     621           0 :         return ret;
     622             : }
     623             : 
     624           0 : static bool test_compound_related6(struct torture_context *tctx,
     625             :                                 struct smb2_tree *tree)
     626             : {
     627             :         struct smb2_handle hd;
     628             :         struct smb2_create cr;
     629             :         struct smb2_read rd;
     630             :         struct smb2_write wr;
     631             :         struct smb2_close cl;
     632             :         NTSTATUS status;
     633           0 :         const char *fname = "compound_related6.dat";
     634             :         struct smb2_request *req[5];
     635             :         uint8_t buf[64];
     636           0 :         bool ret = true;
     637             : 
     638           0 :         smb2_util_unlink(tree, fname);
     639             : 
     640           0 :         ZERO_STRUCT(cr);
     641           0 :         cr.level = RAW_OPEN_SMB2;
     642           0 :         cr.in.create_flags = 0;
     643           0 :         cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
     644           0 :         cr.in.create_options = 0;
     645           0 :         cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     646           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
     647             :                                 NTCREATEX_SHARE_ACCESS_READ |
     648             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     649           0 :         cr.in.alloc_size = 0;
     650           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     651           0 :         cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
     652           0 :         cr.in.security_flags = 0;
     653           0 :         cr.in.fname = fname;
     654             : 
     655           0 :         status = smb2_create(tree, tctx, &cr);
     656           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     657             :                                         "smb2_create failed\n");
     658             : 
     659           0 :         hd = cr.out.file.handle;
     660             : 
     661           0 :         ZERO_STRUCT(buf);
     662           0 :         status = smb2_util_write(tree, hd, buf, 0, ARRAY_SIZE(buf));
     663           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     664             :                                         "smb2_util_write failed\n");
     665             : 
     666           0 :         torture_comment(tctx, "try open for read\n");
     667           0 :         cr.in.desired_access = SEC_FILE_READ_DATA;
     668           0 :         smb2_transport_compound_start(tree->session->transport, 5);
     669             : 
     670           0 :         req[0] = smb2_create_send(tree, &cr);
     671           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
     672             :                                      "smb2_create_send failed\n");
     673             : 
     674           0 :         hd.data[0] = UINT64_MAX;
     675           0 :         hd.data[1] = UINT64_MAX;
     676             : 
     677           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     678             : 
     679           0 :         ZERO_STRUCT(rd);
     680           0 :         rd.in.file.handle = hd;
     681           0 :         rd.in.length      = 1;
     682           0 :         rd.in.offset      = 0;
     683             : 
     684           0 :         req[1] = smb2_read_send(tree, &rd);
     685           0 :         torture_assert_not_null_goto(tctx, req[1], ret, done,
     686             :                                      "smb2_read_send failed\n");
     687             : 
     688           0 :         ZERO_STRUCT(wr);
     689           0 :         wr.in.file.handle = hd;
     690           0 :         wr.in.offset = 0;
     691           0 :         wr.in.data = data_blob_talloc(tctx, NULL, 64);
     692             : 
     693           0 :         req[2] = smb2_write_send(tree, &wr);
     694           0 :         torture_assert_not_null_goto(tctx, req[2], ret, done,
     695             :                                      "smb2_write_send failed\n");
     696             : 
     697           0 :         ZERO_STRUCT(rd);
     698           0 :         rd.in.file.handle = hd;
     699           0 :         rd.in.length      = 1;
     700           0 :         rd.in.offset      = 0;
     701             : 
     702           0 :         req[3] = smb2_read_send(tree, &rd);
     703           0 :         torture_assert_not_null_goto(tctx, req[3], ret, done,
     704             :                                      "smb2_read_send failed\n");
     705             : 
     706           0 :         ZERO_STRUCT(cl);
     707           0 :         cl.in.file.handle = hd;
     708             : 
     709           0 :         req[4] = smb2_close_send(tree, &cl);
     710           0 :         torture_assert_not_null_goto(tctx, req[4], ret, done,
     711             :                                      "smb2_close_send failed\n");
     712             : 
     713           0 :         status = smb2_create_recv(req[0], tree, &cr);
     714           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     715             :                                         "smb2_create_recv failed\n");
     716             : 
     717           0 :         status = smb2_read_recv(req[1], tree, &rd);
     718           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     719             :                                         "smb2_read_recv failed\n");
     720             : 
     721           0 :         status = smb2_write_recv(req[2], &wr);
     722           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     723             :                                            ret, done,
     724             :                                            "smb2_write_recv failed\n");
     725             : 
     726           0 :         status = smb2_read_recv(req[3], tree, &rd);
     727           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     728             :                                         "smb2_read_recv failed\n");
     729             : 
     730           0 :         status = smb2_close_recv(req[4], &cl);
     731           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     732             :                                         "smb2_close_recv failed\n");
     733             : 
     734           0 :   done:
     735           0 :         smb2_util_unlink(tree, fname);
     736           0 :         smb2_tdis(tree);
     737           0 :         smb2_logoff(tree->session);
     738           0 :         return ret;
     739             : }
     740             : 
     741           0 : static bool test_compound_related7(struct torture_context *tctx,
     742             :                         struct smb2_tree *tree)
     743             : {
     744           0 :         const char *fname = "compound_related4.dat";
     745           0 :         struct security_descriptor *sd = NULL;
     746             :         struct smb2_handle hd;
     747             :         struct smb2_create cr;
     748             :         union smb_setfileinfo set;
     749             :         struct smb2_notify nt;
     750             :         struct smb2_close cl;
     751             :         NTSTATUS status;
     752             :         struct smb2_request *req[4];
     753           0 :         bool ret = true;
     754             : 
     755           0 :         smb2_util_unlink(tree, fname);
     756             : 
     757           0 :         ZERO_STRUCT(cr);
     758           0 :         cr.level = RAW_OPEN_SMB2;
     759           0 :         cr.in.create_flags = 0;
     760           0 :         cr.in.desired_access = SEC_STD_READ_CONTROL |
     761             :                                 SEC_STD_WRITE_DAC |
     762             :                                 SEC_STD_WRITE_OWNER;
     763           0 :         cr.in.create_options = 0;
     764           0 :         cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     765           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
     766             :                                 NTCREATEX_SHARE_ACCESS_READ |
     767             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     768           0 :         cr.in.alloc_size = 0;
     769           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     770           0 :         cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
     771           0 :         cr.in.security_flags = 0;
     772           0 :         cr.in.fname = fname;
     773             : 
     774           0 :         status = smb2_create(tree, tctx, &cr);
     775           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     776             :                                         "smb2_create failed\n");
     777             : 
     778           0 :         hd = cr.out.file.handle;
     779           0 :         torture_comment(tctx, "set a sec desc allowing no write by CREATOR_OWNER\n");
     780           0 :         sd = security_descriptor_dacl_create(tctx,
     781             :                         0, NULL, NULL,
     782             :                         SID_CREATOR_OWNER,
     783             :                         SEC_ACE_TYPE_ACCESS_ALLOWED,
     784             :                         SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
     785             :                         0,
     786             :                         NULL);
     787           0 :         torture_assert_not_null_goto(tctx, sd, ret, done,
     788             :                                      "security_descriptor_dacl_create failed\n");
     789             : 
     790           0 :         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
     791           0 :         set.set_secdesc.in.file.handle = hd;
     792           0 :         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
     793           0 :         set.set_secdesc.in.sd = sd;
     794             : 
     795           0 :         status = smb2_setinfo_file(tree, &set);
     796           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     797             :                                         "smb2_setinfo_file failed\n");
     798             : 
     799           0 :         torture_comment(tctx, "try open for write\n");
     800           0 :         cr.in.desired_access = SEC_FILE_WRITE_DATA;
     801           0 :         smb2_transport_compound_start(tree->session->transport, 4);
     802             : 
     803           0 :         req[0] = smb2_create_send(tree, &cr);
     804           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
     805             :                                      "smb2_create_send failed\n");
     806             : 
     807           0 :         hd.data[0] = UINT64_MAX;
     808           0 :         hd.data[1] = UINT64_MAX;
     809             : 
     810           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     811             : 
     812           0 :         ZERO_STRUCT(nt);
     813           0 :         nt.in.recursive          = true;
     814           0 :         nt.in.buffer_size        = 0x1000;
     815           0 :         nt.in.file.handle        = hd;
     816           0 :         nt.in.completion_filter  = FILE_NOTIFY_CHANGE_NAME;
     817           0 :         nt.in.unknown            = 0x00000000;
     818             : 
     819           0 :         req[1] = smb2_notify_send(tree, &nt);
     820           0 :         torture_assert_not_null_goto(tctx, req[1], ret, done,
     821             :                                      "smb2_notify_send failed\n");
     822             : 
     823           0 :         ZERO_STRUCT(cl);
     824           0 :         cl.in.file.handle = hd;
     825             : 
     826           0 :         req[2] = smb2_close_send(tree, &cl);
     827           0 :         torture_assert_not_null_goto(tctx, req[2], ret, done,
     828             :                                      "smb2_close_send failed\n");
     829             : 
     830           0 :         set.set_secdesc.in.file.handle = hd;
     831             : 
     832           0 :         req[3] = smb2_setinfo_file_send(tree, &set);
     833           0 :         torture_assert_not_null_goto(tctx, req[3], ret, done,
     834             :                                      "smb2_setinfo_file_send failed\n");
     835             : 
     836           0 :         status = smb2_create_recv(req[0], tree, &cr);
     837           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     838             :                                            ret, done,
     839             :                                            "smb2_create_recv failed\n");
     840             : 
     841           0 :         status = smb2_notify_recv(req[1], tree, &nt);
     842           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     843             :                                            ret, done,
     844             :                                            "smb2_notify_recv failed\n");
     845             : 
     846           0 :         status = smb2_close_recv(req[2], &cl);
     847           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     848             :                                            ret, done,
     849             :                                            "smb2_close_recv failed\n");
     850             : 
     851           0 :         status = smb2_setinfo_recv(req[3]);
     852           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ACCESS_DENIED,
     853             :                                            ret, done,
     854             :                                            "smb2_setinfo_recv failed\n");
     855             : 
     856           0 : done:
     857           0 :         smb2_util_unlink(tree, fname);
     858           0 :         smb2_tdis(tree);
     859           0 :         smb2_logoff(tree->session);
     860           0 :         return ret;
     861             : }
     862             : 
     863           0 : static bool test_compound_related8(struct torture_context *tctx,
     864             :                                    struct smb2_tree *tree)
     865             : {
     866           0 :         const char *fname = "compound_related8.dat";
     867           0 :         const char *fname_nonexisting = "compound_related8.dat.void";
     868           0 :         struct security_descriptor *sd = NULL;
     869             :         struct smb2_handle hd;
     870             :         struct smb2_create cr;
     871             :         union smb_setfileinfo set;
     872             :         struct smb2_notify nt;
     873             :         struct smb2_close cl;
     874             :         NTSTATUS status;
     875             :         struct smb2_request *req[4];
     876           0 :         bool ret = true;
     877             : 
     878           0 :         smb2_util_unlink(tree, fname);
     879             : 
     880           0 :         ZERO_STRUCT(cr);
     881           0 :         cr.level = RAW_OPEN_SMB2;
     882           0 :         cr.in.create_flags = 0;
     883           0 :         cr.in.desired_access = SEC_STD_READ_CONTROL |
     884             :                                 SEC_STD_WRITE_DAC |
     885             :                                 SEC_STD_WRITE_OWNER;
     886           0 :         cr.in.create_options = 0;
     887           0 :         cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     888           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
     889             :                                 NTCREATEX_SHARE_ACCESS_READ |
     890             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     891           0 :         cr.in.alloc_size = 0;
     892           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     893           0 :         cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
     894           0 :         cr.in.security_flags = 0;
     895           0 :         cr.in.fname = fname;
     896             : 
     897           0 :         status = smb2_create(tree, tctx, &cr);
     898           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     899             :                                         "smb2_create failed\n");
     900             : 
     901           0 :         hd = cr.out.file.handle;
     902             : 
     903           0 :         smb2_transport_compound_start(tree->session->transport, 4);
     904             : 
     905           0 :         torture_comment(tctx, "try open for write\n");
     906           0 :         cr.in.fname = fname_nonexisting;
     907           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN;
     908             : 
     909           0 :         req[0] = smb2_create_send(tree, &cr);
     910           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
     911             :                                      "smb2_create_send failed\n");
     912             : 
     913           0 :         hd.data[0] = UINT64_MAX;
     914           0 :         hd.data[1] = UINT64_MAX;
     915             : 
     916           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
     917             : 
     918           0 :         ZERO_STRUCT(nt);
     919           0 :         nt.in.recursive          = true;
     920           0 :         nt.in.buffer_size        = 0x1000;
     921           0 :         nt.in.file.handle        = hd;
     922           0 :         nt.in.completion_filter  = FILE_NOTIFY_CHANGE_NAME;
     923           0 :         nt.in.unknown            = 0x00000000;
     924             : 
     925           0 :         req[1] = smb2_notify_send(tree, &nt);
     926           0 :         torture_assert_not_null_goto(tctx, req[1], ret, done,
     927             :                                      "smb2_notify_send failed\n");
     928             : 
     929           0 :         ZERO_STRUCT(cl);
     930           0 :         cl.in.file.handle = hd;
     931             : 
     932           0 :         req[2] = smb2_close_send(tree, &cl);
     933           0 :         torture_assert_not_null_goto(tctx, req[2], ret, done,
     934             :                                      "smb2_close_send failed\n");
     935             : 
     936           0 :         sd = security_descriptor_dacl_create(tctx,
     937             :                         0, NULL, NULL,
     938             :                         SID_CREATOR_OWNER,
     939             :                         SEC_ACE_TYPE_ACCESS_ALLOWED,
     940             :                         SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
     941             :                         0,
     942             :                         NULL);
     943           0 :         torture_assert_not_null_goto(tctx, sd, ret, done,
     944             :                                      "security_descriptor_dacl_create failed\n");
     945             : 
     946           0 :         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
     947           0 :         set.set_secdesc.in.file.handle = hd;
     948           0 :         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
     949           0 :         set.set_secdesc.in.sd = sd;
     950             : 
     951           0 :         req[3] = smb2_setinfo_file_send(tree, &set);
     952           0 :         torture_assert_not_null_goto(tctx, req[3], ret, done,
     953             :                                      "smb2_setinfo_file_send failed\n");
     954             : 
     955           0 :         status = smb2_create_recv(req[0], tree, &cr);
     956           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     957             :                                            ret, done,
     958             :                                            "smb2_create_recv failed\n");
     959             : 
     960           0 :         status = smb2_notify_recv(req[1], tree, &nt);
     961           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     962             :                                            ret, done,
     963             :                                            "smb2_notify_recv failed\n");
     964             : 
     965           0 :         status = smb2_close_recv(req[2], &cl);
     966           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     967             :                                            ret, done,
     968             :                                            "smb2_close_recv failed\n");
     969             : 
     970           0 :         status = smb2_setinfo_recv(req[3]);
     971           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     972             :                                            ret, done,
     973             :                                            "smb2_setinfo_recv failed\n");
     974             : 
     975           0 : done:
     976           0 :         smb2_util_unlink(tree, fname);
     977           0 :         smb2_tdis(tree);
     978           0 :         smb2_logoff(tree->session);
     979           0 :         return ret;
     980             : }
     981             : 
     982           0 : static bool test_compound_related9(struct torture_context *tctx,
     983             :                                    struct smb2_tree *tree)
     984             : {
     985           0 :         const char *fname = "compound_related9.dat";
     986           0 :         struct security_descriptor *sd = NULL;
     987             :         struct smb2_handle hd;
     988             :         struct smb2_create cr;
     989             :         union smb_setfileinfo set;
     990             :         struct smb2_notify nt;
     991             :         struct smb2_close cl;
     992             :         NTSTATUS status;
     993             :         struct smb2_request *req[3];
     994           0 :         bool ret = true;
     995             : 
     996           0 :         smb2_util_unlink(tree, fname);
     997             : 
     998           0 :         ZERO_STRUCT(cr);
     999           0 :         cr.level = RAW_OPEN_SMB2;
    1000           0 :         cr.in.create_flags = 0;
    1001           0 :         cr.in.desired_access = SEC_STD_READ_CONTROL |
    1002             :                                 SEC_STD_WRITE_DAC |
    1003             :                                 SEC_STD_WRITE_OWNER;
    1004           0 :         cr.in.create_options = 0;
    1005           0 :         cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1006           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
    1007             :                                 NTCREATEX_SHARE_ACCESS_READ |
    1008             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1009           0 :         cr.in.alloc_size = 0;
    1010           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1011           0 :         cr.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
    1012           0 :         cr.in.security_flags = 0;
    1013           0 :         cr.in.fname = fname;
    1014             : 
    1015           0 :         status = smb2_create(tree, tctx, &cr);
    1016           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1017             :                                         "smb2_create failed\n");
    1018             : 
    1019           0 :         hd = cr.out.file.handle;
    1020             : 
    1021           0 :         smb2_transport_compound_start(tree->session->transport, 3);
    1022           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1023             : 
    1024           0 :         ZERO_STRUCT(nt);
    1025           0 :         nt.in.recursive          = true;
    1026           0 :         nt.in.buffer_size        = 0x1000;
    1027           0 :         nt.in.completion_filter  = FILE_NOTIFY_CHANGE_NAME;
    1028             : 
    1029           0 :         req[0] = smb2_notify_send(tree, &nt);
    1030           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
    1031             :                                      "smb2_notify_send failed\n");
    1032             : 
    1033           0 :         ZERO_STRUCT(cl);
    1034           0 :         cl.in.file.handle = hd;
    1035             : 
    1036           0 :         req[1] = smb2_close_send(tree, &cl);
    1037           0 :         torture_assert_not_null_goto(tctx, req[1], ret, done,
    1038             :                                      "smb2_close_send failed\n");
    1039             : 
    1040           0 :         sd = security_descriptor_dacl_create(tctx,
    1041             :                         0, NULL, NULL,
    1042             :                         SID_CREATOR_OWNER,
    1043             :                         SEC_ACE_TYPE_ACCESS_ALLOWED,
    1044             :                         SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
    1045             :                         0,
    1046             :                         NULL);
    1047           0 :         torture_assert_not_null_goto(tctx, sd, ret, done,
    1048             :                                      "security_descriptor_dacl_create failed\n");
    1049             : 
    1050           0 :         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    1051           0 :         set.set_secdesc.in.file.handle = hd;
    1052           0 :         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    1053           0 :         set.set_secdesc.in.sd = sd;
    1054             : 
    1055           0 :         req[2] = smb2_setinfo_file_send(tree, &set);
    1056           0 :         torture_assert_not_null_goto(tctx, req[2], ret, done,
    1057             :                                      "smb2_setinfo_file_send failed\n");
    1058             : 
    1059           0 :         status = smb2_notify_recv(req[0], tree, &nt);
    1060           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_INVALID_PARAMETER,
    1061             :                                            ret, done,
    1062             :                                            "smb2_notify_recv failed\n");
    1063             : 
    1064           0 :         status = smb2_close_recv(req[1], &cl);
    1065           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_INVALID_PARAMETER,
    1066             :                                            ret, done,
    1067             :                                            "smb2_close_recv failed\n");
    1068             : 
    1069           0 :         status = smb2_setinfo_recv(req[2]);
    1070           0 :         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_INVALID_PARAMETER,
    1071             :                                            ret, done,
    1072             :                                            "smb2_setinfo_recv failed\n");
    1073             : 
    1074           0 : done:
    1075           0 :         smb2_util_unlink(tree, fname);
    1076           0 :         smb2_tdis(tree);
    1077           0 :         smb2_logoff(tree->session);
    1078           0 :         return ret;
    1079             : }
    1080             : 
    1081           0 : static bool test_compound_padding(struct torture_context *tctx,
    1082             :                                   struct smb2_tree *tree)
    1083             : {
    1084             :         struct smb2_handle h;
    1085             :         struct smb2_create cr;
    1086             :         struct smb2_read r;
    1087             :         struct smb2_read r2;
    1088           0 :         const char *fname = "compound_read.dat";
    1089           0 :         const char *sname = "compound_read.dat:foo";
    1090             :         struct smb2_request *req[3];
    1091             :         NTSTATUS status;
    1092           0 :         bool ret = false;
    1093             : 
    1094           0 :         smb2_util_unlink(tree, fname);
    1095             : 
    1096             :         /* Write file */
    1097           0 :         ZERO_STRUCT(cr);
    1098           0 :         cr.in.desired_access = SEC_FILE_WRITE_DATA;
    1099           0 :         cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1100           0 :         cr.in.create_disposition = NTCREATEX_DISP_CREATE;
    1101           0 :         cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1102           0 :         cr.in.fname = fname;
    1103           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1104             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1105             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1106           0 :         status = smb2_create(tree, tctx, &cr);
    1107           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1108           0 :         h = cr.out.file.handle;
    1109             : 
    1110           0 :         status = smb2_util_write(tree, h, "123", 0, 3);
    1111           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1112             : 
    1113           0 :         smb2_util_close(tree, h);
    1114             : 
    1115             :         /* Write stream */
    1116           0 :         ZERO_STRUCT(cr);
    1117           0 :         cr.in.desired_access = SEC_FILE_WRITE_DATA;
    1118           0 :         cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1119           0 :         cr.in.create_disposition = NTCREATEX_DISP_CREATE;
    1120           0 :         cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1121           0 :         cr.in.fname = sname;
    1122           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1123             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1124             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1125           0 :         status = smb2_create(tree, tctx, &cr);
    1126           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1127           0 :         h = cr.out.file.handle;
    1128             : 
    1129           0 :         status = smb2_util_write(tree, h, "456", 0, 3);
    1130           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1131             : 
    1132           0 :         smb2_util_close(tree, h);
    1133             : 
    1134             :         /* Check compound read from basefile */
    1135           0 :         smb2_transport_compound_start(tree->session->transport, 3);
    1136             : 
    1137           0 :         ZERO_STRUCT(cr);
    1138           0 :         cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1139           0 :         cr.in.desired_access    = SEC_FILE_READ_DATA;
    1140           0 :         cr.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
    1141           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN;
    1142           0 :         cr.in.fname             = fname;
    1143           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1144             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1145             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1146           0 :         req[0] = smb2_create_send(tree, &cr);
    1147             : 
    1148           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1149             : 
    1150             :         /*
    1151             :          * We send 2 reads in the compound here as the protocol
    1152             :          * allows the last read to be split off and possibly
    1153             :          * go async. Check the padding on the first read returned,
    1154             :          * not the second as the second may not be part of the
    1155             :          * returned compound.
    1156             :         */
    1157             : 
    1158           0 :         ZERO_STRUCT(r);
    1159           0 :         h.data[0] = UINT64_MAX;
    1160           0 :         h.data[1] = UINT64_MAX;
    1161           0 :         r.in.file.handle = h;
    1162           0 :         r.in.length      = 3;
    1163           0 :         r.in.offset      = 0;
    1164           0 :         r.in.min_count      = 1;
    1165           0 :         req[1] = smb2_read_send(tree, &r);
    1166             : 
    1167           0 :         ZERO_STRUCT(r2);
    1168           0 :         h.data[0] = UINT64_MAX;
    1169           0 :         h.data[1] = UINT64_MAX;
    1170           0 :         r2.in.file.handle = h;
    1171           0 :         r2.in.length      = 3;
    1172           0 :         r2.in.offset      = 0;
    1173           0 :         r2.in.min_count      = 1;
    1174           0 :         req[2] = smb2_read_send(tree, &r2);
    1175             : 
    1176           0 :         status = smb2_create_recv(req[0], tree, &cr);
    1177           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1178             : 
    1179             :         /*
    1180             :          * We must do a manual smb2_request_receive() in order to be
    1181             :          * able to check the transport layer info, as smb2_read_recv()
    1182             :          * will destroy the req. smb2_read_recv() will call
    1183             :          * smb2_request_receive() again, but that's ok.
    1184             :          */
    1185           0 :         if (!smb2_request_receive(req[1]) ||
    1186           0 :             !smb2_request_is_ok(req[1])) {
    1187           0 :                 torture_fail(tctx, "failed to receive read request");
    1188             :         }
    1189             : 
    1190             :         /*
    1191             :          * size must be 24: 16 byte read response header plus 3
    1192             :          * requested bytes padded to an 8 byte boundary.
    1193             :          */
    1194           0 :         CHECK_VALUE(req[1]->in.body_size, 24);
    1195             : 
    1196           0 :         status = smb2_read_recv(req[1], tree, &r);
    1197           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1198             : 
    1199             :         /* Pick up the second, possibly async, read. */
    1200           0 :         status = smb2_read_recv(req[2], tree, &r2);
    1201           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1202             : 
    1203           0 :         smb2_util_close(tree, cr.out.file.handle);
    1204             : 
    1205             :         /* Check compound read from stream */
    1206           0 :         smb2_transport_compound_start(tree->session->transport, 3);
    1207             : 
    1208           0 :         ZERO_STRUCT(cr);
    1209           0 :         cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1210           0 :         cr.in.desired_access    = SEC_FILE_READ_DATA;
    1211           0 :         cr.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
    1212           0 :         cr.in.create_disposition = NTCREATEX_DISP_OPEN;
    1213           0 :         cr.in.fname             = sname;
    1214           0 :         cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
    1215             :                 NTCREATEX_SHARE_ACCESS_WRITE|
    1216             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1217           0 :         req[0] = smb2_create_send(tree, &cr);
    1218             : 
    1219           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1220             : 
    1221             :         /*
    1222             :          * We send 2 reads in the compound here as the protocol
    1223             :          * allows the last read to be split off and possibly
    1224             :          * go async. Check the padding on the first read returned,
    1225             :          * not the second as the second may not be part of the
    1226             :          * returned compound.
    1227             :          */
    1228             : 
    1229           0 :         ZERO_STRUCT(r);
    1230           0 :         h.data[0] = UINT64_MAX;
    1231           0 :         h.data[1] = UINT64_MAX;
    1232           0 :         r.in.file.handle = h;
    1233           0 :         r.in.length      = 3;
    1234           0 :         r.in.offset      = 0;
    1235           0 :         r.in.min_count   = 1;
    1236           0 :         req[1] = smb2_read_send(tree, &r);
    1237             : 
    1238           0 :         ZERO_STRUCT(r2);
    1239           0 :         h.data[0] = UINT64_MAX;
    1240           0 :         h.data[1] = UINT64_MAX;
    1241           0 :         r2.in.file.handle = h;
    1242           0 :         r2.in.length      = 3;
    1243           0 :         r2.in.offset      = 0;
    1244           0 :         r2.in.min_count   = 1;
    1245           0 :         req[2] = smb2_read_send(tree, &r2);
    1246             : 
    1247           0 :         status = smb2_create_recv(req[0], tree, &cr);
    1248           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1249             : 
    1250             :         /*
    1251             :          * We must do a manual smb2_request_receive() in order to be
    1252             :          * able to check the transport layer info, as smb2_read_recv()
    1253             :          * will destroy the req. smb2_read_recv() will call
    1254             :          * smb2_request_receive() again, but that's ok.
    1255             :          */
    1256           0 :         if (!smb2_request_receive(req[1]) ||
    1257           0 :             !smb2_request_is_ok(req[1])) {
    1258           0 :                 torture_fail(tctx, "failed to receive read request");
    1259             :         }
    1260             : 
    1261             :         /*
    1262             :          * size must be 24: 16 byte read response header plus 3
    1263             :          * requested bytes padded to an 8 byte boundary.
    1264             :          */
    1265           0 :         CHECK_VALUE(req[1]->in.body_size, 24);
    1266             : 
    1267           0 :         status = smb2_read_recv(req[1], tree, &r);
    1268           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1269             : 
    1270             :         /* Pick up the second, possibly async, read. */
    1271           0 :         status = smb2_read_recv(req[2], tree, &r2);
    1272           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1273             : 
    1274           0 :         h = cr.out.file.handle;
    1275             : 
    1276             :         /* Check 2 compound (unrelateated) reads from existing stream handle */
    1277           0 :         smb2_transport_compound_start(tree->session->transport, 2);
    1278             : 
    1279           0 :         ZERO_STRUCT(r);
    1280           0 :         r.in.file.handle = h;
    1281           0 :         r.in.length      = 3;
    1282           0 :         r.in.offset      = 0;
    1283           0 :         r.in.min_count   = 1;
    1284           0 :         req[0] = smb2_read_send(tree, &r);
    1285           0 :         req[1] = smb2_read_send(tree, &r);
    1286             : 
    1287             :         /*
    1288             :          * We must do a manual smb2_request_receive() in order to be
    1289             :          * able to check the transport layer info, as smb2_read_recv()
    1290             :          * will destroy the req. smb2_read_recv() will call
    1291             :          * smb2_request_receive() again, but that's ok.
    1292             :          */
    1293           0 :         if (!smb2_request_receive(req[0]) ||
    1294           0 :             !smb2_request_is_ok(req[0])) {
    1295           0 :                 torture_fail(tctx, "failed to receive read request");
    1296             :         }
    1297           0 :         if (!smb2_request_receive(req[1]) ||
    1298           0 :             !smb2_request_is_ok(req[1])) {
    1299           0 :                 torture_fail(tctx, "failed to receive read request");
    1300             :         }
    1301             : 
    1302             :         /*
    1303             :          * size must be 24: 16 byte read response header plus 3
    1304             :          * requested bytes padded to an 8 byte boundary.
    1305             :          */
    1306           0 :         CHECK_VALUE(req[0]->in.body_size, 24);
    1307           0 :         CHECK_VALUE(req[1]->in.body_size, 24);
    1308             : 
    1309           0 :         status = smb2_read_recv(req[0], tree, &r);
    1310           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1311           0 :         status = smb2_read_recv(req[1], tree, &r);
    1312           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1313             : 
    1314             :         /*
    1315             :          * now try a single read from the stream and verify there's no padding
    1316             :          */
    1317           0 :         ZERO_STRUCT(r);
    1318           0 :         r.in.file.handle = h;
    1319           0 :         r.in.length      = 3;
    1320           0 :         r.in.offset      = 0;
    1321           0 :         r.in.min_count   = 1;
    1322           0 :         req[0] = smb2_read_send(tree, &r);
    1323             : 
    1324             :         /*
    1325             :          * We must do a manual smb2_request_receive() in order to be
    1326             :          * able to check the transport layer info, as smb2_read_recv()
    1327             :          * will destroy the req. smb2_read_recv() will call
    1328             :          * smb2_request_receive() again, but that's ok.
    1329             :          */
    1330           0 :         if (!smb2_request_receive(req[0]) ||
    1331           0 :             !smb2_request_is_ok(req[0])) {
    1332           0 :                 torture_fail(tctx, "failed to receive read request");
    1333             :         }
    1334             : 
    1335             :         /*
    1336             :          * size must be 19: 16 byte read response header plus 3
    1337             :          * requested bytes without padding.
    1338             :          */
    1339           0 :         CHECK_VALUE(req[0]->in.body_size, 19);
    1340             : 
    1341           0 :         status = smb2_read_recv(req[0], tree, &r);
    1342           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1343             : 
    1344           0 :         smb2_util_close(tree, h);
    1345             : 
    1346           0 :         status = smb2_util_unlink(tree, fname);
    1347           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1348             : 
    1349           0 :         ret = true;
    1350           0 : done:
    1351           0 :         return ret;
    1352             : }
    1353             : 
    1354           0 : static bool test_compound_create_write_close(struct torture_context *tctx,
    1355             :                                              struct smb2_tree *tree)
    1356             : {
    1357           0 :         struct smb2_handle handle = { .data = { UINT64_MAX, UINT64_MAX } };
    1358             :         struct smb2_create create;
    1359             :         struct smb2_write write;
    1360             :         struct smb2_close close;
    1361           0 :         const char *fname = "compound_create_write_close.dat";
    1362             :         struct smb2_request *req[3];
    1363             :         NTSTATUS status;
    1364           0 :         bool ret = false;
    1365             : 
    1366           0 :         smb2_util_unlink(tree, fname);
    1367             : 
    1368           0 :         ZERO_STRUCT(create);
    1369           0 :         create.in.security_flags = 0x00;
    1370           0 :         create.in.oplock_level = 0;
    1371           0 :         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
    1372           0 :         create.in.create_flags = 0x00000000;
    1373           0 :         create.in.reserved = 0x00000000;
    1374           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    1375           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1376           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1377             :                 NTCREATEX_SHARE_ACCESS_WRITE |
    1378             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    1379           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1380           0 :         create.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1381             :                 NTCREATEX_OPTIONS_ASYNC_ALERT |
    1382             :                 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1383             :                 0x00200000;
    1384           0 :         create.in.fname = fname;
    1385             : 
    1386           0 :         smb2_transport_compound_start(tree->session->transport, 3);
    1387             : 
    1388           0 :         req[0] = smb2_create_send(tree, &create);
    1389             : 
    1390           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1391             : 
    1392           0 :         ZERO_STRUCT(write);
    1393           0 :         write.in.file.handle = handle;
    1394           0 :         write.in.offset = 0;
    1395           0 :         write.in.data = data_blob_talloc(tctx, NULL, 1024);
    1396             : 
    1397           0 :         req[1] = smb2_write_send(tree, &write);
    1398             : 
    1399           0 :         ZERO_STRUCT(close);
    1400           0 :         close.in.file.handle = handle;
    1401             : 
    1402           0 :         req[2] = smb2_close_send(tree, &close);
    1403             : 
    1404           0 :         status = smb2_create_recv(req[0], tree, &create);
    1405           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1406             :                                         "CREATE failed.");
    1407             : 
    1408           0 :         status = smb2_write_recv(req[1], &write);
    1409           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1410             :                                         "WRITE failed.");
    1411             : 
    1412           0 :         status = smb2_close_recv(req[2], &close);
    1413           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1414             :                                         "CLOSE failed.");
    1415             : 
    1416           0 :         status = smb2_util_unlink(tree, fname);
    1417           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    1418             :                                         "File deletion failed.");
    1419             : 
    1420           0 :         ret = true;
    1421           0 : done:
    1422           0 :         return ret;
    1423             : }
    1424             : 
    1425           0 : static bool test_compound_unrelated1(struct torture_context *tctx,
    1426             :                                      struct smb2_tree *tree)
    1427             : {
    1428             :         struct smb2_handle hd;
    1429             :         struct smb2_create cr;
    1430             :         NTSTATUS status;
    1431           0 :         const char *fname = "compound_unrelated1.dat";
    1432             :         struct smb2_close cl;
    1433           0 :         bool ret = true;
    1434             :         struct smb2_request *req[5];
    1435             : 
    1436           0 :         smb2_transport_credits_ask_num(tree->session->transport, 5);
    1437             : 
    1438           0 :         smb2_util_unlink(tree, fname);
    1439             : 
    1440           0 :         smb2_transport_credits_ask_num(tree->session->transport, 1);
    1441             : 
    1442           0 :         ZERO_STRUCT(cr);
    1443           0 :         cr.in.security_flags            = 0x00;
    1444           0 :         cr.in.oplock_level              = 0;
    1445           0 :         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
    1446           0 :         cr.in.create_flags              = 0x00000000;
    1447           0 :         cr.in.reserved                  = 0x00000000;
    1448           0 :         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
    1449           0 :         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
    1450           0 :         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
    1451             :                                           NTCREATEX_SHARE_ACCESS_WRITE |
    1452             :                                           NTCREATEX_SHARE_ACCESS_DELETE;
    1453           0 :         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
    1454           0 :         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1455             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
    1456             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1457             :                                           0x00200000;
    1458           0 :         cr.in.fname                     = fname;
    1459             : 
    1460           0 :         smb2_transport_compound_start(tree->session->transport, 5);
    1461             : 
    1462           0 :         req[0] = smb2_create_send(tree, &cr);
    1463             : 
    1464           0 :         hd.data[0] = UINT64_MAX;
    1465           0 :         hd.data[1] = UINT64_MAX;
    1466             : 
    1467           0 :         ZERO_STRUCT(cl);
    1468           0 :         cl.in.file.handle = hd;
    1469           0 :         req[1] = smb2_close_send(tree, &cl);
    1470           0 :         req[2] = smb2_close_send(tree, &cl);
    1471           0 :         req[3] = smb2_close_send(tree, &cl);
    1472           0 :         req[4] = smb2_close_send(tree, &cl);
    1473             : 
    1474           0 :         status = smb2_create_recv(req[0], tree, &cr);
    1475           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1476           0 :         status = smb2_close_recv(req[1], &cl);
    1477           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1478           0 :         status = smb2_close_recv(req[2], &cl);
    1479           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1480           0 :         status = smb2_close_recv(req[3], &cl);
    1481           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1482           0 :         status = smb2_close_recv(req[4], &cl);
    1483           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1484             : 
    1485           0 :         smb2_util_unlink(tree, fname);
    1486           0 : done:
    1487           0 :         return ret;
    1488             : }
    1489             : 
    1490           0 : static bool test_compound_invalid1(struct torture_context *tctx,
    1491             :                                    struct smb2_tree *tree)
    1492             : {
    1493             :         struct smb2_handle hd;
    1494             :         struct smb2_create cr;
    1495             :         NTSTATUS status;
    1496           0 :         const char *fname = "compound_invalid1.dat";
    1497             :         struct smb2_close cl;
    1498           0 :         bool ret = true;
    1499             :         struct smb2_request *req[3];
    1500             : 
    1501           0 :         smb2_transport_credits_ask_num(tree->session->transport, 3);
    1502             : 
    1503           0 :         smb2_util_unlink(tree, fname);
    1504             : 
    1505           0 :         smb2_transport_credits_ask_num(tree->session->transport, 1);
    1506             : 
    1507           0 :         ZERO_STRUCT(cr);
    1508           0 :         cr.in.security_flags            = 0x00;
    1509           0 :         cr.in.oplock_level              = 0;
    1510           0 :         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
    1511           0 :         cr.in.create_flags              = 0x00000000;
    1512           0 :         cr.in.reserved                  = 0x00000000;
    1513           0 :         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
    1514           0 :         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
    1515           0 :         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
    1516             :                                           NTCREATEX_SHARE_ACCESS_WRITE |
    1517             :                                           NTCREATEX_SHARE_ACCESS_DELETE;
    1518           0 :         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
    1519           0 :         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1520             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
    1521             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1522             :                                           0x00200000;
    1523           0 :         cr.in.fname                     = fname;
    1524             : 
    1525           0 :         smb2_transport_compound_start(tree->session->transport, 3);
    1526             : 
    1527             :         /* passing the first request with the related flag is invalid */
    1528           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1529             : 
    1530           0 :         req[0] = smb2_create_send(tree, &cr);
    1531             : 
    1532           0 :         hd.data[0] = UINT64_MAX;
    1533           0 :         hd.data[1] = UINT64_MAX;
    1534             : 
    1535           0 :         ZERO_STRUCT(cl);
    1536           0 :         cl.in.file.handle = hd;
    1537           0 :         req[1] = smb2_close_send(tree, &cl);
    1538             : 
    1539           0 :         smb2_transport_compound_set_related(tree->session->transport, false);
    1540           0 :         req[2] = smb2_close_send(tree, &cl);
    1541             : 
    1542           0 :         status = smb2_create_recv(req[0], tree, &cr);
    1543             :         /* TODO: check why this fails with --signing=required */
    1544           0 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1545           0 :         status = smb2_close_recv(req[1], &cl);
    1546           0 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1547           0 :         status = smb2_close_recv(req[2], &cl);
    1548           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1549             : 
    1550           0 :         smb2_util_unlink(tree, fname);
    1551           0 : done:
    1552           0 :         return ret;
    1553             : }
    1554             : 
    1555           0 : static bool test_compound_invalid2(struct torture_context *tctx,
    1556             :                                    struct smb2_tree *tree)
    1557             : {
    1558             :         struct smb2_handle hd;
    1559             :         struct smb2_create cr;
    1560             :         NTSTATUS status;
    1561           0 :         const char *fname = "compound_invalid2.dat";
    1562             :         struct smb2_close cl;
    1563           0 :         bool ret = true;
    1564             :         struct smb2_request *req[5];
    1565           0 :         struct smbXcli_tcon *saved_tcon = tree->smbXcli;
    1566           0 :         struct smbXcli_session *saved_session = tree->session->smbXcli;
    1567             : 
    1568           0 :         smb2_transport_credits_ask_num(tree->session->transport, 5);
    1569             : 
    1570           0 :         smb2_util_unlink(tree, fname);
    1571             : 
    1572           0 :         smb2_transport_credits_ask_num(tree->session->transport, 1);
    1573             : 
    1574           0 :         ZERO_STRUCT(cr);
    1575           0 :         cr.in.security_flags            = 0x00;
    1576           0 :         cr.in.oplock_level              = 0;
    1577           0 :         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
    1578           0 :         cr.in.create_flags              = 0x00000000;
    1579           0 :         cr.in.reserved                  = 0x00000000;
    1580           0 :         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
    1581           0 :         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
    1582           0 :         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
    1583             :                                           NTCREATEX_SHARE_ACCESS_WRITE |
    1584             :                                           NTCREATEX_SHARE_ACCESS_DELETE;
    1585           0 :         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
    1586           0 :         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1587             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
    1588             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1589             :                                           0x00200000;
    1590           0 :         cr.in.fname                     = fname;
    1591             : 
    1592           0 :         smb2_transport_compound_start(tree->session->transport, 5);
    1593             : 
    1594           0 :         req[0] = smb2_create_send(tree, &cr);
    1595             : 
    1596           0 :         hd.data[0] = UINT64_MAX;
    1597           0 :         hd.data[1] = UINT64_MAX;
    1598             : 
    1599           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1600             : 
    1601           0 :         ZERO_STRUCT(cl);
    1602           0 :         cl.in.file.handle = hd;
    1603             : 
    1604           0 :         tree->smbXcli = smbXcli_tcon_create(tree);
    1605           0 :         smb2cli_tcon_set_values(tree->smbXcli,
    1606             :                                 NULL, /* session */
    1607             :                                 0xFFFFFFFF, /* tcon_id */
    1608             :                                 0, /* type */
    1609             :                                 0, /* flags */
    1610             :                                 0, /* capabilities */
    1611             :                                 0 /* maximal_access */);
    1612             : 
    1613           0 :         tree->session->smbXcli = smbXcli_session_shallow_copy(tree->session,
    1614           0 :                                                         tree->session->smbXcli);
    1615           0 :         smb2cli_session_set_id_and_flags(tree->session->smbXcli, UINT64_MAX, 0);
    1616             : 
    1617           0 :         req[1] = smb2_close_send(tree, &cl);
    1618             :         /* strange that this is not generating invalid parameter */
    1619           0 :         smb2_transport_compound_set_related(tree->session->transport, false);
    1620           0 :         req[2] = smb2_close_send(tree, &cl);
    1621           0 :         req[3] = smb2_close_send(tree, &cl);
    1622           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1623           0 :         req[4] = smb2_close_send(tree, &cl);
    1624             : 
    1625           0 :         status = smb2_create_recv(req[0], tree, &cr);
    1626           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1627           0 :         status = smb2_close_recv(req[1], &cl);
    1628           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1629           0 :         status = smb2_close_recv(req[2], &cl);
    1630           0 :         CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
    1631           0 :         status = smb2_close_recv(req[3], &cl);
    1632           0 :         CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
    1633           0 :         status = smb2_close_recv(req[4], &cl);
    1634           0 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1635             : 
    1636           0 :         TALLOC_FREE(tree->smbXcli);
    1637           0 :         tree->smbXcli = saved_tcon;
    1638           0 :         TALLOC_FREE(tree->session->smbXcli);
    1639           0 :         tree->session->smbXcli = saved_session;
    1640             : 
    1641           0 :         smb2_util_unlink(tree, fname);
    1642           0 : done:
    1643           0 :         return ret;
    1644             : }
    1645             : 
    1646           0 : static bool test_compound_invalid3(struct torture_context *tctx,
    1647             :                                    struct smb2_tree *tree)
    1648             : {
    1649             :         struct smb2_handle hd;
    1650             :         struct smb2_create cr;
    1651             :         NTSTATUS status;
    1652           0 :         const char *fname = "compound_invalid3.dat";
    1653             :         struct smb2_close cl;
    1654           0 :         bool ret = true;
    1655             :         struct smb2_request *req[5];
    1656             : 
    1657           0 :         smb2_transport_credits_ask_num(tree->session->transport, 5);
    1658             : 
    1659           0 :         smb2_util_unlink(tree, fname);
    1660             : 
    1661           0 :         smb2_transport_credits_ask_num(tree->session->transport, 1);
    1662             : 
    1663           0 :         ZERO_STRUCT(cr);
    1664           0 :         cr.in.security_flags            = 0x00;
    1665           0 :         cr.in.oplock_level              = 0;
    1666           0 :         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
    1667           0 :         cr.in.create_flags              = 0x00000000;
    1668           0 :         cr.in.reserved                  = 0x00000000;
    1669           0 :         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
    1670           0 :         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
    1671           0 :         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
    1672             :                                           NTCREATEX_SHARE_ACCESS_WRITE |
    1673             :                                           NTCREATEX_SHARE_ACCESS_DELETE;
    1674           0 :         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
    1675           0 :         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1676             :                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
    1677             :                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1678             :                                           0x00200000;
    1679           0 :         cr.in.fname                     = fname;
    1680             : 
    1681           0 :         smb2_transport_compound_start(tree->session->transport, 5);
    1682             : 
    1683           0 :         req[0] = smb2_create_send(tree, &cr);
    1684             : 
    1685           0 :         hd.data[0] = UINT64_MAX;
    1686           0 :         hd.data[1] = UINT64_MAX;
    1687             : 
    1688           0 :         ZERO_STRUCT(cl);
    1689           0 :         cl.in.file.handle = hd;
    1690           0 :         req[1] = smb2_close_send(tree, &cl);
    1691           0 :         req[2] = smb2_close_send(tree, &cl);
    1692             :         /* flipping the related flag is invalid */
    1693           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1694           0 :         req[3] = smb2_close_send(tree, &cl);
    1695           0 :         req[4] = smb2_close_send(tree, &cl);
    1696             : 
    1697           0 :         status = smb2_create_recv(req[0], tree, &cr);
    1698           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1699           0 :         status = smb2_close_recv(req[1], &cl);
    1700           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1701           0 :         status = smb2_close_recv(req[2], &cl);
    1702           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1703           0 :         status = smb2_close_recv(req[3], &cl);
    1704           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1705           0 :         status = smb2_close_recv(req[4], &cl);
    1706           0 :         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
    1707             : 
    1708           0 :         smb2_util_unlink(tree, fname);
    1709           0 : done:
    1710           0 :         return ret;
    1711             : }
    1712             : 
    1713           0 : static bool test_compound_invalid4(struct torture_context *tctx,
    1714             :                                    struct smb2_tree *tree)
    1715             : {
    1716             :         struct smb2_create cr;
    1717             :         struct smb2_read rd;
    1718             :         NTSTATUS status;
    1719           0 :         const char *fname = "compound_invalid4.dat";
    1720             :         struct smb2_close cl;
    1721           0 :         bool ret = true;
    1722             :         bool ok;
    1723             :         struct smb2_request *req[2];
    1724             : 
    1725           0 :         smb2_transport_credits_ask_num(tree->session->transport, 2);
    1726             : 
    1727           0 :         smb2_util_unlink(tree, fname);
    1728             : 
    1729           0 :         ZERO_STRUCT(cr);
    1730           0 :         cr.in.security_flags      = 0x00;
    1731           0 :         cr.in.oplock_level        = 0;
    1732           0 :         cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
    1733           0 :         cr.in.create_flags        = 0x00000000;
    1734           0 :         cr.in.reserved            = 0x00000000;
    1735           0 :         cr.in.desired_access      = SEC_RIGHTS_FILE_ALL;
    1736           0 :         cr.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
    1737           0 :         cr.in.share_access        = NTCREATEX_SHARE_ACCESS_READ |
    1738             :                                     NTCREATEX_SHARE_ACCESS_WRITE |
    1739             :                                     NTCREATEX_SHARE_ACCESS_DELETE;
    1740           0 :         cr.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
    1741           0 :         cr.in.create_options      = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
    1742             :                                     NTCREATEX_OPTIONS_ASYNC_ALERT       |
    1743             :                                     NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
    1744             :                                     0x00200000;
    1745           0 :         cr.in.fname               = fname;
    1746             : 
    1747           0 :         status = smb2_create(tree, tctx, &cr);
    1748           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1749             : 
    1750           0 :         smb2_transport_compound_start(tree->session->transport, 2);
    1751             : 
    1752           0 :         ZERO_STRUCT(rd);
    1753           0 :         rd.in.file.handle = cr.out.file.handle;
    1754           0 :         rd.in.length      = 1;
    1755           0 :         rd.in.offset      = 0;
    1756           0 :         req[0] = smb2_read_send(tree, &rd);
    1757             : 
    1758           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1759             : 
    1760             :         /*
    1761             :          * Send a completely bogus request as second compound
    1762             :          * element. This triggers smbd_smb2_request_error() in in
    1763             :          * smbd_smb2_request_dispatch() before calling
    1764             :          * smbd_smb2_request_dispatch_update_counts().
    1765             :          */
    1766             : 
    1767           0 :         req[1] = smb2_request_init_tree(tree, 0xff, 0x04, false, 0);
    1768           0 :         smb2_transport_send(req[1]);
    1769             : 
    1770           0 :         status = smb2_read_recv(req[0], tctx, &rd);
    1771           0 :         CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
    1772             : 
    1773           0 :         ok = smb2_request_receive(req[1]);
    1774           0 :         torture_assert(tctx, ok, "Invalid request failed\n");
    1775           0 :         CHECK_STATUS(req[1]->status, NT_STATUS_INVALID_PARAMETER);
    1776             : 
    1777           0 :         ZERO_STRUCT(cl);
    1778           0 :         cl.in.file.handle = cr.out.file.handle;
    1779             : 
    1780           0 :         status = smb2_close(tree, &cl);
    1781           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1782             : 
    1783           0 :         smb2_util_unlink(tree, fname);
    1784           0 : done:
    1785           0 :         return ret;
    1786             : }
    1787             : 
    1788             : /* Send a compound request where we expect the last request (Create, Notify)
    1789             :  * to go asynchronous. This works against a Win7 server and the reply is
    1790             :  * sent in two different packets. */
    1791           0 : static bool test_compound_interim1(struct torture_context *tctx,
    1792             :                                    struct smb2_tree *tree)
    1793             : {
    1794             :     struct smb2_handle hd;
    1795             :     struct smb2_create cr;
    1796           0 :     NTSTATUS status = NT_STATUS_OK;
    1797           0 :     const char *dname = "compound_interim_dir";
    1798             :     struct smb2_notify nt;
    1799           0 :     bool ret = true;
    1800             :     struct smb2_request *req[2];
    1801             : 
    1802             :     /* Win7 compound request implementation deviates substantially from the
    1803             :      * SMB2 spec as noted in MS-SMB2 <159>, <162>.  This, test currently
    1804             :      * verifies the Windows behavior, not the general spec behavior. */
    1805             : 
    1806           0 :     smb2_transport_credits_ask_num(tree->session->transport, 5);
    1807             : 
    1808           0 :     smb2_deltree(tree, dname);
    1809             : 
    1810           0 :     smb2_transport_credits_ask_num(tree->session->transport, 1);
    1811             : 
    1812           0 :     ZERO_STRUCT(cr);
    1813           0 :     cr.in.desired_access        = SEC_RIGHTS_FILE_ALL;
    1814           0 :     cr.in.create_options        = NTCREATEX_OPTIONS_DIRECTORY;
    1815           0 :     cr.in.file_attributes       = FILE_ATTRIBUTE_DIRECTORY;
    1816           0 :     cr.in.share_access          = NTCREATEX_SHARE_ACCESS_READ |
    1817             :                                   NTCREATEX_SHARE_ACCESS_WRITE |
    1818             :                                   NTCREATEX_SHARE_ACCESS_DELETE;
    1819           0 :     cr.in.create_disposition    = NTCREATEX_DISP_CREATE;
    1820           0 :     cr.in.fname                 = dname;
    1821             : 
    1822           0 :     smb2_transport_compound_start(tree->session->transport, 2);
    1823             : 
    1824           0 :     req[0] = smb2_create_send(tree, &cr);
    1825             : 
    1826           0 :     smb2_transport_compound_set_related(tree->session->transport, true);
    1827             : 
    1828           0 :     hd.data[0] = UINT64_MAX;
    1829           0 :     hd.data[1] = UINT64_MAX;
    1830             : 
    1831           0 :     ZERO_STRUCT(nt);
    1832           0 :     nt.in.recursive          = true;
    1833           0 :     nt.in.buffer_size        = 0x1000;
    1834           0 :     nt.in.file.handle        = hd;
    1835           0 :     nt.in.completion_filter  = FILE_NOTIFY_CHANGE_NAME;
    1836           0 :     nt.in.unknown            = 0x00000000;
    1837             : 
    1838           0 :     req[1] = smb2_notify_send(tree, &nt);
    1839             : 
    1840           0 :     status = smb2_create_recv(req[0], tree, &cr);
    1841           0 :     CHECK_STATUS(status, NT_STATUS_OK);
    1842             : 
    1843           0 :     smb2_cancel(req[1]);
    1844           0 :     status = smb2_notify_recv(req[1], tree, &nt);
    1845           0 :     CHECK_STATUS(status, NT_STATUS_CANCELLED);
    1846             : 
    1847           0 :     smb2_util_close(tree, cr.out.file.handle);
    1848             : 
    1849           0 :     smb2_deltree(tree, dname);
    1850           0 : done:
    1851           0 :     return ret;
    1852             : }
    1853             : 
    1854             : /* Send a compound request where we expect the middle request (Create, Notify,
    1855             :  * GetInfo) to go asynchronous. Against Win7 the sync request succeed while
    1856             :  * the async fails. All are returned in the same compound response. */
    1857           0 : static bool test_compound_interim2(struct torture_context *tctx,
    1858             :                                    struct smb2_tree *tree)
    1859             : {
    1860             :     struct smb2_handle hd;
    1861             :     struct smb2_create cr;
    1862           0 :     NTSTATUS status = NT_STATUS_OK;
    1863           0 :     const char *dname = "compound_interim_dir";
    1864             :     struct smb2_getinfo gf;
    1865             :     struct smb2_notify  nt;
    1866           0 :     bool ret = true;
    1867             :     struct smb2_request *req[3];
    1868             : 
    1869             :     /* Win7 compound request implementation deviates substantially from the
    1870             :      * SMB2 spec as noted in MS-SMB2 <159>, <162>.  This, test currently
    1871             :      * verifies the Windows behavior, not the general spec behavior. */
    1872             : 
    1873           0 :     smb2_transport_credits_ask_num(tree->session->transport, 5);
    1874             : 
    1875           0 :     smb2_deltree(tree, dname);
    1876             : 
    1877           0 :     smb2_transport_credits_ask_num(tree->session->transport, 1);
    1878             : 
    1879           0 :     ZERO_STRUCT(cr);
    1880           0 :     cr.in.desired_access        = SEC_RIGHTS_FILE_ALL;
    1881           0 :     cr.in.create_options        = NTCREATEX_OPTIONS_DIRECTORY;
    1882           0 :     cr.in.file_attributes       = FILE_ATTRIBUTE_DIRECTORY;
    1883           0 :     cr.in.share_access      = NTCREATEX_SHARE_ACCESS_READ |
    1884             :                       NTCREATEX_SHARE_ACCESS_WRITE |
    1885             :                       NTCREATEX_SHARE_ACCESS_DELETE;
    1886           0 :     cr.in.create_disposition    = NTCREATEX_DISP_CREATE;
    1887           0 :     cr.in.fname         = dname;
    1888             : 
    1889           0 :     smb2_transport_compound_start(tree->session->transport, 3);
    1890             : 
    1891           0 :     req[0] = smb2_create_send(tree, &cr);
    1892             : 
    1893           0 :     smb2_transport_compound_set_related(tree->session->transport, true);
    1894             : 
    1895           0 :     hd.data[0] = UINT64_MAX;
    1896           0 :     hd.data[1] = UINT64_MAX;
    1897             : 
    1898           0 :     ZERO_STRUCT(nt);
    1899           0 :     nt.in.recursive          = true;
    1900           0 :     nt.in.buffer_size        = 0x1000;
    1901           0 :     nt.in.file.handle        = hd;
    1902           0 :     nt.in.completion_filter  = FILE_NOTIFY_CHANGE_NAME;
    1903           0 :     nt.in.unknown            = 0x00000000;
    1904             : 
    1905           0 :     req[1] = smb2_notify_send(tree, &nt);
    1906             : 
    1907           0 :     ZERO_STRUCT(gf);
    1908           0 :     gf.in.file.handle = hd;
    1909           0 :     gf.in.info_type   = SMB2_0_INFO_FILE;
    1910           0 :     gf.in.info_class  = 0x04; /* FILE_BASIC_INFORMATION */
    1911           0 :     gf.in.output_buffer_length = 0x1000;
    1912           0 :     gf.in.input_buffer = data_blob_null;
    1913             : 
    1914           0 :     req[2] = smb2_getinfo_send(tree, &gf);
    1915             : 
    1916           0 :     status = smb2_create_recv(req[0], tree, &cr);
    1917           0 :     CHECK_STATUS(status, NT_STATUS_OK);
    1918             : 
    1919           0 :     status = smb2_notify_recv(req[1], tree, &nt);
    1920           0 :     CHECK_STATUS(status, NT_STATUS_INTERNAL_ERROR);
    1921             : 
    1922           0 :     status = smb2_getinfo_recv(req[2], tree, &gf);
    1923           0 :     CHECK_STATUS(status, NT_STATUS_OK);
    1924             : 
    1925           0 :     smb2_util_close(tree, cr.out.file.handle);
    1926             : 
    1927           0 :     smb2_deltree(tree, dname);
    1928           0 : done:
    1929           0 :     return ret;
    1930             : }
    1931             : 
    1932             : /* Test compound related finds */
    1933           0 : static bool test_compound_find_related(struct torture_context *tctx,
    1934             :                                        struct smb2_tree *tree)
    1935             : {
    1936           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    1937           0 :         const char *dname = "compound_find_dir";
    1938             :         struct smb2_create create;
    1939             :         struct smb2_find f;
    1940             :         struct smb2_handle h;
    1941             :         struct smb2_request *req[2];
    1942             :         NTSTATUS status;
    1943           0 :         bool ret = true;
    1944             : 
    1945           0 :         smb2_deltree(tree, dname);
    1946             : 
    1947           0 :         ZERO_STRUCT(create);
    1948           0 :         create.in.desired_access = SEC_RIGHTS_DIR_ALL;
    1949           0 :         create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1950           0 :         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    1951           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1952             :                                  NTCREATEX_SHARE_ACCESS_WRITE |
    1953             :                                  NTCREATEX_SHARE_ACCESS_DELETE;
    1954           0 :         create.in.create_disposition = NTCREATEX_DISP_CREATE;
    1955           0 :         create.in.fname = dname;
    1956             : 
    1957           0 :         status = smb2_create(tree, mem_ctx, &create);
    1958           0 :         h = create.out.file.handle;
    1959             : 
    1960           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
    1961             : 
    1962           0 :         smb2_transport_compound_start(tree->session->transport, 2);
    1963             : 
    1964           0 :         ZERO_STRUCT(f);
    1965           0 :         f.in.file.handle        = h;
    1966           0 :         f.in.pattern            = "*";
    1967           0 :         f.in.max_response_size  = 0x100;
    1968           0 :         f.in.level              = SMB2_FIND_BOTH_DIRECTORY_INFO;
    1969             : 
    1970           0 :         req[0] = smb2_find_send(tree, &f);
    1971             : 
    1972           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    1973             : 
    1974           0 :         req[1] = smb2_find_send(tree, &f);
    1975             : 
    1976           0 :         status = smb2_find_recv(req[0], mem_ctx, &f);
    1977           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_recv failed\n");
    1978             : 
    1979           0 :         status = smb2_find_recv(req[1], mem_ctx, &f);
    1980           0 :         torture_assert_ntstatus_equal_goto(tctx, status, STATUS_NO_MORE_FILES, ret, done, "smb2_find_recv failed\n");
    1981             : 
    1982           0 : done:
    1983           0 :         smb2_util_close(tree, h);
    1984           0 :         smb2_deltree(tree, dname);
    1985           0 :         TALLOC_FREE(mem_ctx);
    1986           0 :         return ret;
    1987             : }
    1988             : 
    1989             : /* Test compound related finds */
    1990           0 : static bool test_compound_find_close(struct torture_context *tctx,
    1991             :                                      struct smb2_tree *tree)
    1992             : {
    1993           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    1994           0 :         const char *dname = "compound_find_dir";
    1995             :         struct smb2_create create;
    1996             :         struct smb2_find f;
    1997             :         struct smb2_handle h;
    1998           0 :         struct smb2_request *req = NULL;
    1999           0 :         const int num_files = 5000;
    2000             :         int i;
    2001             :         NTSTATUS status;
    2002           0 :         bool ret = true;
    2003             : 
    2004           0 :         smb2_deltree(tree, dname);
    2005             : 
    2006           0 :         ZERO_STRUCT(create);
    2007           0 :         create.in.desired_access = SEC_RIGHTS_DIR_ALL;
    2008           0 :         create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2009           0 :         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    2010           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2011             :                                  NTCREATEX_SHARE_ACCESS_WRITE |
    2012             :                                  NTCREATEX_SHARE_ACCESS_DELETE;
    2013           0 :         create.in.create_disposition = NTCREATEX_DISP_CREATE;
    2014           0 :         create.in.fname = dname;
    2015             : 
    2016           0 :         smb2cli_conn_set_max_credits(tree->session->transport->conn, 256);
    2017             : 
    2018           0 :         status = smb2_create(tree, mem_ctx, &create);
    2019           0 :         h = create.out.file.handle;
    2020             : 
    2021           0 :         ZERO_STRUCT(create);
    2022           0 :         create.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2023           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2024           0 :         create.in.create_disposition = NTCREATEX_DISP_CREATE;
    2025             : 
    2026           0 :         for (i = 0; i < num_files; i++) {
    2027           0 :                 create.in.fname = talloc_asprintf(mem_ctx, "%s\\file%d",
    2028             :                                                   dname, i);
    2029           0 :                 status = smb2_create(tree, mem_ctx, &create);
    2030           0 :                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "");
    2031           0 :                 smb2_util_close(tree, create.out.file.handle);
    2032             :         }
    2033             : 
    2034           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
    2035             : 
    2036           0 :         ZERO_STRUCT(f);
    2037           0 :         f.in.file.handle        = h;
    2038           0 :         f.in.pattern            = "*";
    2039           0 :         f.in.max_response_size  = 8*1024*1024;
    2040           0 :         f.in.level              = SMB2_FIND_BOTH_DIRECTORY_INFO;
    2041             : 
    2042           0 :         req = smb2_find_send(tree, &f);
    2043             : 
    2044           0 :         status = smb2_util_close(tree, h);
    2045           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed\n");
    2046             : 
    2047           0 :         status = smb2_find_recv(req, mem_ctx, &f);
    2048           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_recv failed\n");
    2049             : 
    2050           0 : done:
    2051           0 :         smb2_util_close(tree, h);
    2052           0 :         smb2_deltree(tree, dname);
    2053           0 :         TALLOC_FREE(mem_ctx);
    2054           0 :         return ret;
    2055             : }
    2056             : 
    2057             : /* Test compound unrelated finds */
    2058           0 : static bool test_compound_find_unrelated(struct torture_context *tctx,
    2059             :                                          struct smb2_tree *tree)
    2060             : {
    2061           0 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    2062           0 :         const char *dname = "compound_find_dir";
    2063             :         struct smb2_create create;
    2064             :         struct smb2_find f;
    2065             :         struct smb2_handle h;
    2066             :         struct smb2_request *req[2];
    2067             :         NTSTATUS status;
    2068           0 :         bool ret = true;
    2069             : 
    2070           0 :         smb2_deltree(tree, dname);
    2071             : 
    2072           0 :         ZERO_STRUCT(create);
    2073           0 :         create.in.desired_access = SEC_RIGHTS_DIR_ALL;
    2074           0 :         create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2075           0 :         create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    2076           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2077             :                                  NTCREATEX_SHARE_ACCESS_WRITE |
    2078             :                                  NTCREATEX_SHARE_ACCESS_DELETE;
    2079           0 :         create.in.create_disposition = NTCREATEX_DISP_CREATE;
    2080           0 :         create.in.fname = dname;
    2081             : 
    2082           0 :         status = smb2_create(tree, mem_ctx, &create);
    2083           0 :         h = create.out.file.handle;
    2084             : 
    2085           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed\n");
    2086             : 
    2087           0 :         smb2_transport_compound_start(tree->session->transport, 2);
    2088             : 
    2089           0 :         ZERO_STRUCT(f);
    2090           0 :         f.in.file.handle        = h;
    2091           0 :         f.in.pattern            = "*";
    2092           0 :         f.in.max_response_size  = 0x100;
    2093           0 :         f.in.level              = SMB2_FIND_BOTH_DIRECTORY_INFO;
    2094             : 
    2095           0 :         req[0] = smb2_find_send(tree, &f);
    2096           0 :         req[1] = smb2_find_send(tree, &f);
    2097             : 
    2098           0 :         status = smb2_find_recv(req[0], mem_ctx, &f);
    2099           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_recv failed\n");
    2100             : 
    2101           0 :         status = smb2_find_recv(req[1], mem_ctx, &f);
    2102           0 :         torture_assert_ntstatus_equal_goto(tctx, status, STATUS_NO_MORE_FILES, ret, done, "smb2_find_recv failed\n");
    2103             : 
    2104           0 : done:
    2105           0 :         smb2_util_close(tree, h);
    2106           0 :         smb2_deltree(tree, dname);
    2107           0 :         TALLOC_FREE(mem_ctx);
    2108           0 :         return ret;
    2109             : }
    2110             : 
    2111           0 : static bool test_compound_async_flush_close(struct torture_context *tctx,
    2112             :                                             struct smb2_tree *tree)
    2113             : {
    2114           0 :         struct smb2_handle fhandle = { .data = { 0, 0 } };
    2115           0 :         struct smb2_handle relhandle = { .data = { UINT64_MAX, UINT64_MAX } };
    2116             :         struct smb2_close cl;
    2117             :         struct smb2_flush fl;
    2118           0 :         const char *fname = "compound_async_flush_close";
    2119             :         struct smb2_request *req[2];
    2120             :         NTSTATUS status;
    2121           0 :         bool ret = false;
    2122             : 
    2123             :         /* Start clean. */
    2124           0 :         smb2_util_unlink(tree, fname);
    2125             : 
    2126             :         /* Create a file. */
    2127           0 :         status = torture_smb2_testfile_access(tree,
    2128             :                                               fname,
    2129             :                                               &fhandle,
    2130             :                                               SEC_RIGHTS_FILE_ALL);
    2131           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2132             : 
    2133             :         /* Now do a compound flush + close handle. */
    2134           0 :         smb2_transport_compound_start(tree->session->transport, 2);
    2135             : 
    2136           0 :         ZERO_STRUCT(fl);
    2137           0 :         fl.in.file.handle = fhandle;
    2138             : 
    2139           0 :         req[0] = smb2_flush_send(tree, &fl);
    2140           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
    2141             :                 "smb2_flush_send failed\n");
    2142             : 
    2143           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    2144             : 
    2145           0 :         ZERO_STRUCT(cl);
    2146           0 :         cl.in.file.handle = relhandle;
    2147           0 :         req[1] = smb2_close_send(tree, &cl);
    2148           0 :         torture_assert_not_null_goto(tctx, req[1], ret, done,
    2149             :                 "smb2_close_send failed\n");
    2150             : 
    2151           0 :         status = smb2_flush_recv(req[0], &fl);
    2152             :         /*
    2153             :          * On Windows, this flush will usually
    2154             :          * succeed as we have nothing to flush,
    2155             :          * so allow NT_STATUS_OK. Once bug #15172
    2156             :          * is fixed Samba will do the flush synchronously
    2157             :          * so allow NT_STATUS_OK.
    2158             :          */
    2159           0 :         if (!NT_STATUS_IS_OK(status)) {
    2160             :                 /*
    2161             :                  * If we didn't get NT_STATUS_OK, we *must*
    2162             :                  * get NT_STATUS_INTERNAL_ERROR if the flush
    2163             :                  * goes async.
    2164             :                  *
    2165             :                  * For pre-bugfix #15172 Samba, the flush goes async and
    2166             :                  * we should get NT_STATUS_INTERNAL_ERROR.
    2167             :                  */
    2168           0 :                 torture_assert_ntstatus_equal_goto(tctx,
    2169             :                         status,
    2170             :                         NT_STATUS_INTERNAL_ERROR,
    2171             :                         ret,
    2172             :                         done,
    2173             :                         "smb2_flush_recv didn't return "
    2174             :                         "NT_STATUS_INTERNAL_ERROR.\n");
    2175             :         }
    2176           0 :         status = smb2_close_recv(req[1], &cl);
    2177           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2178             :                         "smb2_close_recv failed.");
    2179             : 
    2180           0 :         ZERO_STRUCT(fhandle);
    2181             : 
    2182             :         /*
    2183             :          * Do several more operations on the tree, spaced
    2184             :          * out by 1 sec sleeps to make sure the server didn't
    2185             :          * crash on the close. The sleeps are required to
    2186             :          * make test test for a crash reliable, as we ensure
    2187             :          * the pthread fsync internally finishes and accesses
    2188             :          * freed memory. Without them the test occassionally
    2189             :          * passes as we disconnect before the pthread fsync
    2190             :          * finishes.
    2191             :          */
    2192           0 :         status = smb2_util_unlink(tree, fname);
    2193           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2194             : 
    2195           0 :         sleep(1);
    2196           0 :         status = smb2_util_unlink(tree, fname);
    2197           0 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    2198             : 
    2199           0 :         sleep(1);
    2200           0 :         status = smb2_util_unlink(tree, fname);
    2201           0 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    2202             : 
    2203           0 :         ret = true;
    2204             : 
    2205           0 :   done:
    2206             : 
    2207           0 :         if (fhandle.data[0] != 0) {
    2208           0 :                 smb2_util_close(tree, fhandle);
    2209             :         }
    2210             : 
    2211           0 :         smb2_util_unlink(tree, fname);
    2212           0 :         return ret;
    2213             : }
    2214             : 
    2215           0 : static bool test_compound_async_flush_flush(struct torture_context *tctx,
    2216             :                                             struct smb2_tree *tree)
    2217             : {
    2218           0 :         struct smb2_handle fhandle = { .data = { 0, 0 } };
    2219           0 :         struct smb2_handle relhandle = { .data = { UINT64_MAX, UINT64_MAX } };
    2220             :         struct smb2_flush fl1;
    2221             :         struct smb2_flush fl2;
    2222           0 :         const char *fname = "compound_async_flush_flush";
    2223             :         struct smb2_request *req[2];
    2224             :         NTSTATUS status;
    2225           0 :         bool ret = false;
    2226             : 
    2227             :         /* Start clean. */
    2228           0 :         smb2_util_unlink(tree, fname);
    2229             : 
    2230             :         /* Create a file. */
    2231           0 :         status = torture_smb2_testfile_access(tree,
    2232             :                                               fname,
    2233             :                                               &fhandle,
    2234             :                                               SEC_RIGHTS_FILE_ALL);
    2235           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2236             : 
    2237             :         /* Now do a compound flush + flush handle. */
    2238           0 :         smb2_transport_compound_start(tree->session->transport, 2);
    2239             : 
    2240           0 :         ZERO_STRUCT(fl1);
    2241           0 :         fl1.in.file.handle = fhandle;
    2242             : 
    2243           0 :         req[0] = smb2_flush_send(tree, &fl1);
    2244           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
    2245             :                 "smb2_flush_send (1) failed\n");
    2246             : 
    2247           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    2248             : 
    2249           0 :         ZERO_STRUCT(fl2);
    2250           0 :         fl2.in.file.handle = relhandle;
    2251             : 
    2252           0 :         req[1] = smb2_flush_send(tree, &fl2);
    2253           0 :         torture_assert_not_null_goto(tctx, req[1], ret, done,
    2254             :                 "smb2_flush_send (2) failed\n");
    2255             : 
    2256           0 :         status = smb2_flush_recv(req[0], &fl1);
    2257             :         /*
    2258             :          * On Windows, this flush will usually
    2259             :          * succeed as we have nothing to flush,
    2260             :          * so allow NT_STATUS_OK. Once bug #15172
    2261             :          * is fixed Samba will do the flush synchronously
    2262             :          * so allow NT_STATUS_OK.
    2263             :          */
    2264           0 :         if (!NT_STATUS_IS_OK(status)) {
    2265             :                 /*
    2266             :                  * If we didn't get NT_STATUS_OK, we *must*
    2267             :                  * get NT_STATUS_INTERNAL_ERROR if the flush
    2268             :                  * goes async.
    2269             :                  *
    2270             :                  * For pre-bugfix #15172 Samba, the flush goes async and
    2271             :                  * we should get NT_STATUS_INTERNAL_ERROR.
    2272             :                  */
    2273           0 :                 torture_assert_ntstatus_equal_goto(tctx,
    2274             :                         status,
    2275             :                         NT_STATUS_INTERNAL_ERROR,
    2276             :                         ret,
    2277             :                         done,
    2278             :                         "smb2_flush_recv (1) didn't return "
    2279             :                         "NT_STATUS_INTERNAL_ERROR.\n");
    2280             :         }
    2281             : 
    2282             :         /*
    2283             :          * If the flush is the last entry in a compound,
    2284             :          * it should always succeed even if it goes async.
    2285             :          */
    2286           0 :         status = smb2_flush_recv(req[1], &fl2);
    2287           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2288             :                 "smb2_flush_recv (2) failed.");
    2289             : 
    2290           0 :         status = smb2_util_close(tree, fhandle);
    2291           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2292             :                 "smb2_util_close failed.");
    2293           0 :         ZERO_STRUCT(fhandle);
    2294             : 
    2295             :         /*
    2296             :          * Do several more operations on the tree, spaced
    2297             :          * out by 1 sec sleeps to make sure the server didn't
    2298             :          * crash on the close. The sleeps are required to
    2299             :          * make test test for a crash reliable, as we ensure
    2300             :          * the pthread fsync internally finishes and accesses
    2301             :          * freed memory. Without them the test occassionally
    2302             :          * passes as we disconnect before the pthread fsync
    2303             :          * finishes.
    2304             :          */
    2305           0 :         status = smb2_util_unlink(tree, fname);
    2306           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2307             : 
    2308           0 :         sleep(1);
    2309           0 :         status = smb2_util_unlink(tree, fname);
    2310           0 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    2311             : 
    2312           0 :         sleep(1);
    2313           0 :         status = smb2_util_unlink(tree, fname);
    2314           0 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    2315             : 
    2316           0 :         ret = true;
    2317             : 
    2318           0 :   done:
    2319             : 
    2320           0 :         if (fhandle.data[0] != 0) {
    2321           0 :                 smb2_util_close(tree, fhandle);
    2322             :         }
    2323             : 
    2324           0 :         smb2_util_unlink(tree, fname);
    2325           0 :         return ret;
    2326             : }
    2327             : 
    2328             : /*
    2329             :  * For Samba/smbd this test must be run against the aio_delay_inject share
    2330             :  * as we need to ensure the last write in the compound takes longer than
    2331             :  * 500 us, which is the threshold for going async in smbd SMB2 writes.
    2332             :  */
    2333             : 
    2334           0 : static bool test_compound_async_write_write(struct torture_context *tctx,
    2335             :                                             struct smb2_tree *tree)
    2336             : {
    2337           0 :         struct smb2_handle fhandle = { .data = { 0, 0 } };
    2338           0 :         struct smb2_handle relhandle = { .data = { UINT64_MAX, UINT64_MAX } };
    2339             :         struct smb2_write w1;
    2340             :         struct smb2_write w2;
    2341           0 :         const char *fname = "compound_async_write_write";
    2342             :         struct smb2_request *req[2];
    2343             :         NTSTATUS status;
    2344           0 :         bool is_smbd = torture_setting_bool(tctx, "smbd", true);
    2345           0 :         bool ret = false;
    2346             : 
    2347             :         /* Start clean. */
    2348           0 :         smb2_util_unlink(tree, fname);
    2349             : 
    2350             :         /* Create a file. */
    2351           0 :         status = torture_smb2_testfile_access(tree,
    2352             :                                               fname,
    2353             :                                               &fhandle,
    2354             :                                               SEC_RIGHTS_FILE_ALL);
    2355           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2356             : 
    2357             :         /* Now do a compound write + write handle. */
    2358           0 :         smb2_transport_compound_start(tree->session->transport, 2);
    2359             : 
    2360           0 :         ZERO_STRUCT(w1);
    2361           0 :         w1.in.file.handle = fhandle;
    2362           0 :         w1.in.offset = 0;
    2363           0 :         w1.in.data = data_blob_talloc_zero(tctx, 64);
    2364           0 :         req[0] = smb2_write_send(tree, &w1);
    2365             : 
    2366           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
    2367             :                 "smb2_write_send (1) failed\n");
    2368             : 
    2369           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    2370             : 
    2371           0 :         ZERO_STRUCT(w2);
    2372           0 :         w2.in.file.handle = relhandle;
    2373           0 :         w2.in.offset = 64;
    2374           0 :         w2.in.data = data_blob_talloc_zero(tctx, 64);
    2375           0 :         req[1] = smb2_write_send(tree, &w2);
    2376             : 
    2377           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
    2378             :                 "smb2_write_send (2) failed\n");
    2379             : 
    2380           0 :         status = smb2_write_recv(req[0], &w1);
    2381           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2382             :                 "smb2_write_recv (1) failed.");
    2383             : 
    2384           0 :         if (!is_smbd) {
    2385             :                 /*
    2386             :                  * Windows and other servers don't go async.
    2387             :                  */
    2388           0 :                 status = smb2_write_recv(req[1], &w2);
    2389             :         } else {
    2390             :                 /*
    2391             :                  * For smbd, the second write should go async
    2392             :                  * as it's the last element of a compound.
    2393             :                  */
    2394           0 :                 WAIT_FOR_ASYNC_RESPONSE(req[1]);
    2395           0 :                 CHECK_VALUE(req[1]->cancel.can_cancel, true);
    2396             :                 /*
    2397             :                  * Now pick up the real return.
    2398             :                  */
    2399           0 :                 status = smb2_write_recv(req[1], &w2);
    2400             :         }
    2401             : 
    2402           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2403             :                 "smb2_write_recv (2) failed.");
    2404             : 
    2405           0 :         status = smb2_util_close(tree, fhandle);
    2406           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2407             :                 "smb2_util_close failed.");
    2408           0 :         ZERO_STRUCT(fhandle);
    2409             : 
    2410           0 :         ret = true;
    2411             : 
    2412           0 :   done:
    2413             : 
    2414           0 :         if (fhandle.data[0] != 0) {
    2415           0 :                 smb2_util_close(tree, fhandle);
    2416             :         }
    2417             : 
    2418           0 :         smb2_util_unlink(tree, fname);
    2419           0 :         return ret;
    2420             : }
    2421             : 
    2422             : /*
    2423             :  * For Samba/smbd this test must be run against the aio_delay_inject share
    2424             :  * as we need to ensure the last read in the compound takes longer than
    2425             :  * 500 us, which is the threshold for going async in smbd SMB2 reads.
    2426             :  */
    2427             : 
    2428           0 : static bool test_compound_async_read_read(struct torture_context *tctx,
    2429             :                                             struct smb2_tree *tree)
    2430             : {
    2431           0 :         struct smb2_handle fhandle = { .data = { 0, 0 } };
    2432           0 :         struct smb2_handle relhandle = { .data = { UINT64_MAX, UINT64_MAX } };
    2433             :         struct smb2_write w;
    2434             :         struct smb2_read r1;
    2435             :         struct smb2_read r2;
    2436           0 :         const char *fname = "compound_async_read_read";
    2437             :         struct smb2_request *req[2];
    2438             :         NTSTATUS status;
    2439           0 :         bool is_smbd = torture_setting_bool(tctx, "smbd", true);
    2440           0 :         bool ret = false;
    2441             : 
    2442             :         /* Start clean. */
    2443           0 :         smb2_util_unlink(tree, fname);
    2444             : 
    2445             :         /* Create a file. */
    2446           0 :         status = torture_smb2_testfile_access(tree,
    2447             :                                               fname,
    2448             :                                               &fhandle,
    2449             :                                               SEC_RIGHTS_FILE_ALL);
    2450           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2451             : 
    2452             :         /* Write 128 bytes. */
    2453           0 :         ZERO_STRUCT(w);
    2454           0 :         w.in.file.handle = fhandle;
    2455           0 :         w.in.offset = 0;
    2456           0 :         w.in.data = data_blob_talloc_zero(tctx, 128);
    2457           0 :         status = smb2_write(tree, &w);
    2458           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2459             :                 "smb2_write_recv (1) failed.");
    2460             : 
    2461             :         /* Now do a compound read + read handle. */
    2462           0 :         smb2_transport_compound_start(tree->session->transport, 2);
    2463             : 
    2464           0 :         ZERO_STRUCT(r1);
    2465           0 :         r1.in.file.handle = fhandle;
    2466           0 :         r1.in.length      = 64;
    2467           0 :         r1.in.offset      = 0;
    2468           0 :         req[0] = smb2_read_send(tree, &r1);
    2469             : 
    2470           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
    2471             :                 "smb2_read_send (1) failed\n");
    2472             : 
    2473           0 :         smb2_transport_compound_set_related(tree->session->transport, true);
    2474             : 
    2475           0 :         ZERO_STRUCT(r2);
    2476           0 :         r2.in.file.handle = relhandle;
    2477           0 :         r2.in.length      = 64;
    2478           0 :         r2.in.offset      = 64;
    2479           0 :         req[1] = smb2_read_send(tree, &r2);
    2480             : 
    2481           0 :         torture_assert_not_null_goto(tctx, req[0], ret, done,
    2482             :                 "smb2_read_send (2) failed\n");
    2483             : 
    2484           0 :         status = smb2_read_recv(req[0], tree, &r1);
    2485           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2486             :                 "smb2_read_recv (1) failed.");
    2487             : 
    2488           0 :         if (!is_smbd) {
    2489             :                 /*
    2490             :                  * Windows and other servers don't go async.
    2491             :                  */
    2492           0 :                 status = smb2_read_recv(req[1], tree, &r2);
    2493             :         } else {
    2494             :                 /*
    2495             :                  * For smbd, the second write should go async
    2496             :                  * as it's the last element of a compound.
    2497             :                  */
    2498           0 :                 WAIT_FOR_ASYNC_RESPONSE(req[1]);
    2499           0 :                 CHECK_VALUE(req[1]->cancel.can_cancel, true);
    2500             :                 /*
    2501             :                  * Now pick up the real return.
    2502             :                  */
    2503           0 :                 status = smb2_read_recv(req[1], tree, &r2);
    2504             :         }
    2505             : 
    2506           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2507             :                 "smb2_read_recv (2) failed.");
    2508             : 
    2509           0 :         status = smb2_util_close(tree, fhandle);
    2510           0 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
    2511             :                 "smb2_util_close failed.");
    2512           0 :         ZERO_STRUCT(fhandle);
    2513             : 
    2514           0 :         ret = true;
    2515             : 
    2516           0 :   done:
    2517             : 
    2518           0 :         if (fhandle.data[0] != 0) {
    2519           0 :                 smb2_util_close(tree, fhandle);
    2520             :         }
    2521             : 
    2522           0 :         smb2_util_unlink(tree, fname);
    2523           0 :         return ret;
    2524             : }
    2525             : 
    2526             : 
    2527         966 : struct torture_suite *torture_smb2_compound_init(TALLOC_CTX *ctx)
    2528             : {
    2529         966 :         struct torture_suite *suite = torture_suite_create(ctx, "compound");
    2530             : 
    2531         966 :         torture_suite_add_1smb2_test(suite, "related1", test_compound_related1);
    2532         966 :         torture_suite_add_1smb2_test(suite, "related2", test_compound_related2);
    2533         966 :         torture_suite_add_1smb2_test(suite, "related3",
    2534             :                                      test_compound_related3);
    2535         966 :         torture_suite_add_1smb2_test(suite, "related4",
    2536             :                                      test_compound_related4);
    2537         966 :         torture_suite_add_1smb2_test(suite, "related5",
    2538             :                                      test_compound_related5);
    2539         966 :         torture_suite_add_1smb2_test(suite, "related6",
    2540             :                                      test_compound_related6);
    2541         966 :         torture_suite_add_1smb2_test(suite, "related7",
    2542             :                                      test_compound_related7);
    2543         966 :         torture_suite_add_1smb2_test(suite, "related8",
    2544             :                                      test_compound_related8);
    2545         966 :         torture_suite_add_1smb2_test(suite, "related9",
    2546             :                                      test_compound_related9);
    2547         966 :         torture_suite_add_1smb2_test(suite, "unrelated1", test_compound_unrelated1);
    2548         966 :         torture_suite_add_1smb2_test(suite, "invalid1", test_compound_invalid1);
    2549         966 :         torture_suite_add_1smb2_test(suite, "invalid2", test_compound_invalid2);
    2550         966 :         torture_suite_add_1smb2_test(suite, "invalid3", test_compound_invalid3);
    2551         966 :         torture_suite_add_1smb2_test(
    2552             :                 suite, "invalid4", test_compound_invalid4);
    2553         966 :         torture_suite_add_1smb2_test(suite, "interim1",  test_compound_interim1);
    2554         966 :         torture_suite_add_1smb2_test(suite, "interim2",  test_compound_interim2);
    2555         966 :         torture_suite_add_1smb2_test(suite, "compound-break", test_compound_break);
    2556         966 :         torture_suite_add_1smb2_test(suite, "compound-padding", test_compound_padding);
    2557         966 :         torture_suite_add_1smb2_test(suite, "create-write-close",
    2558             :                                      test_compound_create_write_close);
    2559             : 
    2560         966 :         suite->description = talloc_strdup(suite, "SMB2-COMPOUND tests");
    2561             : 
    2562         966 :         return suite;
    2563             : }
    2564             : 
    2565         966 : struct torture_suite *torture_smb2_compound_find_init(TALLOC_CTX *ctx)
    2566             : {
    2567         966 :         struct torture_suite *suite = torture_suite_create(ctx, "compound_find");
    2568             : 
    2569         966 :         torture_suite_add_1smb2_test(suite, "compound_find_related", test_compound_find_related);
    2570         966 :         torture_suite_add_1smb2_test(suite, "compound_find_unrelated", test_compound_find_unrelated);
    2571         966 :         torture_suite_add_1smb2_test(suite, "compound_find_close", test_compound_find_close);
    2572             : 
    2573         966 :         suite->description = talloc_strdup(suite, "SMB2-COMPOUND-FIND tests");
    2574             : 
    2575         966 :         return suite;
    2576             : }
    2577             : 
    2578         966 : struct torture_suite *torture_smb2_compound_async_init(TALLOC_CTX *ctx)
    2579             : {
    2580         966 :         struct torture_suite *suite = torture_suite_create(ctx,
    2581             :                                         "compound_async");
    2582             : 
    2583         966 :         torture_suite_add_1smb2_test(suite, "flush_close",
    2584             :                 test_compound_async_flush_close);
    2585         966 :         torture_suite_add_1smb2_test(suite, "flush_flush",
    2586             :                 test_compound_async_flush_flush);
    2587         966 :         torture_suite_add_1smb2_test(suite, "write_write",
    2588             :                 test_compound_async_write_write);
    2589         966 :         torture_suite_add_1smb2_test(suite, "read_read",
    2590             :                 test_compound_async_read_read);
    2591             : 
    2592         966 :         suite->description = talloc_strdup(suite, "SMB2-COMPOUND-ASYNC tests");
    2593             : 
    2594         966 :         return suite;
    2595             : }

Generated by: LCOV version 1.14