2 Unix SMB/CIFS implementation.
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/>.
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/popt_common.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)); \
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); \
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, \
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) { \
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
)
87 struct smb2_handle dh
;
89 struct smb2_request
*req
;
90 uint32_t max_buffer_size
;
92 torture_comment(torture
, "TESTING VALIDITY OF CHANGE NOTIFY REQUEST\n");
94 smb2_util_unlink(tree
, FNAME
);
96 status
= smb2_util_roothandle(tree
, &dh
);
97 CHECK_STATUS(status
, NT_STATUS_OK
);
99 /* 0x00080000 is the default max buffer size for Windows servers
101 max_buffer_size
= torture_setting_ulong(torture
, "cn_max_buffer_size",
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) {
117 status
= torture_setup_complex_file(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) {
139 status
= torture_setup_complex_file(tree
, FNAME
);
140 CHECK_STATUS(status
, NT_STATUS_OK
);
142 status
= smb2_notify_recv(req
, torture
, &n
);
143 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
146 * if the change response fits in the buffer we get
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) {
158 status
= torture_setup_complex_file(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) {
190 status
= torture_setup_complex_file(tree
, FNAME
);
191 CHECK_STATUS(status
, NT_STATUS_OK
);
193 status
= smb2_notify_recv(req
, torture
, &n
);
194 CHECK_STATUS(status
, 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) {
204 status
= torture_setup_complex_file(tree
, FNAME
);
205 CHECK_STATUS(status
, NT_STATUS_OK
);
207 status
= smb2_notify_recv(req
, torture
, &n
);
208 CHECK_STATUS(status
, 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
);
225 basic testing of change notify on directories
227 static bool torture_smb2_notify_dir(struct torture_context
*torture
,
228 struct smb2_tree
*tree1
,
229 struct smb2_tree
*tree2
)
233 union smb_notify notify
;
237 struct smb2_handle h1
, h2
;
238 struct smb2_request
*req
, *req2
;
239 const char *fname
= BASEDIR
"\\subdir-name";
240 extern int torture_numops
;
242 torture_comment(torture
, "TESTING CHANGE NOTIFY ON DIRECTORIES\n");
244 smb2_deltree(tree1
, BASEDIR
);
245 smb2_util_rmdir(tree1
, BASEDIR
);
247 get a handle on the directory
249 ZERO_STRUCT(io
.smb2
);
250 io
.generic
.level
= RAW_OPEN_SMB2
;
251 io
.smb2
.in
.create_flags
= 0;
252 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
253 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
254 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
255 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
256 NTCREATEX_SHARE_ACCESS_WRITE
;
257 io
.smb2
.in
.alloc_size
= 0;
258 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
259 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
260 io
.smb2
.in
.security_flags
= 0;
261 io
.smb2
.in
.fname
= BASEDIR
;
263 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
264 CHECK_STATUS(status
, NT_STATUS_OK
);
265 h1
= io
.smb2
.out
.file
.handle
;
267 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
268 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
;
269 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
270 CHECK_STATUS(status
, NT_STATUS_OK
);
271 h2
= io
.smb2
.out
.file
.handle
;
273 /* ask for a change notify,
274 on file or directory name changes */
275 ZERO_STRUCT(notify
.smb2
);
276 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
277 notify
.smb2
.in
.buffer_size
= 1000;
278 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
279 notify
.smb2
.in
.file
.handle
= h1
;
280 notify
.smb2
.in
.recursive
= true;
282 torture_comment(torture
, "Testing notify cancel\n");
284 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
286 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
287 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
289 torture_comment(torture
, "Testing notify mkdir\n");
291 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
292 smb2_util_mkdir(tree2
, fname
);
294 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
295 CHECK_STATUS(status
, NT_STATUS_OK
);
297 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
298 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
299 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
301 torture_comment(torture
, "Testing notify rmdir\n");
303 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
304 smb2_util_rmdir(tree2
, fname
);
306 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
307 CHECK_STATUS(status
, NT_STATUS_OK
);
308 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
309 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
310 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
312 torture_comment(torture
,
313 "Testing notify mkdir - rmdir - mkdir - rmdir\n");
315 smb2_util_mkdir(tree2
, fname
);
316 smb2_util_rmdir(tree2
, fname
);
317 smb2_util_mkdir(tree2
, fname
);
318 smb2_util_rmdir(tree2
, fname
);
320 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
321 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
322 CHECK_STATUS(status
, NT_STATUS_OK
);
323 CHECK_VAL(notify
.smb2
.out
.num_changes
, 4);
324 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
325 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
326 CHECK_VAL(notify
.smb2
.out
.changes
[1].action
, NOTIFY_ACTION_REMOVED
);
327 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[1].name
, "subdir-name");
328 CHECK_VAL(notify
.smb2
.out
.changes
[2].action
, NOTIFY_ACTION_ADDED
);
329 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[2].name
, "subdir-name");
330 CHECK_VAL(notify
.smb2
.out
.changes
[3].action
, NOTIFY_ACTION_REMOVED
);
331 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[3].name
, "subdir-name");
333 count
= torture_numops
;
334 torture_comment(torture
,
335 "Testing buffered notify on create of %d files\n", count
);
336 for (i
=0;i
<count
;i
++) {
337 struct smb2_handle h12
;
338 char *fname2
= talloc_asprintf(torture
, BASEDIR
"\\test%d.txt",
341 ZERO_STRUCT(io
.smb2
);
342 io
.generic
.level
= RAW_OPEN_SMB2
;
343 io
.smb2
.in
.create_flags
= 0;
344 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
345 io
.smb2
.in
.create_options
=
346 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
347 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
348 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
349 NTCREATEX_SHARE_ACCESS_WRITE
;
350 io
.smb2
.in
.alloc_size
= 0;
351 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
352 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
353 io
.smb2
.in
.security_flags
= 0;
354 io
.smb2
.in
.fname
= fname2
;
356 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
357 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
358 torture_comment(torture
, "Failed to create %s \n",
363 h12
= io
.smb2
.out
.file
.handle
;
365 smb2_util_close(tree1
, h12
);
368 /* (1st notify) setup a new notify on a different directory handle.
369 This new notify won't see the events above. */
370 notify
.smb2
.in
.file
.handle
= h2
;
371 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
373 /* (2nd notify) whereas this notify will see the above buffered events,
374 and it directly returns the buffered events */
375 notify
.smb2
.in
.file
.handle
= h1
;
376 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
378 status
= smb2_util_unlink(tree1
, BASEDIR
"\\nonexistent.txt");
379 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
381 /* (1st unlink) as the 2nd notify directly returns,
382 this unlink is only seen by the 1st notify and
383 the 3rd notify (later) */
384 torture_comment(torture
,
385 "Testing notify on unlink for the first file\n");
386 status
= smb2_util_unlink(tree2
, BASEDIR
"\\test0.txt");
387 CHECK_STATUS(status
, NT_STATUS_OK
);
389 /* receive the reply from the 2nd notify */
390 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
391 CHECK_STATUS(status
, NT_STATUS_OK
);
393 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
);
394 for (i
=1;i
<count
;i
++) {
395 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
396 NOTIFY_ACTION_ADDED
);
398 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
400 torture_comment(torture
, "and now from the 1st notify\n");
401 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
402 CHECK_STATUS(status
, NT_STATUS_OK
);
403 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
404 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
405 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
407 torture_comment(torture
,
408 "(3rd notify) this notify will only see the 1st unlink\n");
409 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
411 status
= smb2_util_unlink(tree1
, BASEDIR
"\\nonexistent.txt");
412 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
414 for (i
=1;i
<count
;i
++) {
415 char *fname2
= talloc_asprintf(torture
,
416 BASEDIR
"\\test%d.txt", i
);
417 status
= smb2_util_unlink(tree2
, fname2
);
418 CHECK_STATUS(status
, NT_STATUS_OK
);
422 /* receive the 3rd notify */
423 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
424 CHECK_STATUS(status
, NT_STATUS_OK
);
425 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
426 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
427 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
429 /* and we now see the rest of the unlink calls on both
430 * directory handles */
431 notify
.smb2
.in
.file
.handle
= h1
;
433 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
434 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
435 CHECK_STATUS(status
, NT_STATUS_OK
);
436 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
-1);
437 for (i
=0;i
<notify
.smb2
.out
.num_changes
;i
++) {
438 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
439 NOTIFY_ACTION_REMOVED
);
441 notify
.smb2
.in
.file
.handle
= h2
;
442 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
443 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
444 CHECK_STATUS(status
, NT_STATUS_OK
);
445 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
-1);
446 for (i
=0;i
<notify
.smb2
.out
.num_changes
;i
++) {
447 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
448 NOTIFY_ACTION_REMOVED
);
451 torture_comment(torture
,
452 "Testing if a close() on the dir handle triggers the notify reply\n");
454 notify
.smb2
.in
.file
.handle
= h1
;
455 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
457 ZERO_STRUCT(cl
.smb2
);
458 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
459 cl
.smb2
.in
.file
.handle
= h1
;
460 status
= smb2_close(tree1
, &(cl
.smb2
));
461 CHECK_STATUS(status
, NT_STATUS_OK
);
463 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
464 CHECK_STATUS(status
, STATUS_NOTIFY_CLEANUP
);
465 CHECK_VAL(notify
.smb2
.out
.num_changes
, 9);
468 smb2_util_close(tree1
, h1
);
469 smb2_util_close(tree1
, h2
);
470 smb2_deltree(tree1
, BASEDIR
);
474 static struct smb2_handle
custom_smb2_create(struct smb2_tree
*tree
,
475 struct torture_context
*torture
,
476 struct smb2_create
*smb2
)
478 struct smb2_handle h1
;
481 smb2_deltree(tree
, smb2
->in
.fname
);
482 status
= smb2_create(tree
, torture
, smb2
);
483 CHECK_STATUS(status
, NT_STATUS_OK
);
484 h1
= smb2
->out
.file
.handle
;
490 testing of recursive change notify
493 static bool torture_smb2_notify_recursive(struct torture_context
*torture
,
494 struct smb2_tree
*tree1
,
495 struct smb2_tree
*tree2
)
499 union smb_notify notify
;
500 union smb_open io
, io1
;
501 union smb_setfileinfo sinfo
;
502 struct smb2_handle h1
;
503 struct smb2_request
*req1
, *req2
;
505 smb2_deltree(tree1
, BASEDIR
);
506 smb2_util_rmdir(tree1
, BASEDIR
);
508 torture_comment(torture
, "TESTING CHANGE NOTIFY WITH RECURSION\n");
511 get a handle on the directory
513 ZERO_STRUCT(io
.smb2
);
514 io
.generic
.level
= RAW_OPEN_SMB2
;
515 io
.smb2
.in
.create_flags
= 0;
516 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
517 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
518 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
519 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
520 NTCREATEX_SHARE_ACCESS_WRITE
;
521 io
.smb2
.in
.alloc_size
= 0;
522 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
523 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
524 io
.smb2
.in
.security_flags
= 0;
525 io
.smb2
.in
.fname
= BASEDIR
;
527 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
528 CHECK_STATUS(status
, NT_STATUS_OK
);
529 h1
= io
.smb2
.out
.file
.handle
;
531 /* ask for a change notify, on file or directory name
532 changes. Setup both with and without recursion */
533 ZERO_STRUCT(notify
.smb2
);
534 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
535 notify
.smb2
.in
.buffer_size
= 1000;
536 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
|
537 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
538 FILE_NOTIFY_CHANGE_CREATION
;
539 notify
.smb2
.in
.file
.handle
= h1
;
541 notify
.smb2
.in
.recursive
= true;
542 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
544 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
545 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
547 notify
.smb2
.in
.recursive
= false;
548 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
550 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
551 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
553 ZERO_STRUCT(io1
.smb2
);
554 io1
.generic
.level
= RAW_OPEN_SMB2
;
555 io1
.smb2
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
556 io1
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
557 SEC_RIGHTS_FILE_WRITE
|
559 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
560 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
561 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
562 NTCREATEX_SHARE_ACCESS_WRITE
|
563 NTCREATEX_SHARE_ACCESS_DELETE
;
564 io1
.smb2
.in
.alloc_size
= 0;
565 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
566 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
567 io1
.smb2
.in
.security_flags
= 0;
568 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name";
569 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
570 CHECK_STATUS(status
, NT_STATUS_OK
);
571 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
573 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname1";
574 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
575 CHECK_STATUS(status
, NT_STATUS_OK
);
577 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
578 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
579 sinfo
.rename_information
.in
.overwrite
= 0;
580 sinfo
.rename_information
.in
.root_fid
= 0;
581 sinfo
.rename_information
.in
.new_name
=
582 BASEDIR
"\\subdir-name\\subname1-r";
583 status
= smb2_setinfo_file(tree2
, &sinfo
);
584 CHECK_STATUS(status
, NT_STATUS_OK
);
586 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
587 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname2";
588 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
589 CHECK_STATUS(status
, NT_STATUS_OK
);
591 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
592 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
593 sinfo
.rename_information
.in
.overwrite
= true;
594 sinfo
.rename_information
.in
.root_fid
= 0;
595 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname2-r";
596 status
= smb2_setinfo_file(tree2
, &sinfo
);
597 CHECK_STATUS(status
, NT_STATUS_OK
);
599 io1
.smb2
.in
.fname
= BASEDIR
"\\subname2-r";
600 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
601 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
602 CHECK_STATUS(status
, NT_STATUS_OK
);
604 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
605 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
606 sinfo
.rename_information
.in
.overwrite
= true;
607 sinfo
.rename_information
.in
.root_fid
= 0;
608 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname3-r";
609 status
= smb2_setinfo_file(tree2
, &sinfo
);
610 CHECK_STATUS(status
, NT_STATUS_OK
);
612 notify
.smb2
.in
.completion_filter
= 0;
613 notify
.smb2
.in
.recursive
= true;
615 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
617 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name\\subname1-r");
618 CHECK_STATUS(status
, NT_STATUS_OK
);
619 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name");
620 CHECK_STATUS(status
, NT_STATUS_OK
);
621 status
= smb2_util_unlink(tree2
, BASEDIR
"\\subname3-r");
622 CHECK_STATUS(status
, NT_STATUS_OK
);
624 notify
.smb2
.in
.recursive
= false;
625 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
627 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
628 CHECK_STATUS(status
, NT_STATUS_OK
);
630 CHECK_VAL(notify
.smb2
.out
.num_changes
, 9);
631 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
632 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
633 CHECK_VAL(notify
.smb2
.out
.changes
[1].action
, NOTIFY_ACTION_ADDED
);
634 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[1].name
, "subdir-name\\subname1");
635 CHECK_VAL(notify
.smb2
.out
.changes
[2].action
, NOTIFY_ACTION_OLD_NAME
);
636 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[2].name
, "subdir-name\\subname1");
637 CHECK_VAL(notify
.smb2
.out
.changes
[3].action
, NOTIFY_ACTION_NEW_NAME
);
638 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[3].name
, "subdir-name\\subname1-r");
639 CHECK_VAL(notify
.smb2
.out
.changes
[4].action
, NOTIFY_ACTION_ADDED
);
640 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[4].name
, "subdir-name\\subname2");
641 CHECK_VAL(notify
.smb2
.out
.changes
[5].action
, NOTIFY_ACTION_REMOVED
);
642 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[5].name
, "subdir-name\\subname2");
643 CHECK_VAL(notify
.smb2
.out
.changes
[6].action
, NOTIFY_ACTION_ADDED
);
644 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[6].name
, "subname2-r");
645 CHECK_VAL(notify
.smb2
.out
.changes
[7].action
, NOTIFY_ACTION_OLD_NAME
);
646 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[7].name
, "subname2-r");
647 CHECK_VAL(notify
.smb2
.out
.changes
[8].action
, NOTIFY_ACTION_NEW_NAME
);
648 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[8].name
, "subname3-r");
651 smb2_deltree(tree1
, BASEDIR
);
656 testing of change notify mask change
659 static bool torture_smb2_notify_mask_change(struct torture_context
*torture
,
660 struct smb2_tree
*tree1
,
661 struct smb2_tree
*tree2
)
665 union smb_notify notify
;
666 union smb_open io
, io1
;
667 struct smb2_handle h1
;
668 struct smb2_request
*req1
, *req2
;
669 union smb_setfileinfo sinfo
;
671 smb2_deltree(tree1
, BASEDIR
);
672 smb2_util_rmdir(tree1
, BASEDIR
);
674 torture_comment(torture
, "TESTING CHANGE NOTIFY WITH MASK CHANGE\n");
677 get a handle on the directory
679 ZERO_STRUCT(io
.smb2
);
680 io
.generic
.level
= RAW_OPEN_SMB2
;
681 io
.smb2
.in
.create_flags
= 0;
682 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
683 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
684 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
685 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
686 NTCREATEX_SHARE_ACCESS_WRITE
;
687 io
.smb2
.in
.alloc_size
= 0;
688 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
689 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
690 io
.smb2
.in
.security_flags
= 0;
691 io
.smb2
.in
.fname
= BASEDIR
;
693 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
694 CHECK_STATUS(status
, NT_STATUS_OK
);
695 h1
= io
.smb2
.out
.file
.handle
;
697 /* ask for a change notify, on file or directory name
698 changes. Setup both with and without recursion */
699 ZERO_STRUCT(notify
.smb2
);
700 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
701 notify
.smb2
.in
.buffer_size
= 1000;
702 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
703 notify
.smb2
.in
.file
.handle
= h1
;
705 notify
.smb2
.in
.recursive
= true;
706 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
709 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
710 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
713 notify
.smb2
.in
.recursive
= false;
714 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
717 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
718 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
720 notify
.smb2
.in
.recursive
= true;
721 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
723 /* Set to hidden then back again. */
724 ZERO_STRUCT(io1
.smb2
);
725 io1
.generic
.level
= RAW_OPEN_SMB2
;
726 io1
.smb2
.in
.create_flags
= 0;
727 io1
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
728 SEC_RIGHTS_FILE_WRITE
|
730 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
731 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
732 NTCREATEX_SHARE_ACCESS_WRITE
|
733 NTCREATEX_SHARE_ACCESS_DELETE
;
734 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
735 io1
.smb2
.in
.security_flags
= 0;
736 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
737 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
738 io1
.smb2
.in
.fname
= BASEDIR
"\\tname1";
740 smb2_util_close(tree1
,
741 custom_smb2_create(tree1
, torture
, &(io1
.smb2
)));
742 status
= smb2_util_setatr(tree1
, BASEDIR
"\\tname1",
743 FILE_ATTRIBUTE_HIDDEN
);
744 CHECK_STATUS(status
, NT_STATUS_OK
);
745 smb2_util_unlink(tree1
, BASEDIR
"\\tname1");
747 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
748 CHECK_STATUS(status
, NT_STATUS_OK
);
750 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
751 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
752 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "tname1");
754 /* Now try and change the mask to include other events.
755 * This should not work - once the mask is set on a directory
756 * h1 it seems to be fixed until the fnum is closed. */
758 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
|
759 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
760 FILE_NOTIFY_CHANGE_CREATION
;
761 notify
.smb2
.in
.recursive
= true;
762 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
764 notify
.smb2
.in
.recursive
= false;
765 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
767 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
768 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
769 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name";
770 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
771 CHECK_STATUS(status
, NT_STATUS_OK
);
772 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
775 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname1";
776 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
777 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
778 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
779 CHECK_STATUS(status
, NT_STATUS_OK
);
780 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
781 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
782 sinfo
.rename_information
.in
.overwrite
= true;
783 sinfo
.rename_information
.in
.root_fid
= 0;
784 sinfo
.rename_information
.in
.new_name
=
785 BASEDIR
"\\subdir-name\\subname1-r";
786 status
= smb2_setinfo_file(tree2
, &sinfo
);
787 CHECK_STATUS(status
, NT_STATUS_OK
);
789 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname2";
790 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
791 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
792 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
793 CHECK_STATUS(status
, NT_STATUS_OK
);
794 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
795 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname2-r";
796 status
= smb2_setinfo_file(tree2
, &sinfo
);
797 CHECK_STATUS(status
, NT_STATUS_OK
);
798 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
800 io1
.smb2
.in
.fname
= BASEDIR
"\\subname2-r";
801 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
802 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
803 CHECK_STATUS(status
, NT_STATUS_OK
);
804 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
805 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname3-r";
806 status
= smb2_setinfo_file(tree2
, &sinfo
);
807 CHECK_STATUS(status
, NT_STATUS_OK
);
808 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
810 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name\\subname1-r");
811 CHECK_STATUS(status
, NT_STATUS_OK
);
812 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name");
813 CHECK_STATUS(status
, NT_STATUS_OK
);
814 status
= smb2_util_unlink(tree2
, BASEDIR
"\\subname3-r");
815 CHECK_STATUS(status
, NT_STATUS_OK
);
817 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
818 CHECK_STATUS(status
, NT_STATUS_OK
);
820 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
821 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
822 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subname2-r");
824 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
825 CHECK_STATUS(status
, NT_STATUS_OK
);
827 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
828 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
829 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subname3-r");
836 smb2_deltree(tree1
, BASEDIR
);
841 testing of mask bits for change notify
844 static bool torture_smb2_notify_mask(struct torture_context
*torture
,
845 struct smb2_tree
*tree1
,
846 struct smb2_tree
*tree2
)
850 union smb_notify notify
;
851 union smb_open io
, io1
;
852 struct smb2_handle h1
, h2
;
856 union smb_setfileinfo sinfo
;
858 smb2_deltree(tree1
, BASEDIR
);
859 smb2_util_rmdir(tree1
, BASEDIR
);
861 torture_comment(torture
, "TESTING CHANGE NOTIFY COMPLETION FILTERS\n");
865 get a handle on the directory
867 ZERO_STRUCT(io
.smb2
);
868 io
.generic
.level
= RAW_OPEN_SMB2
;
869 io
.smb2
.in
.create_flags
= 0;
870 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
871 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
872 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
873 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
874 NTCREATEX_SHARE_ACCESS_WRITE
;
875 io
.smb2
.in
.alloc_size
= 0;
876 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
877 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
878 io
.smb2
.in
.security_flags
= 0;
879 io
.smb2
.in
.fname
= BASEDIR
;
881 ZERO_STRUCT(notify
.smb2
);
882 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
883 notify
.smb2
.in
.buffer_size
= 1000;
884 notify
.smb2
.in
.recursive
= true;
886 #define NOTIFY_MASK_TEST(test_name, setup, op, cleanup, Action, \
887 expected, nchanges) \
889 do { for (mask=i=0;i<32;i++) { \
890 struct smb2_request *req; \
891 status = smb2_create(tree1, torture, &(io.smb2)); \
892 CHECK_STATUS(status, NT_STATUS_OK); \
893 h1 = io.smb2.out.file.handle; \
895 notify.smb2.in.file.handle = h1; \
896 notify.smb2.in.completion_filter = (1<<i); \
897 /* cancel initial requests so the buffer is setup */ \
898 req = smb2_notify_send(tree1, &(notify.smb2)); \
900 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
901 CHECK_STATUS(status, NT_STATUS_CANCELLED); \
902 /* send the change notify request */ \
903 req = smb2_notify_send(tree1, &(notify.smb2)); \
905 smb_msleep(200); smb2_cancel(req); \
906 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
908 smb2_util_close(tree1, h1); \
909 if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \
910 CHECK_STATUS(status, NT_STATUS_OK); \
911 /* special case to cope with file rename behaviour */ \
912 if (nchanges == 2 && notify.smb2.out.num_changes == 1 && \
913 notify.smb2.out.changes[0].action == \
914 NOTIFY_ACTION_MODIFIED && \
915 ((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \
916 Action == NOTIFY_ACTION_OLD_NAME) { \
917 torture_comment(torture, \
918 "(rename file special handling OK)\n"); \
919 } else if (nchanges != notify.smb2.out.num_changes) { \
920 torture_result(torture, TORTURE_FAIL, \
921 "ERROR: nchanges=%d expected=%d "\
922 "action=%d filter=0x%08x\n", \
923 notify.smb2.out.num_changes, \
925 notify.smb2.out.changes[0].action, \
926 notify.smb2.in.completion_filter); \
928 } else if (notify.smb2.out.changes[0].action != Action) { \
929 torture_result(torture, TORTURE_FAIL, \
930 "ERROR: nchanges=%d action=%d " \
931 "expectedAction=%d filter=0x%08x\n", \
932 notify.smb2.out.num_changes, \
933 notify.smb2.out.changes[0].action, \
935 notify.smb2.in.completion_filter); \
937 } else if (strcmp(notify.smb2.out.changes[0].name.s, \
939 torture_result(torture, TORTURE_FAIL, \
940 "ERROR: nchanges=%d action=%d " \
941 "filter=0x%08x name=%s\n", \
942 notify.smb2.out.num_changes, \
943 notify.smb2.out.changes[0].action, \
944 notify.smb2.in.completion_filter, \
945 notify.smb2.out.changes[0].name.s); \
953 torture_comment(torture
, "Testing mkdir\n");
954 NOTIFY_MASK_TEST("Testing mkdir",;,
955 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
956 smb2_util_rmdir(tree2
, BASEDIR
"\\tname1");,
958 FILE_NOTIFY_CHANGE_DIR_NAME
, 1);
960 torture_comment(torture
, "Testing create file\n");
961 ZERO_STRUCT(io1
.smb2
);
962 io1
.generic
.level
= RAW_OPEN_SMB2
;
963 io1
.smb2
.in
.create_flags
= 0;
964 io1
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
965 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
966 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
967 NTCREATEX_SHARE_ACCESS_WRITE
;
968 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
969 io1
.smb2
.in
.security_flags
= 0;
970 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
971 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
972 io1
.smb2
.in
.fname
= BASEDIR
"\\tname1";
974 NOTIFY_MASK_TEST("Testing create file",;,
975 smb2_util_close(tree2
, custom_smb2_create(tree2
,
976 torture
, &(io1
.smb2
)));,
977 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
979 FILE_NOTIFY_CHANGE_FILE_NAME
, 1);
981 torture_comment(torture
, "Testing unlink\n");
982 NOTIFY_MASK_TEST("Testing unlink",
983 smb2_util_close(tree2
, custom_smb2_create(tree2
,
984 torture
, &(io1
.smb2
)));,
985 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
987 NOTIFY_ACTION_REMOVED
,
988 FILE_NOTIFY_CHANGE_FILE_NAME
, 1);
990 torture_comment(torture
, "Testing rmdir\n");
991 NOTIFY_MASK_TEST("Testing rmdir",
992 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
993 smb2_util_rmdir(tree2
, BASEDIR
"\\tname1");,
995 NOTIFY_ACTION_REMOVED
,
996 FILE_NOTIFY_CHANGE_DIR_NAME
, 1);
998 torture_comment(torture
, "Testing rename file\n");
1000 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1001 sinfo
.rename_information
.in
.file
.handle
= h1
;
1002 sinfo
.rename_information
.in
.overwrite
= true;
1003 sinfo
.rename_information
.in
.root_fid
= 0;
1004 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\tname2";
1005 NOTIFY_MASK_TEST("Testing rename file",
1006 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1007 torture
, &(io1
.smb2
)));,
1008 smb2_setinfo_file(tree2
, &sinfo
);,
1009 smb2_util_unlink(tree2
, BASEDIR
"\\tname2");,
1010 NOTIFY_ACTION_OLD_NAME
,
1011 FILE_NOTIFY_CHANGE_FILE_NAME
, 2);
1013 torture_comment(torture
, "Testing rename dir\n");
1015 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1016 sinfo
.rename_information
.in
.file
.handle
= h1
;
1017 sinfo
.rename_information
.in
.overwrite
= true;
1018 sinfo
.rename_information
.in
.root_fid
= 0;
1019 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\tname2";
1020 NOTIFY_MASK_TEST("Testing rename dir",
1021 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
1022 smb2_setinfo_file(tree2
, &sinfo
);,
1023 smb2_util_rmdir(tree2
, BASEDIR
"\\tname2");,
1024 NOTIFY_ACTION_OLD_NAME
,
1025 FILE_NOTIFY_CHANGE_DIR_NAME
, 2);
1027 torture_comment(torture
, "Testing set path attribute\n");
1028 NOTIFY_MASK_TEST("Testing set path attribute",
1029 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1030 torture
, &(io
.smb2
)));,
1031 smb2_util_setatr(tree2
, BASEDIR
"\\tname1",
1032 FILE_ATTRIBUTE_HIDDEN
);,
1033 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
1034 NOTIFY_ACTION_MODIFIED
,
1035 FILE_NOTIFY_CHANGE_ATTRIBUTES
, 1);
1037 torture_comment(torture
, "Testing set path write time\n");
1039 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1040 sinfo
.generic
.in
.file
.handle
= h1
;
1041 sinfo
.basic_info
.in
.write_time
= 1000;
1042 NOTIFY_MASK_TEST("Testing set path write time",
1043 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1044 torture
, &(io1
.smb2
)));,
1045 smb2_setinfo_file(tree2
, &sinfo
);,
1046 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
1047 NOTIFY_ACTION_MODIFIED
,
1048 FILE_NOTIFY_CHANGE_LAST_WRITE
, 1);
1050 if (torture_setting_bool(torture
, "samba3", false)) {
1051 torture_comment(torture
,
1052 "Samba3 does not yet support create times "
1057 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1058 sinfo
.generic
.in
.file
.handle
= h1
;
1059 sinfo
.basic_info
.in
.create_time
= 0;
1060 torture_comment(torture
, "Testing set file create time\n");
1061 NOTIFY_MASK_TEST("Testing set file create time",
1062 smb2_create_complex_file(tree2
,
1063 BASEDIR
"\\tname1", &h2
);,
1064 smb2_setinfo_file(tree2
, &sinfo
);,
1065 (smb2_util_close(tree2
, h2
),
1066 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1067 NOTIFY_ACTION_MODIFIED
,
1068 FILE_NOTIFY_CHANGE_CREATION
, 1);
1072 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1073 sinfo
.generic
.in
.file
.handle
= h1
;
1074 sinfo
.basic_info
.in
.access_time
= 0;
1075 torture_comment(torture
, "Testing set file access time\n");
1076 NOTIFY_MASK_TEST("Testing set file access time",
1077 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1078 smb2_setinfo_file(tree2
, &sinfo
);,
1079 (smb2_util_close(tree2
, h2
),
1080 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1081 NOTIFY_ACTION_MODIFIED
,
1082 FILE_NOTIFY_CHANGE_LAST_ACCESS
, 1);
1085 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1086 sinfo
.generic
.in
.file
.handle
= h1
;
1087 sinfo
.basic_info
.in
.change_time
= 0;
1088 torture_comment(torture
, "Testing set file change time\n");
1089 NOTIFY_MASK_TEST("Testing set file change time",
1090 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1091 smb2_setinfo_file(tree2
, &sinfo
);,
1092 (smb2_util_close(tree2
, h2
),
1093 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1094 NOTIFY_ACTION_MODIFIED
,
1098 torture_comment(torture
, "Testing write\n");
1099 NOTIFY_MASK_TEST("Testing write",
1100 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1101 smb2_util_write(tree2
, h2
, &c
, 10000, 1);,
1102 (smb2_util_close(tree2
, h2
),
1103 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1104 NOTIFY_ACTION_MODIFIED
,
1108 smb2_deltree(tree1
, BASEDIR
);
1113 basic testing of change notify on files
1115 static bool torture_smb2_notify_file(struct torture_context
*torture
,
1116 struct smb2_tree
*tree
)
1122 union smb_notify notify
;
1123 struct smb2_request
*req
;
1124 struct smb2_handle h1
;
1125 const char *fname
= BASEDIR
"\\file.txt";
1127 smb2_deltree(tree
, BASEDIR
);
1128 smb2_util_rmdir(tree
, BASEDIR
);
1130 torture_comment(torture
, "TESTING CHANGE NOTIFY ON FILES\n");
1131 status
= torture_smb2_testdir(tree
, BASEDIR
, &h1
);
1132 CHECK_STATUS(status
, NT_STATUS_OK
);
1134 ZERO_STRUCT(io
.smb2
);
1135 io
.generic
.level
= RAW_OPEN_SMB2
;
1136 io
.smb2
.in
.create_flags
= 0;
1137 io
.smb2
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
1138 io
.smb2
.in
.create_options
= 0;
1139 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1140 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1141 NTCREATEX_SHARE_ACCESS_WRITE
;
1142 io
.smb2
.in
.alloc_size
= 0;
1143 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1144 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1145 io
.smb2
.in
.security_flags
= 0;
1146 io
.smb2
.in
.fname
= fname
;
1147 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1148 CHECK_STATUS(status
, NT_STATUS_OK
);
1149 h1
= io
.smb2
.out
.file
.handle
;
1151 /* ask for a change notify,
1152 on file or directory name changes */
1153 ZERO_STRUCT(notify
.smb2
);
1154 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1155 notify
.smb2
.in
.file
.handle
= h1
;
1156 notify
.smb2
.in
.buffer_size
= 1000;
1157 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_STREAM_NAME
;
1158 notify
.smb2
.in
.recursive
= false;
1160 torture_comment(torture
,
1161 "Testing if notifies on file handles are invalid (should be)\n");
1163 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1164 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1165 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
1167 ZERO_STRUCT(cl
.smb2
);
1168 cl
.close
.level
= RAW_CLOSE_SMB2
;
1169 cl
.close
.in
.file
.handle
= h1
;
1170 status
= smb2_close(tree
, &(cl
.smb2
));
1171 CHECK_STATUS(status
, NT_STATUS_OK
);
1173 status
= smb2_util_unlink(tree
, fname
);
1174 CHECK_STATUS(status
, NT_STATUS_OK
);
1177 smb2_deltree(tree
, BASEDIR
);
1181 basic testing of change notifies followed by a tdis
1184 static bool torture_smb2_notify_tree_disconnect(
1185 struct torture_context
*torture
,
1186 struct smb2_tree
*tree
)
1190 union smb_notify notify
;
1192 struct smb2_handle h1
;
1193 struct smb2_request
*req
;
1195 smb2_deltree(tree
, BASEDIR
);
1196 smb2_util_rmdir(tree
, BASEDIR
);
1198 torture_comment(torture
, "TESTING CHANGE NOTIFY+CANCEL FOLLOWED BY "
1199 "TREE-DISCONNECT\n");
1202 get a handle on the directory
1204 ZERO_STRUCT(io
.smb2
);
1205 io
.generic
.level
= RAW_OPEN_SMB2
;
1206 io
.smb2
.in
.create_flags
= 0;
1207 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1208 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1209 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1210 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1211 NTCREATEX_SHARE_ACCESS_WRITE
;
1212 io
.smb2
.in
.alloc_size
= 0;
1213 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1214 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1215 io
.smb2
.in
.security_flags
= 0;
1216 io
.smb2
.in
.fname
= BASEDIR
;
1218 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1219 CHECK_STATUS(status
, NT_STATUS_OK
);
1220 h1
= io
.smb2
.out
.file
.handle
;
1222 /* ask for a change notify,
1223 on file or directory name changes */
1224 ZERO_STRUCT(notify
.smb2
);
1225 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1226 notify
.smb2
.in
.buffer_size
= 1000;
1227 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1228 notify
.smb2
.in
.file
.handle
= h1
;
1229 notify
.smb2
.in
.recursive
= true;
1231 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1233 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1235 status
= smb2_tdis(tree
);
1236 CHECK_STATUS(status
, NT_STATUS_OK
);
1238 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1240 smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1241 CHECK_STATUS(status
, NT_STATUS_OK
);
1242 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1245 smb2_deltree(tree
, BASEDIR
);
1250 testing of change notifies followed by a tdis - no cancel
1253 static bool torture_smb2_notify_tree_disconnect_1(
1254 struct torture_context
*torture
,
1255 struct smb2_tree
*tree
)
1259 union smb_notify notify
;
1261 struct smb2_handle h1
;
1262 struct smb2_request
*req
;
1264 smb2_deltree(tree
, BASEDIR
);
1265 smb2_util_rmdir(tree
, BASEDIR
);
1267 torture_comment(torture
, "TESTING CHANGE NOTIFY ASYNC FOLLOWED BY "
1268 "TREE-DISCONNECT\n");
1271 get a handle on the directory
1273 ZERO_STRUCT(io
.smb2
);
1274 io
.generic
.level
= RAW_OPEN_SMB2
;
1275 io
.smb2
.in
.create_flags
= 0;
1276 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1277 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1278 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1279 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1280 NTCREATEX_SHARE_ACCESS_WRITE
;
1281 io
.smb2
.in
.alloc_size
= 0;
1282 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1283 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1284 io
.smb2
.in
.security_flags
= 0;
1285 io
.smb2
.in
.fname
= BASEDIR
;
1287 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1288 CHECK_STATUS(status
, NT_STATUS_OK
);
1289 h1
= io
.smb2
.out
.file
.handle
;
1291 /* ask for a change notify,
1292 on file or directory name changes */
1293 ZERO_STRUCT(notify
.smb2
);
1294 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1295 notify
.smb2
.in
.buffer_size
= 1000;
1296 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1297 notify
.smb2
.in
.file
.handle
= h1
;
1298 notify
.smb2
.in
.recursive
= true;
1300 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1301 WAIT_FOR_ASYNC_RESPONSE(req
);
1303 status
= smb2_tdis(tree
);
1304 CHECK_STATUS(status
, NT_STATUS_OK
);
1306 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1307 CHECK_STATUS(status
, STATUS_NOTIFY_CLEANUP
);
1308 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1311 smb2_deltree(tree
, BASEDIR
);
1316 basic testing of change notifies followed by a close
1319 static bool torture_smb2_notify_close(struct torture_context
*torture
,
1320 struct smb2_tree
*tree1
)
1324 union smb_notify notify
;
1326 struct smb2_handle h1
;
1327 struct smb2_request
*req
;
1329 smb2_deltree(tree1
, BASEDIR
);
1330 smb2_util_rmdir(tree1
, BASEDIR
);
1332 torture_comment(torture
, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1335 get a handle on the directory
1337 ZERO_STRUCT(io
.smb2
);
1338 io
.generic
.level
= RAW_OPEN_SMB2
;
1339 io
.smb2
.in
.create_flags
= 0;
1340 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1341 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1342 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1343 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1344 NTCREATEX_SHARE_ACCESS_WRITE
;
1345 io
.smb2
.in
.alloc_size
= 0;
1346 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1347 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1348 io
.smb2
.in
.security_flags
= 0;
1349 io
.smb2
.in
.fname
= BASEDIR
;
1351 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1352 CHECK_STATUS(status
, NT_STATUS_OK
);
1354 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1355 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1356 CHECK_STATUS(status
, NT_STATUS_OK
);
1357 h1
= io
.smb2
.out
.file
.handle
;
1359 /* ask for a change notify,
1360 on file or directory name changes */
1361 ZERO_STRUCT(notify
.smb2
);
1362 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1363 notify
.smb2
.in
.buffer_size
= 1000;
1364 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1365 notify
.smb2
.in
.file
.handle
= h1
;
1366 notify
.smb2
.in
.recursive
= true;
1368 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
1370 WAIT_FOR_ASYNC_RESPONSE(req
);
1372 status
= smb2_util_close(tree1
, h1
);
1373 CHECK_STATUS(status
, NT_STATUS_OK
);
1375 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1376 CHECK_STATUS(status
, STATUS_NOTIFY_CLEANUP
);
1377 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1380 smb2_deltree(tree1
, BASEDIR
);
1385 basic testing of change notifies followed by a ulogoff
1388 static bool torture_smb2_notify_ulogoff(struct torture_context
*torture
,
1389 struct smb2_tree
*tree1
)
1393 union smb_notify notify
;
1395 struct smb2_handle h1
;
1396 struct smb2_request
*req
;
1398 smb2_deltree(tree1
, BASEDIR
);
1399 smb2_util_rmdir(tree1
, BASEDIR
);
1401 torture_comment(torture
, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1404 get a handle on the directory
1406 ZERO_STRUCT(io
.smb2
);
1407 io
.generic
.level
= RAW_OPEN_SMB2
;
1408 io
.smb2
.in
.create_flags
= 0;
1409 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1410 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1411 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1412 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1413 NTCREATEX_SHARE_ACCESS_WRITE
;
1414 io
.smb2
.in
.alloc_size
= 0;
1415 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1416 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1417 io
.smb2
.in
.security_flags
= 0;
1418 io
.smb2
.in
.fname
= BASEDIR
;
1420 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1421 CHECK_STATUS(status
, NT_STATUS_OK
);
1423 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1424 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1425 CHECK_STATUS(status
, NT_STATUS_OK
);
1426 h1
= io
.smb2
.out
.file
.handle
;
1428 /* ask for a change notify,
1429 on file or directory name changes */
1430 ZERO_STRUCT(notify
.smb2
);
1431 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1432 notify
.smb2
.in
.buffer_size
= 1000;
1433 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1434 notify
.smb2
.in
.file
.handle
= h1
;
1435 notify
.smb2
.in
.recursive
= true;
1437 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
1439 WAIT_FOR_ASYNC_RESPONSE(req
);
1441 status
= smb2_logoff(tree1
->session
);
1442 CHECK_STATUS(status
, NT_STATUS_OK
);
1444 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1445 CHECK_STATUS(status
, STATUS_NOTIFY_CLEANUP
);
1446 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1449 smb2_deltree(tree1
, BASEDIR
);
1454 basic testing of change notifies followed by an invalid reauth
1457 static bool torture_smb2_notify_invalid_reauth(struct torture_context
*torture
,
1458 struct smb2_tree
*tree1
,
1459 struct smb2_tree
*tree2
)
1463 union smb_notify notify
;
1465 struct smb2_handle h1
;
1466 struct smb2_request
*req
;
1467 struct cli_credentials
*invalid_creds
;
1469 smb2_deltree(tree2
, BASEDIR
);
1470 smb2_util_rmdir(tree2
, BASEDIR
);
1472 torture_comment(torture
, "TESTING CHANGE NOTIFY FOLLOWED BY invalid REAUTH\n");
1475 get a handle on the directory
1477 ZERO_STRUCT(io
.smb2
);
1478 io
.generic
.level
= RAW_OPEN_SMB2
;
1479 io
.smb2
.in
.create_flags
= 0;
1480 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1481 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1482 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1483 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1484 NTCREATEX_SHARE_ACCESS_WRITE
;
1485 io
.smb2
.in
.alloc_size
= 0;
1486 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1487 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1488 io
.smb2
.in
.security_flags
= 0;
1489 io
.smb2
.in
.fname
= BASEDIR
;
1491 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1492 CHECK_STATUS(status
, NT_STATUS_OK
);
1494 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1495 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1496 CHECK_STATUS(status
, NT_STATUS_OK
);
1497 h1
= io
.smb2
.out
.file
.handle
;
1499 /* ask for a change notify,
1500 on file or directory name changes */
1501 ZERO_STRUCT(notify
.smb2
);
1502 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1503 notify
.smb2
.in
.buffer_size
= 1000;
1504 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1505 notify
.smb2
.in
.file
.handle
= h1
;
1506 notify
.smb2
.in
.recursive
= true;
1508 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
1510 WAIT_FOR_ASYNC_RESPONSE(req
);
1512 invalid_creds
= cli_credentials_init(torture
);
1513 torture_assert(torture
, (invalid_creds
!= NULL
), "talloc error");
1514 cli_credentials_set_username(invalid_creds
, "__none__invalid__none__", CRED_SPECIFIED
);
1515 cli_credentials_set_domain(invalid_creds
, "__none__invalid__none__", CRED_SPECIFIED
);
1516 cli_credentials_set_password(invalid_creds
, "__none__invalid__none__", CRED_SPECIFIED
);
1517 cli_credentials_set_realm(invalid_creds
, NULL
, CRED_SPECIFIED
);
1518 cli_credentials_set_workstation(invalid_creds
, "", CRED_UNINITIALISED
);
1520 status
= smb2_session_setup_spnego(tree1
->session
,
1522 0 /* previous_session_id */);
1523 CHECK_STATUS(status
, NT_STATUS_LOGON_FAILURE
);
1525 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1526 CHECK_STATUS(status
, STATUS_NOTIFY_CLEANUP
);
1527 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1530 smb2_deltree(tree2
, BASEDIR
);
1534 static void tcp_dis_handler(struct smb2_transport
*t
, void *p
)
1536 struct smb2_tree
*tree
= (struct smb2_tree
*)p
;
1537 smb2_transport_dead(tree
->session
->transport
,
1538 NT_STATUS_LOCAL_DISCONNECT
);
1544 basic testing of change notifies followed by tcp disconnect
1547 static bool torture_smb2_notify_tcp_disconnect(
1548 struct torture_context
*torture
,
1549 struct smb2_tree
*tree
)
1553 union smb_notify notify
;
1555 struct smb2_handle h1
;
1556 struct smb2_request
*req
;
1558 smb2_deltree(tree
, BASEDIR
);
1559 smb2_util_rmdir(tree
, BASEDIR
);
1561 torture_comment(torture
,
1562 "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
1565 get a handle on the directory
1567 ZERO_STRUCT(io
.smb2
);
1568 io
.generic
.level
= RAW_OPEN_SMB2
;
1569 io
.smb2
.in
.create_flags
= 0;
1570 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1571 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1572 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1573 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1574 NTCREATEX_SHARE_ACCESS_WRITE
;
1575 io
.smb2
.in
.alloc_size
= 0;
1576 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1577 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1578 io
.smb2
.in
.security_flags
= 0;
1579 io
.smb2
.in
.fname
= BASEDIR
;
1581 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1582 CHECK_STATUS(status
, NT_STATUS_OK
);
1583 h1
= io
.smb2
.out
.file
.handle
;
1585 /* ask for a change notify,
1586 on file or directory name changes */
1587 ZERO_STRUCT(notify
.smb2
);
1588 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1589 notify
.smb2
.in
.buffer_size
= 1000;
1590 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1591 notify
.smb2
.in
.file
.handle
= h1
;
1592 notify
.smb2
.in
.recursive
= true;
1594 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1596 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1597 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1599 notify
.smb2
.in
.recursive
= true;
1600 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1601 smb2_transport_idle_handler(tree
->session
->transport
,
1602 tcp_dis_handler
, 250, tree
);
1604 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1605 CHECK_STATUS(status
, NT_STATUS_LOCAL_DISCONNECT
);
1612 test setting up two change notify requests on one handle
1615 static bool torture_smb2_notify_double(struct torture_context
*torture
,
1616 struct smb2_tree
*tree1
,
1617 struct smb2_tree
*tree2
)
1621 union smb_notify notify
;
1623 struct smb2_handle h1
;
1624 struct smb2_request
*req1
, *req2
;
1626 smb2_deltree(tree1
, BASEDIR
);
1627 smb2_util_rmdir(tree1
, BASEDIR
);
1629 torture_comment(torture
,
1630 "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
1633 get a handle on the directory
1635 ZERO_STRUCT(io
.smb2
);
1636 io
.generic
.level
= RAW_OPEN_SMB2
;
1637 io
.smb2
.in
.create_flags
= 0;
1638 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
1639 SEC_RIGHTS_FILE_WRITE
|
1640 SEC_RIGHTS_FILE_ALL
;
1641 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1642 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1643 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1644 NTCREATEX_SHARE_ACCESS_WRITE
;
1645 io
.smb2
.in
.alloc_size
= 0;
1646 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1647 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1648 io
.smb2
.in
.security_flags
= 0;
1649 io
.smb2
.in
.fname
= BASEDIR
;
1651 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1652 CHECK_STATUS(status
, NT_STATUS_OK
);
1653 h1
= io
.smb2
.out
.file
.handle
;
1655 /* ask for a change notify,
1656 on file or directory name changes */
1657 ZERO_STRUCT(notify
.smb2
);
1658 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1659 notify
.smb2
.in
.buffer_size
= 1000;
1660 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1661 notify
.smb2
.in
.file
.handle
= h1
;
1662 notify
.smb2
.in
.recursive
= true;
1664 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1666 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1667 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1669 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
1671 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
1672 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1674 smb2_util_mkdir(tree2
, BASEDIR
"\\subdir-name");
1675 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1676 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
1678 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1679 CHECK_STATUS(status
, NT_STATUS_OK
);
1680 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1681 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1683 smb2_util_mkdir(tree2
, BASEDIR
"\\subdir-name2");
1685 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
1686 CHECK_STATUS(status
, NT_STATUS_OK
);
1687 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1688 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name2");
1691 smb2_deltree(tree1
, BASEDIR
);
1697 test multiple change notifies at different depths and with/without recursion
1700 static bool torture_smb2_notify_tree(struct torture_context
*torture
,
1701 struct smb2_tree
*tree
)
1704 union smb_notify notify
;
1706 struct smb2_request
*req
;
1713 struct smb2_handle h1
;
1716 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 30 },
1717 {BASEDIR
"\\zqy", true, FILE_NOTIFY_CHANGE_NAME
, 8 },
1718 {BASEDIR
"\\atsy", true, FILE_NOTIFY_CHANGE_NAME
, 4 },
1719 {BASEDIR
"\\abc\\foo", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1720 {BASEDIR
"\\abc\\blah", true, FILE_NOTIFY_CHANGE_NAME
, 13 },
1721 {BASEDIR
"\\abc\\blah", false, FILE_NOTIFY_CHANGE_NAME
, 7 },
1722 {BASEDIR
"\\abc\\blah\\a", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1723 {BASEDIR
"\\abc\\blah\\b", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1724 {BASEDIR
"\\abc\\blah\\c", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1725 {BASEDIR
"\\abc\\fooblah", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1726 {BASEDIR
"\\zqy\\xx", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1727 {BASEDIR
"\\zqy\\yyy", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1728 {BASEDIR
"\\zqy\\..", true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1729 {BASEDIR
, true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1730 {BASEDIR
, false,FILE_NOTIFY_CHANGE_NAME
, 6 },
1731 {BASEDIR
"\\atsy", false,FILE_NOTIFY_CHANGE_NAME
, 4 },
1732 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1733 {BASEDIR
"\\abc", false,FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1734 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1735 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1739 bool all_done
= false;
1741 smb2_deltree(tree
, BASEDIR
);
1742 smb2_util_rmdir(tree
, BASEDIR
);
1744 torture_comment(torture
, "TESTING NOTIFY FOR DIFFERENT DEPTHS\n");
1746 ZERO_STRUCT(io
.smb2
);
1747 io
.generic
.level
= RAW_OPEN_SMB2
;
1748 io
.smb2
.in
.create_flags
= 0;
1749 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1750 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1751 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1752 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1753 NTCREATEX_SHARE_ACCESS_WRITE
;
1754 io
.smb2
.in
.alloc_size
= 0;
1755 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1756 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1757 io
.smb2
.in
.security_flags
= 0;
1758 io
.smb2
.in
.fname
= BASEDIR
;
1759 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1760 CHECK_STATUS(status
, NT_STATUS_OK
);
1762 ZERO_STRUCT(notify
.smb2
);
1763 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1764 notify
.smb2
.in
.buffer_size
= 20000;
1767 setup the directory tree, and the notify buffer on each directory
1769 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1770 io
.smb2
.in
.fname
= dirs
[i
].path
;
1771 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1772 CHECK_STATUS(status
, NT_STATUS_OK
);
1773 dirs
[i
].h1
= io
.smb2
.out
.file
.handle
;
1775 notify
.smb2
.in
.completion_filter
= dirs
[i
].filter
;
1776 notify
.smb2
.in
.file
.handle
= dirs
[i
].h1
;
1777 notify
.smb2
.in
.recursive
= dirs
[i
].recursive
;
1778 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1780 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1781 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1784 /* trigger 2 events in each dir */
1785 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1786 char *path
= talloc_asprintf(torture
, "%s\\test.dir",
1788 smb2_util_mkdir(tree
, path
);
1789 smb2_util_rmdir(tree
, path
);
1793 /* give a bit of time for the events to propogate */
1794 tv
= timeval_current();
1797 /* count events that have happened in each dir */
1798 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1799 notify
.smb2
.in
.file
.handle
= dirs
[i
].h1
;
1800 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1802 notify
.smb2
.out
.num_changes
= 0;
1803 status
= smb2_notify_recv(req
, torture
,
1805 dirs
[i
].counted
+= notify
.smb2
.out
.num_changes
;
1810 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1811 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1815 } while (!all_done
&& timeval_elapsed(&tv
) < 20);
1817 torture_comment(torture
, "took %.4f seconds to propogate all events\n",
1818 timeval_elapsed(&tv
));
1820 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1821 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1822 torture_comment(torture
,
1823 "ERROR: i=%d expected %d got %d for '%s'\n",
1824 i
, dirs
[i
].expected
, dirs
[i
].counted
,
1831 run from the back, closing and deleting
1833 for (i
=ARRAY_SIZE(dirs
)-1;i
>=0;i
--) {
1834 smb2_util_close(tree
, dirs
[i
].h1
);
1835 smb2_util_rmdir(tree
, dirs
[i
].path
);
1839 smb2_deltree(tree
, BASEDIR
);
1840 smb2_util_rmdir(tree
, BASEDIR
);
1845 Test response when cached server events exceed single NT NOTFIY response
1849 static bool torture_smb2_notify_overflow(struct torture_context
*torture
,
1850 struct smb2_tree
*tree
)
1854 union smb_notify notify
;
1856 struct smb2_handle h1
, h2
;
1858 struct smb2_request
*req1
;
1861 smb2_deltree(tree
, BASEDIR
);
1862 smb2_util_rmdir(tree
, BASEDIR
);
1864 torture_comment(torture
, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
1866 /* get a handle on the directory */
1867 ZERO_STRUCT(io
.smb2
);
1868 io
.generic
.level
= RAW_OPEN_SMB2
;
1869 io
.smb2
.in
.create_flags
= 0;
1870 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1871 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1872 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1873 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1874 NTCREATEX_SHARE_ACCESS_WRITE
;
1875 io
.smb2
.in
.alloc_size
= 0;
1876 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1877 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1878 io
.smb2
.in
.security_flags
= 0;
1879 io
.smb2
.in
.fname
= BASEDIR
;
1881 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1882 CHECK_STATUS(status
, NT_STATUS_OK
);
1883 h1
= io
.smb2
.out
.file
.handle
;
1885 /* ask for a change notify, on name changes. */
1886 ZERO_STRUCT(notify
.smb2
);
1887 notify
.smb2
.level
= RAW_NOTIFY_NTTRANS
;
1888 notify
.smb2
.in
.buffer_size
= 1000;
1889 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1890 notify
.smb2
.in
.file
.handle
= h1
;
1892 notify
.smb2
.in
.recursive
= true;
1893 req1
= smb2_notify_send(tree
, &(notify
.smb2
));
1895 /* cancel initial requests so the buffer is setup */
1897 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1898 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1900 /* open a lot of files, filling up the server side notify buffer */
1901 torture_comment(torture
,
1902 "Testing overflowed buffer notify on create of %d files\n",
1905 for (i
=0;i
<count
;i
++) {
1906 char *fname
= talloc_asprintf(torture
,
1907 BASEDIR
"\\test%d.txt", i
);
1909 ZERO_STRUCT(io1
.smb2
);
1910 io1
.generic
.level
= RAW_OPEN_SMB2
;
1911 io1
.smb2
.in
.create_flags
= 0;
1912 io1
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1913 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1914 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1915 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1916 NTCREATEX_SHARE_ACCESS_WRITE
;
1917 io1
.smb2
.in
.alloc_size
= 0;
1918 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1919 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1920 io1
.smb2
.in
.security_flags
= 0;
1921 io1
.smb2
.in
.fname
= fname
;
1923 h2
= custom_smb2_create(tree
, torture
, &(io1
.smb2
));
1925 smb2_util_close(tree
, h2
);
1928 req1
= smb2_notify_send(tree
, &(notify
.smb2
));
1929 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1930 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
1931 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1934 smb2_deltree(tree
, BASEDIR
);
1939 Test if notifications are returned for changes to the base directory.
1943 static bool torture_smb2_notify_basedir(struct torture_context
*torture
,
1944 struct smb2_tree
*tree1
,
1945 struct smb2_tree
*tree2
)
1949 union smb_notify notify
;
1951 struct smb2_handle h1
;
1952 struct smb2_request
*req1
;
1954 smb2_deltree(tree1
, BASEDIR
);
1955 smb2_util_rmdir(tree1
, BASEDIR
);
1957 torture_comment(torture
, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
1959 /* get a handle on the directory */
1960 ZERO_STRUCT(io
.smb2
);
1961 io
.generic
.level
= RAW_OPEN_SMB2
;
1962 io
.smb2
.in
.create_flags
= 0;
1963 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1964 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1965 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1966 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1967 NTCREATEX_SHARE_ACCESS_WRITE
;
1968 io
.smb2
.in
.alloc_size
= 0;
1969 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1970 io
.smb2
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1971 io
.smb2
.in
.security_flags
= 0;
1972 io
.smb2
.in
.fname
= BASEDIR
;
1974 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1975 CHECK_STATUS(status
, NT_STATUS_OK
);
1976 h1
= io
.smb2
.out
.file
.handle
;
1978 /* create a test file that will also be modified */
1979 io
.smb2
.in
.fname
= BASEDIR
"\\tname1";
1980 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
1981 status
= smb2_create(tree2
, torture
, &(io
.smb2
));
1982 CHECK_STATUS(status
,NT_STATUS_OK
);
1983 smb2_util_close(tree2
, io
.smb2
.out
.file
.handle
);
1985 /* ask for a change notify, on attribute changes. */
1986 ZERO_STRUCT(notify
.smb2
);
1987 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1988 notify
.smb2
.in
.buffer_size
= 1000;
1989 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
1990 notify
.smb2
.in
.file
.handle
= h1
;
1991 notify
.smb2
.in
.recursive
= true;
1993 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1995 /* set attribute on the base dir */
1996 smb2_util_setatr(tree2
, BASEDIR
, FILE_ATTRIBUTE_HIDDEN
);
1998 /* set attribute on a file to assure we receive a notification */
1999 smb2_util_setatr(tree2
, BASEDIR
"\\tname1", FILE_ATTRIBUTE_HIDDEN
);
2002 /* check how many responses were given, expect only 1 for the file */
2003 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
2004 CHECK_STATUS(status
, NT_STATUS_OK
);
2005 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2006 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
2007 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "tname1");
2010 smb2_deltree(tree1
, BASEDIR
);
2015 very simple change notify test
2017 static bool torture_smb2_notify_tcon(struct torture_context
*torture
,
2018 struct smb2_tree
*tree
)
2022 union smb_notify notify
;
2024 struct smb2_handle h1
;
2025 struct smb2_request
*req
= NULL
;
2026 struct smb2_tree
*tree1
= NULL
;
2027 const char *fname
= BASEDIR
"\\subdir-name";
2029 smb2_deltree(tree
, BASEDIR
);
2030 smb2_util_rmdir(tree
, BASEDIR
);
2032 torture_comment(torture
, "TESTING SIMPLE CHANGE NOTIFY\n");
2035 get a handle on the directory
2038 ZERO_STRUCT(io
.smb2
);
2039 io
.generic
.level
= RAW_OPEN_SMB2
;
2040 io
.smb2
.in
.create_flags
= 0;
2041 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
2042 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
2043 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
|
2044 FILE_ATTRIBUTE_DIRECTORY
;
2045 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2046 NTCREATEX_SHARE_ACCESS_WRITE
;
2047 io
.smb2
.in
.alloc_size
= 0;
2048 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
2049 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
2050 io
.smb2
.in
.security_flags
= 0;
2051 io
.smb2
.in
.fname
= BASEDIR
;
2053 status
= smb2_create(tree
, torture
, &(io
.smb2
));
2054 CHECK_STATUS(status
, NT_STATUS_OK
);
2055 h1
= io
.smb2
.out
.file
.handle
;
2057 /* ask for a change notify,
2058 on file or directory name changes */
2059 ZERO_STRUCT(notify
.smb2
);
2060 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
2061 notify
.smb2
.in
.buffer_size
= 1000;
2062 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
2063 notify
.smb2
.in
.file
.handle
= h1
;
2064 notify
.smb2
.in
.recursive
= true;
2066 torture_comment(torture
, "Testing notify mkdir\n");
2067 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2069 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2070 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
2072 notify
.smb2
.in
.recursive
= true;
2073 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2074 status
= smb2_util_mkdir(tree
, fname
);
2075 CHECK_STATUS(status
, NT_STATUS_OK
);
2077 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2078 CHECK_STATUS(status
, NT_STATUS_OK
);
2080 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2081 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
2082 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2084 torture_comment(torture
, "Testing notify rmdir\n");
2085 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2086 status
= smb2_util_rmdir(tree
, fname
);
2087 CHECK_STATUS(status
, NT_STATUS_OK
);
2089 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2090 CHECK_STATUS(status
, NT_STATUS_OK
);
2091 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2092 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
2093 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2095 torture_comment(torture
, "SIMPLE CHANGE NOTIFY OK\n");
2097 torture_comment(torture
, "TESTING WITH SECONDARY TCON\n");
2098 if (!torture_smb2_tree_connect(torture
, tree
->session
, tree
, &tree1
)) {
2099 torture_warning(torture
, "couldn't reconnect to share, bailing\n");
2104 torture_comment(torture
, "tid1=%d tid2=%d\n",
2105 smb2cli_tcon_current_id(tree
->smbXcli
),
2106 smb2cli_tcon_current_id(tree1
->smbXcli
));
2108 torture_comment(torture
, "Testing notify mkdir\n");
2109 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2110 smb2_util_mkdir(tree1
, fname
);
2112 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2113 CHECK_STATUS(status
, NT_STATUS_OK
);
2115 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2116 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
2117 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2119 torture_comment(torture
, "Testing notify rmdir\n");
2120 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2121 smb2_util_rmdir(tree
, fname
);
2123 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2124 CHECK_STATUS(status
, NT_STATUS_OK
);
2125 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2126 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
2127 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2129 torture_comment(torture
, "CHANGE NOTIFY WITH TCON OK\n");
2131 torture_comment(torture
, "Disconnecting secondary tree\n");
2132 status
= smb2_tdis(tree1
);
2133 CHECK_STATUS(status
, NT_STATUS_OK
);
2136 torture_comment(torture
, "Testing notify mkdir\n");
2137 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2138 smb2_util_mkdir(tree
, fname
);
2140 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2141 CHECK_STATUS(status
, NT_STATUS_OK
);
2143 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2144 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
2145 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2147 torture_comment(torture
, "Testing notify rmdir\n");
2148 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2149 smb2_util_rmdir(tree
, fname
);
2151 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2152 CHECK_STATUS(status
, NT_STATUS_OK
);
2153 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2154 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
2155 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2157 torture_comment(torture
, "CHANGE NOTIFY WITH TDIS OK\n");
2159 smb2_util_close(tree
, h1
);
2160 smb2_deltree(tree
, BASEDIR
);
2166 basic testing of SMB2 change notify
2168 struct torture_suite
*torture_smb2_notify_init(void)
2170 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "notify");
2172 torture_suite_add_1smb2_test(suite
, "valid-req", test_valid_request
);
2173 torture_suite_add_1smb2_test(suite
, "tcon", torture_smb2_notify_tcon
);
2174 torture_suite_add_2smb2_test(suite
, "dir", torture_smb2_notify_dir
);
2175 torture_suite_add_2smb2_test(suite
, "mask", torture_smb2_notify_mask
);
2176 torture_suite_add_1smb2_test(suite
, "tdis", torture_smb2_notify_tree_disconnect
);
2177 torture_suite_add_1smb2_test(suite
, "tdis1", torture_smb2_notify_tree_disconnect_1
);
2178 torture_suite_add_2smb2_test(suite
, "mask-change", torture_smb2_notify_mask_change
);
2179 torture_suite_add_1smb2_test(suite
, "close", torture_smb2_notify_close
);
2180 torture_suite_add_1smb2_test(suite
, "logoff", torture_smb2_notify_ulogoff
);
2181 torture_suite_add_2smb2_test(suite
, "invalid-reauth", torture_smb2_notify_invalid_reauth
);
2182 torture_suite_add_1smb2_test(suite
, "tree", torture_smb2_notify_tree
);
2183 torture_suite_add_2smb2_test(suite
, "basedir", torture_smb2_notify_basedir
);
2184 torture_suite_add_2smb2_test(suite
, "double", torture_smb2_notify_double
);
2185 torture_suite_add_1smb2_test(suite
, "file", torture_smb2_notify_file
);
2186 torture_suite_add_1smb2_test(suite
, "tcp", torture_smb2_notify_tcp_disconnect
);
2187 torture_suite_add_2smb2_test(suite
, "rec", torture_smb2_notify_recursive
);
2188 torture_suite_add_1smb2_test(suite
, "overflow", torture_smb2_notify_overflow
);
2190 suite
->description
= talloc_strdup(suite
, "SMB2-NOTIFY tests");