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_STATUS(status, correct) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 torture_result(torture, TORTURE_FAIL, \
36 "(%s) Incorrect status %s - should be %s\n", \
37 __location__, nt_errstr(status), nt_errstr(correct)); \
42 #define BASEDIR "test_rename"
45 * basic testing of rename: open file with DELETE access
49 static bool torture_smb2_rename_simple(struct torture_context
*torture
,
50 struct smb2_tree
*tree1
)
56 union smb_setfileinfo sinfo
;
57 union smb_fileinfo fi
;
58 struct smb2_handle h1
;
62 smb2_deltree(tree1
, BASEDIR
);
63 smb2_util_rmdir(tree1
, BASEDIR
);
65 torture_comment(torture
, "Creating base directory\n");
67 smb2_util_mkdir(tree1
, BASEDIR
);
70 torture_comment(torture
, "Creating test file\n");
73 io
.generic
.level
= RAW_OPEN_SMB2
;
74 io
.smb2
.in
.create_flags
= 0;
75 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
|SEC_STD_DELETE
;
76 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
77 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
78 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
79 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
80 io
.smb2
.in
.alloc_size
= 0;
81 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
82 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
83 io
.smb2
.in
.security_flags
= 0;
84 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
86 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
87 CHECK_STATUS(status
, NT_STATUS_OK
);
88 h1
= io
.smb2
.out
.file
.handle
;
90 torture_comment(torture
, "Renaming test file\n");
93 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
94 sinfo
.rename_information
.in
.file
.handle
= io
.smb2
.out
.file
.handle
;
95 sinfo
.rename_information
.in
.overwrite
= 0;
96 sinfo
.rename_information
.in
.root_fid
= 0;
97 sinfo
.rename_information
.in
.new_name
=
98 BASEDIR
"\\newname.txt";
99 status
= smb2_setinfo_file(tree1
, &sinfo
);
100 CHECK_STATUS(status
, NT_STATUS_OK
);
102 torture_comment(torture
, "Checking for new filename\n");
105 fi
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
106 fi
.generic
.in
.file
.handle
= h1
;
107 status
= smb2_getinfo_file(tree1
, torture
, &fi
);
108 CHECK_STATUS(status
, NT_STATUS_OK
);
111 torture_comment(torture
, "Closing test file\n");
113 ZERO_STRUCT(cl
.smb2
);
114 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
115 cl
.smb2
.in
.file
.handle
= h1
;
116 status
= smb2_close(tree1
, &(cl
.smb2
));
117 CHECK_STATUS(status
, NT_STATUS_OK
);
123 torture_comment(torture
, "Cleaning up\n");
125 if (h1
.data
[0] || h1
.data
[1]) {
126 ZERO_STRUCT(cl
.smb2
);
127 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
128 cl
.smb2
.in
.file
.handle
= h1
;
129 status
= smb2_close(tree1
, &(cl
.smb2
));
131 smb2_deltree(tree1
, BASEDIR
);
136 * basic testing of rename, this time do not request DELETE access
137 * for the file, this should fail
140 static bool torture_smb2_rename_simple2(struct torture_context
*torture
,
141 struct smb2_tree
*tree1
)
147 union smb_setfileinfo sinfo
;
148 struct smb2_handle h1
;
152 smb2_deltree(tree1
, BASEDIR
);
153 smb2_util_rmdir(tree1
, BASEDIR
);
155 torture_comment(torture
, "Creating base directory\n");
157 smb2_util_mkdir(tree1
, BASEDIR
);
160 torture_comment(torture
, "Creating test file\n");
162 ZERO_STRUCT(io
.smb2
);
163 io
.generic
.level
= RAW_OPEN_SMB2
;
164 io
.smb2
.in
.create_flags
= 0;
165 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
166 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
167 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
168 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
169 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
170 io
.smb2
.in
.alloc_size
= 0;
171 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
172 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
173 io
.smb2
.in
.security_flags
= 0;
174 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
176 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
177 CHECK_STATUS(status
, NT_STATUS_OK
);
178 h1
= io
.smb2
.out
.file
.handle
;
180 torture_comment(torture
, "Renaming test file\n");
183 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
184 sinfo
.rename_information
.in
.file
.handle
= io
.smb2
.out
.file
.handle
;
185 sinfo
.rename_information
.in
.overwrite
= 0;
186 sinfo
.rename_information
.in
.root_fid
= 0;
187 sinfo
.rename_information
.in
.new_name
=
188 BASEDIR
"\\newname.txt";
189 status
= smb2_setinfo_file(tree1
, &sinfo
);
190 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
192 torture_comment(torture
, "Closing test file\n");
194 ZERO_STRUCT(cl
.smb2
);
195 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
196 cl
.smb2
.in
.file
.handle
= h1
;
197 status
= smb2_close(tree1
, &(cl
.smb2
));
198 CHECK_STATUS(status
, NT_STATUS_OK
);
204 torture_comment(torture
, "Cleaning up\n");
206 if (h1
.data
[0] || h1
.data
[1]) {
207 ZERO_STRUCT(cl
.smb2
);
208 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
209 cl
.smb2
.in
.file
.handle
= h1
;
210 status
= smb2_close(tree1
, &(cl
.smb2
));
212 smb2_deltree(tree1
, BASEDIR
);
218 * testing of rename with no sharing allowed on file
222 static bool torture_smb2_rename_no_sharemode(struct torture_context
*torture
,
223 struct smb2_tree
*tree1
)
229 union smb_setfileinfo sinfo
;
230 union smb_fileinfo fi
;
231 struct smb2_handle h1
;
235 smb2_deltree(tree1
, BASEDIR
);
236 smb2_util_rmdir(tree1
, BASEDIR
);
238 torture_comment(torture
, "Creating base directory\n");
240 smb2_util_mkdir(tree1
, BASEDIR
);
243 torture_comment(torture
, "Creating test file\n");
245 ZERO_STRUCT(io
.smb2
);
246 io
.generic
.level
= RAW_OPEN_SMB2
;
247 io
.smb2
.in
.create_flags
= 0;
248 io
.smb2
.in
.desired_access
= 0x0017019f;
249 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
250 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
251 io
.smb2
.in
.share_access
= 0;
252 io
.smb2
.in
.alloc_size
= 0;
253 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
254 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
255 io
.smb2
.in
.security_flags
= 0;
256 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
258 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
259 CHECK_STATUS(status
, NT_STATUS_OK
);
260 h1
= io
.smb2
.out
.file
.handle
;
262 torture_comment(torture
, "Renaming test file\n");
265 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
266 sinfo
.rename_information
.in
.file
.handle
= io
.smb2
.out
.file
.handle
;
267 sinfo
.rename_information
.in
.overwrite
= 0;
268 sinfo
.rename_information
.in
.root_fid
= 0;
269 sinfo
.rename_information
.in
.new_name
=
270 BASEDIR
"\\newname.txt";
271 status
= smb2_setinfo_file(tree1
, &sinfo
);
272 CHECK_STATUS(status
, NT_STATUS_OK
);
274 torture_comment(torture
, "Checking for new filename\n");
277 fi
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
278 fi
.generic
.in
.file
.handle
= h1
;
279 status
= smb2_getinfo_file(tree1
, torture
, &fi
);
280 CHECK_STATUS(status
, NT_STATUS_OK
);
283 torture_comment(torture
, "Closing test file\n");
285 ZERO_STRUCT(cl
.smb2
);
286 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
287 cl
.smb2
.in
.file
.handle
= h1
;
288 status
= smb2_close(tree1
, &(cl
.smb2
));
289 CHECK_STATUS(status
, NT_STATUS_OK
);
295 torture_comment(torture
, "Cleaning up\n");
297 if (h1
.data
[0] || h1
.data
[1]) {
298 ZERO_STRUCT(cl
.smb2
);
299 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
300 cl
.smb2
.in
.file
.handle
= h1
;
301 status
= smb2_close(tree1
, &(cl
.smb2
));
303 smb2_deltree(tree1
, BASEDIR
);
308 * testing of rename when opening parent dir with delete access and delete
310 * should result in sharing violation
313 static bool torture_smb2_rename_with_delete_access(struct torture_context
*torture
,
314 struct smb2_tree
*tree1
)
320 union smb_setfileinfo sinfo
;
321 struct smb2_handle fh
, dh
;
326 smb2_deltree(tree1
, BASEDIR
);
327 smb2_util_rmdir(tree1
, BASEDIR
);
329 torture_comment(torture
, "Creating base directory\n");
331 smb2_util_mkdir(tree1
, BASEDIR
);
333 torture_comment(torture
, "Opening parent directory\n");
335 ZERO_STRUCT(io
.smb2
);
336 io
.generic
.level
= RAW_OPEN_SMB2
;
337 io
.smb2
.in
.create_flags
= 0;
338 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
339 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
340 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
| SEC_FILE_WRITE_EA
|
341 SEC_FILE_READ_EA
| SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
|
343 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
344 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
345 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
346 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
347 io
.smb2
.in
.alloc_size
= 0;
348 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
349 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
350 io
.smb2
.in
.security_flags
= 0;
351 io
.smb2
.in
.fname
= BASEDIR
;
353 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
354 CHECK_STATUS(status
, NT_STATUS_OK
);
355 dh
= io
.smb2
.out
.file
.handle
;
358 torture_comment(torture
, "Creating test file\n");
360 ZERO_STRUCT(io
.smb2
);
361 io
.generic
.level
= RAW_OPEN_SMB2
;
362 io
.smb2
.in
.create_flags
= 0;
363 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
364 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
365 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_WRITE_EA
| SEC_FILE_READ_EA
|
366 SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
367 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
368 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
369 io
.smb2
.in
.share_access
= 0;
370 io
.smb2
.in
.alloc_size
= 0;
371 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
372 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
373 io
.smb2
.in
.security_flags
= 0;
374 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
376 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
377 CHECK_STATUS(status
, NT_STATUS_OK
);
378 fh
= io
.smb2
.out
.file
.handle
;
380 torture_comment(torture
, "Renaming test file\n");
383 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
384 sinfo
.rename_information
.in
.file
.handle
= fh
;
385 sinfo
.rename_information
.in
.overwrite
= 0;
386 sinfo
.rename_information
.in
.root_fid
= 0;
387 sinfo
.rename_information
.in
.new_name
=
388 BASEDIR
"\\newname.txt";
389 status
= smb2_setinfo_file(tree1
, &sinfo
);
390 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
392 torture_comment(torture
, "Closing test file\n");
394 ZERO_STRUCT(cl
.smb2
);
395 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
396 cl
.smb2
.in
.file
.handle
= fh
;
397 status
= smb2_close(tree1
, &(cl
.smb2
));
398 CHECK_STATUS(status
, NT_STATUS_OK
);
402 torture_comment(torture
, "Closing directory\n");
404 ZERO_STRUCT(cl
.smb2
);
405 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
406 cl
.smb2
.in
.file
.handle
= dh
;
407 status
= smb2_close(tree1
, &(cl
.smb2
));
408 CHECK_STATUS(status
, NT_STATUS_OK
);
415 torture_comment(torture
, "Cleaning up\n");
417 if (fh
.data
[0] || fh
.data
[1]) {
418 ZERO_STRUCT(cl
.smb2
);
419 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
420 cl
.smb2
.in
.file
.handle
= fh
;
421 status
= smb2_close(tree1
, &(cl
.smb2
));
423 if (dh
.data
[0] || dh
.data
[1]) {
424 ZERO_STRUCT(cl
.smb2
);
425 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
426 cl
.smb2
.in
.file
.handle
= dh
;
427 status
= smb2_close(tree1
, &(cl
.smb2
));
430 smb2_deltree(tree1
, BASEDIR
);
436 * testing of rename with delete access on parent dir
437 * this is a variation of the test above: parent dir is opened
438 * without share_delete, so rename must fail
441 static bool torture_smb2_rename_with_delete_access2(struct torture_context
*torture
,
442 struct smb2_tree
*tree1
)
448 union smb_setfileinfo sinfo
;
449 struct smb2_handle fh
, dh
;
454 smb2_deltree(tree1
, BASEDIR
);
455 smb2_util_rmdir(tree1
, BASEDIR
);
457 torture_comment(torture
, "Creating base directory\n");
459 smb2_util_mkdir(tree1
, BASEDIR
);
461 torture_comment(torture
, "Opening parent directory\n");
463 ZERO_STRUCT(io
.smb2
);
464 io
.generic
.level
= RAW_OPEN_SMB2
;
465 io
.smb2
.in
.create_flags
= 0;
466 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
467 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
468 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
| SEC_FILE_WRITE_EA
|
469 SEC_FILE_READ_EA
| SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
|
471 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
472 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
473 io
.smb2
.in
.share_access
= 0;
474 io
.smb2
.in
.alloc_size
= 0;
475 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
476 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
477 io
.smb2
.in
.security_flags
= 0;
478 io
.smb2
.in
.fname
= BASEDIR
;
480 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
481 CHECK_STATUS(status
, NT_STATUS_OK
);
482 dh
= io
.smb2
.out
.file
.handle
;
485 torture_comment(torture
, "Creating test file\n");
487 ZERO_STRUCT(io
.smb2
);
488 io
.generic
.level
= RAW_OPEN_SMB2
;
489 io
.smb2
.in
.create_flags
= 0;
490 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
491 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
492 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_WRITE_EA
| SEC_FILE_READ_EA
|
493 SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
494 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
495 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
496 io
.smb2
.in
.share_access
= 0;
497 io
.smb2
.in
.alloc_size
= 0;
498 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
499 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
500 io
.smb2
.in
.security_flags
= 0;
501 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
503 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
504 CHECK_STATUS(status
, NT_STATUS_OK
);
505 fh
= io
.smb2
.out
.file
.handle
;
507 torture_comment(torture
, "Renaming test file\n");
510 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
511 sinfo
.rename_information
.in
.file
.handle
= fh
;
512 sinfo
.rename_information
.in
.overwrite
= 0;
513 sinfo
.rename_information
.in
.root_fid
= 0;
514 sinfo
.rename_information
.in
.new_name
=
515 BASEDIR
"\\newname.txt";
516 status
= smb2_setinfo_file(tree1
, &sinfo
);
517 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
519 torture_comment(torture
, "Closing test file\n");
521 ZERO_STRUCT(cl
.smb2
);
522 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
523 cl
.smb2
.in
.file
.handle
= fh
;
524 status
= smb2_close(tree1
, &(cl
.smb2
));
525 CHECK_STATUS(status
, NT_STATUS_OK
);
529 torture_comment(torture
, "Closing directory\n");
531 ZERO_STRUCT(cl
.smb2
);
532 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
533 cl
.smb2
.in
.file
.handle
= dh
;
534 status
= smb2_close(tree1
, &(cl
.smb2
));
535 CHECK_STATUS(status
, NT_STATUS_OK
);
542 torture_comment(torture
, "Cleaning up\n");
544 if (fh
.data
[0] || fh
.data
[1]) {
545 ZERO_STRUCT(cl
.smb2
);
546 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
547 cl
.smb2
.in
.file
.handle
= fh
;
548 status
= smb2_close(tree1
, &(cl
.smb2
));
550 if (dh
.data
[0] || dh
.data
[1]) {
551 ZERO_STRUCT(cl
.smb2
);
552 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
553 cl
.smb2
.in
.file
.handle
= dh
;
554 status
= smb2_close(tree1
, &(cl
.smb2
));
557 smb2_deltree(tree1
, BASEDIR
);
562 * testing of rename when opening parent dir with no delete access and delete
567 static bool torture_smb2_rename_no_delete_access(struct torture_context
*torture
,
568 struct smb2_tree
*tree1
)
574 union smb_setfileinfo sinfo
;
575 union smb_fileinfo fi
;
576 struct smb2_handle fh
, dh
;
581 smb2_deltree(tree1
, BASEDIR
);
582 smb2_util_rmdir(tree1
, BASEDIR
);
584 torture_comment(torture
, "Creating base directory\n");
586 smb2_util_mkdir(tree1
, BASEDIR
);
588 torture_comment(torture
, "Opening parent directory\n");
590 ZERO_STRUCT(io
.smb2
);
591 io
.generic
.level
= RAW_OPEN_SMB2
;
592 io
.smb2
.in
.create_flags
= 0;
593 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
594 SEC_STD_READ_CONTROL
| SEC_FILE_WRITE_ATTRIBUTE
|
595 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
| SEC_FILE_WRITE_EA
|
596 SEC_FILE_READ_EA
| SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
|
598 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
599 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
600 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
601 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
602 io
.smb2
.in
.alloc_size
= 0;
603 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
604 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
605 io
.smb2
.in
.security_flags
= 0;
606 io
.smb2
.in
.fname
= BASEDIR
;
608 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
609 CHECK_STATUS(status
, NT_STATUS_OK
);
610 dh
= io
.smb2
.out
.file
.handle
;
613 torture_comment(torture
, "Creating test file\n");
615 ZERO_STRUCT(io
.smb2
);
616 io
.generic
.level
= RAW_OPEN_SMB2
;
617 io
.smb2
.in
.create_flags
= 0;
618 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
619 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
620 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_WRITE_EA
| SEC_FILE_READ_EA
|
621 SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
622 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
623 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
624 io
.smb2
.in
.share_access
= 0;
625 io
.smb2
.in
.alloc_size
= 0;
626 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
627 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
628 io
.smb2
.in
.security_flags
= 0;
629 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
631 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
632 CHECK_STATUS(status
, NT_STATUS_OK
);
633 fh
= io
.smb2
.out
.file
.handle
;
635 torture_comment(torture
, "Renaming test file\n");
638 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
639 sinfo
.rename_information
.in
.file
.handle
= fh
;
640 sinfo
.rename_information
.in
.overwrite
= 0;
641 sinfo
.rename_information
.in
.root_fid
= 0;
642 sinfo
.rename_information
.in
.new_name
=
643 BASEDIR
"\\newname.txt";
644 status
= smb2_setinfo_file(tree1
, &sinfo
);
645 CHECK_STATUS(status
, NT_STATUS_OK
);
647 torture_comment(torture
, "Checking for new filename\n");
650 fi
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
651 fi
.generic
.in
.file
.handle
= fh
;
652 status
= smb2_getinfo_file(tree1
, torture
, &fi
);
653 CHECK_STATUS(status
, NT_STATUS_OK
);
656 torture_comment(torture
, "Closing test file\n");
658 ZERO_STRUCT(cl
.smb2
);
659 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
660 cl
.smb2
.in
.file
.handle
= fh
;
661 status
= smb2_close(tree1
, &(cl
.smb2
));
662 CHECK_STATUS(status
, NT_STATUS_OK
);
666 torture_comment(torture
, "Closing directory\n");
668 ZERO_STRUCT(cl
.smb2
);
669 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
670 cl
.smb2
.in
.file
.handle
= dh
;
671 status
= smb2_close(tree1
, &(cl
.smb2
));
672 CHECK_STATUS(status
, NT_STATUS_OK
);
679 torture_comment(torture
, "Cleaning up\n");
681 if (fh
.data
[0] || fh
.data
[1]) {
682 ZERO_STRUCT(cl
.smb2
);
683 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
684 cl
.smb2
.in
.file
.handle
= fh
;
685 status
= smb2_close(tree1
, &(cl
.smb2
));
687 if (dh
.data
[0] || dh
.data
[1]) {
688 ZERO_STRUCT(cl
.smb2
);
689 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
690 cl
.smb2
.in
.file
.handle
= dh
;
691 status
= smb2_close(tree1
, &(cl
.smb2
));
694 smb2_deltree(tree1
, BASEDIR
);
700 * testing of rename with no delete access on parent dir
701 * this is the negative case of the test above: parent dir is opened
702 * without share_delete, so rename must fail
705 static bool torture_smb2_rename_no_delete_access2(struct torture_context
*torture
,
706 struct smb2_tree
*tree1
)
712 union smb_setfileinfo sinfo
;
713 struct smb2_handle fh
, dh
;
718 smb2_deltree(tree1
, BASEDIR
);
719 smb2_util_rmdir(tree1
, BASEDIR
);
721 torture_comment(torture
, "Creating base directory\n");
723 smb2_util_mkdir(tree1
, BASEDIR
);
725 torture_comment(torture
, "Opening parent directory\n");
727 ZERO_STRUCT(io
.smb2
);
728 io
.generic
.level
= RAW_OPEN_SMB2
;
729 io
.smb2
.in
.create_flags
= 0;
730 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
731 SEC_STD_READ_CONTROL
| SEC_FILE_WRITE_ATTRIBUTE
|
732 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
| SEC_FILE_WRITE_EA
|
733 SEC_FILE_READ_EA
| SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
|
735 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
736 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
737 io
.smb2
.in
.share_access
= 0;
738 io
.smb2
.in
.alloc_size
= 0;
739 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
740 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
741 io
.smb2
.in
.security_flags
= 0;
742 io
.smb2
.in
.fname
= BASEDIR
;
744 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
745 CHECK_STATUS(status
, NT_STATUS_OK
);
746 dh
= io
.smb2
.out
.file
.handle
;
749 torture_comment(torture
, "Creating test file\n");
751 ZERO_STRUCT(io
.smb2
);
752 io
.generic
.level
= RAW_OPEN_SMB2
;
753 io
.smb2
.in
.create_flags
= 0;
754 io
.smb2
.in
.desired_access
= SEC_STD_SYNCHRONIZE
| SEC_STD_WRITE_DAC
|
755 SEC_STD_READ_CONTROL
| SEC_STD_DELETE
| SEC_FILE_WRITE_ATTRIBUTE
|
756 SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_WRITE_EA
| SEC_FILE_READ_EA
|
757 SEC_FILE_APPEND_DATA
| SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
;
758 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
759 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
760 io
.smb2
.in
.share_access
= 0;
761 io
.smb2
.in
.alloc_size
= 0;
762 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
763 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
764 io
.smb2
.in
.security_flags
= 0;
765 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
767 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
768 CHECK_STATUS(status
, NT_STATUS_OK
);
769 fh
= io
.smb2
.out
.file
.handle
;
771 torture_comment(torture
, "Renaming test file\n");
774 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
775 sinfo
.rename_information
.in
.file
.handle
= fh
;
776 sinfo
.rename_information
.in
.overwrite
= 0;
777 sinfo
.rename_information
.in
.root_fid
= 0;
778 sinfo
.rename_information
.in
.new_name
=
779 BASEDIR
"\\newname.txt";
780 status
= smb2_setinfo_file(tree1
, &sinfo
);
781 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
783 torture_comment(torture
, "Closing test file\n");
785 ZERO_STRUCT(cl
.smb2
);
786 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
787 cl
.smb2
.in
.file
.handle
= fh
;
788 status
= smb2_close(tree1
, &(cl
.smb2
));
789 CHECK_STATUS(status
, NT_STATUS_OK
);
793 torture_comment(torture
, "Closing directory\n");
795 ZERO_STRUCT(cl
.smb2
);
796 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
797 cl
.smb2
.in
.file
.handle
= dh
;
798 status
= smb2_close(tree1
, &(cl
.smb2
));
799 CHECK_STATUS(status
, NT_STATUS_OK
);
806 torture_comment(torture
, "Cleaning up\n");
808 if (fh
.data
[0] || fh
.data
[1]) {
809 ZERO_STRUCT(cl
.smb2
);
810 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
811 cl
.smb2
.in
.file
.handle
= fh
;
812 status
= smb2_close(tree1
, &(cl
.smb2
));
814 if (dh
.data
[0] || dh
.data
[1]) {
815 ZERO_STRUCT(cl
.smb2
);
816 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
817 cl
.smb2
.in
.file
.handle
= dh
;
818 status
= smb2_close(tree1
, &(cl
.smb2
));
821 smb2_deltree(tree1
, BASEDIR
);
826 * this is a replay of how Word 2010 saves a file
830 static bool torture_smb2_rename_msword(struct torture_context
*torture
,
831 struct smb2_tree
*tree1
)
837 union smb_setfileinfo sinfo
;
838 union smb_fileinfo fi
;
839 struct smb2_handle fh
, dh
;
844 smb2_deltree(tree1
, BASEDIR
);
845 smb2_util_rmdir(tree1
, BASEDIR
);
847 torture_comment(torture
, "Creating base directory\n");
849 smb2_util_mkdir(tree1
, BASEDIR
);
851 torture_comment(torture
, "Creating test file\n");
853 ZERO_STRUCT(io
.smb2
);
854 io
.generic
.level
= RAW_OPEN_SMB2
;
855 io
.smb2
.in
.create_flags
= 0;
856 io
.smb2
.in
.desired_access
= 0x0017019f;
857 io
.smb2
.in
.create_options
= 0x60;
858 io
.smb2
.in
.file_attributes
= 0;
859 io
.smb2
.in
.share_access
= 0;
860 io
.smb2
.in
.alloc_size
= 0;
861 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
862 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
863 io
.smb2
.in
.security_flags
= 0;
864 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
866 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
867 CHECK_STATUS(status
, NT_STATUS_OK
);
868 fh
= io
.smb2
.out
.file
.handle
;
870 torture_comment(torture
, "Opening parent directory\n");
872 ZERO_STRUCT(io
.smb2
);
873 io
.generic
.level
= RAW_OPEN_SMB2
;
874 io
.smb2
.in
.create_flags
= 0;
875 io
.smb2
.in
.desired_access
= 0x00100080;
876 io
.smb2
.in
.create_options
= 0x00800021;
877 io
.smb2
.in
.file_attributes
= 0;
878 io
.smb2
.in
.share_access
= 0;
879 io
.smb2
.in
.alloc_size
= 0;
880 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
881 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
882 io
.smb2
.in
.security_flags
= 0;
883 io
.smb2
.in
.fname
= BASEDIR
;
885 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
886 CHECK_STATUS(status
, NT_STATUS_OK
);
887 dh
= io
.smb2
.out
.file
.handle
;
889 torture_comment(torture
, "Renaming test file\n");
892 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
893 sinfo
.rename_information
.in
.file
.handle
= fh
;
894 sinfo
.rename_information
.in
.overwrite
= 0;
895 sinfo
.rename_information
.in
.root_fid
= 0;
896 sinfo
.rename_information
.in
.new_name
=
897 BASEDIR
"\\newname.txt";
898 status
= smb2_setinfo_file(tree1
, &sinfo
);
899 CHECK_STATUS(status
, NT_STATUS_OK
);
901 torture_comment(torture
, "Checking for new filename\n");
904 fi
.generic
.level
= RAW_FILEINFO_SMB2_ALL_INFORMATION
;
905 fi
.generic
.in
.file
.handle
= fh
;
906 status
= smb2_getinfo_file(tree1
, torture
, &fi
);
907 CHECK_STATUS(status
, NT_STATUS_OK
);
910 torture_comment(torture
, "Closing test file\n");
912 ZERO_STRUCT(cl
.smb2
);
913 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
914 cl
.smb2
.in
.file
.handle
= fh
;
915 status
= smb2_close(tree1
, &(cl
.smb2
));
916 CHECK_STATUS(status
, NT_STATUS_OK
);
920 torture_comment(torture
, "Closing directory\n");
922 ZERO_STRUCT(cl
.smb2
);
923 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
924 cl
.smb2
.in
.file
.handle
= dh
;
925 status
= smb2_close(tree1
, &(cl
.smb2
));
926 CHECK_STATUS(status
, NT_STATUS_OK
);
933 torture_comment(torture
, "Cleaning up\n");
935 if (fh
.data
[0] || fh
.data
[1]) {
936 ZERO_STRUCT(cl
.smb2
);
937 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
938 cl
.smb2
.in
.file
.handle
= fh
;
939 status
= smb2_close(tree1
, &(cl
.smb2
));
941 if (dh
.data
[0] || dh
.data
[1]) {
942 ZERO_STRUCT(cl
.smb2
);
943 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
944 cl
.smb2
.in
.file
.handle
= dh
;
945 status
= smb2_close(tree1
, &(cl
.smb2
));
948 smb2_deltree(tree1
, BASEDIR
);
952 static bool torture_smb2_rename_dir_openfile(struct torture_context
*torture
,
953 struct smb2_tree
*tree1
)
959 union smb_setfileinfo sinfo
;
960 struct smb2_handle d1
, h1
;
965 smb2_deltree(tree1
, BASEDIR
);
966 smb2_util_rmdir(tree1
, BASEDIR
);
968 torture_comment(torture
, "Creating base directory\n");
970 ZERO_STRUCT(io
.smb2
);
971 io
.generic
.level
= RAW_OPEN_SMB2
;
972 io
.smb2
.in
.create_flags
= 0;
973 io
.smb2
.in
.desired_access
= 0x0017019f;
974 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
975 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
976 io
.smb2
.in
.share_access
= 0;
977 io
.smb2
.in
.alloc_size
= 0;
978 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
979 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
980 io
.smb2
.in
.security_flags
= 0;
981 io
.smb2
.in
.fname
= BASEDIR
;
983 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
984 CHECK_STATUS(status
, NT_STATUS_OK
);
985 d1
= io
.smb2
.out
.file
.handle
;
987 torture_comment(torture
, "Creating test file\n");
989 ZERO_STRUCT(io
.smb2
);
990 io
.generic
.level
= RAW_OPEN_SMB2
;
991 io
.smb2
.in
.create_flags
= 0;
992 io
.smb2
.in
.desired_access
= 0x0017019f;
993 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
994 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
995 io
.smb2
.in
.share_access
= 0;
996 io
.smb2
.in
.alloc_size
= 0;
997 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
998 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
999 io
.smb2
.in
.security_flags
= 0;
1000 io
.smb2
.in
.fname
= BASEDIR
"\\file.txt";
1002 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1003 CHECK_STATUS(status
, NT_STATUS_OK
);
1004 h1
= io
.smb2
.out
.file
.handle
;
1006 torture_comment(torture
, "Renaming directory\n");
1009 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1010 sinfo
.rename_information
.in
.file
.handle
= d1
;
1011 sinfo
.rename_information
.in
.overwrite
= 0;
1012 sinfo
.rename_information
.in
.root_fid
= 0;
1013 sinfo
.rename_information
.in
.new_name
=
1015 status
= smb2_setinfo_file(tree1
, &sinfo
);
1016 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1018 torture_comment(torture
, "Closing directory\n");
1020 ZERO_STRUCT(cl
.smb2
);
1021 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
1022 cl
.smb2
.in
.file
.handle
= d1
;
1023 status
= smb2_close(tree1
, &(cl
.smb2
));
1024 CHECK_STATUS(status
, NT_STATUS_OK
);
1027 torture_comment(torture
, "Closing test file\n");
1029 cl
.smb2
.in
.file
.handle
= h1
;
1030 status
= smb2_close(tree1
, &(cl
.smb2
));
1031 CHECK_STATUS(status
, NT_STATUS_OK
);
1036 torture_comment(torture
, "Cleaning up\n");
1038 if (h1
.data
[0] || h1
.data
[1]) {
1039 ZERO_STRUCT(cl
.smb2
);
1040 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
1041 cl
.smb2
.in
.file
.handle
= h1
;
1042 status
= smb2_close(tree1
, &(cl
.smb2
));
1044 smb2_deltree(tree1
, BASEDIR
);
1048 struct rename_one_dir_cycle_state
{
1049 struct tevent_context
*ev
;
1050 struct smb2_tree
*tree
;
1051 struct smb2_handle file
;
1052 const char *base_name
;
1054 unsigned *rename_counter
;
1058 union smb_setfileinfo sinfo
;
1061 static void rename_one_dir_cycle_done(struct smb2_request
*subreq
);
1063 static struct tevent_req
*rename_one_dir_cycle_send(TALLOC_CTX
*mem_ctx
,
1064 struct tevent_context
*ev
,
1065 struct smb2_tree
*tree
,
1066 struct smb2_handle file
,
1067 unsigned max_renames
,
1068 const char *base_name
,
1069 unsigned *rename_counter
)
1071 struct tevent_req
*req
;
1072 struct rename_one_dir_cycle_state
*state
;
1073 struct smb2_request
*subreq
;
1075 req
= tevent_req_create(mem_ctx
, &state
,
1076 struct rename_one_dir_cycle_state
);
1083 state
->base_name
= base_name
;
1084 state
->rename_counter
= rename_counter
;
1086 state
->max
= max_renames
;
1088 ZERO_STRUCT(state
->sinfo
);
1089 state
->sinfo
.rename_information
.level
=
1090 RAW_SFILEINFO_RENAME_INFORMATION
;
1091 state
->sinfo
.rename_information
.in
.file
.handle
= state
->file
;
1092 state
->sinfo
.rename_information
.in
.overwrite
= 0;
1093 state
->sinfo
.rename_information
.in
.root_fid
= 0;
1095 state
->new_name
= talloc_asprintf(
1096 state
, "%s-%u", state
->base_name
, state
->current
);
1097 if (tevent_req_nomem(state
->new_name
, req
)) {
1098 return tevent_req_post(req
, ev
);
1100 state
->sinfo
.rename_information
.in
.new_name
= state
->new_name
;
1102 subreq
= smb2_setinfo_file_send(state
->tree
, &state
->sinfo
);
1103 if (tevent_req_nomem(subreq
, req
)) {
1104 return tevent_req_post(req
, ev
);
1106 subreq
->async
.fn
= rename_one_dir_cycle_done
;
1107 subreq
->async
.private_data
= req
;
1111 static void rename_one_dir_cycle_done(struct smb2_request
*subreq
)
1113 struct tevent_req
*req
= talloc_get_type_abort(
1114 subreq
->async
.private_data
, struct tevent_req
);
1115 struct rename_one_dir_cycle_state
*state
= tevent_req_data(
1116 req
, struct rename_one_dir_cycle_state
);
1119 status
= smb2_setinfo_recv(subreq
);
1120 if (tevent_req_nterror(req
, status
)) {
1123 TALLOC_FREE(state
->new_name
);
1125 *state
->rename_counter
+= 1;
1127 state
->current
+= 1;
1128 if (state
->current
>= state
->max
) {
1129 tevent_req_done(req
);
1133 ZERO_STRUCT(state
->sinfo
);
1134 state
->sinfo
.rename_information
.level
=
1135 RAW_SFILEINFO_RENAME_INFORMATION
;
1136 state
->sinfo
.rename_information
.in
.file
.handle
= state
->file
;
1137 state
->sinfo
.rename_information
.in
.overwrite
= 0;
1138 state
->sinfo
.rename_information
.in
.root_fid
= 0;
1140 state
->new_name
= talloc_asprintf(
1141 state
, "%s-%u", state
->base_name
, state
->current
);
1142 if (tevent_req_nomem(state
->new_name
, req
)) {
1145 state
->sinfo
.rename_information
.in
.new_name
= state
->new_name
;
1147 subreq
= smb2_setinfo_file_send(state
->tree
, &state
->sinfo
);
1148 if (tevent_req_nomem(subreq
, req
)) {
1151 subreq
->async
.fn
= rename_one_dir_cycle_done
;
1152 subreq
->async
.private_data
= req
;
1155 static NTSTATUS
rename_one_dir_cycle_recv(struct tevent_req
*req
)
1157 return tevent_req_simple_recv_ntstatus(req
);
1160 struct rename_dir_bench_state
{
1161 struct tevent_context
*ev
;
1162 struct smb2_tree
*tree
;
1163 const char *base_name
;
1164 unsigned max_renames
;
1165 unsigned *rename_counter
;
1167 struct smb2_create io
;
1168 union smb_setfileinfo sinfo
;
1169 struct smb2_close cl
;
1171 struct smb2_handle file
;
1174 static void rename_dir_bench_opened(struct smb2_request
*subreq
);
1175 static void rename_dir_bench_renamed(struct tevent_req
*subreq
);
1176 static void rename_dir_bench_set_doc(struct smb2_request
*subreq
);
1177 static void rename_dir_bench_closed(struct smb2_request
*subreq
);
1179 static struct tevent_req
*rename_dir_bench_send(TALLOC_CTX
*mem_ctx
,
1180 struct tevent_context
*ev
,
1181 struct smb2_tree
*tree
,
1182 const char *base_name
,
1183 unsigned max_renames
,
1184 unsigned *rename_counter
)
1186 struct tevent_req
*req
;
1187 struct rename_dir_bench_state
*state
;
1188 struct smb2_request
*subreq
;
1190 req
= tevent_req_create(mem_ctx
, &state
,
1191 struct rename_dir_bench_state
);
1197 state
->base_name
= base_name
;
1198 state
->max_renames
= max_renames
;
1199 state
->rename_counter
= rename_counter
;
1201 ZERO_STRUCT(state
->io
);
1202 state
->io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
1203 state
->io
.in
.share_access
=
1204 NTCREATEX_SHARE_ACCESS_READ
|
1205 NTCREATEX_SHARE_ACCESS_WRITE
;
1206 state
->io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1207 state
->io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1208 state
->io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1209 state
->io
.in
.fname
= state
->base_name
;
1211 subreq
= smb2_create_send(state
->tree
, &state
->io
);
1212 if (tevent_req_nomem(subreq
, req
)) {
1213 return tevent_req_post(req
, ev
);
1215 subreq
->async
.fn
= rename_dir_bench_opened
;
1216 subreq
->async
.private_data
= req
;
1220 static void rename_dir_bench_opened(struct smb2_request
*subreq
)
1222 struct tevent_req
*req
= talloc_get_type_abort(
1223 subreq
->async
.private_data
, struct tevent_req
);
1224 struct rename_dir_bench_state
*state
= tevent_req_data(
1225 req
, struct rename_dir_bench_state
);
1226 struct smb2_create
*io
;
1227 struct tevent_req
*subreq2
;
1230 io
= talloc(state
, struct smb2_create
);
1231 if (tevent_req_nomem(io
, req
)) {
1235 status
= smb2_create_recv(subreq
, io
, io
);
1236 if (tevent_req_nterror(req
, status
)) {
1239 state
->file
= io
->out
.file
.handle
;
1242 subreq2
= rename_one_dir_cycle_send(
1243 state
, state
->ev
, state
->tree
, state
->file
,
1244 state
->max_renames
, state
->base_name
,
1245 state
->rename_counter
);
1246 if (tevent_req_nomem(subreq2
, req
)) {
1249 tevent_req_set_callback(subreq2
, rename_dir_bench_renamed
, req
);
1252 static void rename_dir_bench_renamed(struct tevent_req
*subreq
)
1254 struct tevent_req
*req
= tevent_req_callback_data(
1255 subreq
, struct tevent_req
);
1256 struct rename_dir_bench_state
*state
= tevent_req_data(
1257 req
, struct rename_dir_bench_state
);
1258 struct smb2_request
*subreq2
;
1261 status
= rename_one_dir_cycle_recv(subreq
);
1262 TALLOC_FREE(subreq
);
1263 if (tevent_req_nterror(req
, status
)) {
1267 ZERO_STRUCT(state
->sinfo
);
1268 state
->sinfo
.disposition_info
.level
=
1269 RAW_SFILEINFO_DISPOSITION_INFORMATION
;
1270 state
->sinfo
.disposition_info
.in
.file
.handle
= state
->file
;
1271 state
->sinfo
.disposition_info
.in
.delete_on_close
= true;
1273 subreq2
= smb2_setinfo_file_send(state
->tree
, &state
->sinfo
);
1274 if (tevent_req_nomem(subreq2
, req
)) {
1277 subreq2
->async
.fn
= rename_dir_bench_set_doc
;
1278 subreq2
->async
.private_data
= req
;
1281 static void rename_dir_bench_set_doc(struct smb2_request
*subreq
)
1283 struct tevent_req
*req
= talloc_get_type_abort(
1284 subreq
->async
.private_data
, struct tevent_req
);
1285 struct rename_dir_bench_state
*state
= tevent_req_data(
1286 req
, struct rename_dir_bench_state
);
1289 status
= smb2_setinfo_recv(subreq
);
1290 if (tevent_req_nterror(req
, status
)) {
1294 ZERO_STRUCT(state
->cl
);
1295 state
->cl
.in
.file
.handle
= state
->file
;
1297 subreq
= smb2_close_send(state
->tree
, &state
->cl
);
1298 if (tevent_req_nomem(subreq
, req
)) {
1301 subreq
->async
.fn
= rename_dir_bench_closed
;
1302 subreq
->async
.private_data
= req
;
1305 static void rename_dir_bench_closed(struct smb2_request
*subreq
)
1307 struct tevent_req
*req
= talloc_get_type_abort(
1308 subreq
->async
.private_data
, struct tevent_req
);
1309 struct smb2_close cl
;
1312 status
= smb2_close_recv(subreq
, &cl
);
1313 if (tevent_req_nterror(req
, status
)) {
1316 tevent_req_done(req
);
1319 static NTSTATUS
rename_dir_bench_recv(struct tevent_req
*req
)
1321 return tevent_req_simple_recv_ntstatus(req
);
1324 struct rename_dirs_bench_state
{
1329 static void rename_dirs_bench_done(struct tevent_req
*subreq
);
1331 static struct tevent_req
*rename_dirs_bench_send(TALLOC_CTX
*mem_ctx
,
1332 struct tevent_context
*ev
,
1333 struct smb2_tree
*tree
,
1334 const char *base_name
,
1335 unsigned num_parallel
,
1336 unsigned max_renames
,
1337 unsigned *rename_counter
)
1339 struct tevent_req
*req
;
1340 struct rename_dirs_bench_state
*state
;
1343 req
= tevent_req_create(mem_ctx
, &state
,
1344 struct rename_dirs_bench_state
);
1348 state
->num_reqs
= num_parallel
;
1349 state
->num_done
= 0;
1351 for (i
=0; i
<num_parallel
; i
++) {
1352 struct tevent_req
*subreq
;
1355 sub_base
= talloc_asprintf(state
, "%s-%u", base_name
, i
);
1356 if (tevent_req_nomem(sub_base
, req
)) {
1357 return tevent_req_post(req
, ev
);
1360 subreq
= rename_dir_bench_send(state
, ev
, tree
, sub_base
,
1361 max_renames
, rename_counter
);
1362 if (tevent_req_nomem(subreq
, req
)) {
1363 return tevent_req_post(req
, ev
);
1365 tevent_req_set_callback(subreq
, rename_dirs_bench_done
, req
);
1370 static void rename_dirs_bench_done(struct tevent_req
*subreq
)
1372 struct tevent_req
*req
= tevent_req_callback_data(
1373 subreq
, struct tevent_req
);
1374 struct rename_dirs_bench_state
*state
= tevent_req_data(
1375 req
, struct rename_dirs_bench_state
);
1378 status
= rename_dir_bench_recv(subreq
);
1379 TALLOC_FREE(subreq
);
1380 if (tevent_req_nterror(req
, status
)) {
1384 state
->num_done
+= 1;
1385 if (state
->num_done
>= state
->num_reqs
) {
1386 tevent_req_done(req
);
1390 static NTSTATUS
rename_dirs_bench_recv(struct tevent_req
*req
)
1392 return tevent_req_simple_recv_ntstatus(req
);
1395 static bool torture_smb2_rename_dir_bench(struct torture_context
*tctx
,
1396 struct smb2_tree
*tree
)
1398 struct tevent_req
*req
;
1400 unsigned counter
= 0;
1403 req
= rename_dirs_bench_send(tctx
, tctx
->ev
, tree
, "dir", 3, 10,
1405 torture_assert(tctx
, req
!= NULL
, "rename_dirs_bench_send failed");
1407 ret
= tevent_req_poll(req
, tctx
->ev
);
1408 torture_assert(tctx
, ret
, "tevent_req_poll failed");
1410 status
= rename_dirs_bench_recv(req
);
1411 torture_comment(tctx
, "rename_dirs_bench returned %s\n",
1414 torture_assert_ntstatus_ok(tctx
, status
, "bench failed");
1420 basic testing of SMB2 rename
1422 struct torture_suite
*torture_smb2_rename_init(TALLOC_CTX
*ctx
)
1424 struct torture_suite
*suite
=
1425 torture_suite_create(ctx
, "rename");
1427 torture_suite_add_1smb2_test(suite
, "simple",
1428 torture_smb2_rename_simple
);
1430 torture_suite_add_1smb2_test(suite
, "simple_nodelete",
1431 torture_smb2_rename_simple2
);
1433 torture_suite_add_1smb2_test(suite
, "no_sharing",
1434 torture_smb2_rename_no_sharemode
);
1436 torture_suite_add_1smb2_test(suite
,
1437 "share_delete_and_delete_access",
1438 torture_smb2_rename_with_delete_access
);
1440 torture_suite_add_1smb2_test(suite
,
1441 "no_share_delete_but_delete_access",
1442 torture_smb2_rename_with_delete_access2
);
1444 torture_suite_add_1smb2_test(suite
,
1445 "share_delete_no_delete_access",
1446 torture_smb2_rename_no_delete_access
);
1448 torture_suite_add_1smb2_test(suite
,
1449 "no_share_delete_no_delete_access",
1450 torture_smb2_rename_no_delete_access2
);
1452 torture_suite_add_1smb2_test(suite
,
1454 torture_smb2_rename_msword
);
1456 torture_suite_add_1smb2_test(
1457 suite
, "rename_dir_openfile",
1458 torture_smb2_rename_dir_openfile
);
1460 torture_suite_add_1smb2_test(suite
,
1462 torture_smb2_rename_dir_bench
);
1464 suite
->description
= talloc_strdup(suite
, "smb2.rename tests");