2 Unix SMB/CIFS implementation.
6 Copyright (C) Christian Ambach 2012
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
26 #include "lib/util/tevent_ntstatus.h"
28 #include "torture/torture.h"
29 #include "torture/smb2/proto.h"
31 #include "librpc/gen_ndr/security.h"
33 #define CHECK_VAL(v, correct) \
35 if ((v) != (correct)) { \
36 torture_result(torture, \
38 "(%s): wrong value for %s got " \
39 "0x%llx - should be 0x%llx\n", \
41 (unsigned long long)v, \
42 (unsigned long long)correct); \
47 #define CHECK_CREATED(__io, __created, __attribute) \
49 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
50 CHECK_VAL((__io)->out.size, 0); \
51 CHECK_VAL((__io)->out.file_attr, (__attribute)); \
52 CHECK_VAL((__io)->out.reserved2, 0); \
55 #define CHECK_STATUS(status, correct) do { \
56 if (!NT_STATUS_EQUAL(status, correct)) { \
57 torture_result(torture, TORTURE_FAIL, \
58 "(%s) Incorrect status %s - should be %s\n", \
59 __location__, nt_errstr(status), nt_errstr(correct)); \
64 #define BASEDIR "test_rename"
67 * basic testing of rename: open file with DELETE access
71 static bool torture_smb2_rename_simple(struct torture_context
*torture
,
72 struct smb2_tree
*tree1
)
78 union smb_setfileinfo sinfo
;
79 union smb_fileinfo fi
;
80 struct smb2_handle h1
;
84 smb2_deltree(tree1
, BASEDIR
);
85 smb2_util_rmdir(tree1
, BASEDIR
);
87 torture_comment(torture
, "Creating base directory\n");
89 smb2_util_mkdir(tree1
, BASEDIR
);
92 torture_comment(torture
, "Creating test file\n");
95 io
.generic
.level
= RAW_OPEN_SMB2
;
96 io
.smb2
.in
.create_flags
= 0;
97 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
|SEC_STD_DELETE
;
98 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
99 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
100 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
101 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
102 io
.smb2
.in
.alloc_size
= 0;
103 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
104 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
105 io
.smb2
.in
.security_flags
= 0;
106 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
108 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
109 CHECK_STATUS(status
, NT_STATUS_OK
);
110 h1
= io
.smb2
.out
.file
.handle
;
112 torture_comment(torture
, "Renaming test file\n");
115 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
116 sinfo
.rename_information
.in
.file
.handle
= io
.smb2
.out
.file
.handle
;
117 sinfo
.rename_information
.in
.overwrite
= 0;
118 sinfo
.rename_information
.in
.root_fid
= 0;
119 sinfo
.rename_information
.in
.new_name
=
120 BASEDIR
"\\newname.txt";
121 status
= smb2_setinfo_file(tree1
, &sinfo
);
122 CHECK_STATUS(status
, NT_STATUS_OK
);
124 torture_comment(torture
, "Checking for new filename\n");
127 fi
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
128 fi
.generic
.in
.file
.handle
= h1
;
129 status
= smb2_getinfo_file(tree1
, torture
, &fi
);
130 CHECK_STATUS(status
, NT_STATUS_OK
);
133 torture_comment(torture
, "Closing test file\n");
135 ZERO_STRUCT(cl
.smb2
);
136 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
137 cl
.smb2
.in
.file
.handle
= h1
;
138 status
= smb2_close(tree1
, &(cl
.smb2
));
139 CHECK_STATUS(status
, NT_STATUS_OK
);
145 torture_comment(torture
, "Cleaning up\n");
147 if (h1
.data
[0] || h1
.data
[1]) {
148 ZERO_STRUCT(cl
.smb2
);
149 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
150 cl
.smb2
.in
.file
.handle
= h1
;
151 status
= smb2_close(tree1
, &(cl
.smb2
));
153 smb2_deltree(tree1
, BASEDIR
);
158 * basic testing of rename, this time do not request DELETE access
159 * for the file, this should fail
162 static bool torture_smb2_rename_simple2(struct torture_context
*torture
,
163 struct smb2_tree
*tree1
)
169 union smb_setfileinfo sinfo
;
170 struct smb2_handle h1
;
174 smb2_deltree(tree1
, BASEDIR
);
175 smb2_util_rmdir(tree1
, BASEDIR
);
177 torture_comment(torture
, "Creating base directory\n");
179 smb2_util_mkdir(tree1
, BASEDIR
);
182 torture_comment(torture
, "Creating test file\n");
184 ZERO_STRUCT(io
.smb2
);
185 io
.generic
.level
= RAW_OPEN_SMB2
;
186 io
.smb2
.in
.create_flags
= 0;
187 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
188 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
189 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
190 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
191 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
192 io
.smb2
.in
.alloc_size
= 0;
193 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
194 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
195 io
.smb2
.in
.security_flags
= 0;
196 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
198 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
199 CHECK_STATUS(status
, NT_STATUS_OK
);
200 h1
= io
.smb2
.out
.file
.handle
;
202 torture_comment(torture
, "Renaming test file\n");
205 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
206 sinfo
.rename_information
.in
.file
.handle
= io
.smb2
.out
.file
.handle
;
207 sinfo
.rename_information
.in
.overwrite
= 0;
208 sinfo
.rename_information
.in
.root_fid
= 0;
209 sinfo
.rename_information
.in
.new_name
=
210 BASEDIR
"\\newname.txt";
211 status
= smb2_setinfo_file(tree1
, &sinfo
);
212 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
214 torture_comment(torture
, "Closing test file\n");
216 ZERO_STRUCT(cl
.smb2
);
217 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
218 cl
.smb2
.in
.file
.handle
= h1
;
219 status
= smb2_close(tree1
, &(cl
.smb2
));
220 CHECK_STATUS(status
, NT_STATUS_OK
);
226 torture_comment(torture
, "Cleaning up\n");
228 if (h1
.data
[0] || h1
.data
[1]) {
229 ZERO_STRUCT(cl
.smb2
);
230 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
231 cl
.smb2
.in
.file
.handle
= h1
;
232 status
= smb2_close(tree1
, &(cl
.smb2
));
234 smb2_deltree(tree1
, BASEDIR
);
240 * testing of rename with no sharing allowed on file
244 static bool torture_smb2_rename_no_sharemode(struct torture_context
*torture
,
245 struct smb2_tree
*tree1
)
251 union smb_setfileinfo sinfo
;
252 union smb_fileinfo fi
;
253 struct smb2_handle h1
;
257 smb2_deltree(tree1
, BASEDIR
);
258 smb2_util_rmdir(tree1
, BASEDIR
);
260 torture_comment(torture
, "Creating base directory\n");
262 smb2_util_mkdir(tree1
, BASEDIR
);
265 torture_comment(torture
, "Creating test file\n");
267 ZERO_STRUCT(io
.smb2
);
268 io
.generic
.level
= RAW_OPEN_SMB2
;
269 io
.smb2
.in
.create_flags
= 0;
270 io
.smb2
.in
.desired_access
= 0x0017019f;
271 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
272 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
273 io
.smb2
.in
.share_access
= 0;
274 io
.smb2
.in
.alloc_size
= 0;
275 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
276 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
277 io
.smb2
.in
.security_flags
= 0;
278 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
280 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
281 CHECK_STATUS(status
, NT_STATUS_OK
);
282 h1
= io
.smb2
.out
.file
.handle
;
284 torture_comment(torture
, "Renaming test file\n");
287 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
288 sinfo
.rename_information
.in
.file
.handle
= io
.smb2
.out
.file
.handle
;
289 sinfo
.rename_information
.in
.overwrite
= 0;
290 sinfo
.rename_information
.in
.root_fid
= 0;
291 sinfo
.rename_information
.in
.new_name
=
292 BASEDIR
"\\newname.txt";
293 status
= smb2_setinfo_file(tree1
, &sinfo
);
294 CHECK_STATUS(status
, NT_STATUS_OK
);
296 torture_comment(torture
, "Checking for new filename\n");
299 fi
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
300 fi
.generic
.in
.file
.handle
= h1
;
301 status
= smb2_getinfo_file(tree1
, torture
, &fi
);
302 CHECK_STATUS(status
, NT_STATUS_OK
);
305 torture_comment(torture
, "Closing test file\n");
307 ZERO_STRUCT(cl
.smb2
);
308 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
309 cl
.smb2
.in
.file
.handle
= h1
;
310 status
= smb2_close(tree1
, &(cl
.smb2
));
311 CHECK_STATUS(status
, NT_STATUS_OK
);
317 torture_comment(torture
, "Cleaning up\n");
319 if (h1
.data
[0] || h1
.data
[1]) {
320 ZERO_STRUCT(cl
.smb2
);
321 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
322 cl
.smb2
.in
.file
.handle
= h1
;
323 status
= smb2_close(tree1
, &(cl
.smb2
));
325 smb2_deltree(tree1
, BASEDIR
);
330 * testing of rename when opening parent dir with delete access and delete
332 * should result in sharing violation
335 static bool torture_smb2_rename_with_delete_access(struct torture_context
*torture
,
336 struct smb2_tree
*tree1
)
342 union smb_setfileinfo sinfo
;
343 struct smb2_handle fh
, dh
;
348 smb2_deltree(tree1
, BASEDIR
);
349 smb2_util_rmdir(tree1
, BASEDIR
);
351 torture_comment(torture
, "Creating base directory\n");
353 smb2_util_mkdir(tree1
, BASEDIR
);
355 torture_comment(torture
, "Opening parent directory\n");
357 ZERO_STRUCT(io
.smb2
);
358 io
.generic
.level
= RAW_OPEN_SMB2
;
359 io
.smb2
.in
.create_flags
= 0;
360 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
361 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
362 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
| SEC_FILE_WRITE_EA
|
363 SEC_FILE_READ_EA
| SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
|
365 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
366 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
367 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
368 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
369 io
.smb2
.in
.alloc_size
= 0;
370 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
371 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
372 io
.smb2
.in
.security_flags
= 0;
373 io
.smb2
.in
.fname
= BASEDIR
;
375 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
376 CHECK_STATUS(status
, NT_STATUS_OK
);
377 dh
= io
.smb2
.out
.file
.handle
;
380 torture_comment(torture
, "Creating test file\n");
382 ZERO_STRUCT(io
.smb2
);
383 io
.generic
.level
= RAW_OPEN_SMB2
;
384 io
.smb2
.in
.create_flags
= 0;
385 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
386 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
387 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_WRITE_EA
| SEC_FILE_READ_EA
|
388 SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
389 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
390 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
391 io
.smb2
.in
.share_access
= 0;
392 io
.smb2
.in
.alloc_size
= 0;
393 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
394 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
395 io
.smb2
.in
.security_flags
= 0;
396 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
398 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
399 CHECK_STATUS(status
, NT_STATUS_OK
);
400 fh
= io
.smb2
.out
.file
.handle
;
402 torture_comment(torture
, "Renaming test file\n");
405 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
406 sinfo
.rename_information
.in
.file
.handle
= fh
;
407 sinfo
.rename_information
.in
.overwrite
= 0;
408 sinfo
.rename_information
.in
.root_fid
= 0;
409 sinfo
.rename_information
.in
.new_name
=
410 BASEDIR
"\\newname.txt";
411 status
= smb2_setinfo_file(tree1
, &sinfo
);
412 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
414 torture_comment(torture
, "Closing test file\n");
416 ZERO_STRUCT(cl
.smb2
);
417 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
418 cl
.smb2
.in
.file
.handle
= fh
;
419 status
= smb2_close(tree1
, &(cl
.smb2
));
420 CHECK_STATUS(status
, NT_STATUS_OK
);
424 torture_comment(torture
, "Closing directory\n");
426 ZERO_STRUCT(cl
.smb2
);
427 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
428 cl
.smb2
.in
.file
.handle
= dh
;
429 status
= smb2_close(tree1
, &(cl
.smb2
));
430 CHECK_STATUS(status
, NT_STATUS_OK
);
437 torture_comment(torture
, "Cleaning up\n");
439 if (fh
.data
[0] || fh
.data
[1]) {
440 ZERO_STRUCT(cl
.smb2
);
441 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
442 cl
.smb2
.in
.file
.handle
= fh
;
443 status
= smb2_close(tree1
, &(cl
.smb2
));
445 if (dh
.data
[0] || dh
.data
[1]) {
446 ZERO_STRUCT(cl
.smb2
);
447 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
448 cl
.smb2
.in
.file
.handle
= dh
;
449 status
= smb2_close(tree1
, &(cl
.smb2
));
452 smb2_deltree(tree1
, BASEDIR
);
458 * testing of rename with delete access on parent dir
459 * this is a variation of the test above: parent dir is opened
460 * without share_delete, so rename must fail
463 static bool torture_smb2_rename_with_delete_access2(struct torture_context
*torture
,
464 struct smb2_tree
*tree1
)
470 union smb_setfileinfo sinfo
;
471 struct smb2_handle fh
, dh
;
476 smb2_deltree(tree1
, BASEDIR
);
477 smb2_util_rmdir(tree1
, BASEDIR
);
479 torture_comment(torture
, "Creating base directory\n");
481 smb2_util_mkdir(tree1
, BASEDIR
);
483 torture_comment(torture
, "Opening parent directory\n");
485 ZERO_STRUCT(io
.smb2
);
486 io
.generic
.level
= RAW_OPEN_SMB2
;
487 io
.smb2
.in
.create_flags
= 0;
488 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
489 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
490 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
| SEC_FILE_WRITE_EA
|
491 SEC_FILE_READ_EA
| SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
|
493 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
494 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
495 io
.smb2
.in
.share_access
= 0;
496 io
.smb2
.in
.alloc_size
= 0;
497 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
498 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
499 io
.smb2
.in
.security_flags
= 0;
500 io
.smb2
.in
.fname
= BASEDIR
;
502 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
503 CHECK_STATUS(status
, NT_STATUS_OK
);
504 dh
= io
.smb2
.out
.file
.handle
;
507 torture_comment(torture
, "Creating test file\n");
509 ZERO_STRUCT(io
.smb2
);
510 io
.generic
.level
= RAW_OPEN_SMB2
;
511 io
.smb2
.in
.create_flags
= 0;
512 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
513 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
514 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_WRITE_EA
| SEC_FILE_READ_EA
|
515 SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
516 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
517 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
518 io
.smb2
.in
.share_access
= 0;
519 io
.smb2
.in
.alloc_size
= 0;
520 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
521 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
522 io
.smb2
.in
.security_flags
= 0;
523 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
525 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
526 CHECK_STATUS(status
, NT_STATUS_OK
);
527 fh
= io
.smb2
.out
.file
.handle
;
529 torture_comment(torture
, "Renaming test file\n");
532 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
533 sinfo
.rename_information
.in
.file
.handle
= fh
;
534 sinfo
.rename_information
.in
.overwrite
= 0;
535 sinfo
.rename_information
.in
.root_fid
= 0;
536 sinfo
.rename_information
.in
.new_name
=
537 BASEDIR
"\\newname.txt";
538 status
= smb2_setinfo_file(tree1
, &sinfo
);
539 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
541 torture_comment(torture
, "Closing test file\n");
543 ZERO_STRUCT(cl
.smb2
);
544 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
545 cl
.smb2
.in
.file
.handle
= fh
;
546 status
= smb2_close(tree1
, &(cl
.smb2
));
547 CHECK_STATUS(status
, NT_STATUS_OK
);
551 torture_comment(torture
, "Closing directory\n");
553 ZERO_STRUCT(cl
.smb2
);
554 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
555 cl
.smb2
.in
.file
.handle
= dh
;
556 status
= smb2_close(tree1
, &(cl
.smb2
));
557 CHECK_STATUS(status
, NT_STATUS_OK
);
564 torture_comment(torture
, "Cleaning up\n");
566 if (fh
.data
[0] || fh
.data
[1]) {
567 ZERO_STRUCT(cl
.smb2
);
568 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
569 cl
.smb2
.in
.file
.handle
= fh
;
570 status
= smb2_close(tree1
, &(cl
.smb2
));
572 if (dh
.data
[0] || dh
.data
[1]) {
573 ZERO_STRUCT(cl
.smb2
);
574 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
575 cl
.smb2
.in
.file
.handle
= dh
;
576 status
= smb2_close(tree1
, &(cl
.smb2
));
579 smb2_deltree(tree1
, BASEDIR
);
584 * testing of rename when opening parent dir with no delete access and delete
589 static bool torture_smb2_rename_no_delete_access(struct torture_context
*torture
,
590 struct smb2_tree
*tree1
)
596 union smb_setfileinfo sinfo
;
597 union smb_fileinfo fi
;
598 struct smb2_handle fh
, dh
;
603 smb2_deltree(tree1
, BASEDIR
);
604 smb2_util_rmdir(tree1
, BASEDIR
);
606 torture_comment(torture
, "Creating base directory\n");
608 smb2_util_mkdir(tree1
, BASEDIR
);
610 torture_comment(torture
, "Opening parent directory\n");
612 ZERO_STRUCT(io
.smb2
);
613 io
.generic
.level
= RAW_OPEN_SMB2
;
614 io
.smb2
.in
.create_flags
= 0;
615 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
616 SEC_STD_READ_CONTROL
| SEC_FILE_WRITE_ATTRIBUTE
|
617 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
| SEC_FILE_WRITE_EA
|
618 SEC_FILE_READ_EA
| SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
|
620 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
621 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
622 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
623 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
624 io
.smb2
.in
.alloc_size
= 0;
625 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
626 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
627 io
.smb2
.in
.security_flags
= 0;
628 io
.smb2
.in
.fname
= BASEDIR
;
630 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
631 CHECK_STATUS(status
, NT_STATUS_OK
);
632 dh
= io
.smb2
.out
.file
.handle
;
635 torture_comment(torture
, "Creating test file\n");
637 ZERO_STRUCT(io
.smb2
);
638 io
.generic
.level
= RAW_OPEN_SMB2
;
639 io
.smb2
.in
.create_flags
= 0;
640 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
641 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
642 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_WRITE_EA
| SEC_FILE_READ_EA
|
643 SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
644 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
645 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
646 io
.smb2
.in
.share_access
= 0;
647 io
.smb2
.in
.alloc_size
= 0;
648 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
649 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
650 io
.smb2
.in
.security_flags
= 0;
651 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
653 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
654 CHECK_STATUS(status
, NT_STATUS_OK
);
655 fh
= io
.smb2
.out
.file
.handle
;
657 torture_comment(torture
, "Renaming test file\n");
660 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
661 sinfo
.rename_information
.in
.file
.handle
= fh
;
662 sinfo
.rename_information
.in
.overwrite
= 0;
663 sinfo
.rename_information
.in
.root_fid
= 0;
664 sinfo
.rename_information
.in
.new_name
=
665 BASEDIR
"\\newname.txt";
666 status
= smb2_setinfo_file(tree1
, &sinfo
);
667 CHECK_STATUS(status
, NT_STATUS_OK
);
669 torture_comment(torture
, "Checking for new filename\n");
672 fi
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
673 fi
.generic
.in
.file
.handle
= fh
;
674 status
= smb2_getinfo_file(tree1
, torture
, &fi
);
675 CHECK_STATUS(status
, NT_STATUS_OK
);
678 torture_comment(torture
, "Closing test file\n");
680 ZERO_STRUCT(cl
.smb2
);
681 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
682 cl
.smb2
.in
.file
.handle
= fh
;
683 status
= smb2_close(tree1
, &(cl
.smb2
));
684 CHECK_STATUS(status
, NT_STATUS_OK
);
688 torture_comment(torture
, "Closing directory\n");
690 ZERO_STRUCT(cl
.smb2
);
691 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
692 cl
.smb2
.in
.file
.handle
= dh
;
693 status
= smb2_close(tree1
, &(cl
.smb2
));
694 CHECK_STATUS(status
, NT_STATUS_OK
);
701 torture_comment(torture
, "Cleaning up\n");
703 if (fh
.data
[0] || fh
.data
[1]) {
704 ZERO_STRUCT(cl
.smb2
);
705 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
706 cl
.smb2
.in
.file
.handle
= fh
;
707 status
= smb2_close(tree1
, &(cl
.smb2
));
709 if (dh
.data
[0] || dh
.data
[1]) {
710 ZERO_STRUCT(cl
.smb2
);
711 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
712 cl
.smb2
.in
.file
.handle
= dh
;
713 status
= smb2_close(tree1
, &(cl
.smb2
));
716 smb2_deltree(tree1
, BASEDIR
);
722 * testing of rename with no delete access on parent dir
723 * this is the negative case of the test above: parent dir is opened
724 * without share_delete, so rename must fail
727 static bool torture_smb2_rename_no_delete_access2(struct torture_context
*torture
,
728 struct smb2_tree
*tree1
)
734 union smb_setfileinfo sinfo
;
735 struct smb2_handle fh
, dh
;
740 smb2_deltree(tree1
, BASEDIR
);
741 smb2_util_rmdir(tree1
, BASEDIR
);
743 torture_comment(torture
, "Creating base directory\n");
745 smb2_util_mkdir(tree1
, BASEDIR
);
747 torture_comment(torture
, "Opening parent directory\n");
749 ZERO_STRUCT(io
.smb2
);
750 io
.generic
.level
= RAW_OPEN_SMB2
;
751 io
.smb2
.in
.create_flags
= 0;
752 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
753 SEC_STD_READ_CONTROL
| SEC_FILE_WRITE_ATTRIBUTE
|
754 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
| SEC_FILE_WRITE_EA
|
755 SEC_FILE_READ_EA
| SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
|
757 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
758 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
759 io
.smb2
.in
.share_access
= 0;
760 io
.smb2
.in
.alloc_size
= 0;
761 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
762 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
763 io
.smb2
.in
.security_flags
= 0;
764 io
.smb2
.in
.fname
= BASEDIR
;
766 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
767 CHECK_STATUS(status
, NT_STATUS_OK
);
768 dh
= io
.smb2
.out
.file
.handle
;
771 torture_comment(torture
, "Creating test file\n");
773 ZERO_STRUCT(io
.smb2
);
774 io
.generic
.level
= RAW_OPEN_SMB2
;
775 io
.smb2
.in
.create_flags
= 0;
776 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
777 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
778 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_WRITE_EA
| SEC_FILE_READ_EA
|
779 SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
780 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
781 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
782 io
.smb2
.in
.share_access
= 0;
783 io
.smb2
.in
.alloc_size
= 0;
784 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
785 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
786 io
.smb2
.in
.security_flags
= 0;
787 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
789 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
790 CHECK_STATUS(status
, NT_STATUS_OK
);
791 fh
= io
.smb2
.out
.file
.handle
;
793 torture_comment(torture
, "Renaming test file\n");
796 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
797 sinfo
.rename_information
.in
.file
.handle
= fh
;
798 sinfo
.rename_information
.in
.overwrite
= 0;
799 sinfo
.rename_information
.in
.root_fid
= 0;
800 sinfo
.rename_information
.in
.new_name
=
801 BASEDIR
"\\newname.txt";
802 status
= smb2_setinfo_file(tree1
, &sinfo
);
803 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
805 torture_comment(torture
, "Closing test file\n");
807 ZERO_STRUCT(cl
.smb2
);
808 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
809 cl
.smb2
.in
.file
.handle
= fh
;
810 status
= smb2_close(tree1
, &(cl
.smb2
));
811 CHECK_STATUS(status
, NT_STATUS_OK
);
815 torture_comment(torture
, "Closing directory\n");
817 ZERO_STRUCT(cl
.smb2
);
818 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
819 cl
.smb2
.in
.file
.handle
= dh
;
820 status
= smb2_close(tree1
, &(cl
.smb2
));
821 CHECK_STATUS(status
, NT_STATUS_OK
);
828 torture_comment(torture
, "Cleaning up\n");
830 if (fh
.data
[0] || fh
.data
[1]) {
831 ZERO_STRUCT(cl
.smb2
);
832 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
833 cl
.smb2
.in
.file
.handle
= fh
;
834 status
= smb2_close(tree1
, &(cl
.smb2
));
836 if (dh
.data
[0] || dh
.data
[1]) {
837 ZERO_STRUCT(cl
.smb2
);
838 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
839 cl
.smb2
.in
.file
.handle
= dh
;
840 status
= smb2_close(tree1
, &(cl
.smb2
));
843 smb2_deltree(tree1
, BASEDIR
);
848 * this is a replay of how Word 2010 saves a file
852 static bool torture_smb2_rename_msword(struct torture_context
*torture
,
853 struct smb2_tree
*tree1
)
859 union smb_setfileinfo sinfo
;
860 union smb_fileinfo fi
;
861 struct smb2_handle fh
, dh
;
866 smb2_deltree(tree1
, BASEDIR
);
867 smb2_util_rmdir(tree1
, BASEDIR
);
869 torture_comment(torture
, "Creating base directory\n");
871 smb2_util_mkdir(tree1
, BASEDIR
);
873 torture_comment(torture
, "Creating test file\n");
875 ZERO_STRUCT(io
.smb2
);
876 io
.generic
.level
= RAW_OPEN_SMB2
;
877 io
.smb2
.in
.create_flags
= 0;
878 io
.smb2
.in
.desired_access
= 0x0017019f;
879 io
.smb2
.in
.create_options
= 0x60;
880 io
.smb2
.in
.file_attributes
= 0;
881 io
.smb2
.in
.share_access
= 0;
882 io
.smb2
.in
.alloc_size
= 0;
883 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
884 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
885 io
.smb2
.in
.security_flags
= 0;
886 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
888 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
889 CHECK_STATUS(status
, NT_STATUS_OK
);
890 fh
= io
.smb2
.out
.file
.handle
;
892 torture_comment(torture
, "Opening parent directory\n");
894 ZERO_STRUCT(io
.smb2
);
895 io
.generic
.level
= RAW_OPEN_SMB2
;
896 io
.smb2
.in
.create_flags
= 0;
897 io
.smb2
.in
.desired_access
= 0x00100080;
898 io
.smb2
.in
.create_options
= 0x00800021;
899 io
.smb2
.in
.file_attributes
= 0;
900 io
.smb2
.in
.share_access
= 0;
901 io
.smb2
.in
.alloc_size
= 0;
902 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
903 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
904 io
.smb2
.in
.security_flags
= 0;
905 io
.smb2
.in
.fname
= BASEDIR
;
907 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
908 CHECK_STATUS(status
, NT_STATUS_OK
);
909 dh
= io
.smb2
.out
.file
.handle
;
911 torture_comment(torture
, "Renaming test file\n");
914 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
915 sinfo
.rename_information
.in
.file
.handle
= fh
;
916 sinfo
.rename_information
.in
.overwrite
= 0;
917 sinfo
.rename_information
.in
.root_fid
= 0;
918 sinfo
.rename_information
.in
.new_name
=
919 BASEDIR
"\\newname.txt";
920 status
= smb2_setinfo_file(tree1
, &sinfo
);
921 CHECK_STATUS(status
, NT_STATUS_OK
);
923 torture_comment(torture
, "Checking for new filename\n");
926 fi
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
927 fi
.generic
.in
.file
.handle
= fh
;
928 status
= smb2_getinfo_file(tree1
, torture
, &fi
);
929 CHECK_STATUS(status
, NT_STATUS_OK
);
932 torture_comment(torture
, "Closing test file\n");
934 ZERO_STRUCT(cl
.smb2
);
935 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
936 cl
.smb2
.in
.file
.handle
= fh
;
937 status
= smb2_close(tree1
, &(cl
.smb2
));
938 CHECK_STATUS(status
, NT_STATUS_OK
);
942 torture_comment(torture
, "Closing directory\n");
944 ZERO_STRUCT(cl
.smb2
);
945 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
946 cl
.smb2
.in
.file
.handle
= dh
;
947 status
= smb2_close(tree1
, &(cl
.smb2
));
948 CHECK_STATUS(status
, NT_STATUS_OK
);
955 torture_comment(torture
, "Cleaning up\n");
957 if (fh
.data
[0] || fh
.data
[1]) {
958 ZERO_STRUCT(cl
.smb2
);
959 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
960 cl
.smb2
.in
.file
.handle
= fh
;
961 status
= smb2_close(tree1
, &(cl
.smb2
));
963 if (dh
.data
[0] || dh
.data
[1]) {
964 ZERO_STRUCT(cl
.smb2
);
965 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
966 cl
.smb2
.in
.file
.handle
= dh
;
967 status
= smb2_close(tree1
, &(cl
.smb2
));
970 smb2_deltree(tree1
, BASEDIR
);
974 static bool torture_smb2_rename_dir_openfile(struct torture_context
*torture
,
975 struct smb2_tree
*tree1
)
981 union smb_setfileinfo sinfo
;
982 struct smb2_handle d1
, h1
;
987 smb2_deltree(tree1
, BASEDIR
);
988 smb2_util_rmdir(tree1
, BASEDIR
);
990 torture_comment(torture
, "Creating base directory\n");
992 ZERO_STRUCT(io
.smb2
);
993 io
.generic
.level
= RAW_OPEN_SMB2
;
994 io
.smb2
.in
.create_flags
= 0;
995 io
.smb2
.in
.desired_access
= 0x0017019f;
996 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
997 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
998 io
.smb2
.in
.share_access
= 0;
999 io
.smb2
.in
.alloc_size
= 0;
1000 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1001 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1002 io
.smb2
.in
.security_flags
= 0;
1003 io
.smb2
.in
.fname
= BASEDIR
;
1005 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1006 CHECK_STATUS(status
, NT_STATUS_OK
);
1007 d1
= io
.smb2
.out
.file
.handle
;
1009 torture_comment(torture
, "Creating test file\n");
1011 ZERO_STRUCT(io
.smb2
);
1012 io
.generic
.level
= RAW_OPEN_SMB2
;
1013 io
.smb2
.in
.create_flags
= 0;
1014 io
.smb2
.in
.desired_access
= 0x0017019f;
1015 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
1016 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1017 io
.smb2
.in
.share_access
= 0;
1018 io
.smb2
.in
.alloc_size
= 0;
1019 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1020 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1021 io
.smb2
.in
.security_flags
= 0;
1022 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
1024 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1025 CHECK_STATUS(status
, NT_STATUS_OK
);
1026 h1
= io
.smb2
.out
.file
.handle
;
1028 torture_comment(torture
, "Renaming directory\n");
1031 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1032 sinfo
.rename_information
.in
.file
.handle
= d1
;
1033 sinfo
.rename_information
.in
.overwrite
= 0;
1034 sinfo
.rename_information
.in
.root_fid
= 0;
1035 sinfo
.rename_information
.in
.new_name
=
1037 status
= smb2_setinfo_file(tree1
, &sinfo
);
1038 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1040 torture_comment(torture
, "Closing directory\n");
1042 ZERO_STRUCT(cl
.smb2
);
1043 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
1044 cl
.smb2
.in
.file
.handle
= d1
;
1045 status
= smb2_close(tree1
, &(cl
.smb2
));
1046 CHECK_STATUS(status
, NT_STATUS_OK
);
1049 torture_comment(torture
, "Closing test file\n");
1051 cl
.smb2
.in
.file
.handle
= h1
;
1052 status
= smb2_close(tree1
, &(cl
.smb2
));
1053 CHECK_STATUS(status
, NT_STATUS_OK
);
1058 torture_comment(torture
, "Cleaning up\n");
1060 if (h1
.data
[0] || h1
.data
[1]) {
1061 ZERO_STRUCT(cl
.smb2
);
1062 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
1063 cl
.smb2
.in
.file
.handle
= h1
;
1064 status
= smb2_close(tree1
, &(cl
.smb2
));
1066 smb2_deltree(tree1
, BASEDIR
);
1070 struct rename_one_dir_cycle_state
{
1071 struct tevent_context
*ev
;
1072 struct smb2_tree
*tree
;
1073 struct smb2_handle file
;
1074 const char *base_name
;
1076 unsigned *rename_counter
;
1080 union smb_setfileinfo sinfo
;
1083 static void rename_one_dir_cycle_done(struct smb2_request
*subreq
);
1085 static struct tevent_req
*rename_one_dir_cycle_send(TALLOC_CTX
*mem_ctx
,
1086 struct tevent_context
*ev
,
1087 struct smb2_tree
*tree
,
1088 struct smb2_handle file
,
1089 unsigned max_renames
,
1090 const char *base_name
,
1091 unsigned *rename_counter
)
1093 struct tevent_req
*req
;
1094 struct rename_one_dir_cycle_state
*state
;
1095 struct smb2_request
*subreq
;
1097 req
= tevent_req_create(mem_ctx
, &state
,
1098 struct rename_one_dir_cycle_state
);
1105 state
->base_name
= base_name
;
1106 state
->rename_counter
= rename_counter
;
1108 state
->max
= max_renames
;
1110 ZERO_STRUCT(state
->sinfo
);
1111 state
->sinfo
.rename_information
.level
=
1112 RAW_SFILEINFO_RENAME_INFORMATION
;
1113 state
->sinfo
.rename_information
.in
.file
.handle
= state
->file
;
1114 state
->sinfo
.rename_information
.in
.overwrite
= 0;
1115 state
->sinfo
.rename_information
.in
.root_fid
= 0;
1117 state
->new_name
= talloc_asprintf(
1118 state
, "%s-%u", state
->base_name
, state
->current
);
1119 if (tevent_req_nomem(state
->new_name
, req
)) {
1120 return tevent_req_post(req
, ev
);
1122 state
->sinfo
.rename_information
.in
.new_name
= state
->new_name
;
1124 subreq
= smb2_setinfo_file_send(state
->tree
, &state
->sinfo
);
1125 if (tevent_req_nomem(subreq
, req
)) {
1126 return tevent_req_post(req
, ev
);
1128 subreq
->async
.fn
= rename_one_dir_cycle_done
;
1129 subreq
->async
.private_data
= req
;
1133 static void rename_one_dir_cycle_done(struct smb2_request
*subreq
)
1135 struct tevent_req
*req
= talloc_get_type_abort(
1136 subreq
->async
.private_data
, struct tevent_req
);
1137 struct rename_one_dir_cycle_state
*state
= tevent_req_data(
1138 req
, struct rename_one_dir_cycle_state
);
1141 status
= smb2_setinfo_recv(subreq
);
1142 if (tevent_req_nterror(req
, status
)) {
1145 TALLOC_FREE(state
->new_name
);
1147 *state
->rename_counter
+= 1;
1149 state
->current
+= 1;
1150 if (state
->current
>= state
->max
) {
1151 tevent_req_done(req
);
1155 ZERO_STRUCT(state
->sinfo
);
1156 state
->sinfo
.rename_information
.level
=
1157 RAW_SFILEINFO_RENAME_INFORMATION
;
1158 state
->sinfo
.rename_information
.in
.file
.handle
= state
->file
;
1159 state
->sinfo
.rename_information
.in
.overwrite
= 0;
1160 state
->sinfo
.rename_information
.in
.root_fid
= 0;
1162 state
->new_name
= talloc_asprintf(
1163 state
, "%s-%u", state
->base_name
, state
->current
);
1164 if (tevent_req_nomem(state
->new_name
, req
)) {
1167 state
->sinfo
.rename_information
.in
.new_name
= state
->new_name
;
1169 subreq
= smb2_setinfo_file_send(state
->tree
, &state
->sinfo
);
1170 if (tevent_req_nomem(subreq
, req
)) {
1173 subreq
->async
.fn
= rename_one_dir_cycle_done
;
1174 subreq
->async
.private_data
= req
;
1177 static NTSTATUS
rename_one_dir_cycle_recv(struct tevent_req
*req
)
1179 return tevent_req_simple_recv_ntstatus(req
);
1182 struct rename_dir_bench_state
{
1183 struct tevent_context
*ev
;
1184 struct smb2_tree
*tree
;
1185 const char *base_name
;
1186 unsigned max_renames
;
1187 unsigned *rename_counter
;
1189 struct smb2_create io
;
1190 union smb_setfileinfo sinfo
;
1191 struct smb2_close cl
;
1193 struct smb2_handle file
;
1196 static void rename_dir_bench_opened(struct smb2_request
*subreq
);
1197 static void rename_dir_bench_renamed(struct tevent_req
*subreq
);
1198 static void rename_dir_bench_set_doc(struct smb2_request
*subreq
);
1199 static void rename_dir_bench_closed(struct smb2_request
*subreq
);
1201 static struct tevent_req
*rename_dir_bench_send(TALLOC_CTX
*mem_ctx
,
1202 struct tevent_context
*ev
,
1203 struct smb2_tree
*tree
,
1204 const char *base_name
,
1205 unsigned max_renames
,
1206 unsigned *rename_counter
)
1208 struct tevent_req
*req
;
1209 struct rename_dir_bench_state
*state
;
1210 struct smb2_request
*subreq
;
1212 req
= tevent_req_create(mem_ctx
, &state
,
1213 struct rename_dir_bench_state
);
1219 state
->base_name
= base_name
;
1220 state
->max_renames
= max_renames
;
1221 state
->rename_counter
= rename_counter
;
1223 ZERO_STRUCT(state
->io
);
1224 state
->io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
1225 state
->io
.in
.share_access
=
1226 NTCREATEX_SHARE_ACCESS_READ
|
1227 NTCREATEX_SHARE_ACCESS_WRITE
;
1228 state
->io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1229 state
->io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1230 state
->io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1231 state
->io
.in
.fname
= state
->base_name
;
1233 subreq
= smb2_create_send(state
->tree
, &state
->io
);
1234 if (tevent_req_nomem(subreq
, req
)) {
1235 return tevent_req_post(req
, ev
);
1237 subreq
->async
.fn
= rename_dir_bench_opened
;
1238 subreq
->async
.private_data
= req
;
1242 static void rename_dir_bench_opened(struct smb2_request
*subreq
)
1244 struct tevent_req
*req
= talloc_get_type_abort(
1245 subreq
->async
.private_data
, struct tevent_req
);
1246 struct rename_dir_bench_state
*state
= tevent_req_data(
1247 req
, struct rename_dir_bench_state
);
1248 struct smb2_create
*io
;
1249 struct tevent_req
*subreq2
;
1252 io
= talloc(state
, struct smb2_create
);
1253 if (tevent_req_nomem(io
, req
)) {
1257 status
= smb2_create_recv(subreq
, io
, io
);
1258 if (tevent_req_nterror(req
, status
)) {
1261 state
->file
= io
->out
.file
.handle
;
1264 subreq2
= rename_one_dir_cycle_send(
1265 state
, state
->ev
, state
->tree
, state
->file
,
1266 state
->max_renames
, state
->base_name
,
1267 state
->rename_counter
);
1268 if (tevent_req_nomem(subreq2
, req
)) {
1271 tevent_req_set_callback(subreq2
, rename_dir_bench_renamed
, req
);
1274 static void rename_dir_bench_renamed(struct tevent_req
*subreq
)
1276 struct tevent_req
*req
= tevent_req_callback_data(
1277 subreq
, struct tevent_req
);
1278 struct rename_dir_bench_state
*state
= tevent_req_data(
1279 req
, struct rename_dir_bench_state
);
1280 struct smb2_request
*subreq2
;
1283 status
= rename_one_dir_cycle_recv(subreq
);
1284 TALLOC_FREE(subreq
);
1285 if (tevent_req_nterror(req
, status
)) {
1289 ZERO_STRUCT(state
->sinfo
);
1290 state
->sinfo
.disposition_info
.level
=
1291 RAW_SFILEINFO_DISPOSITION_INFORMATION
;
1292 state
->sinfo
.disposition_info
.in
.file
.handle
= state
->file
;
1293 state
->sinfo
.disposition_info
.in
.delete_on_close
= true;
1295 subreq2
= smb2_setinfo_file_send(state
->tree
, &state
->sinfo
);
1296 if (tevent_req_nomem(subreq2
, req
)) {
1299 subreq2
->async
.fn
= rename_dir_bench_set_doc
;
1300 subreq2
->async
.private_data
= req
;
1303 static void rename_dir_bench_set_doc(struct smb2_request
*subreq
)
1305 struct tevent_req
*req
= talloc_get_type_abort(
1306 subreq
->async
.private_data
, struct tevent_req
);
1307 struct rename_dir_bench_state
*state
= tevent_req_data(
1308 req
, struct rename_dir_bench_state
);
1311 status
= smb2_setinfo_recv(subreq
);
1312 if (tevent_req_nterror(req
, status
)) {
1316 ZERO_STRUCT(state
->cl
);
1317 state
->cl
.in
.file
.handle
= state
->file
;
1319 subreq
= smb2_close_send(state
->tree
, &state
->cl
);
1320 if (tevent_req_nomem(subreq
, req
)) {
1323 subreq
->async
.fn
= rename_dir_bench_closed
;
1324 subreq
->async
.private_data
= req
;
1327 static void rename_dir_bench_closed(struct smb2_request
*subreq
)
1329 struct tevent_req
*req
= talloc_get_type_abort(
1330 subreq
->async
.private_data
, struct tevent_req
);
1331 struct smb2_close cl
;
1334 status
= smb2_close_recv(subreq
, &cl
);
1335 if (tevent_req_nterror(req
, status
)) {
1338 tevent_req_done(req
);
1341 static NTSTATUS
rename_dir_bench_recv(struct tevent_req
*req
)
1343 return tevent_req_simple_recv_ntstatus(req
);
1346 struct rename_dirs_bench_state
{
1351 static void rename_dirs_bench_done(struct tevent_req
*subreq
);
1353 static struct tevent_req
*rename_dirs_bench_send(TALLOC_CTX
*mem_ctx
,
1354 struct tevent_context
*ev
,
1355 struct smb2_tree
*tree
,
1356 const char *base_name
,
1357 unsigned num_parallel
,
1358 unsigned max_renames
,
1359 unsigned *rename_counter
)
1361 struct tevent_req
*req
;
1362 struct rename_dirs_bench_state
*state
;
1365 req
= tevent_req_create(mem_ctx
, &state
,
1366 struct rename_dirs_bench_state
);
1370 state
->num_reqs
= num_parallel
;
1371 state
->num_done
= 0;
1373 for (i
=0; i
<num_parallel
; i
++) {
1374 struct tevent_req
*subreq
;
1377 sub_base
= talloc_asprintf(state
, "%s-%u", base_name
, i
);
1378 if (tevent_req_nomem(sub_base
, req
)) {
1379 return tevent_req_post(req
, ev
);
1382 subreq
= rename_dir_bench_send(state
, ev
, tree
, sub_base
,
1383 max_renames
, rename_counter
);
1384 if (tevent_req_nomem(subreq
, req
)) {
1385 return tevent_req_post(req
, ev
);
1387 tevent_req_set_callback(subreq
, rename_dirs_bench_done
, req
);
1392 static void rename_dirs_bench_done(struct tevent_req
*subreq
)
1394 struct tevent_req
*req
= tevent_req_callback_data(
1395 subreq
, struct tevent_req
);
1396 struct rename_dirs_bench_state
*state
= tevent_req_data(
1397 req
, struct rename_dirs_bench_state
);
1400 status
= rename_dir_bench_recv(subreq
);
1401 TALLOC_FREE(subreq
);
1402 if (tevent_req_nterror(req
, status
)) {
1406 state
->num_done
+= 1;
1407 if (state
->num_done
>= state
->num_reqs
) {
1408 tevent_req_done(req
);
1412 static NTSTATUS
rename_dirs_bench_recv(struct tevent_req
*req
)
1414 return tevent_req_simple_recv_ntstatus(req
);
1417 static bool torture_smb2_rename_dir_bench(struct torture_context
*tctx
,
1418 struct smb2_tree
*tree
)
1420 struct tevent_req
*req
;
1422 unsigned counter
= 0;
1425 req
= rename_dirs_bench_send(tctx
, tctx
->ev
, tree
, "dir", 3, 10,
1427 torture_assert(tctx
, req
!= NULL
, "rename_dirs_bench_send failed");
1429 ret
= tevent_req_poll(req
, tctx
->ev
);
1430 torture_assert(tctx
, ret
, "tevent_req_poll failed");
1432 status
= rename_dirs_bench_recv(req
);
1433 torture_comment(tctx
, "rename_dirs_bench returned %s\n",
1436 torture_assert_ntstatus_ok(tctx
, status
, "bench failed");
1440 static bool test_smb2_close_full_information(struct torture_context
*torture
,
1441 struct smb2_tree
*tree1
,
1442 struct smb2_tree
*tree2
)
1445 struct smb2_create io
= {0};
1446 struct smb2_handle h1
= {{0}};
1447 struct smb2_handle h2
= {{0}};
1448 struct smb2_handle h3
= {{0}};
1449 union smb_setfileinfo sinfo
;
1451 const char *fname_src
= "request.dat";
1452 const char *fname_dst
= "renamed.dat";
1455 /* Start with a tidy share. */
1456 smb2_util_unlink(tree1
, fname_src
);
1457 smb2_util_unlink(tree1
, fname_dst
);
1459 /* Create the test file, and leave it open. */
1460 io
.in
.fname
= fname_src
;
1461 io
.in
.desired_access
= SEC_FILE_READ_DATA
| SEC_FILE_READ_ATTRIBUTE
;
1462 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1463 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1464 NTCREATEX_SHARE_ACCESS_WRITE
|
1465 NTCREATEX_SHARE_ACCESS_DELETE
;
1466 status
= smb2_create(tree1
, tree1
, &io
);
1467 CHECK_STATUS(status
, NT_STATUS_OK
);
1468 h1
= io
.out
.file
.handle
;
1469 CHECK_CREATED(&io
, CREATED
, FILE_ATTRIBUTE_ARCHIVE
);
1471 /* Open the test file on the second connection. */
1473 io
.in
.fname
= fname_src
;
1474 io
.in
.desired_access
= SEC_FILE_READ_DATA
| SEC_FILE_READ_ATTRIBUTE
;
1475 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1476 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1477 NTCREATEX_SHARE_ACCESS_WRITE
|
1478 NTCREATEX_SHARE_ACCESS_DELETE
;
1479 status
= smb2_create(tree2
, tree2
, &io
);
1480 CHECK_STATUS(status
, NT_STATUS_OK
);
1481 h2
= io
.out
.file
.handle
;
1483 /* Now open for rename on the first connection. */
1485 io
.in
.fname
= fname_src
;
1486 io
.in
.desired_access
= SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
;
1487 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1488 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1489 NTCREATEX_SHARE_ACCESS_WRITE
|
1490 NTCREATEX_SHARE_ACCESS_DELETE
;
1491 status
= smb2_create(tree1
, tree1
, &io
);
1492 CHECK_STATUS(status
, NT_STATUS_OK
);
1493 h3
= io
.out
.file
.handle
;
1495 /* Do the rename. */
1497 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1498 sinfo
.rename_information
.in
.file
.handle
= h3
;
1499 sinfo
.rename_information
.in
.new_name
= fname_dst
;
1500 status
= smb2_setinfo_file(tree1
, &sinfo
);
1501 CHECK_STATUS(status
, NT_STATUS_OK
);
1504 ZERO_STRUCT(cl
.smb2
);
1505 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
1506 cl
.smb2
.in
.file
.handle
= h3
;
1507 status
= smb2_close(tree1
, &cl
.smb2
);
1508 CHECK_STATUS(status
, NT_STATUS_OK
);
1512 * Close h1 with SMB2_CLOSE_FLAGS_FULL_INFORMATION.
1513 * Ensure we get data.
1515 ZERO_STRUCT(cl
.smb2
);
1516 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
1517 cl
.smb2
.in
.file
.handle
= h1
;
1518 cl
.smb2
.in
.flags
= SMB2_CLOSE_FLAGS_FULL_INFORMATION
;
1519 status
= smb2_close(tree1
, &cl
.smb2
);
1520 CHECK_STATUS(status
, NT_STATUS_OK
);
1522 CHECK_VAL(cl
.smb2
.out
.file_attr
, 0x20);
1525 * Wait 3 seconds for name change to propagate
1526 * to the other connection.
1531 * Close h2 with SMB2_CLOSE_FLAGS_FULL_INFORMATION.
1532 * This is on connection2.
1533 * Ensure we get data.
1535 ZERO_STRUCT(cl
.smb2
);
1536 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
1537 cl
.smb2
.in
.file
.handle
= h2
;
1538 cl
.smb2
.in
.flags
= SMB2_CLOSE_FLAGS_FULL_INFORMATION
;
1539 status
= smb2_close(tree2
, &cl
.smb2
);
1540 CHECK_STATUS(status
, NT_STATUS_OK
);
1542 CHECK_VAL(cl
.smb2
.out
.file_attr
, 0x20);
1546 if (h1
.data
[0] != 0 || h1
.data
[1] != 0) {
1547 smb2_util_close(tree1
, h1
);
1549 if (h2
.data
[0] != 0 || h2
.data
[1] != 0) {
1550 smb2_util_close(tree2
, h2
);
1552 if (h3
.data
[0] != 0 || h3
.data
[1] != 0) {
1553 smb2_util_close(tree1
, h3
);
1556 smb2_util_unlink(tree1
, fname_src
);
1557 smb2_util_unlink(tree1
, fname_dst
);
1563 basic testing of SMB2 rename
1565 struct torture_suite
*torture_smb2_rename_init(TALLOC_CTX
*ctx
)
1567 struct torture_suite
*suite
=
1568 torture_suite_create(ctx
, "rename");
1570 torture_suite_add_1smb2_test(suite
, "simple",
1571 torture_smb2_rename_simple
);
1573 torture_suite_add_1smb2_test(suite
, "simple_nodelete",
1574 torture_smb2_rename_simple2
);
1576 torture_suite_add_1smb2_test(suite
, "no_sharing",
1577 torture_smb2_rename_no_sharemode
);
1579 torture_suite_add_1smb2_test(suite
,
1580 "share_delete_and_delete_access",
1581 torture_smb2_rename_with_delete_access
);
1583 torture_suite_add_1smb2_test(suite
,
1584 "no_share_delete_but_delete_access",
1585 torture_smb2_rename_with_delete_access2
);
1587 torture_suite_add_1smb2_test(suite
,
1588 "share_delete_no_delete_access",
1589 torture_smb2_rename_no_delete_access
);
1591 torture_suite_add_1smb2_test(suite
,
1592 "no_share_delete_no_delete_access",
1593 torture_smb2_rename_no_delete_access2
);
1595 torture_suite_add_1smb2_test(suite
,
1597 torture_smb2_rename_msword
);
1599 torture_suite_add_1smb2_test(
1600 suite
, "rename_dir_openfile",
1601 torture_smb2_rename_dir_openfile
);
1603 torture_suite_add_1smb2_test(suite
,
1605 torture_smb2_rename_dir_bench
);
1607 torture_suite_add_2smb2_test(suite
,
1608 "close-full-information",
1609 test_smb2_close_full_information
);
1611 suite
->description
= talloc_strdup(suite
, "smb2.rename tests");