s3: smbd: Fix schedule_smb2_aio_read() to allow the last read in a compound to go...
[Samba.git] / source4 / torture / smb2 / rename.c
blob1b3dca8bcbaff3fadef89d7b1876094567a1cc43
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 rename test suite
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/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include <tevent.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) \
34 do { \
35 if ((v) != (correct)) { \
36 torture_result(torture, \
37 TORTURE_FAIL, \
38 "(%s): wrong value for %s got " \
39 "0x%llx - should be 0x%llx\n", \
40 __location__, #v, \
41 (unsigned long long)v, \
42 (unsigned long long)correct); \
43 ret = false; \
44 goto done; \
45 }} while (0)
47 #define CHECK_CREATED(__io, __created, __attribute) \
48 do { \
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); \
53 } while(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)); \
60 ret = false; \
61 goto done; \
62 }} while (0)
64 #define BASEDIR "test_rename"
67 * basic testing of rename: open file with DELETE access
68 * this should pass
71 static bool torture_smb2_rename_simple(struct torture_context *torture,
72 struct smb2_tree *tree1)
74 bool ret = true;
75 NTSTATUS status;
76 union smb_open io;
77 union smb_close cl;
78 union smb_setfileinfo sinfo;
79 union smb_fileinfo fi;
80 struct smb2_handle h1;
82 ZERO_STRUCT(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");
94 ZERO_STRUCT(io.smb2);
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");
114 ZERO_STRUCT(sinfo);
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");
126 ZERO_STRUCT(fi);
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);
141 ZERO_STRUCT(h1);
143 done:
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);
154 return ret;
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)
165 bool ret = true;
166 NTSTATUS status;
167 union smb_open io;
168 union smb_close cl;
169 union smb_setfileinfo sinfo;
170 struct smb2_handle h1;
172 ZERO_STRUCT(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");
204 ZERO_STRUCT(sinfo);
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);
222 ZERO_STRUCT(h1);
224 done:
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);
235 return ret;
240 * testing of rename with no sharing allowed on file
241 * this should work
244 static bool torture_smb2_rename_no_sharemode(struct torture_context *torture,
245 struct smb2_tree *tree1)
247 bool ret = true;
248 NTSTATUS status;
249 union smb_open io;
250 union smb_close cl;
251 union smb_setfileinfo sinfo;
252 union smb_fileinfo fi;
253 struct smb2_handle h1;
255 ZERO_STRUCT(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");
286 ZERO_STRUCT(sinfo);
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");
298 ZERO_STRUCT(fi);
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);
313 ZERO_STRUCT(h1);
315 done:
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);
326 return ret;
330 * testing of rename when opening parent dir with delete access and delete
331 * sharing allowed
332 * should result in sharing violation
335 static bool torture_smb2_rename_with_delete_access(struct torture_context *torture,
336 struct smb2_tree *tree1)
338 bool ret = true;
339 NTSTATUS status;
340 union smb_open io;
341 union smb_close cl;
342 union smb_setfileinfo sinfo;
343 struct smb2_handle fh, dh;
345 ZERO_STRUCT(fh);
346 ZERO_STRUCT(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 |
364 SEC_FILE_WRITE_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");
404 ZERO_STRUCT(sinfo);
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);
422 ZERO_STRUCT(fh);
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);
432 ZERO_STRUCT(dh);
435 done:
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);
453 return ret;
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)
466 bool ret = true;
467 NTSTATUS status;
468 union smb_open io;
469 union smb_close cl;
470 union smb_setfileinfo sinfo;
471 struct smb2_handle fh, dh;
473 ZERO_STRUCT(fh);
474 ZERO_STRUCT(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 |
492 SEC_FILE_WRITE_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");
531 ZERO_STRUCT(sinfo);
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);
549 ZERO_STRUCT(fh);
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);
559 ZERO_STRUCT(dh);
562 done:
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);
580 return ret;
584 * testing of rename when opening parent dir with no delete access and delete
585 * sharing allowed
586 * this should pass
589 static bool torture_smb2_rename_no_delete_access(struct torture_context *torture,
590 struct smb2_tree *tree1)
592 bool ret = true;
593 NTSTATUS status;
594 union smb_open io;
595 union smb_close cl;
596 union smb_setfileinfo sinfo;
597 union smb_fileinfo fi;
598 struct smb2_handle fh, dh;
600 ZERO_STRUCT(fh);
601 ZERO_STRUCT(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 |
619 SEC_FILE_WRITE_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");
659 ZERO_STRUCT(sinfo);
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");
671 ZERO_STRUCT(fi);
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);
686 ZERO_STRUCT(fh);
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);
696 ZERO_STRUCT(dh);
699 done:
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);
717 return ret;
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)
730 bool ret = true;
731 NTSTATUS status;
732 union smb_open io;
733 union smb_close cl;
734 union smb_setfileinfo sinfo;
735 struct smb2_handle fh, dh;
737 ZERO_STRUCT(fh);
738 ZERO_STRUCT(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 |
756 SEC_FILE_WRITE_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");
795 ZERO_STRUCT(sinfo);
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);
813 ZERO_STRUCT(fh);
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);
823 ZERO_STRUCT(dh);
826 done:
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);
844 return ret;
848 * this is a replay of how Word 2010 saves a file
849 * this should pass
852 static bool torture_smb2_rename_msword(struct torture_context *torture,
853 struct smb2_tree *tree1)
855 bool ret = true;
856 NTSTATUS status;
857 union smb_open io;
858 union smb_close cl;
859 union smb_setfileinfo sinfo;
860 union smb_fileinfo fi;
861 struct smb2_handle fh, dh;
863 ZERO_STRUCT(fh);
864 ZERO_STRUCT(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");
913 ZERO_STRUCT(sinfo);
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");
925 ZERO_STRUCT(fi);
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);
940 ZERO_STRUCT(fh);
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);
950 ZERO_STRUCT(dh);
953 done:
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);
971 return ret;
974 static bool torture_smb2_rename_dir_openfile(struct torture_context *torture,
975 struct smb2_tree *tree1)
977 bool ret = true;
978 NTSTATUS status;
979 union smb_open io;
980 union smb_close cl;
981 union smb_setfileinfo sinfo;
982 struct smb2_handle d1, h1;
984 ZERO_STRUCT(d1);
985 ZERO_STRUCT(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");
1030 ZERO_STRUCT(sinfo);
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 =
1036 BASEDIR "-new";
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);
1047 ZERO_STRUCT(d1);
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);
1054 ZERO_STRUCT(h1);
1056 done:
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);
1067 return ret;
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;
1075 char *new_name;
1076 unsigned *rename_counter;
1078 unsigned current;
1079 unsigned max;
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);
1099 if (req == NULL) {
1100 return NULL;
1102 state->ev = ev;
1103 state->tree = tree;
1104 state->file = file;
1105 state->base_name = base_name;
1106 state->rename_counter = rename_counter;
1107 state->current = 0;
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;
1130 return 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);
1139 NTSTATUS status;
1141 status = smb2_setinfo_recv(subreq);
1142 if (tevent_req_nterror(req, status)) {
1143 return;
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);
1152 return;
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)) {
1165 return;
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)) {
1171 return;
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);
1214 if (req == NULL) {
1215 return NULL;
1217 state->ev = ev;
1218 state->tree = tree;
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;
1239 return 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;
1250 NTSTATUS status;
1252 io = talloc(state, struct smb2_create);
1253 if (tevent_req_nomem(io, req)) {
1254 return;
1257 status = smb2_create_recv(subreq, io, io);
1258 if (tevent_req_nterror(req, status)) {
1259 return;
1261 state->file = io->out.file.handle;
1262 TALLOC_FREE(io);
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)) {
1269 return;
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;
1281 NTSTATUS status;
1283 status = rename_one_dir_cycle_recv(subreq);
1284 TALLOC_FREE(subreq);
1285 if (tevent_req_nterror(req, status)) {
1286 return;
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)) {
1297 return;
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);
1309 NTSTATUS status;
1311 status = smb2_setinfo_recv(subreq);
1312 if (tevent_req_nterror(req, status)) {
1313 return;
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)) {
1321 return;
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;
1332 NTSTATUS status;
1334 status = smb2_close_recv(subreq, &cl);
1335 if (tevent_req_nterror(req, status)) {
1336 return;
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 {
1347 unsigned num_reqs;
1348 unsigned num_done;
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;
1363 unsigned i;
1365 req = tevent_req_create(mem_ctx, &state,
1366 struct rename_dirs_bench_state);
1367 if (req == NULL) {
1368 return NULL;
1370 state->num_reqs = num_parallel;
1371 state->num_done = 0;
1373 for (i=0; i<num_parallel; i++) {
1374 struct tevent_req *subreq;
1375 char *sub_base;
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);
1389 return 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);
1398 NTSTATUS status;
1400 status = rename_dir_bench_recv(subreq);
1401 TALLOC_FREE(subreq);
1402 if (tevent_req_nterror(req, status)) {
1403 return;
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;
1421 NTSTATUS status;
1422 unsigned counter = 0;
1423 bool ret;
1425 req = rename_dirs_bench_send(tctx, tctx->ev, tree, "dir", 3, 10,
1426 &counter);
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",
1434 nt_errstr(status));
1435 TALLOC_FREE(req);
1436 torture_assert_ntstatus_ok(tctx, status, "bench failed");
1437 return true;
1440 static bool test_smb2_close_full_information(struct torture_context *torture,
1441 struct smb2_tree *tree1,
1442 struct smb2_tree *tree2)
1444 union smb_close cl;
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;
1450 NTSTATUS status;
1451 const char *fname_src = "request.dat";
1452 const char *fname_dst = "renamed.dat";
1453 bool ret = true;
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. */
1472 ZERO_STRUCT(io);
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. */
1484 ZERO_STRUCT(io);
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. */
1496 ZERO_STRUCT(sinfo);
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);
1503 /* And close h3. */
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);
1509 ZERO_STRUCT(h3);
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);
1521 ZERO_STRUCT(h1);
1522 CHECK_VAL(cl.smb2.out.file_attr, 0x20);
1525 * Wait 3 seconds for name change to propagate
1526 * to the other connection.
1528 sleep(3);
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);
1541 ZERO_STRUCT(h2);
1542 CHECK_VAL(cl.smb2.out.file_attr, 0x20);
1544 done:
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);
1559 return ret;
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,
1596 "msword",
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,
1604 "rename_dir_bench",
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");
1613 return suite;