LCOV - code coverage report
Current view: top level - source4/torture/smb2 - notify.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 32 1452 2.2 %
Date: 2024-06-13 04:01:37 Functions: 2 30 6.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    SMB2 notify test suite
       5             : 
       6             :    Copyright (C) Stefan Metzmacher 2006
       7             :    Copyright (C) Andrew Tridgell 2009
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "libcli/smb2/smb2.h"
      25             : #include "libcli/smb2/smb2_calls.h"
      26             : #include "../libcli/smb/smbXcli_base.h"
      27             : 
      28             : #include "torture/torture.h"
      29             : #include "torture/smb2/proto.h"
      30             : #include "librpc/gen_ndr/ndr_security.h"
      31             : #include "libcli/security/security.h"
      32             : #include "torture/util.h"
      33             : 
      34             : #include "system/filesys.h"
      35             : #include "auth/credentials/credentials.h"
      36             : #include "lib/cmdline/cmdline.h"
      37             : #include "librpc/gen_ndr/security.h"
      38             : 
      39             : #include "lib/events/events.h"
      40             : 
      41             : #include "libcli/raw/libcliraw.h"
      42             : #include "libcli/raw/raw_proto.h"
      43             : #include "libcli/libcli.h"
      44             : 
      45             : #define CHECK_STATUS(status, correct) do { \
      46             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      47             :                 torture_result(torture, TORTURE_FAIL, \
      48             :                        "(%s) Incorrect status %s - should be %s\n", \
      49             :                        __location__, nt_errstr(status), nt_errstr(correct)); \
      50             :                 ret = false; \
      51             :                 goto done; \
      52             :         }} while (0)
      53             : 
      54             : #define CHECK_VAL(v, correct) do { \
      55             :         if ((v) != (correct)) { \
      56             :                 torture_result(torture, TORTURE_FAIL, \
      57             :                        "(%s) wrong value for %s  0x%x should be 0x%x\n", \
      58             :                        __location__, #v, (int)v, (int)correct); \
      59             :                 ret = false; \
      60             :                 goto done; \
      61             :         }} while (0)
      62             : 
      63             : #define CHECK_WIRE_STR(field, value) do { \
      64             :         if (!field.s || strcmp(field.s, value)) { \
      65             :                 torture_result(torture, TORTURE_FAIL, \
      66             :                         "(%s) %s [%s] != %s\n",  __location__, #field, \
      67             :                         field.s, value); \
      68             :                 ret = false; \
      69             :                 goto done; \
      70             :         }} while (0)
      71             : 
      72             : #define WAIT_FOR_ASYNC_RESPONSE(req) \
      73             :         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \
      74             :                 if (tevent_loop_once(torture->ev) != 0) { \
      75             :                         break; \
      76             :                 } \
      77             :         }
      78             : 
      79             : #define BASEDIR "test_notify"
      80             : #define FNAME "smb2-notify01.dat"
      81             : 
      82           0 : static bool test_valid_request(struct torture_context *torture,
      83             :                                struct smb2_tree *tree)
      84             : {
      85           0 :         bool ret = true;
      86             :         NTSTATUS status;
      87             :         struct smb2_handle dh;
      88             :         struct smb2_notify n;
      89             :         struct smb2_request *req;
      90             :         uint32_t max_buffer_size;
      91             : 
      92           0 :         torture_comment(torture, "TESTING VALIDITY OF CHANGE NOTIFY REQUEST\n");
      93             : 
      94           0 :         smb2_transport_credits_ask_num(tree->session->transport, 256);
      95             : 
      96           0 :         smb2_util_unlink(tree, FNAME);
      97             : 
      98           0 :         status = smb2_util_roothandle(tree, &dh);
      99           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     100             : 
     101           0 :         max_buffer_size =
     102           0 :                 smb2cli_conn_max_trans_size(tree->session->transport->conn);
     103             : 
     104           0 :         n.in.recursive          = 0x0000;
     105           0 :         n.in.buffer_size        = max_buffer_size;
     106           0 :         n.in.file.handle        = dh;
     107           0 :         n.in.completion_filter  = FILE_NOTIFY_CHANGE_ALL;
     108           0 :         n.in.unknown            = 0x00000000;
     109           0 :         req = smb2_notify_send(tree, &n);
     110             : 
     111           0 :         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
     112           0 :                 if (tevent_loop_once(torture->ev) != 0) {
     113           0 :                         break;
     114             :                 }
     115             :         }
     116             : 
     117           0 :         status = torture_setup_simple_file(torture, tree, FNAME);
     118           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     119             : 
     120           0 :         status = smb2_notify_recv(req, torture, &n);
     121           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     122           0 :         CHECK_VAL(n.out.num_changes, 1);
     123           0 :         CHECK_VAL(n.out.changes[0].action, NOTIFY_ACTION_ADDED);
     124           0 :         CHECK_WIRE_STR(n.out.changes[0].name, FNAME);
     125             : 
     126             :         /*
     127             :          * if the change response doesn't fit in the buffer
     128             :          * NOTIFY_ENUM_DIR is returned.
     129             :          */
     130           0 :         n.in.buffer_size        = 0x00000000;
     131           0 :         req = smb2_notify_send(tree, &n);
     132             : 
     133           0 :         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
     134           0 :                 if (tevent_loop_once(torture->ev) != 0) {
     135           0 :                         break;
     136             :                 }
     137             :         }
     138             : 
     139           0 :         status = torture_setup_simple_file(torture, tree, FNAME);
     140           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     141             : 
     142           0 :         status = smb2_notify_recv(req, torture, &n);
     143           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_ENUM_DIR);
     144             : 
     145             :         /*
     146             :          * if the change response fits in the buffer we get
     147             :          * NT_STATUS_OK again
     148             :          */
     149           0 :         n.in.buffer_size        = max_buffer_size;
     150           0 :         req = smb2_notify_send(tree, &n);
     151             : 
     152           0 :         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
     153           0 :                 if (tevent_loop_once(torture->ev) != 0) {
     154           0 :                         break;
     155             :                 }
     156             :         }
     157             : 
     158           0 :         status = torture_setup_simple_file(torture, tree, FNAME);
     159           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     160             : 
     161           0 :         status = smb2_notify_recv(req, torture, &n);
     162           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     163           0 :         CHECK_VAL(n.out.num_changes, 3);
     164           0 :         CHECK_VAL(n.out.changes[0].action, NOTIFY_ACTION_REMOVED);
     165           0 :         CHECK_WIRE_STR(n.out.changes[0].name, FNAME);
     166           0 :         CHECK_VAL(n.out.changes[1].action, NOTIFY_ACTION_ADDED);
     167           0 :         CHECK_WIRE_STR(n.out.changes[1].name, FNAME);
     168           0 :         CHECK_VAL(n.out.changes[2].action, NOTIFY_ACTION_MODIFIED);
     169           0 :         CHECK_WIRE_STR(n.out.changes[2].name, FNAME);
     170             : 
     171             :         /* if the first notify returns NOTIFY_ENUM_DIR, all do */
     172           0 :         status = smb2_util_close(tree, dh);
     173           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     174           0 :         status = smb2_util_roothandle(tree, &dh);
     175           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     176             : 
     177           0 :         n.in.recursive          = 0x0000;
     178           0 :         n.in.buffer_size        = 0x00000001;
     179           0 :         n.in.file.handle        = dh;
     180           0 :         n.in.completion_filter  = FILE_NOTIFY_CHANGE_ALL;
     181           0 :         n.in.unknown            = 0x00000000;
     182           0 :         req = smb2_notify_send(tree, &n);
     183             : 
     184           0 :         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
     185           0 :                 if (tevent_loop_once(torture->ev) != 0) {
     186           0 :                         break;
     187             :                 }
     188             :         }
     189             : 
     190           0 :         status = torture_setup_simple_file(torture, tree, FNAME);
     191           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     192             : 
     193           0 :         status = smb2_notify_recv(req, torture, &n);
     194           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_ENUM_DIR);
     195             : 
     196           0 :         n.in.buffer_size        = max_buffer_size;
     197           0 :         req = smb2_notify_send(tree, &n);
     198           0 :         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
     199           0 :                 if (tevent_loop_once(torture->ev) != 0) {
     200           0 :                         break;
     201             :                 }
     202             :         }
     203             : 
     204           0 :         status = torture_setup_simple_file(torture, tree, FNAME);
     205           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     206             : 
     207           0 :         status = smb2_notify_recv(req, torture, &n);
     208           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_ENUM_DIR);
     209             : 
     210             :         /* if the buffer size is too large, we get invalid parameter */
     211           0 :         n.in.recursive          = 0x0000;
     212           0 :         n.in.buffer_size        = max_buffer_size + 1;
     213           0 :         n.in.file.handle        = dh;
     214           0 :         n.in.completion_filter  = FILE_NOTIFY_CHANGE_ALL;
     215           0 :         n.in.unknown            = 0x00000000;
     216           0 :         req = smb2_notify_send(tree, &n);
     217           0 :         status = smb2_notify_recv(req, torture, &n);
     218           0 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
     219             : 
     220           0 : done:
     221           0 :         return ret;
     222             : }
     223             : 
     224             : /*
     225             :    basic testing of change notify on directories
     226             : */
     227             : 
     228             : #define BASEDIR_DIR BASEDIR "_DIR"
     229             : 
     230           0 : static bool torture_smb2_notify_dir(struct torture_context *torture,
     231             :                               struct smb2_tree *tree1,
     232             :                               struct smb2_tree *tree2)
     233             : {
     234           0 :         bool ret = true;
     235             :         NTSTATUS status;
     236             :         union smb_notify notify;
     237             :         union smb_open io;
     238             :         union smb_close cl;
     239             :         int i, count;
     240           0 :         struct smb2_handle h1 = {{0}};
     241           0 :         struct smb2_handle h2 = {{0}};
     242             :         struct smb2_request *req, *req2;
     243           0 :         const char *fname = BASEDIR_DIR "\\subdir-name";
     244             :         extern int torture_numops;
     245             : 
     246           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY ON DIRECTORIES\n");
     247             : 
     248           0 :         smb2_deltree(tree1, BASEDIR_DIR);
     249           0 :         smb2_util_rmdir(tree1, BASEDIR_DIR);
     250             :         /*
     251             :           get a handle on the directory
     252             :         */
     253           0 :         ZERO_STRUCT(io.smb2);
     254           0 :         io.generic.level = RAW_OPEN_SMB2;
     255           0 :         io.smb2.in.create_flags = 0;
     256           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
     257           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     258           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     259           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     260             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     261           0 :         io.smb2.in.alloc_size = 0;
     262           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     263           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     264           0 :         io.smb2.in.security_flags = 0;
     265           0 :         io.smb2.in.fname = BASEDIR_DIR;
     266             : 
     267           0 :         status = smb2_create(tree1, torture, &(io.smb2));
     268           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     269           0 :         h1 = io.smb2.out.file.handle;
     270             : 
     271           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     272           0 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ;
     273           0 :         status = smb2_create(tree1, torture, &(io.smb2));
     274           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     275           0 :         h2 = io.smb2.out.file.handle;
     276             : 
     277             :         /* ask for a change notify,
     278             :            on file or directory name changes */
     279           0 :         ZERO_STRUCT(notify.smb2);
     280           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
     281           0 :         notify.smb2.in.buffer_size = 1000;
     282           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
     283           0 :         notify.smb2.in.file.handle = h1;
     284           0 :         notify.smb2.in.recursive = true;
     285             : 
     286           0 :         torture_comment(torture, "Testing notify cancel\n");
     287             : 
     288           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     289           0 :         smb2_cancel(req);
     290           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     291           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
     292             : 
     293           0 :         torture_comment(torture, "Testing notify mkdir\n");
     294             : 
     295           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     296           0 :         smb2_util_mkdir(tree2, fname);
     297             : 
     298           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     299           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     300             : 
     301           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
     302           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
     303           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
     304             : 
     305           0 :         torture_comment(torture, "Testing notify rmdir\n");
     306             : 
     307           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     308           0 :         smb2_util_rmdir(tree2, fname);
     309             : 
     310           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     311           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     312           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
     313           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
     314           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
     315             : 
     316           0 :         torture_comment(torture,
     317             :                 "Testing notify mkdir - rmdir - mkdir - rmdir\n");
     318             : 
     319           0 :         smb2_util_mkdir(tree2, fname);
     320           0 :         smb2_util_rmdir(tree2, fname);
     321           0 :         smb2_util_mkdir(tree2, fname);
     322           0 :         smb2_util_rmdir(tree2, fname);
     323           0 :         smb_msleep(200);
     324           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     325           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     326           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     327           0 :         CHECK_VAL(notify.smb2.out.num_changes, 4);
     328           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
     329           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
     330           0 :         CHECK_VAL(notify.smb2.out.changes[1].action, NOTIFY_ACTION_REMOVED);
     331           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[1].name, "subdir-name");
     332           0 :         CHECK_VAL(notify.smb2.out.changes[2].action, NOTIFY_ACTION_ADDED);
     333           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[2].name, "subdir-name");
     334           0 :         CHECK_VAL(notify.smb2.out.changes[3].action, NOTIFY_ACTION_REMOVED);
     335           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[3].name, "subdir-name");
     336             : 
     337           0 :         count = torture_numops;
     338           0 :         torture_comment(torture,
     339             :                 "Testing buffered notify on create of %d files\n", count);
     340           0 :         for (i=0;i<count;i++) {
     341             :                 struct smb2_handle h12;
     342           0 :                 char *fname2 = talloc_asprintf(torture,
     343             :                                                 BASEDIR_DIR "\\test%d.txt",
     344             :                                                 i);
     345             : 
     346           0 :                 ZERO_STRUCT(io.smb2);
     347           0 :                 io.generic.level = RAW_OPEN_SMB2;
     348           0 :                 io.smb2.in.create_flags = 0;
     349           0 :                 io.smb2.in.desired_access = SEC_FILE_ALL;
     350           0 :                 io.smb2.in.create_options =
     351             :                     NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     352           0 :                 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     353           0 :                 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     354             :                                         NTCREATEX_SHARE_ACCESS_WRITE;
     355           0 :                 io.smb2.in.alloc_size = 0;
     356           0 :                 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     357           0 :                 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     358           0 :                 io.smb2.in.security_flags = 0;
     359           0 :                 io.smb2.in.fname = fname2;
     360             : 
     361           0 :                 status = smb2_create(tree1, torture, &(io.smb2));
     362           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
     363           0 :                         torture_comment(torture, "Failed to create %s \n",
     364             :                                fname);
     365           0 :                         ret = false;
     366           0 :                         goto done;
     367             :                 }
     368           0 :                 h12 = io.smb2.out.file.handle;
     369           0 :                 talloc_free(fname2);
     370           0 :                 smb2_util_close(tree1, h12);
     371             :         }
     372             : 
     373             :         /* (1st notify) setup a new notify on a different directory handle.
     374             :            This new notify won't see the events above. */
     375           0 :         notify.smb2.in.file.handle = h2;
     376           0 :         req2 = smb2_notify_send(tree1, &(notify.smb2));
     377             : 
     378             :         /* (2nd notify) whereas this notify will see the above buffered events,
     379             :            and it directly returns the buffered events */
     380           0 :         notify.smb2.in.file.handle = h1;
     381           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     382             : 
     383           0 :         status = smb2_util_unlink(tree1, BASEDIR_DIR "\\nonexistent.txt");
     384           0 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     385             : 
     386             :         /* (1st unlink) as the 2nd notify directly returns,
     387             :            this unlink is only seen by the 1st notify and
     388             :            the 3rd notify (later) */
     389           0 :         torture_comment(torture,
     390             :                 "Testing notify on unlink for the first file\n");
     391           0 :         status = smb2_util_unlink(tree2, BASEDIR_DIR "\\test0.txt");
     392           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     393             : 
     394             :         /* receive the reply from the 2nd notify */
     395           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     396           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     397             : 
     398           0 :         CHECK_VAL(notify.smb2.out.num_changes, count);
     399           0 :         for (i=1;i<count;i++) {
     400           0 :                 CHECK_VAL(notify.smb2.out.changes[i].action,
     401             :                           NOTIFY_ACTION_ADDED);
     402             :         }
     403           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
     404             : 
     405           0 :         torture_comment(torture, "and now from the 1st notify\n");
     406           0 :         status = smb2_notify_recv(req2, torture, &(notify.smb2));
     407           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     408           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
     409           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
     410           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
     411             : 
     412           0 :         torture_comment(torture,
     413             :                 "(3rd notify) this notify will only see the 1st unlink\n");
     414           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     415             : 
     416           0 :         status = smb2_util_unlink(tree1, BASEDIR_DIR "\\nonexistent.txt");
     417           0 :         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
     418             : 
     419           0 :         for (i=1;i<count;i++) {
     420           0 :                 char *fname2 = talloc_asprintf(torture,
     421             :                               BASEDIR_DIR "\\test%d.txt", i);
     422           0 :                 status = smb2_util_unlink(tree2, fname2);
     423           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     424           0 :                 talloc_free(fname2);
     425             :         }
     426             : 
     427             :         /* receive the 3rd notify */
     428           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     429           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     430           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
     431           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
     432           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
     433             : 
     434             :         /* and we now see the rest of the unlink calls on both
     435             :          * directory handles */
     436           0 :         notify.smb2.in.file.handle = h1;
     437           0 :         sleep(3);
     438           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     439           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     440           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     441           0 :         CHECK_VAL(notify.smb2.out.num_changes, count-1);
     442           0 :         for (i=0;i<notify.smb2.out.num_changes;i++) {
     443           0 :                 CHECK_VAL(notify.smb2.out.changes[i].action,
     444             :                           NOTIFY_ACTION_REMOVED);
     445             :         }
     446           0 :         notify.smb2.in.file.handle = h2;
     447           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     448           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     449           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     450           0 :         CHECK_VAL(notify.smb2.out.num_changes, count-1);
     451           0 :         for (i=0;i<notify.smb2.out.num_changes;i++) {
     452           0 :                 CHECK_VAL(notify.smb2.out.changes[i].action,
     453             :                           NOTIFY_ACTION_REMOVED);
     454             :         }
     455             : 
     456           0 :         torture_comment(torture,
     457             :         "Testing if a close() on the dir handle triggers the notify reply\n");
     458             : 
     459           0 :         notify.smb2.in.file.handle = h1;
     460           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
     461             : 
     462           0 :         ZERO_STRUCT(cl.smb2);
     463           0 :         cl.smb2.level = RAW_CLOSE_SMB2;
     464           0 :         cl.smb2.in.file.handle = h1;
     465           0 :         status = smb2_close(tree1, &(cl.smb2));
     466           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     467             : 
     468           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
     469           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
     470           0 :         CHECK_VAL(notify.smb2.out.num_changes, 9);
     471             : 
     472           0 : done:
     473           0 :         smb2_util_close(tree1, h1);
     474           0 :         smb2_util_close(tree1, h2);
     475           0 :         smb2_deltree(tree1, BASEDIR_DIR);
     476           0 :         return ret;
     477             : }
     478             : 
     479           0 : static struct smb2_handle custom_smb2_create(struct smb2_tree *tree,
     480             :                                                 struct torture_context *torture,
     481             :                                                 struct smb2_create *smb2)
     482             : {
     483             :         struct smb2_handle h1;
     484           0 :         bool ret = true;
     485             :         NTSTATUS status;
     486           0 :         smb2_deltree(tree, smb2->in.fname);
     487           0 :         status = smb2_create(tree, torture, smb2);
     488           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     489           0 :         h1 = smb2->out.file.handle;
     490           0 : done:
     491           0 :         if (!ret) {
     492           0 :                 h1 = (struct smb2_handle) {
     493             :                         .data = { 0 , 0},
     494             :                 };
     495             :         }
     496           0 :         return h1;
     497             : }
     498             : 
     499             : /*
     500             :    testing of recursive change notify
     501             : */
     502             : 
     503             : #define BASEDIR_REC BASEDIR "_REC"
     504             : 
     505           0 : static bool torture_smb2_notify_recursive(struct torture_context *torture,
     506             :                                 struct smb2_tree *tree1,
     507             :                                 struct smb2_tree *tree2)
     508             : {
     509           0 :         bool ret = true;
     510             :         NTSTATUS status;
     511             :         union smb_notify notify;
     512             :         union smb_open io, io1;
     513             :         union smb_setfileinfo sinfo;
     514             :         struct smb2_handle h1;
     515             :         struct smb2_request *req1, *req2;
     516             : 
     517           0 :         smb2_deltree(tree1, BASEDIR_REC);
     518           0 :         smb2_util_rmdir(tree1, BASEDIR_REC);
     519             : 
     520           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY WITH RECURSION\n");
     521             : 
     522             :         /*
     523             :           get a handle on the directory
     524             :         */
     525           0 :         ZERO_STRUCT(io.smb2);
     526           0 :         io.generic.level = RAW_OPEN_SMB2;
     527           0 :         io.smb2.in.create_flags = 0;
     528           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
     529           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     530           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     531           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     532             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     533           0 :         io.smb2.in.alloc_size = 0;
     534           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     535           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     536           0 :         io.smb2.in.security_flags = 0;
     537           0 :         io.smb2.in.fname = BASEDIR_REC;
     538             : 
     539           0 :         status = smb2_create(tree1, torture, &(io.smb2));
     540           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     541           0 :         h1 = io.smb2.out.file.handle;
     542             : 
     543             :         /* ask for a change notify, on file or directory name
     544             :            changes. Setup both with and without recursion */
     545           0 :         ZERO_STRUCT(notify.smb2);
     546           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
     547           0 :         notify.smb2.in.buffer_size = 1000;
     548           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME |
     549             :                                 FILE_NOTIFY_CHANGE_ATTRIBUTES |
     550             :                                 FILE_NOTIFY_CHANGE_CREATION;
     551           0 :         notify.smb2.in.file.handle = h1;
     552             : 
     553           0 :         notify.smb2.in.recursive = true;
     554           0 :         req1 = smb2_notify_send(tree1, &(notify.smb2));
     555           0 :         smb2_cancel(req1);
     556           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
     557           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
     558             : 
     559           0 :         notify.smb2.in.recursive = false;
     560           0 :         req2 = smb2_notify_send(tree1, &(notify.smb2));
     561           0 :         smb2_cancel(req2);
     562           0 :         status = smb2_notify_recv(req2, torture, &(notify.smb2));
     563           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
     564             : 
     565           0 :         ZERO_STRUCT(io1.smb2);
     566           0 :         io1.generic.level = RAW_OPEN_SMB2;
     567           0 :         io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
     568           0 :         io1.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
     569             :                                 SEC_RIGHTS_FILE_WRITE|
     570             :                                 SEC_RIGHTS_FILE_ALL;
     571           0 :         io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     572           0 :         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     573           0 :         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     574             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
     575             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
     576           0 :         io1.smb2.in.alloc_size = 0;
     577           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     578           0 :         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     579           0 :         io1.smb2.in.security_flags = 0;
     580           0 :         io1.smb2.in.fname = BASEDIR_REC "\\subdir-name";
     581           0 :         status = smb2_create(tree2, torture, &(io1.smb2));
     582           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     583           0 :         smb2_util_close(tree2, io1.smb2.out.file.handle);
     584             : 
     585           0 :         io1.smb2.in.fname = BASEDIR_REC "\\subdir-name\\subname1";
     586           0 :         status = smb2_create(tree2, torture, &(io1.smb2));
     587           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     588           0 :         ZERO_STRUCT(sinfo);
     589           0 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     590           0 :         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
     591           0 :         sinfo.rename_information.in.overwrite = 0;
     592           0 :         sinfo.rename_information.in.root_fid = 0;
     593           0 :         sinfo.rename_information.in.new_name =
     594             :                                 BASEDIR_REC "\\subdir-name\\subname1-r";
     595           0 :         status = smb2_setinfo_file(tree2, &sinfo);
     596           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     597             : 
     598           0 :         io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     599           0 :         io1.smb2.in.fname = BASEDIR_REC "\\subdir-name\\subname2";
     600           0 :         status = smb2_create(tree2, torture, &(io1.smb2));
     601           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     602           0 :         ZERO_STRUCT(sinfo);
     603           0 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     604           0 :         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
     605           0 :         sinfo.rename_information.in.overwrite = true;
     606           0 :         sinfo.rename_information.in.root_fid = 0;
     607           0 :         sinfo.rename_information.in.new_name = BASEDIR_REC "\\subname2-r";
     608           0 :         status = smb2_setinfo_file(tree2, &sinfo);
     609           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     610             : 
     611           0 :         io1.smb2.in.fname = BASEDIR_REC "\\subname2-r";
     612           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     613           0 :         status = smb2_create(tree2, torture, &(io1.smb2));
     614           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     615           0 :         ZERO_STRUCT(sinfo);
     616           0 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     617           0 :         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
     618           0 :         sinfo.rename_information.in.overwrite = true;
     619           0 :         sinfo.rename_information.in.root_fid = 0;
     620           0 :         sinfo.rename_information.in.new_name = BASEDIR_REC "\\subname3-r";
     621           0 :         status = smb2_setinfo_file(tree2, &sinfo);
     622           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     623             : 
     624           0 :         notify.smb2.in.completion_filter = 0;
     625           0 :         notify.smb2.in.recursive = true;
     626           0 :         smb_msleep(200);
     627           0 :         req1 = smb2_notify_send(tree1, &(notify.smb2));
     628             : 
     629           0 :         status = smb2_util_rmdir(tree2,
     630             :                 BASEDIR_REC "\\subdir-name\\subname1-r");
     631           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     632           0 :         status = smb2_util_rmdir(tree2,
     633             :                 BASEDIR_REC "\\subdir-name");
     634           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     635           0 :         status = smb2_util_unlink(tree2, BASEDIR_REC "\\subname3-r");
     636           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     637             : 
     638           0 :         notify.smb2.in.recursive = false;
     639           0 :         req2 = smb2_notify_send(tree1, &(notify.smb2));
     640             : 
     641           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
     642           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     643             : 
     644           0 :         CHECK_VAL(notify.smb2.out.num_changes, 9);
     645           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
     646           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
     647           0 :         CHECK_VAL(notify.smb2.out.changes[1].action, NOTIFY_ACTION_ADDED);
     648           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[1].name, "subdir-name\\subname1");
     649           0 :         CHECK_VAL(notify.smb2.out.changes[2].action, NOTIFY_ACTION_OLD_NAME);
     650           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[2].name, "subdir-name\\subname1");
     651           0 :         CHECK_VAL(notify.smb2.out.changes[3].action, NOTIFY_ACTION_NEW_NAME);
     652           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[3].name, "subdir-name\\subname1-r");
     653           0 :         CHECK_VAL(notify.smb2.out.changes[4].action, NOTIFY_ACTION_ADDED);
     654           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[4].name, "subdir-name\\subname2");
     655           0 :         CHECK_VAL(notify.smb2.out.changes[5].action, NOTIFY_ACTION_REMOVED);
     656           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[5].name, "subdir-name\\subname2");
     657           0 :         CHECK_VAL(notify.smb2.out.changes[6].action, NOTIFY_ACTION_ADDED);
     658           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[6].name, "subname2-r");
     659           0 :         CHECK_VAL(notify.smb2.out.changes[7].action, NOTIFY_ACTION_OLD_NAME);
     660           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[7].name, "subname2-r");
     661           0 :         CHECK_VAL(notify.smb2.out.changes[8].action, NOTIFY_ACTION_NEW_NAME);
     662           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[8].name, "subname3-r");
     663             : 
     664           0 : done:
     665           0 :         smb2_deltree(tree1, BASEDIR_REC);
     666           0 :         return ret;
     667             : }
     668             : 
     669             : /*
     670             :    testing of change notify mask change
     671             : */
     672             : 
     673             : #define BASEDIR_MC BASEDIR "_MC"
     674             : 
     675           0 : static bool torture_smb2_notify_mask_change(struct torture_context *torture,
     676             :                                             struct smb2_tree *tree1,
     677             :                                             struct smb2_tree *tree2)
     678             : {
     679           0 :         bool ret = true;
     680             :         NTSTATUS status;
     681             :         union smb_notify notify;
     682             :         union smb_open io, io1;
     683             :         struct smb2_handle h1;
     684             :         struct smb2_request *req1, *req2;
     685             :         union smb_setfileinfo sinfo;
     686             : 
     687           0 :         smb2_deltree(tree1, BASEDIR_MC);
     688           0 :         smb2_util_rmdir(tree1, BASEDIR_MC);
     689             : 
     690           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY WITH MASK CHANGE\n");
     691             : 
     692             :         /*
     693             :           get a handle on the directory
     694             :         */
     695           0 :         ZERO_STRUCT(io.smb2);
     696           0 :         io.generic.level = RAW_OPEN_SMB2;
     697           0 :         io.smb2.in.create_flags = 0;
     698           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
     699           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     700           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     701           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     702             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     703           0 :         io.smb2.in.alloc_size = 0;
     704           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     705           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     706           0 :         io.smb2.in.security_flags = 0;
     707           0 :         io.smb2.in.fname = BASEDIR_MC;
     708             : 
     709           0 :         status = smb2_create(tree1, torture, &(io.smb2));
     710           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     711           0 :         h1 = io.smb2.out.file.handle;
     712             : 
     713             :         /* ask for a change notify, on file or directory name
     714             :            changes. Setup both with and without recursion */
     715           0 :         ZERO_STRUCT(notify.smb2);
     716           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
     717           0 :         notify.smb2.in.buffer_size = 1000;
     718           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
     719           0 :         notify.smb2.in.file.handle = h1;
     720             : 
     721           0 :         notify.smb2.in.recursive = true;
     722           0 :         req1 = smb2_notify_send(tree1, &(notify.smb2));
     723             : 
     724           0 :         smb2_cancel(req1);
     725           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
     726           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
     727             : 
     728             : 
     729           0 :         notify.smb2.in.recursive = false;
     730           0 :         req2 = smb2_notify_send(tree1, &(notify.smb2));
     731             : 
     732           0 :         smb2_cancel(req2);
     733           0 :         status = smb2_notify_recv(req2, torture, &(notify.smb2));
     734           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
     735             : 
     736           0 :         notify.smb2.in.recursive = true;
     737           0 :         req1 = smb2_notify_send(tree1, &(notify.smb2));
     738             : 
     739             :         /* Set to hidden then back again. */
     740           0 :         ZERO_STRUCT(io1.smb2);
     741           0 :         io1.generic.level = RAW_OPEN_SMB2;
     742           0 :         io1.smb2.in.create_flags = 0;
     743           0 :         io1.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
     744             :                                 SEC_RIGHTS_FILE_WRITE|
     745             :                                 SEC_RIGHTS_FILE_ALL;
     746           0 :         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     747           0 :         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     748             :                                 NTCREATEX_SHARE_ACCESS_WRITE |
     749             :                                 NTCREATEX_SHARE_ACCESS_DELETE;
     750           0 :         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     751           0 :         io1.smb2.in.security_flags = 0;
     752           0 :         io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     753           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     754           0 :         io1.smb2.in.fname = BASEDIR_MC "\\tname1";
     755             : 
     756           0 :         smb2_util_close(tree1,
     757             :                 custom_smb2_create(tree1, torture, &(io1.smb2)));
     758           0 :         status = smb2_util_setatr(tree1, BASEDIR_MC "\\tname1",
     759             :                                 FILE_ATTRIBUTE_HIDDEN);
     760           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     761           0 :         smb2_util_unlink(tree1, BASEDIR_MC "\\tname1");
     762             : 
     763           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
     764           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     765             : 
     766           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
     767           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
     768           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "tname1");
     769             : 
     770             :         /* Now try and change the mask to include other events.
     771             :          * This should not work - once the mask is set on a directory
     772             :          * h1 it seems to be fixed until the fnum is closed. */
     773             : 
     774           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME |
     775             :                                         FILE_NOTIFY_CHANGE_ATTRIBUTES |
     776             :                                         FILE_NOTIFY_CHANGE_CREATION;
     777           0 :         notify.smb2.in.recursive = true;
     778           0 :         req1 = smb2_notify_send(tree1, &(notify.smb2));
     779             : 
     780           0 :         notify.smb2.in.recursive = false;
     781           0 :         req2 = smb2_notify_send(tree1, &(notify.smb2));
     782             : 
     783           0 :         io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     784           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     785           0 :         io1.smb2.in.fname = BASEDIR_MC "\\subdir-name";
     786           0 :         status = smb2_create(tree2, torture, &(io1.smb2));
     787           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     788           0 :         smb2_util_close(tree2, io1.smb2.out.file.handle);
     789             : 
     790           0 :         ZERO_STRUCT(sinfo);
     791           0 :         io1.smb2.in.fname = BASEDIR_MC "\\subdir-name\\subname1";
     792           0 :         io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     793           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     794           0 :         status = smb2_create(tree2, torture, &(io1.smb2));
     795           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     796           0 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
     797           0 :         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
     798           0 :         sinfo.rename_information.in.overwrite = true;
     799           0 :         sinfo.rename_information.in.root_fid = 0;
     800           0 :         sinfo.rename_information.in.new_name =
     801             :                                 BASEDIR_MC "\\subdir-name\\subname1-r";
     802           0 :         status = smb2_setinfo_file(tree2, &sinfo);
     803           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     804             : 
     805           0 :         io1.smb2.in.fname = BASEDIR_MC "\\subdir-name\\subname2";
     806           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     807           0 :         io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     808           0 :         status = smb2_create(tree2, torture, &(io1.smb2));
     809           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     810           0 :         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
     811           0 :         sinfo.rename_information.in.new_name = BASEDIR_MC "\\subname2-r";
     812           0 :         status = smb2_setinfo_file(tree2, &sinfo);
     813           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     814           0 :         smb2_util_close(tree2, io1.smb2.out.file.handle);
     815             : 
     816           0 :         io1.smb2.in.fname = BASEDIR_MC "\\subname2-r";
     817           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
     818           0 :         status = smb2_create(tree2, torture, &(io1.smb2));
     819           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     820           0 :         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
     821           0 :         sinfo.rename_information.in.new_name = BASEDIR_MC "\\subname3-r";
     822           0 :         status = smb2_setinfo_file(tree2, &sinfo);
     823           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     824           0 :         smb2_util_close(tree2, io1.smb2.out.file.handle);
     825             : 
     826           0 :         status = smb2_util_rmdir(tree2, BASEDIR_MC "\\subdir-name\\subname1-r");
     827           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     828           0 :         status = smb2_util_rmdir(tree2, BASEDIR_MC "\\subdir-name");
     829           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     830           0 :         status = smb2_util_unlink(tree2, BASEDIR_MC "\\subname3-r");
     831           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     832             : 
     833           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
     834           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     835             : 
     836           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
     837           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
     838           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subname2-r");
     839             : 
     840           0 :         status = smb2_notify_recv(req2, torture, &(notify.smb2));
     841           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     842             : 
     843           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
     844           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
     845           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subname3-r");
     846             : 
     847           0 :         if (!ret) {
     848           0 :                 goto done;
     849             :         }
     850             : 
     851           0 : done:
     852           0 :         smb2_deltree(tree1, BASEDIR_MC);
     853           0 :         return ret;
     854             : }
     855             : 
     856             : /*
     857             :    testing of mask bits for change notify
     858             : */
     859             : 
     860             : #define BASEDIR_MSK BASEDIR "_MSK"
     861             : 
     862           0 : static bool torture_smb2_notify_mask(struct torture_context *torture,
     863             :                                      struct smb2_tree *tree1,
     864             :                                      struct smb2_tree *tree2)
     865             : {
     866           0 :         bool ret = true;
     867             :         NTSTATUS status;
     868             :         union smb_notify notify;
     869             :         union smb_open io, io1;
     870             :         struct smb2_handle h1, h2;
     871             :         int i;
     872           0 :         char c = 1;
     873             :         union smb_setfileinfo sinfo;
     874             : 
     875           0 :         smb2_deltree(tree1, BASEDIR_MSK);
     876           0 :         smb2_util_rmdir(tree1, BASEDIR_MSK);
     877             : 
     878           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY COMPLETION FILTERS\n");
     879             : 
     880             : 
     881           0 :         ZERO_STRUCT(h1);
     882           0 :         ZERO_STRUCT(h2);
     883             :         /*
     884             :           get a handle on the directory
     885             :         */
     886           0 :         ZERO_STRUCT(io.smb2);
     887           0 :         io.generic.level = RAW_OPEN_SMB2;
     888           0 :         io.smb2.in.create_flags = 0;
     889           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
     890           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     891           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     892           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     893             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     894           0 :         io.smb2.in.alloc_size = 0;
     895           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
     896           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     897           0 :         io.smb2.in.security_flags = 0;
     898           0 :         io.smb2.in.fname = BASEDIR_MSK;
     899             : 
     900           0 :         ZERO_STRUCT(notify.smb2);
     901           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
     902           0 :         notify.smb2.in.buffer_size = 1000;
     903           0 :         notify.smb2.in.recursive = true;
     904             : 
     905             : #define NOTIFY_MASK_TEST(test_name, setup, op, cleanup, Action, \
     906             :                          expected, nchanges) \
     907             :         do { \
     908             :         do { for (i=0;i<32;i++) { \
     909             :                 struct smb2_request *req; \
     910             :                 status = smb2_create(tree1, torture, &(io.smb2)); \
     911             :                 CHECK_STATUS(status, NT_STATUS_OK); \
     912             :                 h1 = io.smb2.out.file.handle; \
     913             :                 setup \
     914             :                 notify.smb2.in.file.handle = h1;        \
     915             :                 notify.smb2.in.completion_filter = ((uint32_t)1<<i); \
     916             :                 /* cancel initial requests so the buffer is setup */    \
     917             :                 req = smb2_notify_send(tree1, &(notify.smb2)); \
     918             :                 smb2_cancel(req); \
     919             :                 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
     920             :                 CHECK_STATUS(status, NT_STATUS_CANCELLED); \
     921             :                 /* send the change notify request */ \
     922             :                 req = smb2_notify_send(tree1, &(notify.smb2)); \
     923             :                 op \
     924             :                 smb_msleep(200); smb2_cancel(req); \
     925             :                 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
     926             :                 cleanup \
     927             :                 smb2_util_close(tree1, h1); \
     928             :                 if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \
     929             :                 CHECK_STATUS(status, NT_STATUS_OK); \
     930             :                 /* special case to cope with file rename behaviour */ \
     931             :                 if (nchanges == 2 && notify.smb2.out.num_changes == 1 && \
     932             :                     notify.smb2.out.changes[0].action == \
     933             :                         NOTIFY_ACTION_MODIFIED && \
     934             :                     ((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \
     935             :                     Action == NOTIFY_ACTION_OLD_NAME) { \
     936             :                         torture_comment(torture, \
     937             :                                 "(rename file special handling OK)\n"); \
     938             :                 } else if (nchanges != notify.smb2.out.num_changes) { \
     939             :                         torture_result(torture, TORTURE_FAIL, \
     940             :                                "ERROR: nchanges=%d expected=%d "\
     941             :                                "action=%d filter=0x%08x\n", \
     942             :                                notify.smb2.out.num_changes, \
     943             :                                nchanges, \
     944             :                                notify.smb2.out.changes[0].action, \
     945             :                                notify.smb2.in.completion_filter); \
     946             :                         ret = false; \
     947             :                 } else if (notify.smb2.out.changes[0].action != Action) { \
     948             :                         torture_result(torture, TORTURE_FAIL, \
     949             :                                "ERROR: nchanges=%d action=%d " \
     950             :                                "expectedAction=%d filter=0x%08x\n", \
     951             :                                notify.smb2.out.num_changes, \
     952             :                                notify.smb2.out.changes[0].action, \
     953             :                                Action, \
     954             :                                notify.smb2.in.completion_filter); \
     955             :                         ret = false; \
     956             :                 } else if (strcmp(notify.smb2.out.changes[0].name.s, \
     957             :                            "tname1") != 0) { \
     958             :                         torture_result(torture, TORTURE_FAIL, \
     959             :                                "ERROR: nchanges=%d action=%d " \
     960             :                                "filter=0x%08x name=%s\n", \
     961             :                                notify.smb2.out.num_changes, \
     962             :                                notify.smb2.out.changes[0].action, \
     963             :                                notify.smb2.in.completion_filter, \
     964             :                                notify.smb2.out.changes[0].name.s);      \
     965             :                         ret = false; \
     966             :                 } \
     967             :         } \
     968             :         } while (0); \
     969             :         } while (0);
     970             : 
     971           0 :         torture_comment(torture, "Testing mkdir\n");
     972           0 :         NOTIFY_MASK_TEST("Testing mkdir",;,
     973             :                          smb2_util_mkdir(tree2, BASEDIR_MSK "\\tname1");,
     974             :                          smb2_util_rmdir(tree2, BASEDIR_MSK "\\tname1");,
     975             :                          NOTIFY_ACTION_ADDED,
     976             :                          FILE_NOTIFY_CHANGE_DIR_NAME, 1);
     977             : 
     978           0 :         torture_comment(torture, "Testing create file\n");
     979           0 :         ZERO_STRUCT(io1.smb2);
     980           0 :         io1.generic.level = RAW_OPEN_SMB2;
     981           0 :         io1.smb2.in.create_flags = 0;
     982           0 :         io1.smb2.in.desired_access = SEC_FILE_ALL;
     983           0 :         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     984           0 :         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
     985             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     986           0 :         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
     987           0 :         io1.smb2.in.security_flags = 0;
     988           0 :         io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     989           0 :         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
     990           0 :         io1.smb2.in.fname = BASEDIR_MSK "\\tname1";
     991             : 
     992           0 :         NOTIFY_MASK_TEST("Testing create file",;,
     993             :                          smb2_util_close(tree2, custom_smb2_create(tree2,
     994             :                                                 torture, &(io1.smb2)));,
     995             :                          smb2_util_unlink(tree2, BASEDIR_MSK "\\tname1");,
     996             :                          NOTIFY_ACTION_ADDED,
     997             :                          FILE_NOTIFY_CHANGE_FILE_NAME, 1);
     998             : 
     999           0 :         torture_comment(torture, "Testing unlink\n");
    1000           0 :         NOTIFY_MASK_TEST("Testing unlink",
    1001             :                          smb2_util_close(tree2, custom_smb2_create(tree2,
    1002             :                                                 torture, &(io1.smb2)));,
    1003             :                          smb2_util_unlink(tree2, BASEDIR_MSK "\\tname1");,
    1004             :                          ;,
    1005             :                          NOTIFY_ACTION_REMOVED,
    1006             :                          FILE_NOTIFY_CHANGE_FILE_NAME, 1);
    1007             : 
    1008           0 :         torture_comment(torture, "Testing rmdir\n");
    1009           0 :         NOTIFY_MASK_TEST("Testing rmdir",
    1010             :                          smb2_util_mkdir(tree2, BASEDIR_MSK "\\tname1");,
    1011             :                          smb2_util_rmdir(tree2, BASEDIR_MSK "\\tname1");,
    1012             :                          ;,
    1013             :                          NOTIFY_ACTION_REMOVED,
    1014             :                          FILE_NOTIFY_CHANGE_DIR_NAME, 1);
    1015             : 
    1016           0 :         torture_comment(torture, "Testing rename file\n");
    1017           0 :         ZERO_STRUCT(sinfo);
    1018           0 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
    1019           0 :         sinfo.rename_information.in.file.handle = h1;
    1020           0 :         sinfo.rename_information.in.overwrite = true;
    1021           0 :         sinfo.rename_information.in.root_fid = 0;
    1022           0 :         sinfo.rename_information.in.new_name = BASEDIR_MSK "\\tname2";
    1023           0 :         NOTIFY_MASK_TEST("Testing rename file",
    1024             :                          smb2_util_close(tree2, custom_smb2_create(tree2,
    1025             :                                                 torture, &(io1.smb2)));,
    1026             :                          smb2_setinfo_file(tree2, &sinfo);,
    1027             :                          smb2_util_unlink(tree2, BASEDIR_MSK "\\tname2");,
    1028             :                          NOTIFY_ACTION_OLD_NAME,
    1029             :                          FILE_NOTIFY_CHANGE_FILE_NAME, 2);
    1030             : 
    1031           0 :         torture_comment(torture, "Testing rename dir\n");
    1032           0 :         ZERO_STRUCT(sinfo);
    1033           0 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
    1034           0 :         sinfo.rename_information.in.file.handle = h1;
    1035           0 :         sinfo.rename_information.in.overwrite = true;
    1036           0 :         sinfo.rename_information.in.root_fid = 0;
    1037           0 :         sinfo.rename_information.in.new_name = BASEDIR_MSK "\\tname2";
    1038           0 :         NOTIFY_MASK_TEST("Testing rename dir",
    1039             :                 smb2_util_mkdir(tree2, BASEDIR_MSK "\\tname1");,
    1040             :                 smb2_setinfo_file(tree2, &sinfo);,
    1041             :                 smb2_util_rmdir(tree2, BASEDIR_MSK "\\tname2");,
    1042             :                 NOTIFY_ACTION_OLD_NAME,
    1043             :                 FILE_NOTIFY_CHANGE_DIR_NAME, 2);
    1044             : 
    1045           0 :         torture_comment(torture, "Testing set path attribute\n");
    1046           0 :         NOTIFY_MASK_TEST("Testing set path attribute",
    1047             :                 smb2_util_close(tree2, custom_smb2_create(tree2,
    1048             :                                        torture, &(io.smb2)));,
    1049             :                 smb2_util_setatr(tree2, BASEDIR_MSK "\\tname1",
    1050             :                                  FILE_ATTRIBUTE_HIDDEN);,
    1051             :                 smb2_util_unlink(tree2, BASEDIR_MSK "\\tname1");,
    1052             :                 NOTIFY_ACTION_MODIFIED,
    1053             :                 FILE_NOTIFY_CHANGE_ATTRIBUTES, 1);
    1054             : 
    1055           0 :         torture_comment(torture, "Testing set path write time\n");
    1056           0 :         ZERO_STRUCT(sinfo);
    1057           0 :         sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
    1058           0 :         sinfo.generic.in.file.handle = h1;
    1059           0 :         sinfo.basic_info.in.write_time = 1000;
    1060           0 :         NOTIFY_MASK_TEST("Testing set path write time",
    1061             :                 smb2_util_close(tree2, custom_smb2_create(tree2,
    1062             :                                        torture, &(io1.smb2)));,
    1063             :                 smb2_setinfo_file(tree2, &sinfo);,
    1064             :                 smb2_util_unlink(tree2, BASEDIR_MSK "\\tname1");,
    1065             :                 NOTIFY_ACTION_MODIFIED,
    1066             :                 FILE_NOTIFY_CHANGE_LAST_WRITE, 1);
    1067             : 
    1068           0 :         if (torture_setting_bool(torture, "samba3", false)) {
    1069           0 :                 torture_comment(torture,
    1070             :                        "Samba3 does not yet support create times "
    1071             :                        "everywhere\n");
    1072             :         }
    1073             :         else {
    1074           0 :                 ZERO_STRUCT(sinfo);
    1075           0 :                 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
    1076           0 :                 sinfo.generic.in.file.handle = h1;
    1077           0 :                 sinfo.basic_info.in.create_time = 0;
    1078           0 :                 torture_comment(torture, "Testing set file create time\n");
    1079           0 :                 NOTIFY_MASK_TEST("Testing set file create time",
    1080             :                         smb2_create_complex_file(torture, tree2,
    1081             :                         BASEDIR_MSK "\\tname1", &h2);,
    1082             :                         smb2_setinfo_file(tree2, &sinfo);,
    1083             :                         (smb2_util_close(tree2, h2),
    1084             :                          smb2_util_unlink(tree2, BASEDIR_MSK "\\tname1"));,
    1085             :                         NOTIFY_ACTION_MODIFIED,
    1086             :                         FILE_NOTIFY_CHANGE_CREATION, 1);
    1087             :         }
    1088             : 
    1089           0 :         ZERO_STRUCT(sinfo);
    1090           0 :         sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
    1091           0 :         sinfo.generic.in.file.handle = h1;
    1092           0 :         sinfo.basic_info.in.access_time = 0;
    1093           0 :         torture_comment(torture, "Testing set file access time\n");
    1094           0 :         NOTIFY_MASK_TEST("Testing set file access time",
    1095             :                 smb2_create_complex_file(torture,
    1096             :                         tree2,
    1097             :                         BASEDIR_MSK "\\tname1",
    1098             :                         &h2);,
    1099             :                 smb2_setinfo_file(tree2, &sinfo);,
    1100             :                 (smb2_util_close(tree2, h2),
    1101             :                 smb2_util_unlink(tree2, BASEDIR_MSK "\\tname1"));,
    1102             :                 NOTIFY_ACTION_MODIFIED,
    1103             :                 FILE_NOTIFY_CHANGE_LAST_ACCESS, 1);
    1104             : 
    1105           0 :         ZERO_STRUCT(sinfo);
    1106           0 :         sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
    1107           0 :         sinfo.generic.in.file.handle = h1;
    1108           0 :         sinfo.basic_info.in.change_time = 0;
    1109           0 :         torture_comment(torture, "Testing set file change time\n");
    1110           0 :         NOTIFY_MASK_TEST("Testing set file change time",
    1111             :                 smb2_create_complex_file(torture,
    1112             :                         tree2,
    1113             :                         BASEDIR_MSK "\\tname1",
    1114             :                         &h2);,
    1115             :                 smb2_setinfo_file(tree2, &sinfo);,
    1116             :                 (smb2_util_close(tree2, h2),
    1117             :                 smb2_util_unlink(tree2, BASEDIR_MSK "\\tname1"));,
    1118             :                 NOTIFY_ACTION_MODIFIED,
    1119             :                 0, 1);
    1120             : 
    1121             : 
    1122           0 :         torture_comment(torture, "Testing write\n");
    1123           0 :         NOTIFY_MASK_TEST("Testing write",
    1124             :                 smb2_create_complex_file(torture,
    1125             :                         tree2,
    1126             :                         BASEDIR_MSK "\\tname1",
    1127             :                         &h2);,
    1128             :                 smb2_util_write(tree2, h2, &c, 10000, 1);,
    1129             :                 (smb2_util_close(tree2, h2),
    1130             :                 smb2_util_unlink(tree2, BASEDIR_MSK "\\tname1"));,
    1131             :                 NOTIFY_ACTION_MODIFIED,
    1132             :                 0, 1);
    1133             : 
    1134           0 : done:
    1135           0 :         smb2_deltree(tree1, BASEDIR_MSK);
    1136           0 :         return ret;
    1137             : }
    1138             : 
    1139             : #define BASEDIR_FL BASEDIR "_FL"
    1140             : /*
    1141             :   basic testing of change notify on files
    1142             : */
    1143           0 : static bool torture_smb2_notify_file(struct torture_context *torture,
    1144             :                                 struct smb2_tree *tree)
    1145             : {
    1146             :         NTSTATUS status;
    1147           0 :         bool ret = true;
    1148             :         union smb_open io;
    1149             :         union smb_close cl;
    1150             :         union smb_notify notify;
    1151             :         struct smb2_request *req;
    1152             :         struct smb2_handle h1;
    1153           0 :         const char *fname = BASEDIR_FL "\\file.txt";
    1154             : 
    1155           0 :         smb2_deltree(tree, BASEDIR_FL);
    1156           0 :         smb2_util_rmdir(tree, BASEDIR_FL);
    1157             : 
    1158           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY ON FILES\n");
    1159           0 :         status = torture_smb2_testdir(tree, BASEDIR_FL, &h1);
    1160           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1161             : 
    1162           0 :         ZERO_STRUCT(io.smb2);
    1163           0 :         io.generic.level = RAW_OPEN_SMB2;
    1164           0 :         io.smb2.in.create_flags = 0;
    1165           0 :         io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    1166           0 :         io.smb2.in.create_options = 0;
    1167           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1168           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1169             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1170           0 :         io.smb2.in.alloc_size = 0;
    1171           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1172           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1173           0 :         io.smb2.in.security_flags = 0;
    1174           0 :         io.smb2.in.fname = fname;
    1175           0 :         status = smb2_create(tree, torture, &(io.smb2));
    1176           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1177           0 :         h1 = io.smb2.out.file.handle;
    1178             : 
    1179             :         /* ask for a change notify,
    1180             :            on file or directory name changes */
    1181           0 :         ZERO_STRUCT(notify.smb2);
    1182           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1183           0 :         notify.smb2.in.file.handle = h1;
    1184           0 :         notify.smb2.in.buffer_size = 1000;
    1185           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_STREAM_NAME;
    1186           0 :         notify.smb2.in.recursive = false;
    1187             : 
    1188           0 :         torture_comment(torture,
    1189             :         "Testing if notifies on file handles are invalid (should be)\n");
    1190             : 
    1191           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    1192           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1193           0 :         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    1194             : 
    1195           0 :         ZERO_STRUCT(cl.smb2);
    1196           0 :         cl.close.level = RAW_CLOSE_SMB2;
    1197           0 :         cl.close.in.file.handle = h1;
    1198           0 :         status = smb2_close(tree, &(cl.smb2));
    1199           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1200             : 
    1201           0 :         status = smb2_util_unlink(tree, fname);
    1202           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1203             : 
    1204           0 : done:
    1205           0 :         smb2_deltree(tree, BASEDIR_FL);
    1206           0 :         return ret;
    1207             : }
    1208             : /*
    1209             :   basic testing of change notifies followed by a tdis
    1210             : */
    1211             : 
    1212             : #define BASEDIR_TD BASEDIR "_TD"
    1213             : 
    1214           0 : static bool torture_smb2_notify_tree_disconnect(
    1215             :                 struct torture_context *torture,
    1216             :                 struct smb2_tree *tree)
    1217             : {
    1218           0 :         bool ret = true;
    1219             :         NTSTATUS status;
    1220             :         union smb_notify notify;
    1221             :         union smb_open io;
    1222             :         struct smb2_handle h1;
    1223             :         struct smb2_request *req;
    1224             : 
    1225           0 :         smb2_deltree(tree, BASEDIR_TD);
    1226           0 :         smb2_util_rmdir(tree, BASEDIR_TD);
    1227             : 
    1228           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY+CANCEL FOLLOWED BY "
    1229             :                         "TREE-DISCONNECT\n");
    1230             : 
    1231             :         /*
    1232             :           get a handle on the directory
    1233             :         */
    1234           0 :         ZERO_STRUCT(io.smb2);
    1235           0 :         io.generic.level = RAW_OPEN_SMB2;
    1236           0 :         io.smb2.in.create_flags = 0;
    1237           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    1238           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1239           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1240           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1241             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1242           0 :         io.smb2.in.alloc_size = 0;
    1243           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1244           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1245           0 :         io.smb2.in.security_flags = 0;
    1246           0 :         io.smb2.in.fname = BASEDIR_TD;
    1247             : 
    1248           0 :         status = smb2_create(tree, torture, &(io.smb2));
    1249           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1250           0 :         h1 = io.smb2.out.file.handle;
    1251             : 
    1252             :         /* ask for a change notify,
    1253             :            on file or directory name changes */
    1254           0 :         ZERO_STRUCT(notify.smb2);
    1255           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1256           0 :         notify.smb2.in.buffer_size = 1000;
    1257           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    1258           0 :         notify.smb2.in.file.handle = h1;
    1259           0 :         notify.smb2.in.recursive = true;
    1260             : 
    1261           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    1262           0 :         smb2_cancel(req);
    1263           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1264             : 
    1265           0 :         status = smb2_tdis(tree);
    1266           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1267             : 
    1268           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    1269             : 
    1270           0 :         smb2_notify_recv(req, torture, &(notify.smb2));
    1271           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1272           0 :         CHECK_VAL(notify.smb2.out.num_changes, 0);
    1273             : 
    1274           0 : done:
    1275           0 :         smb2_deltree(tree, BASEDIR_TD);
    1276           0 :         return ret;
    1277             : }
    1278             : 
    1279             : /*
    1280             :   testing of change notifies followed by a tdis - no cancel
    1281             : */
    1282             : 
    1283             : #define BASEDIR_NTDIS BASEDIR "_NTDIS"
    1284             : 
    1285           0 : static bool torture_smb2_notify_tree_disconnect_1(
    1286             :                 struct torture_context *torture,
    1287             :                 struct smb2_tree *tree)
    1288             : {
    1289           0 :         bool ret = true;
    1290             :         NTSTATUS status;
    1291             :         union smb_notify notify;
    1292             :         union smb_open io;
    1293             :         struct smb2_handle h1;
    1294             :         struct smb2_request *req;
    1295             : 
    1296           0 :         smb2_deltree(tree, BASEDIR_NTDIS);
    1297           0 :         smb2_util_rmdir(tree, BASEDIR_NTDIS);
    1298             : 
    1299           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY ASYNC FOLLOWED BY "
    1300             :                         "TREE-DISCONNECT\n");
    1301             : 
    1302             :         /*
    1303             :           get a handle on the directory
    1304             :         */
    1305           0 :         ZERO_STRUCT(io.smb2);
    1306           0 :         io.generic.level = RAW_OPEN_SMB2;
    1307           0 :         io.smb2.in.create_flags = 0;
    1308           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    1309           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1310           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1311           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1312             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1313           0 :         io.smb2.in.alloc_size = 0;
    1314           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1315           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1316           0 :         io.smb2.in.security_flags = 0;
    1317           0 :         io.smb2.in.fname = BASEDIR_NTDIS;
    1318             : 
    1319           0 :         status = smb2_create(tree, torture, &(io.smb2));
    1320           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1321           0 :         h1 = io.smb2.out.file.handle;
    1322             : 
    1323             :         /* ask for a change notify,
    1324             :            on file or directory name changes */
    1325           0 :         ZERO_STRUCT(notify.smb2);
    1326           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1327           0 :         notify.smb2.in.buffer_size = 1000;
    1328           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    1329           0 :         notify.smb2.in.file.handle = h1;
    1330           0 :         notify.smb2.in.recursive = true;
    1331             : 
    1332           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    1333           0 :         WAIT_FOR_ASYNC_RESPONSE(req);
    1334             : 
    1335           0 :         status = smb2_tdis(tree);
    1336           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1337             : 
    1338           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1339           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
    1340           0 :         CHECK_VAL(notify.smb2.out.num_changes, 0);
    1341             : 
    1342           0 : done:
    1343           0 :         smb2_deltree(tree, BASEDIR_NTDIS);
    1344           0 :         return ret;
    1345             : }
    1346             : 
    1347             : /*
    1348             :   basic testing of change notifies followed by a close
    1349             : */
    1350             : 
    1351             : #define BASEDIR_CNC BASEDIR "_CNC"
    1352             : 
    1353           0 : static bool torture_smb2_notify_close(struct torture_context *torture,
    1354             :                                 struct smb2_tree *tree1)
    1355             : {
    1356           0 :         bool ret = true;
    1357             :         NTSTATUS status;
    1358             :         union smb_notify notify;
    1359             :         union smb_open io;
    1360             :         struct smb2_handle h1;
    1361             :         struct smb2_request *req;
    1362             : 
    1363           0 :         smb2_deltree(tree1, BASEDIR_CNC);
    1364           0 :         smb2_util_rmdir(tree1, BASEDIR_CNC);
    1365             : 
    1366           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
    1367             : 
    1368             :         /*
    1369             :           get a handle on the directory
    1370             :         */
    1371           0 :         ZERO_STRUCT(io.smb2);
    1372           0 :         io.generic.level = RAW_OPEN_SMB2;
    1373           0 :         io.smb2.in.create_flags = 0;
    1374           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    1375           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1376           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1377           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1378             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1379           0 :         io.smb2.in.alloc_size = 0;
    1380           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1381           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1382           0 :         io.smb2.in.security_flags = 0;
    1383           0 :         io.smb2.in.fname = BASEDIR_CNC;
    1384             : 
    1385           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1386           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1387             : 
    1388           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1389           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1390           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1391           0 :         h1 = io.smb2.out.file.handle;
    1392             : 
    1393             :         /* ask for a change notify,
    1394             :            on file or directory name changes */
    1395           0 :         ZERO_STRUCT(notify.smb2);
    1396           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1397           0 :         notify.smb2.in.buffer_size = 1000;
    1398           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    1399           0 :         notify.smb2.in.file.handle = h1;
    1400           0 :         notify.smb2.in.recursive = true;
    1401             : 
    1402           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
    1403             : 
    1404           0 :         WAIT_FOR_ASYNC_RESPONSE(req);
    1405             : 
    1406           0 :         status = smb2_util_close(tree1, h1);
    1407           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1408             : 
    1409           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1410           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
    1411           0 :         CHECK_VAL(notify.smb2.out.num_changes, 0);
    1412             : 
    1413           0 : done:
    1414           0 :         smb2_deltree(tree1, BASEDIR_CNC);
    1415           0 :         return ret;
    1416             : }
    1417             : 
    1418             : /*
    1419             :   basic testing of change notifies followed by a ulogoff
    1420             : */
    1421             : 
    1422             : #define BASEDIR_NUL BASEDIR "_NUL"
    1423           0 : static bool torture_smb2_notify_ulogoff(struct torture_context *torture,
    1424             :                                 struct smb2_tree *tree1)
    1425             : {
    1426           0 :         bool ret = true;
    1427             :         NTSTATUS status;
    1428             :         union smb_notify notify;
    1429             :         union smb_open io;
    1430             :         struct smb2_handle h1;
    1431             :         struct smb2_request *req;
    1432             : 
    1433           0 :         smb2_deltree(tree1, BASEDIR_NUL);
    1434           0 :         smb2_util_rmdir(tree1, BASEDIR_NUL);
    1435             : 
    1436           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
    1437             : 
    1438             :         /*
    1439             :           get a handle on the directory
    1440             :         */
    1441           0 :         ZERO_STRUCT(io.smb2);
    1442           0 :         io.generic.level = RAW_OPEN_SMB2;
    1443           0 :         io.smb2.in.create_flags = 0;
    1444           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    1445           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1446           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1447           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1448             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1449           0 :         io.smb2.in.alloc_size = 0;
    1450           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1451           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1452           0 :         io.smb2.in.security_flags = 0;
    1453           0 :         io.smb2.in.fname = BASEDIR_NUL;
    1454             : 
    1455           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1456           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1457             : 
    1458           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1459           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1460           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1461           0 :         h1 = io.smb2.out.file.handle;
    1462             : 
    1463             :         /* ask for a change notify,
    1464             :            on file or directory name changes */
    1465           0 :         ZERO_STRUCT(notify.smb2);
    1466           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1467           0 :         notify.smb2.in.buffer_size = 1000;
    1468           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    1469           0 :         notify.smb2.in.file.handle = h1;
    1470           0 :         notify.smb2.in.recursive = true;
    1471             : 
    1472           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
    1473             : 
    1474           0 :         WAIT_FOR_ASYNC_RESPONSE(req);
    1475             : 
    1476           0 :         status = smb2_logoff(tree1->session);
    1477           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1478             : 
    1479           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1480           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
    1481           0 :         CHECK_VAL(notify.smb2.out.num_changes, 0);
    1482             : 
    1483           0 : done:
    1484           0 :         smb2_deltree(tree1, BASEDIR_NUL);
    1485           0 :         return ret;
    1486             : }
    1487             : 
    1488             : /*
    1489             :   basic testing of change notifies followed by a session reconnect
    1490             : */
    1491             : 
    1492             : #define BASEDIR_NSR BASEDIR "_NSR"
    1493             : 
    1494           0 : static bool torture_smb2_notify_session_reconnect(struct torture_context *torture,
    1495             :                                 struct smb2_tree *tree1)
    1496             : {
    1497           0 :         bool ret = true;
    1498             :         NTSTATUS status;
    1499             :         union smb_notify notify;
    1500             :         union smb_open io;
    1501             :         struct smb2_handle h1;
    1502             :         struct smb2_request *req;
    1503           0 :         uint64_t previous_session_id = 0;
    1504           0 :         struct smb2_session *session2 = NULL;
    1505             : 
    1506           0 :         smb2_deltree(tree1, BASEDIR_NSR);
    1507           0 :         smb2_util_rmdir(tree1, BASEDIR_NSR);
    1508             : 
    1509           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY SESSION RECONNECT\n");
    1510             : 
    1511             :         /*
    1512             :           get a handle on the directory
    1513             :         */
    1514           0 :         ZERO_STRUCT(io.smb2);
    1515           0 :         io.generic.level = RAW_OPEN_SMB2;
    1516           0 :         io.smb2.in.create_flags = 0;
    1517           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    1518           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1519           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1520           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1521             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1522           0 :         io.smb2.in.alloc_size = 0;
    1523           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1524           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1525           0 :         io.smb2.in.security_flags = 0;
    1526           0 :         io.smb2.in.fname = BASEDIR_NSR;
    1527             : 
    1528           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1529           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1530             : 
    1531           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1532           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1533           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1534           0 :         h1 = io.smb2.out.file.handle;
    1535             : 
    1536             :         /* ask for a change notify,
    1537             :            on file or directory name changes */
    1538           0 :         ZERO_STRUCT(notify.smb2);
    1539           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1540           0 :         notify.smb2.in.buffer_size = 1000;
    1541           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    1542           0 :         notify.smb2.in.file.handle = h1;
    1543           0 :         notify.smb2.in.recursive = true;
    1544             : 
    1545           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
    1546             : 
    1547           0 :         WAIT_FOR_ASYNC_RESPONSE(req);
    1548             : 
    1549           0 :         previous_session_id = smb2cli_session_current_id(tree1->session->smbXcli);
    1550           0 :         torture_assert(torture, torture_smb2_session_setup(torture,
    1551             :                        tree1->session->transport,
    1552             :                        previous_session_id,
    1553             :                        torture, &session2),
    1554             :                        "session setup with previous_session_id failed");
    1555             : 
    1556           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1557           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
    1558           0 :         CHECK_VAL(notify.smb2.out.num_changes, 0);
    1559             : 
    1560           0 :         status = smb2_logoff(tree1->session);
    1561           0 :         CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
    1562             : 
    1563           0 :         status = smb2_logoff(session2);
    1564           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1565           0 : done:
    1566           0 :         smb2_deltree(tree1, BASEDIR_NSR);
    1567           0 :         return ret;
    1568             : }
    1569             : 
    1570             : /*
    1571             :   basic testing of change notifies followed by an invalid reauth
    1572             : */
    1573             : 
    1574             : #define BASEDIR_IR BASEDIR "_IR"
    1575             : 
    1576           0 : static bool torture_smb2_notify_invalid_reauth(struct torture_context *torture,
    1577             :                                                struct smb2_tree *tree1,
    1578             :                                                struct smb2_tree *tree2)
    1579             : {
    1580           0 :         bool ret = true;
    1581             :         NTSTATUS status;
    1582             :         union smb_notify notify;
    1583             :         union smb_open io;
    1584             :         struct smb2_handle h1;
    1585             :         struct smb2_request *req;
    1586             :         struct cli_credentials *invalid_creds;
    1587             : 
    1588           0 :         smb2_deltree(tree2, BASEDIR_IR);
    1589           0 :         smb2_util_rmdir(tree2, BASEDIR_IR);
    1590             : 
    1591           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY invalid REAUTH\n");
    1592             : 
    1593             :         /*
    1594             :           get a handle on the directory
    1595             :         */
    1596           0 :         ZERO_STRUCT(io.smb2);
    1597           0 :         io.generic.level = RAW_OPEN_SMB2;
    1598           0 :         io.smb2.in.create_flags = 0;
    1599           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    1600           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1601           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1602           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1603             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1604           0 :         io.smb2.in.alloc_size = 0;
    1605           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1606           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1607           0 :         io.smb2.in.security_flags = 0;
    1608           0 :         io.smb2.in.fname = BASEDIR_IR;
    1609             : 
    1610           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1611           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1612             : 
    1613           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    1614           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1615           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1616           0 :         h1 = io.smb2.out.file.handle;
    1617             : 
    1618             :         /* ask for a change notify,
    1619             :            on file or directory name changes */
    1620           0 :         ZERO_STRUCT(notify.smb2);
    1621           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1622           0 :         notify.smb2.in.buffer_size = 1000;
    1623           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    1624           0 :         notify.smb2.in.file.handle = h1;
    1625           0 :         notify.smb2.in.recursive = true;
    1626             : 
    1627           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
    1628             : 
    1629           0 :         WAIT_FOR_ASYNC_RESPONSE(req);
    1630             : 
    1631           0 :         invalid_creds = cli_credentials_init(torture);
    1632           0 :         torture_assert(torture, (invalid_creds != NULL), "talloc error");
    1633           0 :         cli_credentials_set_username(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
    1634           0 :         cli_credentials_set_domain(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
    1635           0 :         cli_credentials_set_password(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
    1636           0 :         cli_credentials_set_realm(invalid_creds, NULL, CRED_SPECIFIED);
    1637           0 :         cli_credentials_set_workstation(invalid_creds, "", CRED_UNINITIALISED);
    1638             : 
    1639           0 :         status = smb2_session_setup_spnego(tree1->session,
    1640             :                                            invalid_creds,
    1641             :                                            0 /* previous_session_id */);
    1642           0 :         CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
    1643             : 
    1644           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1645           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
    1646           0 :         CHECK_VAL(notify.smb2.out.num_changes, 0);
    1647             : 
    1648             :         /*
    1649             :          * Demonstrate that the session is no longer valid.
    1650             :          */
    1651           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1652           0 :         CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
    1653           0 : done:
    1654           0 :         smb2_deltree(tree2, BASEDIR_IR);
    1655           0 :         return ret;
    1656             : }
    1657             : 
    1658           0 : static void tcp_dis_handler(struct smb2_transport *t, void *p)
    1659             : {
    1660           0 :         struct smb2_tree *tree = (struct smb2_tree *)p;
    1661           0 :         smb2_transport_dead(tree->session->transport,
    1662           0 :                         NT_STATUS_LOCAL_DISCONNECT);
    1663           0 :         t = NULL;
    1664           0 :         tree = NULL;
    1665           0 : }
    1666             : 
    1667             : /*
    1668             :   basic testing of change notifies followed by tcp disconnect
    1669             : */
    1670             : 
    1671             : #define BASEDIR_NTCPD BASEDIR "_NTCPD"
    1672             : 
    1673           0 : static bool torture_smb2_notify_tcp_disconnect(
    1674             :                 struct torture_context *torture,
    1675             :                 struct smb2_tree *tree)
    1676             : {
    1677           0 :         bool ret = true;
    1678             :         NTSTATUS status;
    1679             :         union smb_notify notify;
    1680             :         union smb_open io;
    1681             :         struct smb2_handle h1;
    1682             :         struct smb2_request *req;
    1683             : 
    1684           0 :         smb2_deltree(tree, BASEDIR_NTCPD);
    1685           0 :         smb2_util_rmdir(tree, BASEDIR_NTCPD);
    1686             : 
    1687           0 :         torture_comment(torture,
    1688             :                 "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
    1689             : 
    1690             :         /*
    1691             :           get a handle on the directory
    1692             :         */
    1693           0 :         ZERO_STRUCT(io.smb2);
    1694           0 :         io.generic.level = RAW_OPEN_SMB2;
    1695           0 :         io.smb2.in.create_flags = 0;
    1696           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    1697           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1698           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1699           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1700             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1701           0 :         io.smb2.in.alloc_size = 0;
    1702           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1703           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1704           0 :         io.smb2.in.security_flags = 0;
    1705           0 :         io.smb2.in.fname = BASEDIR_NTCPD;
    1706             : 
    1707           0 :         status = smb2_create(tree, torture, &(io.smb2));
    1708           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1709           0 :         h1 = io.smb2.out.file.handle;
    1710             : 
    1711             :         /* ask for a change notify,
    1712             :            on file or directory name changes */
    1713           0 :         ZERO_STRUCT(notify.smb2);
    1714           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1715           0 :         notify.smb2.in.buffer_size = 1000;
    1716           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    1717           0 :         notify.smb2.in.file.handle = h1;
    1718           0 :         notify.smb2.in.recursive = true;
    1719             : 
    1720           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    1721           0 :         smb2_cancel(req);
    1722           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1723           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
    1724             : 
    1725           0 :         notify.smb2.in.recursive = true;
    1726           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    1727           0 :         smb2_transport_idle_handler(tree->session->transport,
    1728             :                                 tcp_dis_handler, 250000, tree);
    1729           0 :         tree = NULL;
    1730           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    1731           0 :         CHECK_STATUS(status, NT_STATUS_LOCAL_DISCONNECT);
    1732             : 
    1733           0 : done:
    1734           0 :         return ret;
    1735             : }
    1736             : 
    1737             : /*
    1738             :    test setting up two change notify requests on one handle
    1739             : */
    1740             : 
    1741             : #define BASEDIR_NDOH BASEDIR "_NDOH"
    1742             : 
    1743           0 : static bool torture_smb2_notify_double(struct torture_context *torture,
    1744             :                         struct smb2_tree *tree1,
    1745             :                         struct smb2_tree *tree2)
    1746             : {
    1747           0 :         bool ret = true;
    1748             :         NTSTATUS status;
    1749             :         union smb_notify notify;
    1750             :         union smb_open io;
    1751             :         struct smb2_handle h1;
    1752             :         struct smb2_request *req1, *req2;
    1753             : 
    1754           0 :         smb2_deltree(tree1, BASEDIR_NDOH);
    1755           0 :         smb2_util_rmdir(tree1, BASEDIR_NDOH);
    1756             : 
    1757           0 :         torture_comment(torture,
    1758             :                 "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
    1759             : 
    1760             :         /*
    1761             :           get a handle on the directory
    1762             :         */
    1763           0 :         ZERO_STRUCT(io.smb2);
    1764           0 :         io.generic.level = RAW_OPEN_SMB2;
    1765           0 :         io.smb2.in.create_flags = 0;
    1766           0 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ|
    1767             :                                 SEC_RIGHTS_FILE_WRITE|
    1768             :                                 SEC_RIGHTS_FILE_ALL;
    1769           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1770           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1771           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1772             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1773           0 :         io.smb2.in.alloc_size = 0;
    1774           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    1775           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1776           0 :         io.smb2.in.security_flags = 0;
    1777           0 :         io.smb2.in.fname = BASEDIR_NDOH;
    1778             : 
    1779           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    1780           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1781           0 :         h1 = io.smb2.out.file.handle;
    1782             : 
    1783             :         /* ask for a change notify,
    1784             :            on file or directory name changes */
    1785           0 :         ZERO_STRUCT(notify.smb2);
    1786           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1787           0 :         notify.smb2.in.buffer_size = 1000;
    1788           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    1789           0 :         notify.smb2.in.file.handle = h1;
    1790           0 :         notify.smb2.in.recursive = true;
    1791             : 
    1792           0 :         req1 = smb2_notify_send(tree1, &(notify.smb2));
    1793           0 :         smb2_cancel(req1);
    1794           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
    1795           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
    1796             : 
    1797           0 :         req2 = smb2_notify_send(tree1, &(notify.smb2));
    1798           0 :         smb2_cancel(req2);
    1799           0 :         status = smb2_notify_recv(req2, torture, &(notify.smb2));
    1800           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
    1801             : 
    1802           0 :         smb2_util_mkdir(tree2, BASEDIR_NDOH "\\subdir-name");
    1803           0 :         req1 = smb2_notify_send(tree1, &(notify.smb2));
    1804           0 :         req2 = smb2_notify_send(tree1, &(notify.smb2));
    1805             : 
    1806           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
    1807           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1808           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    1809           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
    1810             : 
    1811           0 :         smb2_util_mkdir(tree2, BASEDIR_NDOH "\\subdir-name2");
    1812             : 
    1813           0 :         status = smb2_notify_recv(req2, torture, &(notify.smb2));
    1814           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1815           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    1816           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name2");
    1817             : 
    1818           0 : done:
    1819           0 :         smb2_deltree(tree1, BASEDIR_NDOH);
    1820           0 :         return ret;
    1821             : }
    1822             : 
    1823             : 
    1824             : /*
    1825             :    test multiple change notifies at different depths and with/without recursion
    1826             : */
    1827             : 
    1828             : #define BASEDIR_TREE BASEDIR "_TREE"
    1829             : 
    1830           0 : static bool torture_smb2_notify_tree(struct torture_context *torture,
    1831             :                              struct smb2_tree *tree)
    1832             : {
    1833           0 :         bool ret = true;
    1834             :         union smb_notify notify;
    1835             :         union smb_open io;
    1836             :         struct smb2_request *req;
    1837             :         struct timeval tv;
    1838             :         struct {
    1839             :                 const char *path;
    1840             :                 bool recursive;
    1841             :                 uint32_t filter;
    1842             :                 int expected;
    1843             :                 struct smb2_handle h1;
    1844             :                 int counted;
    1845           0 :         } dirs[] = {
    1846             :                 {
    1847             :                         .path      = BASEDIR_TREE "\\abc",
    1848             :                         .recursive = true,
    1849             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1850             :                         .expected  = 30,
    1851             :                 },
    1852             :                 {
    1853             :                         .path      = BASEDIR_TREE "\\zqy",
    1854             :                         .recursive = true,
    1855             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1856             :                         .expected  = 8,
    1857             :                 },
    1858             :                 {
    1859             :                         .path      = BASEDIR_TREE "\\atsy",
    1860             :                         .recursive = true,
    1861             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1862             :                         .expected  = 4,
    1863             :                 },
    1864             :                 {
    1865             :                         .path      = BASEDIR_TREE "\\abc\\foo",
    1866             :                         .recursive = true,
    1867             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1868             :                         .expected  = 2,
    1869             :                 },
    1870             :                 {
    1871             :                         .path      = BASEDIR_TREE "\\abc\\blah",
    1872             :                         .recursive = true,
    1873             :                         .filter    =  FILE_NOTIFY_CHANGE_NAME,
    1874             :                         .expected  = 13,
    1875             :                 },
    1876             :                 {
    1877             :                         .path      = BASEDIR_TREE "\\abc\\blah",
    1878             :                         .recursive = false,
    1879             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1880             :                         .expected  = 7,
    1881             :                 },
    1882             :                 {
    1883             :                         .path      = BASEDIR_TREE "\\abc\\blah\\a",
    1884             :                         .recursive = true,
    1885             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1886             :                         .expected  = 2,
    1887             :                 },
    1888             :                 {
    1889             :                         .path      = BASEDIR_TREE "\\abc\\blah\\b",
    1890             :                         .recursive = true,
    1891             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1892             :                         .expected  = 2,
    1893             :                 },
    1894             :                 {
    1895             :                         .path      = BASEDIR_TREE "\\abc\\blah\\c",
    1896             :                         .recursive = true,
    1897             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1898             :                         .expected  = 2,
    1899             :                 },
    1900             :                 {
    1901             :                         .path      = BASEDIR_TREE "\\abc\\fooblah",
    1902             :                         .recursive = true,
    1903             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1904             :                         .expected  = 2,
    1905             :                 },
    1906             :                 {
    1907             :                         .path      = BASEDIR_TREE "\\zqy\\xx",
    1908             :                         .recursive = true,
    1909             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1910             :                         .expected  = 2,
    1911             :                 },
    1912             :                 {
    1913             :                         .path      = BASEDIR_TREE "\\zqy\\yyy",
    1914             :                         .recursive = true,
    1915             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1916             :                         .expected  = 2,
    1917             :                 },
    1918             :                 {
    1919             :                         .path      = BASEDIR_TREE "\\zqy\\..",
    1920             :                         .recursive = true,
    1921             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1922             :                         .expected  = 40,
    1923             :                 },
    1924             :                 {
    1925             :                         .path      = BASEDIR_TREE,
    1926             :                         .recursive = true,
    1927             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1928             :                         .expected  = 40,
    1929             :                 },
    1930             :                 {
    1931             :                         .path      = BASEDIR_TREE,
    1932             :                         .recursive = false,
    1933             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1934             :                         .expected  = 6,
    1935             :                 },
    1936             :                 {
    1937             :                         .path      = BASEDIR_TREE "\\atsy",
    1938             :                         .recursive = false,
    1939             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1940             :                         .expected  = 4,
    1941             :                 },
    1942             :                 {
    1943             :                         .path      = BASEDIR_TREE "\\abc",
    1944             :                         .recursive = true,
    1945             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1946             :                         .expected  = 24,
    1947             :                 },
    1948             :                 {
    1949             :                         .path      = BASEDIR_TREE "\\abc",
    1950             :                         .recursive = false,
    1951             :                         .filter    = FILE_NOTIFY_CHANGE_FILE_NAME,
    1952             :                         .expected  = 0,
    1953             :                 },
    1954             :                 {
    1955             :                         .path      = BASEDIR_TREE "\\abc",
    1956             :                         .recursive = true,
    1957             :                         .filter    = FILE_NOTIFY_CHANGE_FILE_NAME,
    1958             :                         .expected  = 0,
    1959             :                 },
    1960             :                 {
    1961             :                         .path      = BASEDIR_TREE "\\abc",
    1962             :                         .recursive = true,
    1963             :                         .filter    = FILE_NOTIFY_CHANGE_NAME,
    1964             :                         .expected  = 24,
    1965             :                 },
    1966             :         };
    1967             :         int i;
    1968             :         NTSTATUS status;
    1969           0 :         bool all_done = false;
    1970             : 
    1971           0 :         smb2_deltree(tree, BASEDIR_TREE);
    1972           0 :         smb2_util_rmdir(tree, BASEDIR_TREE);
    1973             : 
    1974           0 :         torture_comment(torture, "TESTING NOTIFY FOR DIFFERENT DEPTHS\n");
    1975             : 
    1976           0 :         ZERO_STRUCT(io.smb2);
    1977           0 :         io.generic.level = RAW_OPEN_SMB2;
    1978           0 :         io.smb2.in.create_flags = 0;
    1979           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    1980           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    1981           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    1982           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    1983             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    1984           0 :         io.smb2.in.alloc_size = 0;
    1985           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    1986           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    1987           0 :         io.smb2.in.security_flags = 0;
    1988           0 :         io.smb2.in.fname = BASEDIR_TREE;
    1989           0 :         status = smb2_create(tree, torture, &(io.smb2));
    1990           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    1991             : 
    1992           0 :         ZERO_STRUCT(notify.smb2);
    1993           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    1994           0 :         notify.smb2.in.buffer_size = 20000;
    1995             : 
    1996             :         /*
    1997             :           setup the directory tree, and the notify buffer on each directory
    1998             :         */
    1999           0 :         for (i=0;i<ARRAY_SIZE(dirs);i++) {
    2000           0 :                 io.smb2.in.fname = dirs[i].path;
    2001           0 :                 status = smb2_create(tree, torture, &(io.smb2));
    2002           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2003           0 :                 dirs[i].h1 = io.smb2.out.file.handle;
    2004             : 
    2005           0 :                 notify.smb2.in.completion_filter = dirs[i].filter;
    2006           0 :                 notify.smb2.in.file.handle = dirs[i].h1;
    2007           0 :                 notify.smb2.in.recursive = dirs[i].recursive;
    2008           0 :                 req = smb2_notify_send(tree, &(notify.smb2));
    2009           0 :                 smb2_cancel(req);
    2010           0 :                 status = smb2_notify_recv(req, torture, &(notify.smb2));
    2011           0 :                 CHECK_STATUS(status, NT_STATUS_CANCELLED);
    2012             :         }
    2013             : 
    2014             :         /* trigger 2 events in each dir */
    2015           0 :         for (i=0;i<ARRAY_SIZE(dirs);i++) {
    2016           0 :                 char *path = talloc_asprintf(torture, "%s\\test.dir",
    2017             :                                              dirs[i].path);
    2018           0 :                 smb2_util_mkdir(tree, path);
    2019           0 :                 smb2_util_rmdir(tree, path);
    2020           0 :                 talloc_free(path);
    2021             :         }
    2022             : 
    2023             :         /* give a bit of time for the events to propagate */
    2024           0 :         tv = timeval_current();
    2025             : 
    2026             :         do {
    2027             :                 /* count events that have happened in each dir */
    2028           0 :                 for (i=0;i<ARRAY_SIZE(dirs);i++) {
    2029           0 :                         notify.smb2.in.completion_filter = dirs[i].filter;
    2030           0 :                         notify.smb2.in.file.handle = dirs[i].h1;
    2031           0 :                         notify.smb2.in.recursive = dirs[i].recursive;
    2032           0 :                         req = smb2_notify_send(tree, &(notify.smb2));
    2033           0 :                         smb2_cancel(req);
    2034           0 :                         notify.smb2.out.num_changes = 0;
    2035           0 :                         status = smb2_notify_recv(req, torture,
    2036             :                                  &(notify.smb2));
    2037           0 :                         dirs[i].counted += notify.smb2.out.num_changes;
    2038             :                 }
    2039             : 
    2040           0 :                 all_done = true;
    2041             : 
    2042           0 :                 for (i=0;i<ARRAY_SIZE(dirs);i++) {
    2043           0 :                         if (dirs[i].counted != dirs[i].expected) {
    2044           0 :                                 all_done = false;
    2045             :                         }
    2046             :                 }
    2047           0 :         } while (!all_done && timeval_elapsed(&tv) < 20);
    2048             : 
    2049           0 :         torture_comment(torture, "took %.4f seconds to propagate all events\n",
    2050             :                         timeval_elapsed(&tv));
    2051             : 
    2052           0 :         for (i=0;i<ARRAY_SIZE(dirs);i++) {
    2053           0 :                 if (dirs[i].counted != dirs[i].expected) {
    2054           0 :                         torture_comment(torture,
    2055             :                                 "ERROR: i=%d expected %d got %d for '%s'\n",
    2056             :                                 i, dirs[i].expected, dirs[i].counted,
    2057             :                                 dirs[i].path);
    2058           0 :                         ret = false;
    2059             :                 }
    2060             :         }
    2061             : 
    2062             :         /*
    2063             :           run from the back, closing and deleting
    2064             :         */
    2065           0 :         for (i=ARRAY_SIZE(dirs)-1;i>=0;i--) {
    2066           0 :                 smb2_util_close(tree, dirs[i].h1);
    2067           0 :                 smb2_util_rmdir(tree, dirs[i].path);
    2068             :         }
    2069             : 
    2070           0 : done:
    2071           0 :         smb2_deltree(tree, BASEDIR_TREE);
    2072           0 :         smb2_util_rmdir(tree, BASEDIR_TREE);
    2073           0 :         return ret;
    2074             : }
    2075             : 
    2076             : /*
    2077             :    Test response when cached server events exceed single NT NOTFIY response
    2078             :    packet size.
    2079             : */
    2080             : 
    2081             : #define BASEDIR_OVF BASEDIR "_OVF"
    2082             : 
    2083           0 : static bool torture_smb2_notify_overflow(struct torture_context *torture,
    2084             :                                 struct smb2_tree *tree)
    2085             : {
    2086           0 :         bool ret = true;
    2087             :         NTSTATUS status;
    2088             :         union smb_notify notify;
    2089             :         union smb_open io;
    2090             :         struct smb2_handle h1, h2;
    2091           0 :         int count = 100;
    2092             :         struct smb2_request *req1;
    2093             :         int i;
    2094             : 
    2095           0 :         smb2_deltree(tree, BASEDIR_OVF);
    2096           0 :         smb2_util_rmdir(tree, BASEDIR_OVF);
    2097             : 
    2098           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
    2099             : 
    2100             :         /* get a handle on the directory */
    2101           0 :         ZERO_STRUCT(io.smb2);
    2102           0 :         io.generic.level = RAW_OPEN_SMB2;
    2103           0 :         io.smb2.in.create_flags = 0;
    2104           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    2105           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2106           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2107           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2108             :                             NTCREATEX_SHARE_ACCESS_WRITE;
    2109           0 :         io.smb2.in.alloc_size = 0;
    2110           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    2111           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2112           0 :         io.smb2.in.security_flags = 0;
    2113           0 :         io.smb2.in.fname = BASEDIR_OVF;
    2114             : 
    2115           0 :         status = smb2_create(tree, torture, &(io.smb2));
    2116           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2117           0 :         h1 = io.smb2.out.file.handle;
    2118             : 
    2119             :         /* ask for a change notify, on name changes. */
    2120           0 :         ZERO_STRUCT(notify.smb2);
    2121           0 :         notify.smb2.level = RAW_NOTIFY_NTTRANS;
    2122           0 :         notify.smb2.in.buffer_size = 1000;
    2123           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    2124           0 :         notify.smb2.in.file.handle = h1;
    2125             : 
    2126           0 :         notify.smb2.in.recursive = true;
    2127           0 :         req1 = smb2_notify_send(tree, &(notify.smb2));
    2128             : 
    2129             :         /* cancel initial requests so the buffer is setup */
    2130           0 :         smb2_cancel(req1);
    2131           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
    2132           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
    2133             : 
    2134             :         /* open a lot of files, filling up the server side notify buffer */
    2135           0 :         torture_comment(torture,
    2136             :                 "Testing overflowed buffer notify on create of %d files\n",
    2137             :                 count);
    2138             : 
    2139           0 :         for (i=0;i<count;i++) {
    2140           0 :                 char *fname = talloc_asprintf(torture,
    2141             :                               BASEDIR_OVF "\\test%d.txt", i);
    2142             :                 union smb_open io1;
    2143           0 :                 ZERO_STRUCT(io1.smb2);
    2144           0 :                 io1.generic.level = RAW_OPEN_SMB2;
    2145           0 :                 io1.smb2.in.create_flags = 0;
    2146           0 :                 io1.smb2.in.desired_access = SEC_FILE_ALL;
    2147           0 :                 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2148           0 :                 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2149           0 :                 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2150             :                                     NTCREATEX_SHARE_ACCESS_WRITE;
    2151           0 :                 io1.smb2.in.alloc_size = 0;
    2152           0 :                 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    2153           0 :                 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2154           0 :                 io1.smb2.in.security_flags = 0;
    2155           0 :                 io1.smb2.in.fname = fname;
    2156             : 
    2157           0 :                 h2 = custom_smb2_create(tree, torture, &(io1.smb2));
    2158           0 :                 talloc_free(fname);
    2159           0 :                 smb2_util_close(tree, h2);
    2160             :         }
    2161             : 
    2162           0 :         req1 = smb2_notify_send(tree, &(notify.smb2));
    2163           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
    2164           0 :         CHECK_STATUS(status, NT_STATUS_NOTIFY_ENUM_DIR);
    2165           0 :         CHECK_VAL(notify.smb2.out.num_changes, 0);
    2166             : 
    2167           0 : done:
    2168           0 :         smb2_deltree(tree, BASEDIR_OVF);
    2169           0 :         return ret;
    2170             : }
    2171             : 
    2172             : /*
    2173             :    Test if notifications are returned for changes to the base directory.
    2174             :    They shouldn't be.
    2175             : */
    2176             : 
    2177             : #define BASEDIR_BAS BASEDIR "_BAS"
    2178             : 
    2179           0 : static bool torture_smb2_notify_basedir(struct torture_context *torture,
    2180             :                                 struct smb2_tree *tree1,
    2181             :                                 struct smb2_tree *tree2)
    2182             : {
    2183           0 :         bool ret = true;
    2184             :         NTSTATUS status;
    2185             :         union smb_notify notify;
    2186             :         union smb_open io;
    2187             :         struct smb2_handle h1;
    2188             :         struct smb2_request *req1;
    2189             : 
    2190           0 :         smb2_deltree(tree1, BASEDIR_BAS);
    2191           0 :         smb2_util_rmdir(tree1, BASEDIR_BAS);
    2192             : 
    2193           0 :         torture_comment(torture, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
    2194             : 
    2195             :         /* get a handle on the directory */
    2196           0 :         ZERO_STRUCT(io.smb2);
    2197           0 :         io.generic.level = RAW_OPEN_SMB2;
    2198           0 :         io.smb2.in.create_flags = 0;
    2199           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    2200           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2201           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2202           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2203             :             NTCREATEX_SHARE_ACCESS_WRITE;
    2204           0 :         io.smb2.in.alloc_size = 0;
    2205           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2206           0 :         io.smb2.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
    2207           0 :         io.smb2.in.security_flags = 0;
    2208           0 :         io.smb2.in.fname = BASEDIR_BAS;
    2209             : 
    2210           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    2211           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2212           0 :         h1 = io.smb2.out.file.handle;
    2213             : 
    2214             :         /* create a test file that will also be modified */
    2215           0 :         io.smb2.in.fname = BASEDIR_BAS "\\tname1";
    2216           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
    2217           0 :         status =  smb2_create(tree2, torture, &(io.smb2));
    2218           0 :         CHECK_STATUS(status,NT_STATUS_OK);
    2219           0 :         smb2_util_close(tree2, io.smb2.out.file.handle);
    2220             : 
    2221             :         /* ask for a change notify, on attribute changes. */
    2222           0 :         ZERO_STRUCT(notify.smb2);
    2223           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    2224           0 :         notify.smb2.in.buffer_size = 1000;
    2225           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
    2226           0 :         notify.smb2.in.file.handle = h1;
    2227           0 :         notify.smb2.in.recursive = true;
    2228             : 
    2229           0 :         req1 = smb2_notify_send(tree1, &(notify.smb2));
    2230             : 
    2231             :         /* set attribute on the base dir */
    2232           0 :         smb2_util_setatr(tree2, BASEDIR_BAS, FILE_ATTRIBUTE_HIDDEN);
    2233             : 
    2234             :         /* set attribute on a file to assure we receive a notification */
    2235           0 :         smb2_util_setatr(tree2, BASEDIR_BAS "\\tname1", FILE_ATTRIBUTE_HIDDEN);
    2236           0 :         smb_msleep(200);
    2237             : 
    2238             :         /* check how many responses were given, expect only 1 for the file */
    2239           0 :         status = smb2_notify_recv(req1, torture, &(notify.smb2));
    2240           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2241           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    2242           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
    2243           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "tname1");
    2244             : 
    2245           0 : done:
    2246           0 :         smb2_deltree(tree1, BASEDIR_BAS);
    2247           0 :         return ret;
    2248             : }
    2249             : 
    2250             : /*
    2251             :    very simple change notify test
    2252             : */
    2253             : 
    2254             : #define BASEDIR_TCON BASEDIR "_TCON"
    2255             : 
    2256           0 : static bool torture_smb2_notify_tcon(struct torture_context *torture,
    2257             :                                   struct smb2_tree *tree)
    2258             : {
    2259           0 :         bool ret = true;
    2260             :         NTSTATUS status;
    2261             :         union smb_notify notify;
    2262             :         union smb_open io;
    2263           0 :         struct smb2_handle h1 = {{0}};
    2264           0 :         struct smb2_request *req = NULL;
    2265           0 :         struct smb2_tree *tree1 = NULL;
    2266           0 :         const char *fname = BASEDIR_TCON "\\subdir-name";
    2267             : 
    2268           0 :         smb2_deltree(tree, BASEDIR_TCON);
    2269           0 :         smb2_util_rmdir(tree, BASEDIR_TCON);
    2270             : 
    2271           0 :         torture_comment(torture, "TESTING SIMPLE CHANGE NOTIFY\n");
    2272             : 
    2273             :         /*
    2274             :           get a handle on the directory
    2275             :         */
    2276             : 
    2277           0 :         ZERO_STRUCT(io.smb2);
    2278           0 :         io.generic.level = RAW_OPEN_SMB2;
    2279           0 :         io.smb2.in.create_flags = 0;
    2280           0 :         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    2281           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2282           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL |
    2283             :                                 FILE_ATTRIBUTE_DIRECTORY;
    2284           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2285             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    2286           0 :         io.smb2.in.alloc_size = 0;
    2287           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2288           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2289           0 :         io.smb2.in.security_flags = 0;
    2290           0 :         io.smb2.in.fname = BASEDIR_TCON;
    2291             : 
    2292           0 :         status = smb2_create(tree, torture, &(io.smb2));
    2293           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2294           0 :         h1 = io.smb2.out.file.handle;
    2295             : 
    2296             :         /* ask for a change notify,
    2297             :            on file or directory name changes */
    2298           0 :         ZERO_STRUCT(notify.smb2);
    2299           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    2300           0 :         notify.smb2.in.buffer_size = 1000;
    2301           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    2302           0 :         notify.smb2.in.file.handle = h1;
    2303           0 :         notify.smb2.in.recursive = true;
    2304             : 
    2305           0 :         torture_comment(torture, "Testing notify mkdir\n");
    2306           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    2307           0 :         smb2_cancel(req);
    2308           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    2309           0 :         CHECK_STATUS(status, NT_STATUS_CANCELLED);
    2310             : 
    2311           0 :         notify.smb2.in.recursive = true;
    2312           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    2313           0 :         status = smb2_util_mkdir(tree, fname);
    2314           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2315             : 
    2316           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    2317           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2318             : 
    2319           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    2320           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
    2321           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
    2322             : 
    2323           0 :         torture_comment(torture, "Testing notify rmdir\n");
    2324           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    2325           0 :         status = smb2_util_rmdir(tree, fname);
    2326           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2327             : 
    2328           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    2329           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2330           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    2331           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
    2332           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
    2333             : 
    2334           0 :         torture_comment(torture, "SIMPLE CHANGE NOTIFY OK\n");
    2335             : 
    2336           0 :         torture_comment(torture, "TESTING WITH SECONDARY TCON\n");
    2337           0 :         if (!torture_smb2_tree_connect(torture, tree->session, tree, &tree1)) {
    2338           0 :                 torture_warning(torture, "couldn't reconnect to share, bailing\n");
    2339           0 :                 ret = false;
    2340           0 :                 goto done;
    2341             :         }
    2342             : 
    2343           0 :         torture_comment(torture, "tid1=%d tid2=%d\n",
    2344             :                         smb2cli_tcon_current_id(tree->smbXcli),
    2345           0 :                         smb2cli_tcon_current_id(tree1->smbXcli));
    2346             : 
    2347           0 :         torture_comment(torture, "Testing notify mkdir\n");
    2348           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    2349           0 :         smb2_util_mkdir(tree1, fname);
    2350             : 
    2351           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    2352           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2353             : 
    2354           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    2355           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
    2356           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
    2357             : 
    2358           0 :         torture_comment(torture, "Testing notify rmdir\n");
    2359           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    2360           0 :         smb2_util_rmdir(tree, fname);
    2361             : 
    2362           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    2363           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2364           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    2365           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
    2366           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
    2367             : 
    2368           0 :         torture_comment(torture, "CHANGE NOTIFY WITH TCON OK\n");
    2369             : 
    2370           0 :         torture_comment(torture, "Disconnecting secondary tree\n");
    2371           0 :         status = smb2_tdis(tree1);
    2372           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2373           0 :         talloc_free(tree1);
    2374             : 
    2375           0 :         torture_comment(torture, "Testing notify mkdir\n");
    2376           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    2377           0 :         smb2_util_mkdir(tree, fname);
    2378             : 
    2379           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    2380           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2381             : 
    2382           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    2383           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
    2384           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
    2385             : 
    2386           0 :         torture_comment(torture, "Testing notify rmdir\n");
    2387           0 :         req = smb2_notify_send(tree, &(notify.smb2));
    2388           0 :         smb2_util_rmdir(tree, fname);
    2389             : 
    2390           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    2391           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2392           0 :         CHECK_VAL(notify.smb2.out.num_changes, 1);
    2393           0 :         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
    2394           0 :         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
    2395             : 
    2396           0 :         torture_comment(torture, "CHANGE NOTIFY WITH TDIS OK\n");
    2397           0 : done:
    2398           0 :         smb2_util_close(tree, h1);
    2399           0 :         smb2_deltree(tree, BASEDIR_TCON);
    2400             : 
    2401           0 :         return ret;
    2402             : }
    2403             : 
    2404             : #define BASEDIR_RMD BASEDIR "_RMD"
    2405             : 
    2406           0 : static bool torture_smb2_notify_rmdir(struct torture_context *torture,
    2407             :                                       struct smb2_tree *tree1,
    2408             :                                       struct smb2_tree *tree2,
    2409             :                                       bool initial_delete_on_close)
    2410             : {
    2411           0 :         bool ret = true;
    2412             :         NTSTATUS status;
    2413           0 :         union smb_notify notify = {};
    2414           0 :         union smb_setfileinfo sfinfo = {};
    2415           0 :         union smb_open io = {};
    2416           0 :         struct smb2_handle h = {};
    2417             :         struct smb2_request *req;
    2418             : 
    2419           0 :         torture_comment(torture, "TESTING NOTIFY CANCEL FOR DELETED DIR\n");
    2420             : 
    2421           0 :         smb2_deltree(tree1, BASEDIR_RMD);
    2422           0 :         smb2_util_rmdir(tree1, BASEDIR_RMD);
    2423             : 
    2424           0 :         ZERO_STRUCT(io.smb2);
    2425           0 :         io.generic.level = RAW_OPEN_SMB2;
    2426           0 :         io.smb2.in.create_flags = 0;
    2427           0 :         io.smb2.in.desired_access = SEC_FILE_ALL;
    2428           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2429           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2430           0 :         io.smb2.in.share_access =
    2431             :                 NTCREATEX_SHARE_ACCESS_READ |
    2432             :                 NTCREATEX_SHARE_ACCESS_WRITE |
    2433             :                 NTCREATEX_SHARE_ACCESS_DELETE ;
    2434           0 :         io.smb2.in.alloc_size = 0;
    2435           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    2436           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2437           0 :         io.smb2.in.security_flags = 0;
    2438           0 :         io.smb2.in.fname = BASEDIR_RMD;
    2439             : 
    2440           0 :         status = smb2_create(tree1, torture, &(io.smb2));
    2441           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2442           0 :         h = io.smb2.out.file.handle;
    2443             : 
    2444           0 :         ZERO_STRUCT(notify.smb2);
    2445           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    2446           0 :         notify.smb2.in.buffer_size = 1000;
    2447           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    2448           0 :         notify.smb2.in.file.handle = h;
    2449           0 :         notify.smb2.in.recursive = false;
    2450             : 
    2451           0 :         io.smb2.in.desired_access |= SEC_STD_DELETE;
    2452           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    2453           0 :         req = smb2_notify_send(tree1, &(notify.smb2));
    2454             : 
    2455           0 :         if (initial_delete_on_close) {
    2456           0 :                 status = smb2_util_rmdir(tree2, BASEDIR_RMD);
    2457           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2458             :         } else {
    2459           0 :                 status = smb2_create(tree2, torture, &(io.smb2));
    2460           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2461             : 
    2462           0 :                 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
    2463           0 :                 sfinfo.generic.in.file.handle = io.smb2.out.file.handle;
    2464           0 :                 sfinfo.disposition_info.in.delete_on_close = 1;
    2465           0 :                 status = smb2_setinfo_file(tree2, &sfinfo);
    2466           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
    2467             : 
    2468           0 :                 smb2_util_close(tree2, io.smb2.out.file.handle);
    2469             :         }
    2470             : 
    2471           0 :         status = smb2_notify_recv(req, torture, &(notify.smb2));
    2472           0 :         CHECK_STATUS(status, NT_STATUS_DELETE_PENDING);
    2473             : 
    2474           0 : done:
    2475             : 
    2476           0 :         smb2_util_close(tree1, h);
    2477           0 :         smb2_deltree(tree1, BASEDIR_RMD);
    2478             : 
    2479           0 :         return ret;
    2480             : }
    2481             : 
    2482           0 : static bool torture_smb2_notify_rmdir1(struct torture_context *torture,
    2483             :                                        struct smb2_tree *tree)
    2484             : {
    2485           0 :         return torture_smb2_notify_rmdir(torture, tree, tree, false);
    2486             : }
    2487             : 
    2488           0 : static bool torture_smb2_notify_rmdir2(struct torture_context *torture,
    2489             :                                        struct smb2_tree *tree)
    2490             : {
    2491           0 :         return torture_smb2_notify_rmdir(torture, tree, tree, true);
    2492             : }
    2493             : 
    2494           0 : static bool torture_smb2_notify_rmdir3(struct torture_context *torture,
    2495             :                                        struct smb2_tree *tree1,
    2496             :                                        struct smb2_tree *tree2)
    2497             : {
    2498           0 :         return torture_smb2_notify_rmdir(torture, tree1, tree2, false);
    2499             : }
    2500             : 
    2501           0 : static bool torture_smb2_notify_rmdir4(struct torture_context *torture,
    2502             :                                        struct smb2_tree *tree1,
    2503             :                                        struct smb2_tree *tree2)
    2504             : {
    2505           0 :         return torture_smb2_notify_rmdir(torture, tree1, tree2, true);
    2506             : }
    2507             : 
    2508           0 : static void notify_timeout(struct tevent_context *ev,
    2509             :                            struct tevent_timer *te,
    2510             :                            struct timeval current_time,
    2511             :                            void *private_data)
    2512             : {
    2513           0 :         struct smb2_request *req = talloc_get_type_abort(
    2514             :                 private_data, struct smb2_request);
    2515             : 
    2516           0 :         smb2_cancel(req);
    2517           0 : }
    2518             : 
    2519             : #define BASEDIR_INR BASEDIR "_INR"
    2520             : 
    2521           0 : static bool torture_smb2_inotify_rename(struct torture_context *torture,
    2522             :                                         struct smb2_tree *tree1,
    2523             :                                         struct smb2_tree *tree2)
    2524             : {
    2525             :         NTSTATUS status;
    2526             :         struct smb2_notify notify;
    2527           0 :         struct notify_changes change1 = {0};
    2528           0 :         struct notify_changes change2 = {0};
    2529             :         struct smb2_create create;
    2530             :         union smb_setfileinfo sinfo;
    2531           0 :         struct smb2_handle h1 = {{0}};
    2532           0 :         struct smb2_handle h2 = {{0}};
    2533             :         struct smb2_request *req;
    2534           0 :         struct tevent_timer *te = NULL;
    2535           0 :         bool ok = false;
    2536             : 
    2537           0 :         smb2_deltree(tree1, BASEDIR_INR);
    2538             : 
    2539           0 :         torture_comment(torture, "Testing change notify of a rename with inotify\n");
    2540             : 
    2541           0 :         status = torture_smb2_testdir(tree1, BASEDIR_INR, &h1);
    2542           0 :         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "torture_smb2_testdir failed");
    2543             : 
    2544           0 :         ZERO_STRUCT(create);
    2545           0 :         create.in.desired_access = SEC_RIGHTS_FILE_READ |
    2546             :                 SEC_RIGHTS_FILE_WRITE|
    2547             :                 SEC_RIGHTS_FILE_ALL;
    2548           0 :         create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2549           0 :         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2550           0 :         create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2551             :                 NTCREATEX_SHARE_ACCESS_WRITE |
    2552             :                 NTCREATEX_SHARE_ACCESS_DELETE;
    2553           0 :         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    2554           0 :         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2555           0 :         create.in.fname = BASEDIR_INR "\\subdir-name";
    2556             : 
    2557           0 :         status = smb2_create(tree2, torture, &create);
    2558           0 :         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_create failed\n");
    2559           0 :         h2 = create.out.file.handle;
    2560             : 
    2561           0 :         ZERO_STRUCT(notify);
    2562           0 :         notify.level = RAW_NOTIFY_SMB2;
    2563           0 :         notify.in.buffer_size = 4096;
    2564           0 :         notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    2565           0 :         notify.in.file.handle = h1;
    2566           0 :         notify.in.recursive = true;
    2567           0 :         req = smb2_notify_send(tree1, &notify);
    2568           0 :         torture_assert_not_null_goto(torture, req, ok, done, "smb2_notify_send failed\n");
    2569             : 
    2570           0 :         while (!NT_STATUS_EQUAL(req->status, NT_STATUS_PENDING)) {
    2571           0 :                 if (tevent_loop_once(torture->ev) != 0) {
    2572           0 :                         goto done;
    2573             :                 }
    2574             :         }
    2575             : 
    2576           0 :         ZERO_STRUCT(sinfo);
    2577           0 :         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
    2578           0 :         sinfo.rename_information.in.file.handle = h2;
    2579           0 :         sinfo.rename_information.in.new_name = BASEDIR_INR "\\subdir-name-r";
    2580             : 
    2581           0 :         status = smb2_setinfo_file(tree2, &sinfo);
    2582           0 :         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_setinfo_file failed\n");
    2583             : 
    2584           0 :         smb2_util_close(tree2, h2);
    2585             : 
    2586           0 :         te = tevent_add_timer(torture->ev,
    2587             :                               tree1,
    2588             :                               tevent_timeval_current_ofs(1, 0),
    2589             :                               notify_timeout,
    2590             :                               req);
    2591           0 :         torture_assert_not_null_goto(torture, te, ok, done, "tevent_add_timer failed\n");
    2592             : 
    2593           0 :         status = smb2_notify_recv(req, torture, &notify);
    2594           0 :         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_notify_recv failed\n");
    2595             : 
    2596           0 :         torture_assert_goto(torture, notify.out.num_changes == 1 || notify.out.num_changes == 2,
    2597             :                             ok, done, "bad notify\n");
    2598             : 
    2599           0 :         change1 = notify.out.changes[0];
    2600           0 :         if (notify.out.num_changes == 2) {
    2601           0 :                 change2 = notify.out.changes[1];
    2602             :         } else {
    2603             :                 /*
    2604             :                  * We may only get one event at a time, so check for the
    2605             :                  * matching second event for the oldname/newname or
    2606             :                  * removed/added pair.
    2607             :                  */
    2608           0 :                 ZERO_STRUCT(notify);
    2609           0 :                 notify.level = RAW_NOTIFY_SMB2;
    2610           0 :                 notify.in.buffer_size = 4096;
    2611           0 :                 notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    2612           0 :                 notify.in.file.handle = h1;
    2613           0 :                 notify.in.recursive = true;
    2614           0 :                 req = smb2_notify_send(tree1, &notify);
    2615           0 :                 torture_assert_not_null_goto(torture, req, ok, done, "smb2_notify_send failed\n");
    2616             : 
    2617           0 :                 status = smb2_notify_recv(req, torture, &notify);
    2618           0 :                 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_notify_recv failed\n");
    2619             : 
    2620           0 :                 torture_assert_goto(torture, notify.out.num_changes == 1, ok, done,
    2621             :                                     "bad notify\n");
    2622             : 
    2623           0 :                 change2 = notify.out.changes[0];
    2624             :         }
    2625             : 
    2626           0 :         if ((change1.action != NOTIFY_ACTION_OLD_NAME) &&
    2627           0 :             (change1.action != NOTIFY_ACTION_REMOVED))
    2628             :         {
    2629           0 :                 torture_fail_goto(torture, done, "bad change notification\n");
    2630             :         }
    2631           0 :         torture_assert_str_equal_goto(torture, change1.name.s, "subdir-name",
    2632             :                             ok, done, "bad change notification\n");
    2633             : 
    2634           0 :         if ((change2.action != NOTIFY_ACTION_NEW_NAME) &&
    2635           0 :             (change2.action != NOTIFY_ACTION_ADDED))
    2636             :         {
    2637           0 :                 torture_fail_goto(torture, done, "bad change notification\n");
    2638             :         }
    2639           0 :         torture_assert_str_equal_goto(torture, change2.name.s, "subdir-name-r",
    2640             :                             ok, done, "bad change notification\n");
    2641             : 
    2642           0 :         ok = true;
    2643           0 : done:
    2644           0 :         if (!smb2_util_handle_empty(h1)) {
    2645           0 :                 smb2_util_close(tree1, h1);
    2646             :         }
    2647           0 :         if (!smb2_util_handle_empty(h2)) {
    2648           0 :                 smb2_util_close(tree2, h2);
    2649             :         }
    2650             : 
    2651           0 :         smb2_deltree(tree1, BASEDIR_INR);
    2652           0 :         return ok;
    2653             : }
    2654             : 
    2655             : /*
    2656             :   Test asking for a change notify on a handle without permissions.
    2657             : */
    2658             : 
    2659             : #define BASEDIR_HPERM BASEDIR "_HPERM"
    2660             : 
    2661           0 : static bool torture_smb2_notify_handle_permissions(
    2662             :                 struct torture_context *torture,
    2663             :                 struct smb2_tree *tree)
    2664             : {
    2665           0 :         bool ret = true;
    2666             :         NTSTATUS status;
    2667             :         union smb_notify notify;
    2668             :         union smb_open io;
    2669           0 :         struct smb2_handle h1 = {{0}};
    2670             :         struct smb2_request *req;
    2671             : 
    2672           0 :         smb2_deltree(tree, BASEDIR_HPERM);
    2673           0 :         smb2_util_rmdir(tree, BASEDIR_HPERM);
    2674             : 
    2675           0 :         torture_comment(torture,
    2676             :                 "TESTING CHANGE NOTIFY "
    2677             :                 "ON A HANDLE WITHOUT PERMISSIONS\n");
    2678             : 
    2679             :         /*
    2680             :           get a handle on the directory
    2681             :         */
    2682           0 :         ZERO_STRUCT(io.smb2);
    2683           0 :         io.generic.level = RAW_OPEN_SMB2;
    2684           0 :         io.smb2.in.create_flags = 0;
    2685           0 :         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
    2686           0 :         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    2687           0 :         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    2688           0 :         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
    2689             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
    2690           0 :         io.smb2.in.alloc_size = 0;
    2691           0 :         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    2692           0 :         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    2693           0 :         io.smb2.in.security_flags = 0;
    2694           0 :         io.smb2.in.fname = BASEDIR_HPERM;
    2695             : 
    2696           0 :         status = smb2_create(tree, torture, &io.smb2);
    2697           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2698           0 :         h1 = io.smb2.out.file.handle;
    2699             : 
    2700             :         /* ask for a change notify,
    2701             :            on file or directory name changes */
    2702           0 :         ZERO_STRUCT(notify.smb2);
    2703           0 :         notify.smb2.level = RAW_NOTIFY_SMB2;
    2704           0 :         notify.smb2.in.buffer_size = 1000;
    2705           0 :         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
    2706           0 :         notify.smb2.in.file.handle = h1;
    2707           0 :         notify.smb2.in.recursive = true;
    2708             : 
    2709           0 :         req = smb2_notify_send(tree, &notify.smb2);
    2710           0 :         torture_assert_goto(torture,
    2711             :                         req != NULL,
    2712             :                         ret,
    2713             :                         done,
    2714             :                         "smb2_notify_send failed\n");
    2715             : 
    2716             :         /*
    2717             :          * Cancel it, we don't really want to wait.
    2718             :          */
    2719           0 :         smb2_cancel(req);
    2720           0 :         status = smb2_notify_recv(req, torture, &notify.smb2);
    2721             :         /* Handle h1 doesn't have permissions for ChangeNotify. */
    2722           0 :         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    2723             : 
    2724           0 : done:
    2725           0 :         if (!smb2_util_handle_empty(h1)) {
    2726           0 :                 smb2_util_close(tree, h1);
    2727             :         }
    2728           0 :         smb2_deltree(tree, BASEDIR_HPERM);
    2729           0 :         return ret;
    2730             : }
    2731             : 
    2732             : /*
    2733             :    basic testing of SMB2 change notify
    2734             : */
    2735         964 : struct torture_suite *torture_smb2_notify_init(TALLOC_CTX *ctx)
    2736             : {
    2737         964 :         struct torture_suite *suite = torture_suite_create(ctx, "notify");
    2738             : 
    2739         964 :         torture_suite_add_1smb2_test(suite, "valid-req", test_valid_request);
    2740         964 :         torture_suite_add_1smb2_test(suite, "tcon", torture_smb2_notify_tcon);
    2741         964 :         torture_suite_add_2smb2_test(suite, "dir", torture_smb2_notify_dir);
    2742         964 :         torture_suite_add_2smb2_test(suite, "mask", torture_smb2_notify_mask);
    2743         964 :         torture_suite_add_1smb2_test(suite, "tdis", torture_smb2_notify_tree_disconnect);
    2744         964 :         torture_suite_add_1smb2_test(suite, "tdis1", torture_smb2_notify_tree_disconnect_1);
    2745         964 :         torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
    2746         964 :         torture_suite_add_1smb2_test(suite, "close", torture_smb2_notify_close);
    2747         964 :         torture_suite_add_1smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
    2748         964 :         torture_suite_add_1smb2_test(suite, "session-reconnect", torture_smb2_notify_session_reconnect);
    2749         964 :         torture_suite_add_2smb2_test(suite, "invalid-reauth", torture_smb2_notify_invalid_reauth);
    2750         964 :         torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
    2751         964 :         torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
    2752         964 :         torture_suite_add_2smb2_test(suite, "double", torture_smb2_notify_double);
    2753         964 :         torture_suite_add_1smb2_test(suite, "file", torture_smb2_notify_file);
    2754         964 :         torture_suite_add_1smb2_test(suite, "tcp", torture_smb2_notify_tcp_disconnect);
    2755         964 :         torture_suite_add_2smb2_test(suite, "rec", torture_smb2_notify_recursive);
    2756         964 :         torture_suite_add_1smb2_test(suite, "overflow", torture_smb2_notify_overflow);
    2757         964 :         torture_suite_add_1smb2_test(suite, "rmdir1",
    2758             :                                      torture_smb2_notify_rmdir1);
    2759         964 :         torture_suite_add_1smb2_test(suite, "rmdir2",
    2760             :                                      torture_smb2_notify_rmdir2);
    2761         964 :         torture_suite_add_2smb2_test(suite, "rmdir3",
    2762             :                                      torture_smb2_notify_rmdir3);
    2763         964 :         torture_suite_add_2smb2_test(suite, "rmdir4",
    2764             :                                      torture_smb2_notify_rmdir4);
    2765         964 :         torture_suite_add_1smb2_test(suite,
    2766             :                                     "handle-permissions",
    2767             :                                     torture_smb2_notify_handle_permissions);
    2768             : 
    2769         964 :         suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests");
    2770             : 
    2771         964 :         return suite;
    2772             : }
    2773             : 
    2774             : /*
    2775             :    basic testing of SMB2 change notify
    2776             : */
    2777         964 : struct torture_suite *torture_smb2_notify_inotify_init(TALLOC_CTX *ctx)
    2778             : {
    2779         964 :         struct torture_suite *suite = torture_suite_create(ctx, "notify-inotify");
    2780             : 
    2781         964 :         suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests that use inotify");
    2782             : 
    2783         964 :         torture_suite_add_2smb2_test(suite, "inotify-rename", torture_smb2_inotify_rename);
    2784             : 
    2785         964 :         return suite;
    2786             : }

Generated by: LCOV version 1.13