ctdb/docs: Include ceph rados namespace support in man page
[Samba.git] / source4 / torture / smb2 / notify.c
blob0aadc50c6077dee55711b2363aed2be5504310cc
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 notify test suite
6 Copyright (C) Stefan Metzmacher 2006
7 Copyright (C) Andrew Tridgell 2009
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.
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.
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/>.
23 #include "includes.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "../libcli/smb/smbXcli_base.h"
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"
34 #include "system/filesys.h"
35 #include "auth/credentials/credentials.h"
36 #include "lib/cmdline/cmdline.h"
37 #include "librpc/gen_ndr/security.h"
39 #include "lib/events/events.h"
41 #include "libcli/raw/libcliraw.h"
42 #include "libcli/raw/raw_proto.h"
43 #include "libcli/libcli.h"
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)
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)
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)
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 } \
79 #define BASEDIR "test_notify"
80 #define FNAME "smb2-notify01.dat"
82 static bool test_valid_request(struct torture_context *torture,
83 struct smb2_tree *tree)
85 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;
92 torture_comment(torture, "TESTING VALIDITY OF CHANGE NOTIFY REQUEST\n");
94 smb2_transport_credits_ask_num(tree->session->transport, 256);
96 smb2_util_unlink(tree, FNAME);
98 status = smb2_util_roothandle(tree, &dh);
99 CHECK_STATUS(status, NT_STATUS_OK);
101 max_buffer_size =
102 smb2cli_conn_max_trans_size(tree->session->transport->conn);
104 n.in.recursive = 0x0000;
105 n.in.buffer_size = max_buffer_size;
106 n.in.file.handle = dh;
107 n.in.completion_filter = FILE_NOTIFY_CHANGE_ALL;
108 n.in.unknown = 0x00000000;
109 req = smb2_notify_send(tree, &n);
111 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
112 if (tevent_loop_once(torture->ev) != 0) {
113 break;
117 status = torture_setup_simple_file(torture, tree, FNAME);
118 CHECK_STATUS(status, NT_STATUS_OK);
120 status = smb2_notify_recv(req, torture, &n);
121 CHECK_STATUS(status, NT_STATUS_OK);
122 CHECK_VAL(n.out.num_changes, 1);
123 CHECK_VAL(n.out.changes[0].action, NOTIFY_ACTION_ADDED);
124 CHECK_WIRE_STR(n.out.changes[0].name, FNAME);
127 * if the change response doesn't fit in the buffer
128 * NOTIFY_ENUM_DIR is returned.
130 n.in.buffer_size = 0x00000000;
131 req = smb2_notify_send(tree, &n);
133 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
134 if (tevent_loop_once(torture->ev) != 0) {
135 break;
139 status = torture_setup_simple_file(torture, tree, FNAME);
140 CHECK_STATUS(status, NT_STATUS_OK);
142 status = smb2_notify_recv(req, torture, &n);
143 CHECK_STATUS(status, NT_STATUS_NOTIFY_ENUM_DIR);
146 * if the change response fits in the buffer we get
147 * NT_STATUS_OK again
149 n.in.buffer_size = max_buffer_size;
150 req = smb2_notify_send(tree, &n);
152 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
153 if (tevent_loop_once(torture->ev) != 0) {
154 break;
158 status = torture_setup_simple_file(torture, tree, FNAME);
159 CHECK_STATUS(status, NT_STATUS_OK);
161 status = smb2_notify_recv(req, torture, &n);
162 CHECK_STATUS(status, NT_STATUS_OK);
163 CHECK_VAL(n.out.num_changes, 3);
164 CHECK_VAL(n.out.changes[0].action, NOTIFY_ACTION_REMOVED);
165 CHECK_WIRE_STR(n.out.changes[0].name, FNAME);
166 CHECK_VAL(n.out.changes[1].action, NOTIFY_ACTION_ADDED);
167 CHECK_WIRE_STR(n.out.changes[1].name, FNAME);
168 CHECK_VAL(n.out.changes[2].action, NOTIFY_ACTION_MODIFIED);
169 CHECK_WIRE_STR(n.out.changes[2].name, FNAME);
171 /* if the first notify returns NOTIFY_ENUM_DIR, all do */
172 status = smb2_util_close(tree, dh);
173 CHECK_STATUS(status, NT_STATUS_OK);
174 status = smb2_util_roothandle(tree, &dh);
175 CHECK_STATUS(status, NT_STATUS_OK);
177 n.in.recursive = 0x0000;
178 n.in.buffer_size = 0x00000001;
179 n.in.file.handle = dh;
180 n.in.completion_filter = FILE_NOTIFY_CHANGE_ALL;
181 n.in.unknown = 0x00000000;
182 req = smb2_notify_send(tree, &n);
184 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
185 if (tevent_loop_once(torture->ev) != 0) {
186 break;
190 status = torture_setup_simple_file(torture, tree, FNAME);
191 CHECK_STATUS(status, NT_STATUS_OK);
193 status = smb2_notify_recv(req, torture, &n);
194 CHECK_STATUS(status, NT_STATUS_NOTIFY_ENUM_DIR);
196 n.in.buffer_size = max_buffer_size;
197 req = smb2_notify_send(tree, &n);
198 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
199 if (tevent_loop_once(torture->ev) != 0) {
200 break;
204 status = torture_setup_simple_file(torture, tree, FNAME);
205 CHECK_STATUS(status, NT_STATUS_OK);
207 status = smb2_notify_recv(req, torture, &n);
208 CHECK_STATUS(status, NT_STATUS_NOTIFY_ENUM_DIR);
210 /* if the buffer size is too large, we get invalid parameter */
211 n.in.recursive = 0x0000;
212 n.in.buffer_size = max_buffer_size + 1;
213 n.in.file.handle = dh;
214 n.in.completion_filter = FILE_NOTIFY_CHANGE_ALL;
215 n.in.unknown = 0x00000000;
216 req = smb2_notify_send(tree, &n);
217 status = smb2_notify_recv(req, torture, &n);
218 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
220 done:
221 return ret;
225 basic testing of change notify on directories
228 #define BASEDIR_DIR BASEDIR "_DIR"
230 static bool torture_smb2_notify_dir(struct torture_context *torture,
231 struct smb2_tree *tree1,
232 struct smb2_tree *tree2)
234 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 struct smb2_handle h1 = {{0}};
241 struct smb2_handle h2 = {{0}};
242 struct smb2_request *req, *req2;
243 const char *fname = BASEDIR_DIR "\\subdir-name";
244 extern int torture_numops;
246 torture_comment(torture, "TESTING CHANGE NOTIFY ON DIRECTORIES\n");
248 smb2_deltree(tree1, BASEDIR_DIR);
249 smb2_util_rmdir(tree1, BASEDIR_DIR);
251 get a handle on the directory
253 ZERO_STRUCT(io.smb2);
254 io.generic.level = RAW_OPEN_SMB2;
255 io.smb2.in.create_flags = 0;
256 io.smb2.in.desired_access = SEC_FILE_ALL;
257 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
258 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
259 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
260 NTCREATEX_SHARE_ACCESS_WRITE;
261 io.smb2.in.alloc_size = 0;
262 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
263 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
264 io.smb2.in.security_flags = 0;
265 io.smb2.in.fname = BASEDIR_DIR;
267 status = smb2_create(tree1, torture, &(io.smb2));
268 CHECK_STATUS(status, NT_STATUS_OK);
269 h1 = io.smb2.out.file.handle;
271 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
272 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ;
273 status = smb2_create(tree1, torture, &(io.smb2));
274 CHECK_STATUS(status, NT_STATUS_OK);
275 h2 = io.smb2.out.file.handle;
277 /* ask for a change notify,
278 on file or directory name changes */
279 ZERO_STRUCT(notify.smb2);
280 notify.smb2.level = RAW_NOTIFY_SMB2;
281 notify.smb2.in.buffer_size = 1000;
282 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
283 notify.smb2.in.file.handle = h1;
284 notify.smb2.in.recursive = true;
286 torture_comment(torture, "Testing notify cancel\n");
288 req = smb2_notify_send(tree1, &(notify.smb2));
289 smb2_cancel(req);
290 status = smb2_notify_recv(req, torture, &(notify.smb2));
291 CHECK_STATUS(status, NT_STATUS_CANCELLED);
293 torture_comment(torture, "Testing notify mkdir\n");
295 req = smb2_notify_send(tree1, &(notify.smb2));
296 smb2_util_mkdir(tree2, fname);
298 status = smb2_notify_recv(req, torture, &(notify.smb2));
299 CHECK_STATUS(status, NT_STATUS_OK);
301 CHECK_VAL(notify.smb2.out.num_changes, 1);
302 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
303 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
305 torture_comment(torture, "Testing notify rmdir\n");
307 req = smb2_notify_send(tree1, &(notify.smb2));
308 smb2_util_rmdir(tree2, fname);
310 status = smb2_notify_recv(req, torture, &(notify.smb2));
311 CHECK_STATUS(status, NT_STATUS_OK);
312 CHECK_VAL(notify.smb2.out.num_changes, 1);
313 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
314 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
316 torture_comment(torture,
317 "Testing notify mkdir - rmdir - mkdir - rmdir\n");
319 smb2_util_mkdir(tree2, fname);
320 smb2_util_rmdir(tree2, fname);
321 smb2_util_mkdir(tree2, fname);
322 smb2_util_rmdir(tree2, fname);
323 smb_msleep(200);
324 req = smb2_notify_send(tree1, &(notify.smb2));
325 status = smb2_notify_recv(req, torture, &(notify.smb2));
326 CHECK_STATUS(status, NT_STATUS_OK);
327 CHECK_VAL(notify.smb2.out.num_changes, 4);
328 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
329 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
330 CHECK_VAL(notify.smb2.out.changes[1].action, NOTIFY_ACTION_REMOVED);
331 CHECK_WIRE_STR(notify.smb2.out.changes[1].name, "subdir-name");
332 CHECK_VAL(notify.smb2.out.changes[2].action, NOTIFY_ACTION_ADDED);
333 CHECK_WIRE_STR(notify.smb2.out.changes[2].name, "subdir-name");
334 CHECK_VAL(notify.smb2.out.changes[3].action, NOTIFY_ACTION_REMOVED);
335 CHECK_WIRE_STR(notify.smb2.out.changes[3].name, "subdir-name");
337 count = torture_numops;
338 torture_comment(torture,
339 "Testing buffered notify on create of %d files\n", count);
340 for (i=0;i<count;i++) {
341 struct smb2_handle h12;
342 char *fname2 = talloc_asprintf(torture,
343 BASEDIR_DIR "\\test%d.txt",
346 ZERO_STRUCT(io.smb2);
347 io.generic.level = RAW_OPEN_SMB2;
348 io.smb2.in.create_flags = 0;
349 io.smb2.in.desired_access = SEC_FILE_ALL;
350 io.smb2.in.create_options =
351 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
352 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
353 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
354 NTCREATEX_SHARE_ACCESS_WRITE;
355 io.smb2.in.alloc_size = 0;
356 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
357 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
358 io.smb2.in.security_flags = 0;
359 io.smb2.in.fname = fname2;
361 status = smb2_create(tree1, torture, &(io.smb2));
362 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
363 torture_comment(torture, "Failed to create %s \n",
364 fname);
365 ret = false;
366 goto done;
368 h12 = io.smb2.out.file.handle;
369 talloc_free(fname2);
370 smb2_util_close(tree1, h12);
373 /* (1st notify) setup a new notify on a different directory handle.
374 This new notify won't see the events above. */
375 notify.smb2.in.file.handle = h2;
376 req2 = smb2_notify_send(tree1, &(notify.smb2));
378 /* (2nd notify) whereas this notify will see the above buffered events,
379 and it directly returns the buffered events */
380 notify.smb2.in.file.handle = h1;
381 req = smb2_notify_send(tree1, &(notify.smb2));
383 status = smb2_util_unlink(tree1, BASEDIR_DIR "\\nonexistent.txt");
384 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
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 torture_comment(torture,
390 "Testing notify on unlink for the first file\n");
391 status = smb2_util_unlink(tree2, BASEDIR_DIR "\\test0.txt");
392 CHECK_STATUS(status, NT_STATUS_OK);
394 /* receive the reply from the 2nd notify */
395 status = smb2_notify_recv(req, torture, &(notify.smb2));
396 CHECK_STATUS(status, NT_STATUS_OK);
398 CHECK_VAL(notify.smb2.out.num_changes, count);
399 for (i=1;i<count;i++) {
400 CHECK_VAL(notify.smb2.out.changes[i].action,
401 NOTIFY_ACTION_ADDED);
403 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
405 torture_comment(torture, "and now from the 1st notify\n");
406 status = smb2_notify_recv(req2, torture, &(notify.smb2));
407 CHECK_STATUS(status, NT_STATUS_OK);
408 CHECK_VAL(notify.smb2.out.num_changes, 1);
409 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
410 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
412 torture_comment(torture,
413 "(3rd notify) this notify will only see the 1st unlink\n");
414 req = smb2_notify_send(tree1, &(notify.smb2));
416 status = smb2_util_unlink(tree1, BASEDIR_DIR "\\nonexistent.txt");
417 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
419 for (i=1;i<count;i++) {
420 char *fname2 = talloc_asprintf(torture,
421 BASEDIR_DIR "\\test%d.txt", i);
422 status = smb2_util_unlink(tree2, fname2);
423 CHECK_STATUS(status, NT_STATUS_OK);
424 talloc_free(fname2);
427 /* receive the 3rd notify */
428 status = smb2_notify_recv(req, torture, &(notify.smb2));
429 CHECK_STATUS(status, NT_STATUS_OK);
430 CHECK_VAL(notify.smb2.out.num_changes, 1);
431 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
432 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
434 /* and we now see the rest of the unlink calls on both
435 * directory handles */
436 notify.smb2.in.file.handle = h1;
437 sleep(3);
438 req = smb2_notify_send(tree1, &(notify.smb2));
439 status = smb2_notify_recv(req, torture, &(notify.smb2));
440 CHECK_STATUS(status, NT_STATUS_OK);
441 CHECK_VAL(notify.smb2.out.num_changes, count-1);
442 for (i=0;i<notify.smb2.out.num_changes;i++) {
443 CHECK_VAL(notify.smb2.out.changes[i].action,
444 NOTIFY_ACTION_REMOVED);
446 notify.smb2.in.file.handle = h2;
447 req = smb2_notify_send(tree1, &(notify.smb2));
448 status = smb2_notify_recv(req, torture, &(notify.smb2));
449 CHECK_STATUS(status, NT_STATUS_OK);
450 CHECK_VAL(notify.smb2.out.num_changes, count-1);
451 for (i=0;i<notify.smb2.out.num_changes;i++) {
452 CHECK_VAL(notify.smb2.out.changes[i].action,
453 NOTIFY_ACTION_REMOVED);
456 torture_comment(torture,
457 "Testing if a close() on the dir handle triggers the notify reply\n");
459 notify.smb2.in.file.handle = h1;
460 req = smb2_notify_send(tree1, &(notify.smb2));
462 ZERO_STRUCT(cl.smb2);
463 cl.smb2.level = RAW_CLOSE_SMB2;
464 cl.smb2.in.file.handle = h1;
465 status = smb2_close(tree1, &(cl.smb2));
466 CHECK_STATUS(status, NT_STATUS_OK);
468 status = smb2_notify_recv(req, torture, &(notify.smb2));
469 CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
470 CHECK_VAL(notify.smb2.out.num_changes, 9);
472 done:
473 smb2_util_close(tree1, h1);
474 smb2_util_close(tree1, h2);
475 smb2_deltree(tree1, BASEDIR_DIR);
476 return ret;
479 static struct smb2_handle custom_smb2_create(struct smb2_tree *tree,
480 struct torture_context *torture,
481 struct smb2_create *smb2)
483 struct smb2_handle h1;
484 bool ret = true;
485 NTSTATUS status;
486 smb2_deltree(tree, smb2->in.fname);
487 status = smb2_create(tree, torture, smb2);
488 CHECK_STATUS(status, NT_STATUS_OK);
489 h1 = smb2->out.file.handle;
490 done:
491 if (!ret) {
492 h1 = (struct smb2_handle) {
493 .data = { 0 , 0},
496 return h1;
500 testing of recursive change notify
503 #define BASEDIR_REC BASEDIR "_REC"
505 static bool torture_smb2_notify_recursive(struct torture_context *torture,
506 struct smb2_tree *tree1,
507 struct smb2_tree *tree2)
509 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;
517 smb2_deltree(tree1, BASEDIR_REC);
518 smb2_util_rmdir(tree1, BASEDIR_REC);
520 torture_comment(torture, "TESTING CHANGE NOTIFY WITH RECURSION\n");
523 get a handle on the directory
525 ZERO_STRUCT(io.smb2);
526 io.generic.level = RAW_OPEN_SMB2;
527 io.smb2.in.create_flags = 0;
528 io.smb2.in.desired_access = SEC_FILE_ALL;
529 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
530 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
531 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
532 NTCREATEX_SHARE_ACCESS_WRITE;
533 io.smb2.in.alloc_size = 0;
534 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
535 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
536 io.smb2.in.security_flags = 0;
537 io.smb2.in.fname = BASEDIR_REC;
539 status = smb2_create(tree1, torture, &(io.smb2));
540 CHECK_STATUS(status, NT_STATUS_OK);
541 h1 = io.smb2.out.file.handle;
543 /* ask for a change notify, on file or directory name
544 changes. Setup both with and without recursion */
545 ZERO_STRUCT(notify.smb2);
546 notify.smb2.level = RAW_NOTIFY_SMB2;
547 notify.smb2.in.buffer_size = 1000;
548 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME |
549 FILE_NOTIFY_CHANGE_ATTRIBUTES |
550 FILE_NOTIFY_CHANGE_CREATION;
551 notify.smb2.in.file.handle = h1;
553 notify.smb2.in.recursive = true;
554 req1 = smb2_notify_send(tree1, &(notify.smb2));
555 smb2_cancel(req1);
556 status = smb2_notify_recv(req1, torture, &(notify.smb2));
557 CHECK_STATUS(status, NT_STATUS_CANCELLED);
559 notify.smb2.in.recursive = false;
560 req2 = smb2_notify_send(tree1, &(notify.smb2));
561 smb2_cancel(req2);
562 status = smb2_notify_recv(req2, torture, &(notify.smb2));
563 CHECK_STATUS(status, NT_STATUS_CANCELLED);
565 ZERO_STRUCT(io1.smb2);
566 io1.generic.level = RAW_OPEN_SMB2;
567 io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
568 io1.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
569 SEC_RIGHTS_FILE_WRITE|
570 SEC_RIGHTS_FILE_ALL;
571 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
572 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
573 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
574 NTCREATEX_SHARE_ACCESS_WRITE |
575 NTCREATEX_SHARE_ACCESS_DELETE;
576 io1.smb2.in.alloc_size = 0;
577 io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
578 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
579 io1.smb2.in.security_flags = 0;
580 io1.smb2.in.fname = BASEDIR_REC "\\subdir-name";
581 status = smb2_create(tree2, torture, &(io1.smb2));
582 CHECK_STATUS(status, NT_STATUS_OK);
583 smb2_util_close(tree2, io1.smb2.out.file.handle);
585 io1.smb2.in.fname = BASEDIR_REC "\\subdir-name\\subname1";
586 status = smb2_create(tree2, torture, &(io1.smb2));
587 CHECK_STATUS(status, NT_STATUS_OK);
588 ZERO_STRUCT(sinfo);
589 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
590 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
591 sinfo.rename_information.in.overwrite = 0;
592 sinfo.rename_information.in.root_fid = 0;
593 sinfo.rename_information.in.new_name =
594 BASEDIR_REC "\\subdir-name\\subname1-r";
595 status = smb2_setinfo_file(tree2, &sinfo);
596 CHECK_STATUS(status, NT_STATUS_OK);
598 io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
599 io1.smb2.in.fname = BASEDIR_REC "\\subdir-name\\subname2";
600 status = smb2_create(tree2, torture, &(io1.smb2));
601 CHECK_STATUS(status, NT_STATUS_OK);
602 ZERO_STRUCT(sinfo);
603 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
604 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
605 sinfo.rename_information.in.overwrite = true;
606 sinfo.rename_information.in.root_fid = 0;
607 sinfo.rename_information.in.new_name = BASEDIR_REC "\\subname2-r";
608 status = smb2_setinfo_file(tree2, &sinfo);
609 CHECK_STATUS(status, NT_STATUS_OK);
611 io1.smb2.in.fname = BASEDIR_REC "\\subname2-r";
612 io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
613 status = smb2_create(tree2, torture, &(io1.smb2));
614 CHECK_STATUS(status, NT_STATUS_OK);
615 ZERO_STRUCT(sinfo);
616 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
617 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
618 sinfo.rename_information.in.overwrite = true;
619 sinfo.rename_information.in.root_fid = 0;
620 sinfo.rename_information.in.new_name = BASEDIR_REC "\\subname3-r";
621 status = smb2_setinfo_file(tree2, &sinfo);
622 CHECK_STATUS(status, NT_STATUS_OK);
624 notify.smb2.in.completion_filter = 0;
625 notify.smb2.in.recursive = true;
626 smb_msleep(200);
627 req1 = smb2_notify_send(tree1, &(notify.smb2));
629 status = smb2_util_rmdir(tree2,
630 BASEDIR_REC "\\subdir-name\\subname1-r");
631 CHECK_STATUS(status, NT_STATUS_OK);
632 status = smb2_util_rmdir(tree2,
633 BASEDIR_REC "\\subdir-name");
634 CHECK_STATUS(status, NT_STATUS_OK);
635 status = smb2_util_unlink(tree2, BASEDIR_REC "\\subname3-r");
636 CHECK_STATUS(status, NT_STATUS_OK);
638 notify.smb2.in.recursive = false;
639 req2 = smb2_notify_send(tree1, &(notify.smb2));
641 status = smb2_notify_recv(req1, torture, &(notify.smb2));
642 CHECK_STATUS(status, NT_STATUS_OK);
644 CHECK_VAL(notify.smb2.out.num_changes, 9);
645 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
646 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
647 CHECK_VAL(notify.smb2.out.changes[1].action, NOTIFY_ACTION_ADDED);
648 CHECK_WIRE_STR(notify.smb2.out.changes[1].name, "subdir-name\\subname1");
649 CHECK_VAL(notify.smb2.out.changes[2].action, NOTIFY_ACTION_OLD_NAME);
650 CHECK_WIRE_STR(notify.smb2.out.changes[2].name, "subdir-name\\subname1");
651 CHECK_VAL(notify.smb2.out.changes[3].action, NOTIFY_ACTION_NEW_NAME);
652 CHECK_WIRE_STR(notify.smb2.out.changes[3].name, "subdir-name\\subname1-r");
653 CHECK_VAL(notify.smb2.out.changes[4].action, NOTIFY_ACTION_ADDED);
654 CHECK_WIRE_STR(notify.smb2.out.changes[4].name, "subdir-name\\subname2");
655 CHECK_VAL(notify.smb2.out.changes[5].action, NOTIFY_ACTION_REMOVED);
656 CHECK_WIRE_STR(notify.smb2.out.changes[5].name, "subdir-name\\subname2");
657 CHECK_VAL(notify.smb2.out.changes[6].action, NOTIFY_ACTION_ADDED);
658 CHECK_WIRE_STR(notify.smb2.out.changes[6].name, "subname2-r");
659 CHECK_VAL(notify.smb2.out.changes[7].action, NOTIFY_ACTION_OLD_NAME);
660 CHECK_WIRE_STR(notify.smb2.out.changes[7].name, "subname2-r");
661 CHECK_VAL(notify.smb2.out.changes[8].action, NOTIFY_ACTION_NEW_NAME);
662 CHECK_WIRE_STR(notify.smb2.out.changes[8].name, "subname3-r");
664 done:
665 smb2_deltree(tree1, BASEDIR_REC);
666 return ret;
670 testing of change notify mask change
673 #define BASEDIR_MC BASEDIR "_MC"
675 static bool torture_smb2_notify_mask_change(struct torture_context *torture,
676 struct smb2_tree *tree1,
677 struct smb2_tree *tree2)
679 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;
687 smb2_deltree(tree1, BASEDIR_MC);
688 smb2_util_rmdir(tree1, BASEDIR_MC);
690 torture_comment(torture, "TESTING CHANGE NOTIFY WITH MASK CHANGE\n");
693 get a handle on the directory
695 ZERO_STRUCT(io.smb2);
696 io.generic.level = RAW_OPEN_SMB2;
697 io.smb2.in.create_flags = 0;
698 io.smb2.in.desired_access = SEC_FILE_ALL;
699 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
700 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
701 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
702 NTCREATEX_SHARE_ACCESS_WRITE;
703 io.smb2.in.alloc_size = 0;
704 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
705 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
706 io.smb2.in.security_flags = 0;
707 io.smb2.in.fname = BASEDIR_MC;
709 status = smb2_create(tree1, torture, &(io.smb2));
710 CHECK_STATUS(status, NT_STATUS_OK);
711 h1 = io.smb2.out.file.handle;
713 /* ask for a change notify, on file or directory name
714 changes. Setup both with and without recursion */
715 ZERO_STRUCT(notify.smb2);
716 notify.smb2.level = RAW_NOTIFY_SMB2;
717 notify.smb2.in.buffer_size = 1000;
718 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
719 notify.smb2.in.file.handle = h1;
721 notify.smb2.in.recursive = true;
722 req1 = smb2_notify_send(tree1, &(notify.smb2));
724 smb2_cancel(req1);
725 status = smb2_notify_recv(req1, torture, &(notify.smb2));
726 CHECK_STATUS(status, NT_STATUS_CANCELLED);
729 notify.smb2.in.recursive = false;
730 req2 = smb2_notify_send(tree1, &(notify.smb2));
732 smb2_cancel(req2);
733 status = smb2_notify_recv(req2, torture, &(notify.smb2));
734 CHECK_STATUS(status, NT_STATUS_CANCELLED);
736 notify.smb2.in.recursive = true;
737 req1 = smb2_notify_send(tree1, &(notify.smb2));
739 /* Set to hidden then back again. */
740 ZERO_STRUCT(io1.smb2);
741 io1.generic.level = RAW_OPEN_SMB2;
742 io1.smb2.in.create_flags = 0;
743 io1.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
744 SEC_RIGHTS_FILE_WRITE|
745 SEC_RIGHTS_FILE_ALL;
746 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
747 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
748 NTCREATEX_SHARE_ACCESS_WRITE |
749 NTCREATEX_SHARE_ACCESS_DELETE;
750 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
751 io1.smb2.in.security_flags = 0;
752 io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
753 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
754 io1.smb2.in.fname = BASEDIR_MC "\\tname1";
756 smb2_util_close(tree1,
757 custom_smb2_create(tree1, torture, &(io1.smb2)));
758 status = smb2_util_setatr(tree1, BASEDIR_MC "\\tname1",
759 FILE_ATTRIBUTE_HIDDEN);
760 CHECK_STATUS(status, NT_STATUS_OK);
761 smb2_util_unlink(tree1, BASEDIR_MC "\\tname1");
763 status = smb2_notify_recv(req1, torture, &(notify.smb2));
764 CHECK_STATUS(status, NT_STATUS_OK);
766 CHECK_VAL(notify.smb2.out.num_changes, 1);
767 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
768 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "tname1");
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. */
774 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME |
775 FILE_NOTIFY_CHANGE_ATTRIBUTES |
776 FILE_NOTIFY_CHANGE_CREATION;
777 notify.smb2.in.recursive = true;
778 req1 = smb2_notify_send(tree1, &(notify.smb2));
780 notify.smb2.in.recursive = false;
781 req2 = smb2_notify_send(tree1, &(notify.smb2));
783 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
784 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
785 io1.smb2.in.fname = BASEDIR_MC "\\subdir-name";
786 status = smb2_create(tree2, torture, &(io1.smb2));
787 CHECK_STATUS(status, NT_STATUS_OK);
788 smb2_util_close(tree2, io1.smb2.out.file.handle);
790 ZERO_STRUCT(sinfo);
791 io1.smb2.in.fname = BASEDIR_MC "\\subdir-name\\subname1";
792 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
793 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
794 status = smb2_create(tree2, torture, &(io1.smb2));
795 CHECK_STATUS(status, NT_STATUS_OK);
796 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
797 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
798 sinfo.rename_information.in.overwrite = true;
799 sinfo.rename_information.in.root_fid = 0;
800 sinfo.rename_information.in.new_name =
801 BASEDIR_MC "\\subdir-name\\subname1-r";
802 status = smb2_setinfo_file(tree2, &sinfo);
803 CHECK_STATUS(status, NT_STATUS_OK);
805 io1.smb2.in.fname = BASEDIR_MC "\\subdir-name\\subname2";
806 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
807 io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
808 status = smb2_create(tree2, torture, &(io1.smb2));
809 CHECK_STATUS(status, NT_STATUS_OK);
810 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
811 sinfo.rename_information.in.new_name = BASEDIR_MC "\\subname2-r";
812 status = smb2_setinfo_file(tree2, &sinfo);
813 CHECK_STATUS(status, NT_STATUS_OK);
814 smb2_util_close(tree2, io1.smb2.out.file.handle);
816 io1.smb2.in.fname = BASEDIR_MC "\\subname2-r";
817 io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
818 status = smb2_create(tree2, torture, &(io1.smb2));
819 CHECK_STATUS(status, NT_STATUS_OK);
820 sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
821 sinfo.rename_information.in.new_name = BASEDIR_MC "\\subname3-r";
822 status = smb2_setinfo_file(tree2, &sinfo);
823 CHECK_STATUS(status, NT_STATUS_OK);
824 smb2_util_close(tree2, io1.smb2.out.file.handle);
826 status = smb2_util_rmdir(tree2, BASEDIR_MC "\\subdir-name\\subname1-r");
827 CHECK_STATUS(status, NT_STATUS_OK);
828 status = smb2_util_rmdir(tree2, BASEDIR_MC "\\subdir-name");
829 CHECK_STATUS(status, NT_STATUS_OK);
830 status = smb2_util_unlink(tree2, BASEDIR_MC "\\subname3-r");
831 CHECK_STATUS(status, NT_STATUS_OK);
833 status = smb2_notify_recv(req1, torture, &(notify.smb2));
834 CHECK_STATUS(status, NT_STATUS_OK);
836 CHECK_VAL(notify.smb2.out.num_changes, 1);
837 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
838 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subname2-r");
840 status = smb2_notify_recv(req2, torture, &(notify.smb2));
841 CHECK_STATUS(status, NT_STATUS_OK);
843 CHECK_VAL(notify.smb2.out.num_changes, 1);
844 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
845 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subname3-r");
847 if (!ret) {
848 goto done;
851 done:
852 smb2_deltree(tree1, BASEDIR_MC);
853 return ret;
857 testing of mask bits for change notify
860 #define BASEDIR_MSK BASEDIR "_MSK"
862 static bool torture_smb2_notify_mask(struct torture_context *torture,
863 struct smb2_tree *tree1,
864 struct smb2_tree *tree2)
866 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 char c = 1;
873 union smb_setfileinfo sinfo;
875 smb2_deltree(tree1, BASEDIR_MSK);
876 smb2_util_rmdir(tree1, BASEDIR_MSK);
878 torture_comment(torture, "TESTING CHANGE NOTIFY COMPLETION FILTERS\n");
881 ZERO_STRUCT(h1);
882 ZERO_STRUCT(h2);
884 get a handle on the directory
886 ZERO_STRUCT(io.smb2);
887 io.generic.level = RAW_OPEN_SMB2;
888 io.smb2.in.create_flags = 0;
889 io.smb2.in.desired_access = SEC_FILE_ALL;
890 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
891 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
892 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
893 NTCREATEX_SHARE_ACCESS_WRITE;
894 io.smb2.in.alloc_size = 0;
895 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
896 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
897 io.smb2.in.security_flags = 0;
898 io.smb2.in.fname = BASEDIR_MSK;
900 ZERO_STRUCT(notify.smb2);
901 notify.smb2.level = RAW_NOTIFY_SMB2;
902 notify.smb2.in.buffer_size = 1000;
903 notify.smb2.in.recursive = true;
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; \
968 } while (0); \
969 } while (0);
971 torture_comment(torture, "Testing mkdir\n");
972 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);
978 torture_comment(torture, "Testing create file\n");
979 ZERO_STRUCT(io1.smb2);
980 io1.generic.level = RAW_OPEN_SMB2;
981 io1.smb2.in.create_flags = 0;
982 io1.smb2.in.desired_access = SEC_FILE_ALL;
983 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
984 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
985 NTCREATEX_SHARE_ACCESS_WRITE;
986 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
987 io1.smb2.in.security_flags = 0;
988 io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
989 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
990 io1.smb2.in.fname = BASEDIR_MSK "\\tname1";
992 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);
999 torture_comment(torture, "Testing unlink\n");
1000 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");,
1005 NOTIFY_ACTION_REMOVED,
1006 FILE_NOTIFY_CHANGE_FILE_NAME, 1);
1008 torture_comment(torture, "Testing rmdir\n");
1009 NOTIFY_MASK_TEST("Testing rmdir",
1010 smb2_util_mkdir(tree2, BASEDIR_MSK "\\tname1");,
1011 smb2_util_rmdir(tree2, BASEDIR_MSK "\\tname1");,
1013 NOTIFY_ACTION_REMOVED,
1014 FILE_NOTIFY_CHANGE_DIR_NAME, 1);
1016 torture_comment(torture, "Testing rename file\n");
1017 ZERO_STRUCT(sinfo);
1018 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
1019 sinfo.rename_information.in.file.handle = h1;
1020 sinfo.rename_information.in.overwrite = true;
1021 sinfo.rename_information.in.root_fid = 0;
1022 sinfo.rename_information.in.new_name = BASEDIR_MSK "\\tname2";
1023 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);
1031 torture_comment(torture, "Testing rename dir\n");
1032 ZERO_STRUCT(sinfo);
1033 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
1034 sinfo.rename_information.in.file.handle = h1;
1035 sinfo.rename_information.in.overwrite = true;
1036 sinfo.rename_information.in.root_fid = 0;
1037 sinfo.rename_information.in.new_name = BASEDIR_MSK "\\tname2";
1038 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);
1045 torture_comment(torture, "Testing set path attribute\n");
1046 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);
1055 torture_comment(torture, "Testing set path write time\n");
1056 ZERO_STRUCT(sinfo);
1057 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1058 sinfo.generic.in.file.handle = h1;
1059 sinfo.basic_info.in.write_time = 1000;
1060 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);
1068 if (torture_setting_bool(torture, "samba3", false)) {
1069 torture_comment(torture,
1070 "Samba3 does not yet support create times "
1071 "everywhere\n");
1073 else {
1074 ZERO_STRUCT(sinfo);
1075 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1076 sinfo.generic.in.file.handle = h1;
1077 sinfo.basic_info.in.create_time = 0;
1078 torture_comment(torture, "Testing set file create time\n");
1079 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);
1089 ZERO_STRUCT(sinfo);
1090 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1091 sinfo.generic.in.file.handle = h1;
1092 sinfo.basic_info.in.access_time = 0;
1093 torture_comment(torture, "Testing set file access time\n");
1094 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);
1105 ZERO_STRUCT(sinfo);
1106 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1107 sinfo.generic.in.file.handle = h1;
1108 sinfo.basic_info.in.change_time = 0;
1109 torture_comment(torture, "Testing set file change time\n");
1110 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);
1122 torture_comment(torture, "Testing write\n");
1123 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);
1134 done:
1135 smb2_deltree(tree1, BASEDIR_MSK);
1136 return ret;
1139 #define BASEDIR_FL BASEDIR "_FL"
1141 basic testing of change notify on files
1143 static bool torture_smb2_notify_file(struct torture_context *torture,
1144 struct smb2_tree *tree)
1146 NTSTATUS status;
1147 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 const char *fname = BASEDIR_FL "\\file.txt";
1155 smb2_deltree(tree, BASEDIR_FL);
1156 smb2_util_rmdir(tree, BASEDIR_FL);
1158 torture_comment(torture, "TESTING CHANGE NOTIFY ON FILES\n");
1159 status = torture_smb2_testdir(tree, BASEDIR_FL, &h1);
1160 CHECK_STATUS(status, NT_STATUS_OK);
1162 ZERO_STRUCT(io.smb2);
1163 io.generic.level = RAW_OPEN_SMB2;
1164 io.smb2.in.create_flags = 0;
1165 io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1166 io.smb2.in.create_options = 0;
1167 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1168 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1169 NTCREATEX_SHARE_ACCESS_WRITE;
1170 io.smb2.in.alloc_size = 0;
1171 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1172 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1173 io.smb2.in.security_flags = 0;
1174 io.smb2.in.fname = fname;
1175 status = smb2_create(tree, torture, &(io.smb2));
1176 CHECK_STATUS(status, NT_STATUS_OK);
1177 h1 = io.smb2.out.file.handle;
1179 /* ask for a change notify,
1180 on file or directory name changes */
1181 ZERO_STRUCT(notify.smb2);
1182 notify.smb2.level = RAW_NOTIFY_SMB2;
1183 notify.smb2.in.file.handle = h1;
1184 notify.smb2.in.buffer_size = 1000;
1185 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_STREAM_NAME;
1186 notify.smb2.in.recursive = false;
1188 torture_comment(torture,
1189 "Testing if notifies on file handles are invalid (should be)\n");
1191 req = smb2_notify_send(tree, &(notify.smb2));
1192 status = smb2_notify_recv(req, torture, &(notify.smb2));
1193 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1195 ZERO_STRUCT(cl.smb2);
1196 cl.close.level = RAW_CLOSE_SMB2;
1197 cl.close.in.file.handle = h1;
1198 status = smb2_close(tree, &(cl.smb2));
1199 CHECK_STATUS(status, NT_STATUS_OK);
1201 status = smb2_util_unlink(tree, fname);
1202 CHECK_STATUS(status, NT_STATUS_OK);
1204 done:
1205 smb2_deltree(tree, BASEDIR_FL);
1206 return ret;
1209 basic testing of change notifies followed by a tdis
1212 #define BASEDIR_TD BASEDIR "_TD"
1214 static bool torture_smb2_notify_tree_disconnect(
1215 struct torture_context *torture,
1216 struct smb2_tree *tree)
1218 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;
1225 smb2_deltree(tree, BASEDIR_TD);
1226 smb2_util_rmdir(tree, BASEDIR_TD);
1228 torture_comment(torture, "TESTING CHANGE NOTIFY+CANCEL FOLLOWED BY "
1229 "TREE-DISCONNECT\n");
1232 get a handle on the directory
1234 ZERO_STRUCT(io.smb2);
1235 io.generic.level = RAW_OPEN_SMB2;
1236 io.smb2.in.create_flags = 0;
1237 io.smb2.in.desired_access = SEC_FILE_ALL;
1238 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1239 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1240 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1241 NTCREATEX_SHARE_ACCESS_WRITE;
1242 io.smb2.in.alloc_size = 0;
1243 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1244 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1245 io.smb2.in.security_flags = 0;
1246 io.smb2.in.fname = BASEDIR_TD;
1248 status = smb2_create(tree, torture, &(io.smb2));
1249 CHECK_STATUS(status, NT_STATUS_OK);
1250 h1 = io.smb2.out.file.handle;
1252 /* ask for a change notify,
1253 on file or directory name changes */
1254 ZERO_STRUCT(notify.smb2);
1255 notify.smb2.level = RAW_NOTIFY_SMB2;
1256 notify.smb2.in.buffer_size = 1000;
1257 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1258 notify.smb2.in.file.handle = h1;
1259 notify.smb2.in.recursive = true;
1261 req = smb2_notify_send(tree, &(notify.smb2));
1262 smb2_cancel(req);
1263 status = smb2_notify_recv(req, torture, &(notify.smb2));
1265 status = smb2_tdis(tree);
1266 CHECK_STATUS(status, NT_STATUS_OK);
1268 req = smb2_notify_send(tree, &(notify.smb2));
1270 smb2_notify_recv(req, torture, &(notify.smb2));
1271 CHECK_STATUS(status, NT_STATUS_OK);
1272 CHECK_VAL(notify.smb2.out.num_changes, 0);
1274 done:
1275 smb2_deltree(tree, BASEDIR_TD);
1276 return ret;
1280 testing of change notifies followed by a tdis - no cancel
1283 #define BASEDIR_NTDIS BASEDIR "_NTDIS"
1285 static bool torture_smb2_notify_tree_disconnect_1(
1286 struct torture_context *torture,
1287 struct smb2_tree *tree)
1289 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;
1296 smb2_deltree(tree, BASEDIR_NTDIS);
1297 smb2_util_rmdir(tree, BASEDIR_NTDIS);
1299 torture_comment(torture, "TESTING CHANGE NOTIFY ASYNC FOLLOWED BY "
1300 "TREE-DISCONNECT\n");
1303 get a handle on the directory
1305 ZERO_STRUCT(io.smb2);
1306 io.generic.level = RAW_OPEN_SMB2;
1307 io.smb2.in.create_flags = 0;
1308 io.smb2.in.desired_access = SEC_FILE_ALL;
1309 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1310 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1311 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1312 NTCREATEX_SHARE_ACCESS_WRITE;
1313 io.smb2.in.alloc_size = 0;
1314 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1315 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1316 io.smb2.in.security_flags = 0;
1317 io.smb2.in.fname = BASEDIR_NTDIS;
1319 status = smb2_create(tree, torture, &(io.smb2));
1320 CHECK_STATUS(status, NT_STATUS_OK);
1321 h1 = io.smb2.out.file.handle;
1323 /* ask for a change notify,
1324 on file or directory name changes */
1325 ZERO_STRUCT(notify.smb2);
1326 notify.smb2.level = RAW_NOTIFY_SMB2;
1327 notify.smb2.in.buffer_size = 1000;
1328 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1329 notify.smb2.in.file.handle = h1;
1330 notify.smb2.in.recursive = true;
1332 req = smb2_notify_send(tree, &(notify.smb2));
1333 WAIT_FOR_ASYNC_RESPONSE(req);
1335 status = smb2_tdis(tree);
1336 CHECK_STATUS(status, NT_STATUS_OK);
1338 status = smb2_notify_recv(req, torture, &(notify.smb2));
1339 CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
1340 CHECK_VAL(notify.smb2.out.num_changes, 0);
1342 done:
1343 smb2_deltree(tree, BASEDIR_NTDIS);
1344 return ret;
1348 basic testing of change notifies followed by a close
1351 #define BASEDIR_CNC BASEDIR "_CNC"
1353 static bool torture_smb2_notify_close(struct torture_context *torture,
1354 struct smb2_tree *tree1)
1356 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;
1363 smb2_deltree(tree1, BASEDIR_CNC);
1364 smb2_util_rmdir(tree1, BASEDIR_CNC);
1366 torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1369 get a handle on the directory
1371 ZERO_STRUCT(io.smb2);
1372 io.generic.level = RAW_OPEN_SMB2;
1373 io.smb2.in.create_flags = 0;
1374 io.smb2.in.desired_access = SEC_FILE_ALL;
1375 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1376 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1377 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1378 NTCREATEX_SHARE_ACCESS_WRITE;
1379 io.smb2.in.alloc_size = 0;
1380 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1381 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1382 io.smb2.in.security_flags = 0;
1383 io.smb2.in.fname = BASEDIR_CNC;
1385 status = smb2_create(tree1, torture, &(io.smb2));
1386 CHECK_STATUS(status, NT_STATUS_OK);
1388 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1389 status = smb2_create(tree1, torture, &(io.smb2));
1390 CHECK_STATUS(status, NT_STATUS_OK);
1391 h1 = io.smb2.out.file.handle;
1393 /* ask for a change notify,
1394 on file or directory name changes */
1395 ZERO_STRUCT(notify.smb2);
1396 notify.smb2.level = RAW_NOTIFY_SMB2;
1397 notify.smb2.in.buffer_size = 1000;
1398 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1399 notify.smb2.in.file.handle = h1;
1400 notify.smb2.in.recursive = true;
1402 req = smb2_notify_send(tree1, &(notify.smb2));
1404 WAIT_FOR_ASYNC_RESPONSE(req);
1406 status = smb2_util_close(tree1, h1);
1407 CHECK_STATUS(status, NT_STATUS_OK);
1409 status = smb2_notify_recv(req, torture, &(notify.smb2));
1410 CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
1411 CHECK_VAL(notify.smb2.out.num_changes, 0);
1413 done:
1414 smb2_deltree(tree1, BASEDIR_CNC);
1415 return ret;
1419 basic testing of change notifies followed by a ulogoff
1422 #define BASEDIR_NUL BASEDIR "_NUL"
1423 static bool torture_smb2_notify_ulogoff(struct torture_context *torture,
1424 struct smb2_tree *tree1)
1426 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;
1433 smb2_deltree(tree1, BASEDIR_NUL);
1434 smb2_util_rmdir(tree1, BASEDIR_NUL);
1436 torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1439 get a handle on the directory
1441 ZERO_STRUCT(io.smb2);
1442 io.generic.level = RAW_OPEN_SMB2;
1443 io.smb2.in.create_flags = 0;
1444 io.smb2.in.desired_access = SEC_FILE_ALL;
1445 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1446 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1447 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1448 NTCREATEX_SHARE_ACCESS_WRITE;
1449 io.smb2.in.alloc_size = 0;
1450 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1451 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1452 io.smb2.in.security_flags = 0;
1453 io.smb2.in.fname = BASEDIR_NUL;
1455 status = smb2_create(tree1, torture, &(io.smb2));
1456 CHECK_STATUS(status, NT_STATUS_OK);
1458 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1459 status = smb2_create(tree1, torture, &(io.smb2));
1460 CHECK_STATUS(status, NT_STATUS_OK);
1461 h1 = io.smb2.out.file.handle;
1463 /* ask for a change notify,
1464 on file or directory name changes */
1465 ZERO_STRUCT(notify.smb2);
1466 notify.smb2.level = RAW_NOTIFY_SMB2;
1467 notify.smb2.in.buffer_size = 1000;
1468 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1469 notify.smb2.in.file.handle = h1;
1470 notify.smb2.in.recursive = true;
1472 req = smb2_notify_send(tree1, &(notify.smb2));
1474 WAIT_FOR_ASYNC_RESPONSE(req);
1476 status = smb2_logoff(tree1->session);
1477 CHECK_STATUS(status, NT_STATUS_OK);
1479 status = smb2_notify_recv(req, torture, &(notify.smb2));
1480 CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
1481 CHECK_VAL(notify.smb2.out.num_changes, 0);
1483 done:
1484 smb2_deltree(tree1, BASEDIR_NUL);
1485 return ret;
1489 basic testing of change notifies followed by a session reconnect
1492 #define BASEDIR_NSR BASEDIR "_NSR"
1494 static bool torture_smb2_notify_session_reconnect(struct torture_context *torture,
1495 struct smb2_tree *tree1)
1497 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 uint64_t previous_session_id = 0;
1504 struct smb2_session *session2 = NULL;
1506 smb2_deltree(tree1, BASEDIR_NSR);
1507 smb2_util_rmdir(tree1, BASEDIR_NSR);
1509 torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY SESSION RECONNECT\n");
1512 get a handle on the directory
1514 ZERO_STRUCT(io.smb2);
1515 io.generic.level = RAW_OPEN_SMB2;
1516 io.smb2.in.create_flags = 0;
1517 io.smb2.in.desired_access = SEC_FILE_ALL;
1518 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1519 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1520 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1521 NTCREATEX_SHARE_ACCESS_WRITE;
1522 io.smb2.in.alloc_size = 0;
1523 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1524 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1525 io.smb2.in.security_flags = 0;
1526 io.smb2.in.fname = BASEDIR_NSR;
1528 status = smb2_create(tree1, torture, &(io.smb2));
1529 CHECK_STATUS(status, NT_STATUS_OK);
1531 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1532 status = smb2_create(tree1, torture, &(io.smb2));
1533 CHECK_STATUS(status, NT_STATUS_OK);
1534 h1 = io.smb2.out.file.handle;
1536 /* ask for a change notify,
1537 on file or directory name changes */
1538 ZERO_STRUCT(notify.smb2);
1539 notify.smb2.level = RAW_NOTIFY_SMB2;
1540 notify.smb2.in.buffer_size = 1000;
1541 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1542 notify.smb2.in.file.handle = h1;
1543 notify.smb2.in.recursive = true;
1545 req = smb2_notify_send(tree1, &(notify.smb2));
1547 WAIT_FOR_ASYNC_RESPONSE(req);
1549 previous_session_id = smb2cli_session_current_id(tree1->session->smbXcli);
1550 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");
1556 status = smb2_notify_recv(req, torture, &(notify.smb2));
1557 CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
1558 CHECK_VAL(notify.smb2.out.num_changes, 0);
1560 status = smb2_logoff(tree1->session);
1561 CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
1563 status = smb2_logoff(session2);
1564 CHECK_STATUS(status, NT_STATUS_OK);
1565 done:
1566 smb2_deltree(tree1, BASEDIR_NSR);
1567 return ret;
1571 basic testing of change notifies followed by an invalid reauth
1574 #define BASEDIR_IR BASEDIR "_IR"
1576 static bool torture_smb2_notify_invalid_reauth(struct torture_context *torture,
1577 struct smb2_tree *tree1,
1578 struct smb2_tree *tree2)
1580 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;
1588 smb2_deltree(tree2, BASEDIR_IR);
1589 smb2_util_rmdir(tree2, BASEDIR_IR);
1591 torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY invalid REAUTH\n");
1594 get a handle on the directory
1596 ZERO_STRUCT(io.smb2);
1597 io.generic.level = RAW_OPEN_SMB2;
1598 io.smb2.in.create_flags = 0;
1599 io.smb2.in.desired_access = SEC_FILE_ALL;
1600 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1601 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1602 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1603 NTCREATEX_SHARE_ACCESS_WRITE;
1604 io.smb2.in.alloc_size = 0;
1605 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1606 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1607 io.smb2.in.security_flags = 0;
1608 io.smb2.in.fname = BASEDIR_IR;
1610 status = smb2_create(tree1, torture, &(io.smb2));
1611 CHECK_STATUS(status, NT_STATUS_OK);
1613 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1614 status = smb2_create(tree1, torture, &(io.smb2));
1615 CHECK_STATUS(status, NT_STATUS_OK);
1616 h1 = io.smb2.out.file.handle;
1618 /* ask for a change notify,
1619 on file or directory name changes */
1620 ZERO_STRUCT(notify.smb2);
1621 notify.smb2.level = RAW_NOTIFY_SMB2;
1622 notify.smb2.in.buffer_size = 1000;
1623 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1624 notify.smb2.in.file.handle = h1;
1625 notify.smb2.in.recursive = true;
1627 req = smb2_notify_send(tree1, &(notify.smb2));
1629 WAIT_FOR_ASYNC_RESPONSE(req);
1631 invalid_creds = cli_credentials_init(torture);
1632 torture_assert(torture, (invalid_creds != NULL), "talloc error");
1633 cli_credentials_set_username(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
1634 cli_credentials_set_domain(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
1635 cli_credentials_set_password(invalid_creds, "__none__invalid__none__", CRED_SPECIFIED);
1636 cli_credentials_set_realm(invalid_creds, NULL, CRED_SPECIFIED);
1637 cli_credentials_set_workstation(invalid_creds, "", CRED_UNINITIALISED);
1639 status = smb2_session_setup_spnego(tree1->session,
1640 invalid_creds,
1641 0 /* previous_session_id */);
1642 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
1644 status = smb2_notify_recv(req, torture, &(notify.smb2));
1645 CHECK_STATUS(status, NT_STATUS_NOTIFY_CLEANUP);
1646 CHECK_VAL(notify.smb2.out.num_changes, 0);
1649 * Demonstrate that the session is no longer valid.
1651 status = smb2_create(tree1, torture, &(io.smb2));
1652 CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
1653 done:
1654 smb2_deltree(tree2, BASEDIR_IR);
1655 return ret;
1658 static void tcp_dis_handler(struct smb2_transport *t, void *p)
1660 struct smb2_tree *tree = (struct smb2_tree *)p;
1661 smb2_transport_dead(tree->session->transport,
1662 NT_STATUS_LOCAL_DISCONNECT);
1663 t = NULL;
1664 tree = NULL;
1668 basic testing of change notifies followed by tcp disconnect
1671 #define BASEDIR_NTCPD BASEDIR "_NTCPD"
1673 static bool torture_smb2_notify_tcp_disconnect(
1674 struct torture_context *torture,
1675 struct smb2_tree *tree)
1677 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;
1684 smb2_deltree(tree, BASEDIR_NTCPD);
1685 smb2_util_rmdir(tree, BASEDIR_NTCPD);
1687 torture_comment(torture,
1688 "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
1691 get a handle on the directory
1693 ZERO_STRUCT(io.smb2);
1694 io.generic.level = RAW_OPEN_SMB2;
1695 io.smb2.in.create_flags = 0;
1696 io.smb2.in.desired_access = SEC_FILE_ALL;
1697 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1698 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1699 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1700 NTCREATEX_SHARE_ACCESS_WRITE;
1701 io.smb2.in.alloc_size = 0;
1702 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1703 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1704 io.smb2.in.security_flags = 0;
1705 io.smb2.in.fname = BASEDIR_NTCPD;
1707 status = smb2_create(tree, torture, &(io.smb2));
1708 CHECK_STATUS(status, NT_STATUS_OK);
1709 h1 = io.smb2.out.file.handle;
1711 /* ask for a change notify,
1712 on file or directory name changes */
1713 ZERO_STRUCT(notify.smb2);
1714 notify.smb2.level = RAW_NOTIFY_SMB2;
1715 notify.smb2.in.buffer_size = 1000;
1716 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1717 notify.smb2.in.file.handle = h1;
1718 notify.smb2.in.recursive = true;
1720 req = smb2_notify_send(tree, &(notify.smb2));
1721 smb2_cancel(req);
1722 status = smb2_notify_recv(req, torture, &(notify.smb2));
1723 CHECK_STATUS(status, NT_STATUS_CANCELLED);
1725 notify.smb2.in.recursive = true;
1726 req = smb2_notify_send(tree, &(notify.smb2));
1727 smb2_transport_idle_handler(tree->session->transport,
1728 tcp_dis_handler, 250000, tree);
1729 tree = NULL;
1730 status = smb2_notify_recv(req, torture, &(notify.smb2));
1731 CHECK_STATUS(status, NT_STATUS_LOCAL_DISCONNECT);
1733 done:
1734 return ret;
1738 test setting up two change notify requests on one handle
1741 #define BASEDIR_NDOH BASEDIR "_NDOH"
1743 static bool torture_smb2_notify_double(struct torture_context *torture,
1744 struct smb2_tree *tree1,
1745 struct smb2_tree *tree2)
1747 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;
1754 smb2_deltree(tree1, BASEDIR_NDOH);
1755 smb2_util_rmdir(tree1, BASEDIR_NDOH);
1757 torture_comment(torture,
1758 "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
1761 get a handle on the directory
1763 ZERO_STRUCT(io.smb2);
1764 io.generic.level = RAW_OPEN_SMB2;
1765 io.smb2.in.create_flags = 0;
1766 io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ|
1767 SEC_RIGHTS_FILE_WRITE|
1768 SEC_RIGHTS_FILE_ALL;
1769 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1770 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1771 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1772 NTCREATEX_SHARE_ACCESS_WRITE;
1773 io.smb2.in.alloc_size = 0;
1774 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1775 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1776 io.smb2.in.security_flags = 0;
1777 io.smb2.in.fname = BASEDIR_NDOH;
1779 status = smb2_create(tree1, torture, &(io.smb2));
1780 CHECK_STATUS(status, NT_STATUS_OK);
1781 h1 = io.smb2.out.file.handle;
1783 /* ask for a change notify,
1784 on file or directory name changes */
1785 ZERO_STRUCT(notify.smb2);
1786 notify.smb2.level = RAW_NOTIFY_SMB2;
1787 notify.smb2.in.buffer_size = 1000;
1788 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1789 notify.smb2.in.file.handle = h1;
1790 notify.smb2.in.recursive = true;
1792 req1 = smb2_notify_send(tree1, &(notify.smb2));
1793 smb2_cancel(req1);
1794 status = smb2_notify_recv(req1, torture, &(notify.smb2));
1795 CHECK_STATUS(status, NT_STATUS_CANCELLED);
1797 req2 = smb2_notify_send(tree1, &(notify.smb2));
1798 smb2_cancel(req2);
1799 status = smb2_notify_recv(req2, torture, &(notify.smb2));
1800 CHECK_STATUS(status, NT_STATUS_CANCELLED);
1802 smb2_util_mkdir(tree2, BASEDIR_NDOH "\\subdir-name");
1803 req1 = smb2_notify_send(tree1, &(notify.smb2));
1804 req2 = smb2_notify_send(tree1, &(notify.smb2));
1806 status = smb2_notify_recv(req1, torture, &(notify.smb2));
1807 CHECK_STATUS(status, NT_STATUS_OK);
1808 CHECK_VAL(notify.smb2.out.num_changes, 1);
1809 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
1811 smb2_util_mkdir(tree2, BASEDIR_NDOH "\\subdir-name2");
1813 status = smb2_notify_recv(req2, torture, &(notify.smb2));
1814 CHECK_STATUS(status, NT_STATUS_OK);
1815 CHECK_VAL(notify.smb2.out.num_changes, 1);
1816 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name2");
1818 done:
1819 smb2_deltree(tree1, BASEDIR_NDOH);
1820 return ret;
1825 test multiple change notifies at different depths and with/without recursion
1828 #define BASEDIR_TREE BASEDIR "_TREE"
1830 static bool torture_smb2_notify_tree(struct torture_context *torture,
1831 struct smb2_tree *tree)
1833 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 } dirs[] = {
1847 .path = BASEDIR_TREE "\\abc",
1848 .recursive = true,
1849 .filter = FILE_NOTIFY_CHANGE_NAME,
1850 .expected = 30,
1853 .path = BASEDIR_TREE "\\zqy",
1854 .recursive = true,
1855 .filter = FILE_NOTIFY_CHANGE_NAME,
1856 .expected = 8,
1859 .path = BASEDIR_TREE "\\atsy",
1860 .recursive = true,
1861 .filter = FILE_NOTIFY_CHANGE_NAME,
1862 .expected = 4,
1865 .path = BASEDIR_TREE "\\abc\\foo",
1866 .recursive = true,
1867 .filter = FILE_NOTIFY_CHANGE_NAME,
1868 .expected = 2,
1871 .path = BASEDIR_TREE "\\abc\\blah",
1872 .recursive = true,
1873 .filter = FILE_NOTIFY_CHANGE_NAME,
1874 .expected = 13,
1877 .path = BASEDIR_TREE "\\abc\\blah",
1878 .recursive = false,
1879 .filter = FILE_NOTIFY_CHANGE_NAME,
1880 .expected = 7,
1883 .path = BASEDIR_TREE "\\abc\\blah\\a",
1884 .recursive = true,
1885 .filter = FILE_NOTIFY_CHANGE_NAME,
1886 .expected = 2,
1889 .path = BASEDIR_TREE "\\abc\\blah\\b",
1890 .recursive = true,
1891 .filter = FILE_NOTIFY_CHANGE_NAME,
1892 .expected = 2,
1895 .path = BASEDIR_TREE "\\abc\\blah\\c",
1896 .recursive = true,
1897 .filter = FILE_NOTIFY_CHANGE_NAME,
1898 .expected = 2,
1901 .path = BASEDIR_TREE "\\abc\\fooblah",
1902 .recursive = true,
1903 .filter = FILE_NOTIFY_CHANGE_NAME,
1904 .expected = 2,
1907 .path = BASEDIR_TREE "\\zqy\\xx",
1908 .recursive = true,
1909 .filter = FILE_NOTIFY_CHANGE_NAME,
1910 .expected = 2,
1913 .path = BASEDIR_TREE "\\zqy\\yyy",
1914 .recursive = true,
1915 .filter = FILE_NOTIFY_CHANGE_NAME,
1916 .expected = 2,
1919 .path = BASEDIR_TREE "\\zqy\\..",
1920 .recursive = true,
1921 .filter = FILE_NOTIFY_CHANGE_NAME,
1922 .expected = 40,
1925 .path = BASEDIR_TREE,
1926 .recursive = true,
1927 .filter = FILE_NOTIFY_CHANGE_NAME,
1928 .expected = 40,
1931 .path = BASEDIR_TREE,
1932 .recursive = false,
1933 .filter = FILE_NOTIFY_CHANGE_NAME,
1934 .expected = 6,
1937 .path = BASEDIR_TREE "\\atsy",
1938 .recursive = false,
1939 .filter = FILE_NOTIFY_CHANGE_NAME,
1940 .expected = 4,
1943 .path = BASEDIR_TREE "\\abc",
1944 .recursive = true,
1945 .filter = FILE_NOTIFY_CHANGE_NAME,
1946 .expected = 24,
1949 .path = BASEDIR_TREE "\\abc",
1950 .recursive = false,
1951 .filter = FILE_NOTIFY_CHANGE_FILE_NAME,
1952 .expected = 0,
1955 .path = BASEDIR_TREE "\\abc",
1956 .recursive = true,
1957 .filter = FILE_NOTIFY_CHANGE_FILE_NAME,
1958 .expected = 0,
1961 .path = BASEDIR_TREE "\\abc",
1962 .recursive = true,
1963 .filter = FILE_NOTIFY_CHANGE_NAME,
1964 .expected = 24,
1967 int i;
1968 NTSTATUS status;
1969 bool all_done = false;
1971 smb2_deltree(tree, BASEDIR_TREE);
1972 smb2_util_rmdir(tree, BASEDIR_TREE);
1974 torture_comment(torture, "TESTING NOTIFY FOR DIFFERENT DEPTHS\n");
1976 ZERO_STRUCT(io.smb2);
1977 io.generic.level = RAW_OPEN_SMB2;
1978 io.smb2.in.create_flags = 0;
1979 io.smb2.in.desired_access = SEC_FILE_ALL;
1980 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1981 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1982 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1983 NTCREATEX_SHARE_ACCESS_WRITE;
1984 io.smb2.in.alloc_size = 0;
1985 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1986 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1987 io.smb2.in.security_flags = 0;
1988 io.smb2.in.fname = BASEDIR_TREE;
1989 status = smb2_create(tree, torture, &(io.smb2));
1990 CHECK_STATUS(status, NT_STATUS_OK);
1992 ZERO_STRUCT(notify.smb2);
1993 notify.smb2.level = RAW_NOTIFY_SMB2;
1994 notify.smb2.in.buffer_size = 20000;
1997 setup the directory tree, and the notify buffer on each directory
1999 for (i=0;i<ARRAY_SIZE(dirs);i++) {
2000 io.smb2.in.fname = dirs[i].path;
2001 status = smb2_create(tree, torture, &(io.smb2));
2002 CHECK_STATUS(status, NT_STATUS_OK);
2003 dirs[i].h1 = io.smb2.out.file.handle;
2005 notify.smb2.in.completion_filter = dirs[i].filter;
2006 notify.smb2.in.file.handle = dirs[i].h1;
2007 notify.smb2.in.recursive = dirs[i].recursive;
2008 req = smb2_notify_send(tree, &(notify.smb2));
2009 smb2_cancel(req);
2010 status = smb2_notify_recv(req, torture, &(notify.smb2));
2011 CHECK_STATUS(status, NT_STATUS_CANCELLED);
2014 /* trigger 2 events in each dir */
2015 for (i=0;i<ARRAY_SIZE(dirs);i++) {
2016 char *path = talloc_asprintf(torture, "%s\\test.dir",
2017 dirs[i].path);
2018 smb2_util_mkdir(tree, path);
2019 smb2_util_rmdir(tree, path);
2020 talloc_free(path);
2023 /* give a bit of time for the events to propagate */
2024 tv = timeval_current();
2026 do {
2027 /* count events that have happened in each dir */
2028 for (i=0;i<ARRAY_SIZE(dirs);i++) {
2029 notify.smb2.in.completion_filter = dirs[i].filter;
2030 notify.smb2.in.file.handle = dirs[i].h1;
2031 notify.smb2.in.recursive = dirs[i].recursive;
2032 req = smb2_notify_send(tree, &(notify.smb2));
2033 smb2_cancel(req);
2034 notify.smb2.out.num_changes = 0;
2035 status = smb2_notify_recv(req, torture,
2036 &(notify.smb2));
2037 dirs[i].counted += notify.smb2.out.num_changes;
2040 all_done = true;
2042 for (i=0;i<ARRAY_SIZE(dirs);i++) {
2043 if (dirs[i].counted != dirs[i].expected) {
2044 all_done = false;
2047 } while (!all_done && timeval_elapsed(&tv) < 20);
2049 torture_comment(torture, "took %.4f seconds to propagate all events\n",
2050 timeval_elapsed(&tv));
2052 for (i=0;i<ARRAY_SIZE(dirs);i++) {
2053 if (dirs[i].counted != dirs[i].expected) {
2054 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 ret = false;
2063 run from the back, closing and deleting
2065 for (i=ARRAY_SIZE(dirs)-1;i>=0;i--) {
2066 smb2_util_close(tree, dirs[i].h1);
2067 smb2_util_rmdir(tree, dirs[i].path);
2070 done:
2071 smb2_deltree(tree, BASEDIR_TREE);
2072 smb2_util_rmdir(tree, BASEDIR_TREE);
2073 return ret;
2077 Test response when cached server events exceed single NT NOTFIY response
2078 packet size.
2081 #define BASEDIR_OVF BASEDIR "_OVF"
2083 static bool torture_smb2_notify_overflow(struct torture_context *torture,
2084 struct smb2_tree *tree)
2086 bool ret = true;
2087 NTSTATUS status;
2088 union smb_notify notify;
2089 union smb_open io;
2090 struct smb2_handle h1, h2;
2091 int count = 100;
2092 struct smb2_request *req1;
2093 int i;
2095 smb2_deltree(tree, BASEDIR_OVF);
2096 smb2_util_rmdir(tree, BASEDIR_OVF);
2098 torture_comment(torture, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
2100 /* get a handle on the directory */
2101 ZERO_STRUCT(io.smb2);
2102 io.generic.level = RAW_OPEN_SMB2;
2103 io.smb2.in.create_flags = 0;
2104 io.smb2.in.desired_access = SEC_FILE_ALL;
2105 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2106 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2107 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2108 NTCREATEX_SHARE_ACCESS_WRITE;
2109 io.smb2.in.alloc_size = 0;
2110 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2111 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2112 io.smb2.in.security_flags = 0;
2113 io.smb2.in.fname = BASEDIR_OVF;
2115 status = smb2_create(tree, torture, &(io.smb2));
2116 CHECK_STATUS(status, NT_STATUS_OK);
2117 h1 = io.smb2.out.file.handle;
2119 /* ask for a change notify, on name changes. */
2120 ZERO_STRUCT(notify.smb2);
2121 notify.smb2.level = RAW_NOTIFY_NTTRANS;
2122 notify.smb2.in.buffer_size = 1000;
2123 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
2124 notify.smb2.in.file.handle = h1;
2126 notify.smb2.in.recursive = true;
2127 req1 = smb2_notify_send(tree, &(notify.smb2));
2129 /* cancel initial requests so the buffer is setup */
2130 smb2_cancel(req1);
2131 status = smb2_notify_recv(req1, torture, &(notify.smb2));
2132 CHECK_STATUS(status, NT_STATUS_CANCELLED);
2134 /* open a lot of files, filling up the server side notify buffer */
2135 torture_comment(torture,
2136 "Testing overflowed buffer notify on create of %d files\n",
2137 count);
2139 for (i=0;i<count;i++) {
2140 char *fname = talloc_asprintf(torture,
2141 BASEDIR_OVF "\\test%d.txt", i);
2142 union smb_open io1;
2143 ZERO_STRUCT(io1.smb2);
2144 io1.generic.level = RAW_OPEN_SMB2;
2145 io1.smb2.in.create_flags = 0;
2146 io1.smb2.in.desired_access = SEC_FILE_ALL;
2147 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2148 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2149 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2150 NTCREATEX_SHARE_ACCESS_WRITE;
2151 io1.smb2.in.alloc_size = 0;
2152 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2153 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2154 io1.smb2.in.security_flags = 0;
2155 io1.smb2.in.fname = fname;
2157 h2 = custom_smb2_create(tree, torture, &(io1.smb2));
2158 talloc_free(fname);
2159 smb2_util_close(tree, h2);
2162 req1 = smb2_notify_send(tree, &(notify.smb2));
2163 status = smb2_notify_recv(req1, torture, &(notify.smb2));
2164 CHECK_STATUS(status, NT_STATUS_NOTIFY_ENUM_DIR);
2165 CHECK_VAL(notify.smb2.out.num_changes, 0);
2167 done:
2168 smb2_deltree(tree, BASEDIR_OVF);
2169 return ret;
2173 Test if notifications are returned for changes to the base directory.
2174 They shouldn't be.
2177 #define BASEDIR_BAS BASEDIR "_BAS"
2179 static bool torture_smb2_notify_basedir(struct torture_context *torture,
2180 struct smb2_tree *tree1,
2181 struct smb2_tree *tree2)
2183 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;
2190 smb2_deltree(tree1, BASEDIR_BAS);
2191 smb2_util_rmdir(tree1, BASEDIR_BAS);
2193 torture_comment(torture, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
2195 /* get a handle on the directory */
2196 ZERO_STRUCT(io.smb2);
2197 io.generic.level = RAW_OPEN_SMB2;
2198 io.smb2.in.create_flags = 0;
2199 io.smb2.in.desired_access = SEC_FILE_ALL;
2200 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2201 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2202 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2203 NTCREATEX_SHARE_ACCESS_WRITE;
2204 io.smb2.in.alloc_size = 0;
2205 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2206 io.smb2.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
2207 io.smb2.in.security_flags = 0;
2208 io.smb2.in.fname = BASEDIR_BAS;
2210 status = smb2_create(tree1, torture, &(io.smb2));
2211 CHECK_STATUS(status, NT_STATUS_OK);
2212 h1 = io.smb2.out.file.handle;
2214 /* create a test file that will also be modified */
2215 io.smb2.in.fname = BASEDIR_BAS "\\tname1";
2216 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
2217 status = smb2_create(tree2, torture, &(io.smb2));
2218 CHECK_STATUS(status,NT_STATUS_OK);
2219 smb2_util_close(tree2, io.smb2.out.file.handle);
2221 /* ask for a change notify, on attribute changes. */
2222 ZERO_STRUCT(notify.smb2);
2223 notify.smb2.level = RAW_NOTIFY_SMB2;
2224 notify.smb2.in.buffer_size = 1000;
2225 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
2226 notify.smb2.in.file.handle = h1;
2227 notify.smb2.in.recursive = true;
2229 req1 = smb2_notify_send(tree1, &(notify.smb2));
2231 /* set attribute on the base dir */
2232 smb2_util_setatr(tree2, BASEDIR_BAS, FILE_ATTRIBUTE_HIDDEN);
2234 /* set attribute on a file to assure we receive a notification */
2235 smb2_util_setatr(tree2, BASEDIR_BAS "\\tname1", FILE_ATTRIBUTE_HIDDEN);
2236 smb_msleep(200);
2238 /* check how many responses were given, expect only 1 for the file */
2239 status = smb2_notify_recv(req1, torture, &(notify.smb2));
2240 CHECK_STATUS(status, NT_STATUS_OK);
2241 CHECK_VAL(notify.smb2.out.num_changes, 1);
2242 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
2243 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "tname1");
2245 done:
2246 smb2_deltree(tree1, BASEDIR_BAS);
2247 return ret;
2251 very simple change notify test
2254 #define BASEDIR_TCON BASEDIR "_TCON"
2256 static bool torture_smb2_notify_tcon(struct torture_context *torture,
2257 struct smb2_tree *tree)
2259 bool ret = true;
2260 NTSTATUS status;
2261 union smb_notify notify;
2262 union smb_open io;
2263 struct smb2_handle h1 = {{0}};
2264 struct smb2_request *req = NULL;
2265 struct smb2_tree *tree1 = NULL;
2266 const char *fname = BASEDIR_TCON "\\subdir-name";
2268 smb2_deltree(tree, BASEDIR_TCON);
2269 smb2_util_rmdir(tree, BASEDIR_TCON);
2271 torture_comment(torture, "TESTING SIMPLE CHANGE NOTIFY\n");
2274 get a handle on the directory
2277 ZERO_STRUCT(io.smb2);
2278 io.generic.level = RAW_OPEN_SMB2;
2279 io.smb2.in.create_flags = 0;
2280 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
2281 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2282 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL |
2283 FILE_ATTRIBUTE_DIRECTORY;
2284 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2285 NTCREATEX_SHARE_ACCESS_WRITE;
2286 io.smb2.in.alloc_size = 0;
2287 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2288 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2289 io.smb2.in.security_flags = 0;
2290 io.smb2.in.fname = BASEDIR_TCON;
2292 status = smb2_create(tree, torture, &(io.smb2));
2293 CHECK_STATUS(status, NT_STATUS_OK);
2294 h1 = io.smb2.out.file.handle;
2296 /* ask for a change notify,
2297 on file or directory name changes */
2298 ZERO_STRUCT(notify.smb2);
2299 notify.smb2.level = RAW_NOTIFY_SMB2;
2300 notify.smb2.in.buffer_size = 1000;
2301 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
2302 notify.smb2.in.file.handle = h1;
2303 notify.smb2.in.recursive = true;
2305 torture_comment(torture, "Testing notify mkdir\n");
2306 req = smb2_notify_send(tree, &(notify.smb2));
2307 smb2_cancel(req);
2308 status = smb2_notify_recv(req, torture, &(notify.smb2));
2309 CHECK_STATUS(status, NT_STATUS_CANCELLED);
2311 notify.smb2.in.recursive = true;
2312 req = smb2_notify_send(tree, &(notify.smb2));
2313 status = smb2_util_mkdir(tree, fname);
2314 CHECK_STATUS(status, NT_STATUS_OK);
2316 status = smb2_notify_recv(req, torture, &(notify.smb2));
2317 CHECK_STATUS(status, NT_STATUS_OK);
2319 CHECK_VAL(notify.smb2.out.num_changes, 1);
2320 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
2321 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
2323 torture_comment(torture, "Testing notify rmdir\n");
2324 req = smb2_notify_send(tree, &(notify.smb2));
2325 status = smb2_util_rmdir(tree, fname);
2326 CHECK_STATUS(status, NT_STATUS_OK);
2328 status = smb2_notify_recv(req, torture, &(notify.smb2));
2329 CHECK_STATUS(status, NT_STATUS_OK);
2330 CHECK_VAL(notify.smb2.out.num_changes, 1);
2331 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
2332 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
2334 torture_comment(torture, "SIMPLE CHANGE NOTIFY OK\n");
2336 torture_comment(torture, "TESTING WITH SECONDARY TCON\n");
2337 if (!torture_smb2_tree_connect(torture, tree->session, tree, &tree1)) {
2338 torture_warning(torture, "couldn't reconnect to share, bailing\n");
2339 ret = false;
2340 goto done;
2343 torture_comment(torture, "tid1=%d tid2=%d\n",
2344 smb2cli_tcon_current_id(tree->smbXcli),
2345 smb2cli_tcon_current_id(tree1->smbXcli));
2347 torture_comment(torture, "Testing notify mkdir\n");
2348 req = smb2_notify_send(tree, &(notify.smb2));
2349 smb2_util_mkdir(tree1, fname);
2351 status = smb2_notify_recv(req, torture, &(notify.smb2));
2352 CHECK_STATUS(status, NT_STATUS_OK);
2354 CHECK_VAL(notify.smb2.out.num_changes, 1);
2355 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
2356 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
2358 torture_comment(torture, "Testing notify rmdir\n");
2359 req = smb2_notify_send(tree, &(notify.smb2));
2360 smb2_util_rmdir(tree, fname);
2362 status = smb2_notify_recv(req, torture, &(notify.smb2));
2363 CHECK_STATUS(status, NT_STATUS_OK);
2364 CHECK_VAL(notify.smb2.out.num_changes, 1);
2365 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
2366 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
2368 torture_comment(torture, "CHANGE NOTIFY WITH TCON OK\n");
2370 torture_comment(torture, "Disconnecting secondary tree\n");
2371 status = smb2_tdis(tree1);
2372 CHECK_STATUS(status, NT_STATUS_OK);
2373 talloc_free(tree1);
2375 torture_comment(torture, "Testing notify mkdir\n");
2376 req = smb2_notify_send(tree, &(notify.smb2));
2377 smb2_util_mkdir(tree, fname);
2379 status = smb2_notify_recv(req, torture, &(notify.smb2));
2380 CHECK_STATUS(status, NT_STATUS_OK);
2382 CHECK_VAL(notify.smb2.out.num_changes, 1);
2383 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
2384 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
2386 torture_comment(torture, "Testing notify rmdir\n");
2387 req = smb2_notify_send(tree, &(notify.smb2));
2388 smb2_util_rmdir(tree, fname);
2390 status = smb2_notify_recv(req, torture, &(notify.smb2));
2391 CHECK_STATUS(status, NT_STATUS_OK);
2392 CHECK_VAL(notify.smb2.out.num_changes, 1);
2393 CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
2394 CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
2396 torture_comment(torture, "CHANGE NOTIFY WITH TDIS OK\n");
2397 done:
2398 smb2_util_close(tree, h1);
2399 smb2_deltree(tree, BASEDIR_TCON);
2401 return ret;
2404 #define BASEDIR_RMD BASEDIR "_RMD"
2406 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)
2411 bool ret = true;
2412 NTSTATUS status;
2413 union smb_notify notify = {};
2414 union smb_setfileinfo sfinfo = {};
2415 union smb_open io = {};
2416 struct smb2_handle h = {};
2417 struct smb2_request *req;
2419 torture_comment(torture, "TESTING NOTIFY CANCEL FOR DELETED DIR\n");
2421 smb2_deltree(tree1, BASEDIR_RMD);
2422 smb2_util_rmdir(tree1, BASEDIR_RMD);
2424 ZERO_STRUCT(io.smb2);
2425 io.generic.level = RAW_OPEN_SMB2;
2426 io.smb2.in.create_flags = 0;
2427 io.smb2.in.desired_access = SEC_FILE_ALL;
2428 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2429 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2430 io.smb2.in.share_access =
2431 NTCREATEX_SHARE_ACCESS_READ |
2432 NTCREATEX_SHARE_ACCESS_WRITE |
2433 NTCREATEX_SHARE_ACCESS_DELETE ;
2434 io.smb2.in.alloc_size = 0;
2435 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2436 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2437 io.smb2.in.security_flags = 0;
2438 io.smb2.in.fname = BASEDIR_RMD;
2440 status = smb2_create(tree1, torture, &(io.smb2));
2441 CHECK_STATUS(status, NT_STATUS_OK);
2442 h = io.smb2.out.file.handle;
2444 ZERO_STRUCT(notify.smb2);
2445 notify.smb2.level = RAW_NOTIFY_SMB2;
2446 notify.smb2.in.buffer_size = 1000;
2447 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
2448 notify.smb2.in.file.handle = h;
2449 notify.smb2.in.recursive = false;
2451 io.smb2.in.desired_access |= SEC_STD_DELETE;
2452 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2453 req = smb2_notify_send(tree1, &(notify.smb2));
2455 if (initial_delete_on_close) {
2456 status = smb2_util_rmdir(tree2, BASEDIR_RMD);
2457 CHECK_STATUS(status, NT_STATUS_OK);
2458 } else {
2459 status = smb2_create(tree2, torture, &(io.smb2));
2460 CHECK_STATUS(status, NT_STATUS_OK);
2462 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
2463 sfinfo.generic.in.file.handle = io.smb2.out.file.handle;
2464 sfinfo.disposition_info.in.delete_on_close = 1;
2465 status = smb2_setinfo_file(tree2, &sfinfo);
2466 CHECK_STATUS(status, NT_STATUS_OK);
2468 smb2_util_close(tree2, io.smb2.out.file.handle);
2471 status = smb2_notify_recv(req, torture, &(notify.smb2));
2472 CHECK_STATUS(status, NT_STATUS_DELETE_PENDING);
2474 done:
2476 smb2_util_close(tree1, h);
2477 smb2_deltree(tree1, BASEDIR_RMD);
2479 return ret;
2482 static bool torture_smb2_notify_rmdir1(struct torture_context *torture,
2483 struct smb2_tree *tree)
2485 return torture_smb2_notify_rmdir(torture, tree, tree, false);
2488 static bool torture_smb2_notify_rmdir2(struct torture_context *torture,
2489 struct smb2_tree *tree)
2491 return torture_smb2_notify_rmdir(torture, tree, tree, true);
2494 static bool torture_smb2_notify_rmdir3(struct torture_context *torture,
2495 struct smb2_tree *tree1,
2496 struct smb2_tree *tree2)
2498 return torture_smb2_notify_rmdir(torture, tree1, tree2, false);
2501 static bool torture_smb2_notify_rmdir4(struct torture_context *torture,
2502 struct smb2_tree *tree1,
2503 struct smb2_tree *tree2)
2505 return torture_smb2_notify_rmdir(torture, tree1, tree2, true);
2508 static void notify_timeout(struct tevent_context *ev,
2509 struct tevent_timer *te,
2510 struct timeval current_time,
2511 void *private_data)
2513 struct smb2_request *req = talloc_get_type_abort(
2514 private_data, struct smb2_request);
2516 smb2_cancel(req);
2519 #define BASEDIR_INR BASEDIR "_INR"
2521 static bool torture_smb2_inotify_rename(struct torture_context *torture,
2522 struct smb2_tree *tree1,
2523 struct smb2_tree *tree2)
2525 NTSTATUS status;
2526 struct smb2_notify notify;
2527 struct notify_changes change1 = {0};
2528 struct notify_changes change2 = {0};
2529 struct smb2_create create;
2530 union smb_setfileinfo sinfo;
2531 struct smb2_handle h1 = {{0}};
2532 struct smb2_handle h2 = {{0}};
2533 struct smb2_request *req;
2534 struct tevent_timer *te = NULL;
2535 bool ok = false;
2537 smb2_deltree(tree1, BASEDIR_INR);
2539 torture_comment(torture, "Testing change notify of a rename with inotify\n");
2541 status = torture_smb2_testdir(tree1, BASEDIR_INR, &h1);
2542 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "torture_smb2_testdir failed");
2544 ZERO_STRUCT(create);
2545 create.in.desired_access = SEC_RIGHTS_FILE_READ |
2546 SEC_RIGHTS_FILE_WRITE|
2547 SEC_RIGHTS_FILE_ALL;
2548 create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2549 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2550 create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2551 NTCREATEX_SHARE_ACCESS_WRITE |
2552 NTCREATEX_SHARE_ACCESS_DELETE;
2553 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2554 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2555 create.in.fname = BASEDIR_INR "\\subdir-name";
2557 status = smb2_create(tree2, torture, &create);
2558 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_create failed\n");
2559 h2 = create.out.file.handle;
2561 ZERO_STRUCT(notify);
2562 notify.level = RAW_NOTIFY_SMB2;
2563 notify.in.buffer_size = 4096;
2564 notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
2565 notify.in.file.handle = h1;
2566 notify.in.recursive = true;
2567 req = smb2_notify_send(tree1, &notify);
2568 torture_assert_not_null_goto(torture, req, ok, done, "smb2_notify_send failed\n");
2570 while (!NT_STATUS_EQUAL(req->status, NT_STATUS_PENDING)) {
2571 if (tevent_loop_once(torture->ev) != 0) {
2572 goto done;
2576 ZERO_STRUCT(sinfo);
2577 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
2578 sinfo.rename_information.in.file.handle = h2;
2579 sinfo.rename_information.in.new_name = BASEDIR_INR "\\subdir-name-r";
2581 status = smb2_setinfo_file(tree2, &sinfo);
2582 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_setinfo_file failed\n");
2584 smb2_util_close(tree2, h2);
2586 te = tevent_add_timer(torture->ev,
2587 tree1,
2588 tevent_timeval_current_ofs(1, 0),
2589 notify_timeout,
2590 req);
2591 torture_assert_not_null_goto(torture, te, ok, done, "tevent_add_timer failed\n");
2593 status = smb2_notify_recv(req, torture, &notify);
2594 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_notify_recv failed\n");
2596 torture_assert_goto(torture, notify.out.num_changes == 1 || notify.out.num_changes == 2,
2597 ok, done, "bad notify\n");
2599 change1 = notify.out.changes[0];
2600 if (notify.out.num_changes == 2) {
2601 change2 = notify.out.changes[1];
2602 } else {
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.
2608 ZERO_STRUCT(notify);
2609 notify.level = RAW_NOTIFY_SMB2;
2610 notify.in.buffer_size = 4096;
2611 notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
2612 notify.in.file.handle = h1;
2613 notify.in.recursive = true;
2614 req = smb2_notify_send(tree1, &notify);
2615 torture_assert_not_null_goto(torture, req, ok, done, "smb2_notify_send failed\n");
2617 status = smb2_notify_recv(req, torture, &notify);
2618 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_notify_recv failed\n");
2620 torture_assert_goto(torture, notify.out.num_changes == 1, ok, done,
2621 "bad notify\n");
2623 change2 = notify.out.changes[0];
2626 if ((change1.action != NOTIFY_ACTION_OLD_NAME) &&
2627 (change1.action != NOTIFY_ACTION_REMOVED))
2629 torture_fail_goto(torture, done, "bad change notification\n");
2631 torture_assert_str_equal_goto(torture, change1.name.s, "subdir-name",
2632 ok, done, "bad change notification\n");
2634 if ((change2.action != NOTIFY_ACTION_NEW_NAME) &&
2635 (change2.action != NOTIFY_ACTION_ADDED))
2637 torture_fail_goto(torture, done, "bad change notification\n");
2639 torture_assert_str_equal_goto(torture, change2.name.s, "subdir-name-r",
2640 ok, done, "bad change notification\n");
2642 ok = true;
2643 done:
2644 if (!smb2_util_handle_empty(h1)) {
2645 smb2_util_close(tree1, h1);
2647 if (!smb2_util_handle_empty(h2)) {
2648 smb2_util_close(tree2, h2);
2651 smb2_deltree(tree1, BASEDIR_INR);
2652 return ok;
2656 Test asking for a change notify on a handle without permissions.
2659 #define BASEDIR_HPERM BASEDIR "_HPERM"
2661 static bool torture_smb2_notify_handle_permissions(
2662 struct torture_context *torture,
2663 struct smb2_tree *tree)
2665 bool ret = true;
2666 NTSTATUS status;
2667 union smb_notify notify;
2668 union smb_open io;
2669 struct smb2_handle h1 = {{0}};
2670 struct smb2_request *req;
2672 smb2_deltree(tree, BASEDIR_HPERM);
2673 smb2_util_rmdir(tree, BASEDIR_HPERM);
2675 torture_comment(torture,
2676 "TESTING CHANGE NOTIFY "
2677 "ON A HANDLE WITHOUT PERMISSIONS\n");
2680 get a handle on the directory
2682 ZERO_STRUCT(io.smb2);
2683 io.generic.level = RAW_OPEN_SMB2;
2684 io.smb2.in.create_flags = 0;
2685 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
2686 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2687 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2688 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2689 NTCREATEX_SHARE_ACCESS_WRITE;
2690 io.smb2.in.alloc_size = 0;
2691 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2692 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2693 io.smb2.in.security_flags = 0;
2694 io.smb2.in.fname = BASEDIR_HPERM;
2696 status = smb2_create(tree, torture, &io.smb2);
2697 CHECK_STATUS(status, NT_STATUS_OK);
2698 h1 = io.smb2.out.file.handle;
2700 /* ask for a change notify,
2701 on file or directory name changes */
2702 ZERO_STRUCT(notify.smb2);
2703 notify.smb2.level = RAW_NOTIFY_SMB2;
2704 notify.smb2.in.buffer_size = 1000;
2705 notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
2706 notify.smb2.in.file.handle = h1;
2707 notify.smb2.in.recursive = true;
2709 req = smb2_notify_send(tree, &notify.smb2);
2710 torture_assert_goto(torture,
2711 req != NULL,
2712 ret,
2713 done,
2714 "smb2_notify_send failed\n");
2717 * Cancel it, we don't really want to wait.
2719 smb2_cancel(req);
2720 status = smb2_notify_recv(req, torture, &notify.smb2);
2721 /* Handle h1 doesn't have permissions for ChangeNotify. */
2722 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
2724 done:
2725 if (!smb2_util_handle_empty(h1)) {
2726 smb2_util_close(tree, h1);
2728 smb2_deltree(tree, BASEDIR_HPERM);
2729 return ret;
2733 basic testing of SMB2 change notify
2735 struct torture_suite *torture_smb2_notify_init(TALLOC_CTX *ctx)
2737 struct torture_suite *suite = torture_suite_create(ctx, "notify");
2739 torture_suite_add_1smb2_test(suite, "valid-req", test_valid_request);
2740 torture_suite_add_1smb2_test(suite, "tcon", torture_smb2_notify_tcon);
2741 torture_suite_add_2smb2_test(suite, "dir", torture_smb2_notify_dir);
2742 torture_suite_add_2smb2_test(suite, "mask", torture_smb2_notify_mask);
2743 torture_suite_add_1smb2_test(suite, "tdis", torture_smb2_notify_tree_disconnect);
2744 torture_suite_add_1smb2_test(suite, "tdis1", torture_smb2_notify_tree_disconnect_1);
2745 torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
2746 torture_suite_add_1smb2_test(suite, "close", torture_smb2_notify_close);
2747 torture_suite_add_1smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
2748 torture_suite_add_1smb2_test(suite, "session-reconnect", torture_smb2_notify_session_reconnect);
2749 torture_suite_add_2smb2_test(suite, "invalid-reauth", torture_smb2_notify_invalid_reauth);
2750 torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
2751 torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
2752 torture_suite_add_2smb2_test(suite, "double", torture_smb2_notify_double);
2753 torture_suite_add_1smb2_test(suite, "file", torture_smb2_notify_file);
2754 torture_suite_add_1smb2_test(suite, "tcp", torture_smb2_notify_tcp_disconnect);
2755 torture_suite_add_2smb2_test(suite, "rec", torture_smb2_notify_recursive);
2756 torture_suite_add_1smb2_test(suite, "overflow", torture_smb2_notify_overflow);
2757 torture_suite_add_1smb2_test(suite, "rmdir1",
2758 torture_smb2_notify_rmdir1);
2759 torture_suite_add_1smb2_test(suite, "rmdir2",
2760 torture_smb2_notify_rmdir2);
2761 torture_suite_add_2smb2_test(suite, "rmdir3",
2762 torture_smb2_notify_rmdir3);
2763 torture_suite_add_2smb2_test(suite, "rmdir4",
2764 torture_smb2_notify_rmdir4);
2765 torture_suite_add_1smb2_test(suite,
2766 "handle-permissions",
2767 torture_smb2_notify_handle_permissions);
2769 suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests");
2771 return suite;
2775 basic testing of SMB2 change notify
2777 struct torture_suite *torture_smb2_notify_inotify_init(TALLOC_CTX *ctx)
2779 struct torture_suite *suite = torture_suite_create(ctx, "notify-inotify");
2781 suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests that use inotify");
2783 torture_suite_add_2smb2_test(suite, "inotify-rename", torture_smb2_inotify_rename);
2785 return suite;