2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2008
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"
25 #include "torture/torture.h"
26 #include "torture/util.h"
27 #include "torture/smb2/proto.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "libcli/security/security.h"
31 #include "system/filesys.h"
32 #include "auth/credentials/credentials.h"
33 #include "lib/cmdline/popt_common.h"
34 #include "librpc/gen_ndr/security.h"
35 #include "lib/events/events.h"
37 #define FNAME "test_create.dat"
38 #define DNAME "smb2_open"
40 #define CHECK_STATUS(status, correct) do { \
41 if (!NT_STATUS_EQUAL(status, correct)) { \
42 torture_result(torture, TORTURE_FAIL, \
43 "(%s) Incorrect status %s - should be %s\n", \
44 __location__, nt_errstr(status), nt_errstr(correct)); \
48 #define CHECK_EQUAL(v, correct) do { \
50 torture_result(torture, TORTURE_FAIL, \
51 "(%s) Incorrect value for %s 0x%08llx - " \
52 "should be 0x%08llx\n", \
54 (unsigned long long)v, \
55 (unsigned long long)correct); \
59 #define CHECK_TIME(t, field) do { \
61 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
62 finfo.all_info.in.file.handle = h1; \
63 status = smb2_getinfo_file(tree, torture, &finfo); \
64 CHECK_STATUS(status, NT_STATUS_OK); \
66 t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
67 if (abs(t1-t2) > 2) { \
68 torture_result(torture, TORTURE_FAIL, \
69 "(%s) wrong time for field %s %s - %s\n", \
70 __location__, #field, \
71 timestring(torture, t1), \
72 timestring(torture, t2)); \
73 dump_all_info(torture, &finfo); \
77 #define CHECK_NTTIME(t, field) do { \
79 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
80 finfo.all_info.in.file.handle = h1; \
81 status = smb2_getinfo_file(tree, torture, &finfo); \
82 CHECK_STATUS(status, NT_STATUS_OK); \
83 t2 = finfo.all_info.out.field; \
85 torture_result(torture, TORTURE_FAIL, \
86 "(%s) wrong time for field %s %s - %s\n", \
87 __location__, #field, \
88 nt_time_string(torture, t), \
89 nt_time_string(torture, t2)); \
90 dump_all_info(torture, &finfo); \
94 #define CHECK_ALL_INFO(v, field) do { \
95 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
96 finfo.all_info.in.file.handle = h1; \
97 status = smb2_getinfo_file(tree, torture, &finfo); \
98 CHECK_STATUS(status, NT_STATUS_OK); \
99 if ((v) != (finfo.all_info.out.field)) { \
100 torture_result(torture, TORTURE_FAIL, \
101 "(%s) wrong value for field %s 0x%x - 0x%x\n", \
102 __location__, #field, (int)v,\
103 (int)(finfo.all_info.out.field)); \
104 dump_all_info(torture, &finfo); \
108 #define CHECK_VAL(v, correct) do { \
109 if ((v) != (correct)) { \
110 torture_result(torture, TORTURE_FAIL, \
111 "(%s) wrong value for %s 0x%x - should be 0x%x\n", \
112 __location__, #v, (int)(v), (int)correct); \
116 #define SET_ATTRIB(sattrib) do { \
117 union smb_setfileinfo sfinfo; \
118 ZERO_STRUCT(sfinfo.basic_info.in); \
119 sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
120 sfinfo.basic_info.in.file.handle = h1; \
121 sfinfo.basic_info.in.attrib = sattrib; \
122 status = smb2_setinfo_file(tree, &sfinfo); \
123 if (!NT_STATUS_IS_OK(status)) { \
124 torture_comment(torture, \
125 "(%s) Failed to set attrib 0x%x on %s\n", \
126 __location__, sattrib, fname); \
129 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
132 test some interesting combinations found by gentest
134 static bool test_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
136 struct smb2_create io;
138 TALLOC_CTX *tmp_ctx = talloc_new(tree);
139 uint32_t access_mask, file_attributes_set;
140 uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
141 uint32_t not_a_directory_mask, unexpected_mask;
142 union smb_fileinfo q;
145 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
146 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
147 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
149 NTCREATEX_SHARE_ACCESS_DELETE|
150 NTCREATEX_SHARE_ACCESS_READ|
151 NTCREATEX_SHARE_ACCESS_WRITE;
152 io.in.create_options = 0;
155 status = smb2_create(tree, tmp_ctx, &io);
156 CHECK_STATUS(status, NT_STATUS_OK);
158 status = smb2_util_close(tree, io.out.file.handle);
159 CHECK_STATUS(status, NT_STATUS_OK);
161 io.in.create_options = 0xF0000000;
162 status = smb2_create(tree, tmp_ctx, &io);
163 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
165 io.in.create_options = 0;
167 io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
168 status = smb2_create(tree, tmp_ctx, &io);
169 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
171 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
172 status = smb2_create(tree, tmp_ctx, &io);
173 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
175 io.in.create_disposition = NTCREATEX_DISP_OPEN;
176 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
177 status = smb2_create(tree, tmp_ctx, &io);
178 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
180 io.in.create_disposition = NTCREATEX_DISP_CREATE;
181 io.in.desired_access = 0x08000000;
182 status = smb2_create(tree, tmp_ctx, &io);
183 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
185 io.in.desired_access = 0x04000000;
186 status = smb2_create(tree, tmp_ctx, &io);
187 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
189 io.in.file_attributes = 0;
190 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
191 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
193 not_supported_mask = 0;
194 invalid_parameter_mask = 0;
195 not_a_directory_mask = 0;
200 io.in.create_options = 1<<i;
201 if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
204 status = smb2_create(tree, tmp_ctx, &io);
205 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
206 not_supported_mask |= 1<<i;
207 } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
208 invalid_parameter_mask |= 1<<i;
209 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
210 not_a_directory_mask |= 1<<i;
211 } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
213 status = smb2_util_close(tree, io.out.file.handle);
214 CHECK_STATUS(status, NT_STATUS_OK);
216 unexpected_mask |= 1<<i;
217 torture_comment(torture,
218 "create option 0x%08x returned %s\n",
219 1<<i, nt_errstr(status));
223 io.in.create_options = 0;
225 CHECK_EQUAL(ok_mask, 0x00efcf7e);
226 CHECK_EQUAL(not_a_directory_mask, 0x00000001);
227 CHECK_EQUAL(not_supported_mask, 0x00102080);
228 CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
229 CHECK_EQUAL(unexpected_mask, 0x00000000);
231 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
232 io.in.file_attributes = 0;
237 io.in.desired_access = 1<<i;
238 status = smb2_create(tree, tmp_ctx, &io);
239 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
240 NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
241 access_mask |= io.in.desired_access;
243 CHECK_STATUS(status, NT_STATUS_OK);
244 status = smb2_util_close(tree, io.out.file.handle);
245 CHECK_STATUS(status, NT_STATUS_OK);
250 if (TARGET_IS_WIN7(torture)) {
251 CHECK_EQUAL(access_mask, 0x0de0fe00);
253 CHECK_EQUAL(access_mask, 0x0df0fe00);
256 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
257 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
258 io.in.file_attributes = 0;
260 invalid_parameter_mask = 0;
262 file_attributes_set = 0;
266 io.in.file_attributes = 1<<i;
267 if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
270 smb2_deltree(tree, FNAME);
271 status = smb2_create(tree, tmp_ctx, &io);
272 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
273 invalid_parameter_mask |= 1<<i;
274 } else if (NT_STATUS_IS_OK(status)) {
278 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
279 CHECK_EQUAL(io.out.file_attr, expected);
280 file_attributes_set |= io.out.file_attr;
282 status = smb2_util_close(tree, io.out.file.handle);
283 CHECK_STATUS(status, NT_STATUS_OK);
285 unexpected_mask |= 1<<i;
286 torture_comment(torture,
287 "file attribute 0x%08x returned %s\n",
288 1<<i, nt_errstr(status));
293 CHECK_EQUAL(ok_mask, 0x00003fb7);
294 CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
295 CHECK_EQUAL(unexpected_mask, 0x00000000);
296 CHECK_EQUAL(file_attributes_set, 0x00001127);
298 smb2_deltree(tree, FNAME);
301 * Standalone servers doesn't support encryption
303 io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
304 status = smb2_create(tree, tmp_ctx, &io);
305 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
306 torture_comment(torture,
307 "FILE_ATTRIBUTE_ENCRYPTED returned %s\n",
310 CHECK_STATUS(status, NT_STATUS_OK);
311 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
312 status = smb2_util_close(tree, io.out.file.handle);
313 CHECK_STATUS(status, NT_STATUS_OK);
316 smb2_deltree(tree, FNAME);
319 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
320 io.in.file_attributes = 0;
321 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
323 NTCREATEX_SHARE_ACCESS_READ|
324 NTCREATEX_SHARE_ACCESS_WRITE;
325 io.in.create_options = 0;
326 io.in.fname = FNAME ":stream1";
327 status = smb2_create(tree, tmp_ctx, &io);
328 CHECK_STATUS(status, NT_STATUS_OK);
330 status = smb2_util_close(tree, io.out.file.handle);
331 CHECK_STATUS(status, NT_STATUS_OK);
334 io.in.file_attributes = 0x8040;
336 NTCREATEX_SHARE_ACCESS_READ;
337 status = smb2_create(tree, tmp_ctx, &io);
338 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
341 io.in.file_attributes = 0;
342 io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
343 io.in.query_maximal_access = true;
344 status = smb2_create(tree, tmp_ctx, &io);
345 CHECK_STATUS(status, NT_STATUS_OK);
346 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
348 q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
349 q.access_information.in.file.handle = io.out.file.handle;
350 status = smb2_getinfo_file(tree, tmp_ctx, &q);
351 CHECK_STATUS(status, NT_STATUS_OK);
352 CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
354 io.in.file_attributes = 0;
355 io.in.desired_access = 0;
356 io.in.query_maximal_access = false;
357 io.in.share_access = 0;
358 status = smb2_create(tree, tmp_ctx, &io);
359 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
361 talloc_free(tmp_ctx);
363 smb2_deltree(tree, FNAME);
370 try the various request blobs
372 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
374 struct smb2_create io;
376 TALLOC_CTX *tmp_ctx = talloc_new(tree);
378 smb2_deltree(tree, FNAME);
381 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
382 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
383 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
385 NTCREATEX_SHARE_ACCESS_DELETE|
386 NTCREATEX_SHARE_ACCESS_READ|
387 NTCREATEX_SHARE_ACCESS_WRITE;
388 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
389 NTCREATEX_OPTIONS_ASYNC_ALERT |
390 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
394 status = smb2_create(tree, tmp_ctx, &io);
395 CHECK_STATUS(status, NT_STATUS_OK);
397 status = smb2_util_close(tree, io.out.file.handle);
398 CHECK_STATUS(status, NT_STATUS_OK);
400 torture_comment(torture, "testing alloc size\n");
401 io.in.alloc_size = 4096;
402 status = smb2_create(tree, tmp_ctx, &io);
403 CHECK_STATUS(status, NT_STATUS_OK);
404 CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
406 status = smb2_util_close(tree, io.out.file.handle);
407 CHECK_STATUS(status, NT_STATUS_OK);
409 torture_comment(torture, "testing durable open\n");
410 io.in.durable_open = true;
411 status = smb2_create(tree, tmp_ctx, &io);
412 CHECK_STATUS(status, NT_STATUS_OK);
414 status = smb2_util_close(tree, io.out.file.handle);
415 CHECK_STATUS(status, NT_STATUS_OK);
417 torture_comment(torture, "testing query maximal access\n");
418 io.in.query_maximal_access = true;
419 status = smb2_create(tree, tmp_ctx, &io);
420 CHECK_STATUS(status, NT_STATUS_OK);
421 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
423 status = smb2_util_close(tree, io.out.file.handle);
424 CHECK_STATUS(status, NT_STATUS_OK);
426 torture_comment(torture, "testing timewarp\n");
427 io.in.timewarp = 10000;
428 status = smb2_create(tree, tmp_ctx, &io);
429 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
432 torture_comment(torture, "testing query_on_disk\n");
433 io.in.query_on_disk_id = true;
434 status = smb2_create(tree, tmp_ctx, &io);
435 CHECK_STATUS(status, NT_STATUS_OK);
437 status = smb2_util_close(tree, io.out.file.handle);
438 CHECK_STATUS(status, NT_STATUS_OK);
440 torture_comment(torture, "testing unknown tag\n");
441 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
442 "FooO", data_blob(NULL, 0));
443 CHECK_STATUS(status, NT_STATUS_OK);
445 status = smb2_create(tree, tmp_ctx, &io);
446 CHECK_STATUS(status, NT_STATUS_OK);
448 status = smb2_util_close(tree, io.out.file.handle);
449 CHECK_STATUS(status, NT_STATUS_OK);
451 torture_comment(torture, "testing bad tag length\n");
452 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
453 "xxx", data_blob(NULL, 0));
454 CHECK_STATUS(status, NT_STATUS_OK);
456 status = smb2_create(tree, tmp_ctx, &io);
457 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
459 talloc_free(tmp_ctx);
461 smb2_deltree(tree, FNAME);
467 try creating with acls
469 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
471 struct smb2_create io;
473 TALLOC_CTX *tmp_ctx = talloc_new(tree);
474 struct security_ace ace;
475 struct security_descriptor *sd, *sd2;
476 struct dom_sid *test_sid;
477 union smb_fileinfo q;
479 smb2_deltree(tree, FNAME);
482 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
483 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
484 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
486 NTCREATEX_SHARE_ACCESS_DELETE|
487 NTCREATEX_SHARE_ACCESS_READ|
488 NTCREATEX_SHARE_ACCESS_WRITE;
489 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
490 NTCREATEX_OPTIONS_ASYNC_ALERT |
491 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
495 status = smb2_create(tree, tmp_ctx, &io);
496 CHECK_STATUS(status, NT_STATUS_OK);
498 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
499 q.query_secdesc.in.file.handle = io.out.file.handle;
500 q.query_secdesc.in.secinfo_flags =
504 status = smb2_getinfo_file(tree, tmp_ctx, &q);
505 CHECK_STATUS(status, NT_STATUS_OK);
506 sd = q.query_secdesc.out.sd;
508 status = smb2_util_close(tree, io.out.file.handle);
509 CHECK_STATUS(status, NT_STATUS_OK);
511 smb2_util_unlink(tree, FNAME);
513 torture_comment(torture, "adding a new ACE\n");
514 test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
516 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
518 ace.access_mask = SEC_STD_ALL;
519 ace.trustee = *test_sid;
521 status = security_descriptor_dacl_add(sd, &ace);
522 CHECK_STATUS(status, NT_STATUS_OK);
524 torture_comment(torture, "creating a file with an initial ACL\n");
527 status = smb2_create(tree, tmp_ctx, &io);
528 CHECK_STATUS(status, NT_STATUS_OK);
530 q.query_secdesc.in.file.handle = io.out.file.handle;
531 status = smb2_getinfo_file(tree, tmp_ctx, &q);
532 CHECK_STATUS(status, NT_STATUS_OK);
533 sd2 = q.query_secdesc.out.sd;
535 if (!security_acl_equal(sd->dacl, sd2->dacl)) {
536 torture_comment(torture,
537 "%s: security descriptors don't match!\n", __location__);
538 torture_comment(torture, "got:\n");
539 NDR_PRINT_DEBUG(security_descriptor, sd2);
540 torture_comment(torture, "expected:\n");
541 NDR_PRINT_DEBUG(security_descriptor, sd);
545 talloc_free(tmp_ctx);
553 static bool test_smb2_open(struct torture_context *torture,
554 struct smb2_tree *tree)
556 TALLOC_CTX *mem_ctx = talloc_new(torture);
558 union smb_fileinfo finfo;
559 const char *fname = DNAME "\\torture_ntcreatex.txt";
560 const char *dname = DNAME "\\torture_ntcreatex.dir";
562 struct smb2_handle h, h1;
566 uint32_t create_disp;
568 NTSTATUS correct_status;
570 { NTCREATEX_DISP_SUPERSEDE, true, NT_STATUS_OK },
571 { NTCREATEX_DISP_SUPERSEDE, false, NT_STATUS_OK },
572 { NTCREATEX_DISP_OPEN, true, NT_STATUS_OK },
573 { NTCREATEX_DISP_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
574 { NTCREATEX_DISP_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
575 { NTCREATEX_DISP_CREATE, false, NT_STATUS_OK },
576 { NTCREATEX_DISP_OPEN_IF, true, NT_STATUS_OK },
577 { NTCREATEX_DISP_OPEN_IF, false, NT_STATUS_OK },
578 { NTCREATEX_DISP_OVERWRITE, true, NT_STATUS_OK },
579 { NTCREATEX_DISP_OVERWRITE, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
580 { NTCREATEX_DISP_OVERWRITE_IF, true, NT_STATUS_OK },
581 { NTCREATEX_DISP_OVERWRITE_IF, false, NT_STATUS_OK },
582 { 6, true, NT_STATUS_INVALID_PARAMETER },
583 { 6, false, NT_STATUS_INVALID_PARAMETER },
586 torture_comment(torture, "Checking SMB2 Open\n");
588 smb2_util_unlink(tree, fname);
589 smb2_util_rmdir(tree, dname);
591 status = torture_smb2_testdir(tree, DNAME, &h);
592 CHECK_STATUS(status, NT_STATUS_OK);
594 ZERO_STRUCT(io.smb2);
595 /* reasonable default parameters */
596 io.generic.level = RAW_OPEN_SMB2;
597 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
598 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
599 io.smb2.in.alloc_size = 1024*1024;
600 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
601 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
602 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
603 io.smb2.in.create_options = 0;
604 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
605 io.smb2.in.security_flags = 0;
606 io.smb2.in.fname = fname;
608 /* test the create disposition */
609 for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
610 if (open_funcs[i].with_file) {
611 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
612 status= smb2_create(tree, mem_ctx, &(io.smb2));
613 if (!NT_STATUS_IS_OK(status)) {
614 torture_comment(torture,
615 "Failed to create file %s status %s %d\n",
616 fname, nt_errstr(status), i);
621 smb2_util_close(tree, io.smb2.out.file.handle);
623 io.smb2.in.create_disposition = open_funcs[i].create_disp;
624 status = smb2_create(tree, mem_ctx, &(io.smb2));
625 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
626 torture_comment(torture,
627 "(%s) incorrect status %s should be %s (i=%d "
628 "with_file=%d open_disp=%d)\n",
629 __location__, nt_errstr(status),
630 nt_errstr(open_funcs[i].correct_status),
631 i, (int)open_funcs[i].with_file,
632 (int)open_funcs[i].create_disp);
637 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
638 smb2_util_close(tree, io.smb2.out.file.handle);
639 smb2_util_unlink(tree, fname);
643 /* basic field testing */
644 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
646 status = smb2_create(tree, mem_ctx, &(io.smb2));
647 CHECK_STATUS(status, NT_STATUS_OK);
648 h1 = io.smb2.out.file.handle;
650 CHECK_VAL(io.smb2.out.oplock_level, 0);
651 CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
652 CHECK_NTTIME(io.smb2.out.create_time, create_time);
653 CHECK_NTTIME(io.smb2.out.access_time, access_time);
654 CHECK_NTTIME(io.smb2.out.write_time, write_time);
655 CHECK_NTTIME(io.smb2.out.change_time, change_time);
656 CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
657 CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
658 CHECK_ALL_INFO(io.smb2.out.size, size);
660 /* check fields when the file already existed */
661 smb2_util_close(tree, h1);
662 smb2_util_unlink(tree, fname);
664 status = smb2_create_complex_file(tree, fname, &h1);
665 CHECK_STATUS(status, NT_STATUS_OK);
667 smb2_util_close(tree, h1);
669 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
670 status = smb2_create(tree, mem_ctx, &(io.smb2));
671 CHECK_STATUS(status, NT_STATUS_OK);
672 h1 = io.smb2.out.file.handle;
674 CHECK_VAL(io.smb2.out.oplock_level, 0);
675 CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_EXISTED);
676 CHECK_NTTIME(io.smb2.out.create_time, create_time);
677 CHECK_NTTIME(io.smb2.out.access_time, access_time);
678 CHECK_NTTIME(io.smb2.out.write_time, write_time);
679 CHECK_NTTIME(io.smb2.out.change_time, change_time);
680 CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
681 CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
682 CHECK_ALL_INFO(io.smb2.out.size, size);
683 smb2_util_close(tree, h1);
684 smb2_util_unlink(tree, fname);
686 /* create a directory */
687 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
688 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
689 io.smb2.in.alloc_size = 0;
690 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
691 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
692 io.smb2.in.create_options = 0;
693 io.smb2.in.fname = dname;
696 smb2_util_rmdir(tree, fname);
697 smb2_util_unlink(tree, fname);
699 io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
700 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
701 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
702 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
703 NTCREATEX_SHARE_ACCESS_WRITE;
704 status = smb2_create(tree, mem_ctx, &(io.smb2));
705 CHECK_STATUS(status, NT_STATUS_OK);
706 h1 = io.smb2.out.file.handle;
708 CHECK_VAL(io.smb2.out.oplock_level, 0);
709 CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
710 CHECK_NTTIME(io.smb2.out.create_time, create_time);
711 CHECK_NTTIME(io.smb2.out.access_time, access_time);
712 CHECK_NTTIME(io.smb2.out.write_time, write_time);
713 CHECK_NTTIME(io.smb2.out.change_time, change_time);
714 CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
715 CHECK_VAL(io.smb2.out.file_attr & ~FILE_ATTRIBUTE_NONINDEXED,
716 FILE_ATTRIBUTE_DIRECTORY);
717 CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
718 CHECK_ALL_INFO(io.smb2.out.size, size);
719 CHECK_VAL(io.smb2.out.size, 0);
720 CHECK_VAL(io.smb2.out.alloc_size, 0);
721 smb2_util_unlink(tree, fname);
724 smb2_util_close(tree, h1);
725 smb2_util_unlink(tree, fname);
726 smb2_deltree(tree, DNAME);
727 talloc_free(mem_ctx);
732 test with an already opened and byte range locked file
735 static bool test_smb2_open_brlocked(struct torture_context *torture,
736 struct smb2_tree *tree)
738 union smb_open io, io1;
740 struct smb2_lock_element lock[1];
741 const char *fname = DNAME "\\torture_ntcreatex.txt";
744 struct smb2_handle h;
746 torture_comment(torture,
747 "Testing SMB2 open with a byte range locked file\n");
749 smb2_util_unlink(tree, fname);
751 status = torture_smb2_testdir(tree, DNAME, &h);
752 CHECK_STATUS(status, NT_STATUS_OK);
754 ZERO_STRUCT(io.smb2);
755 io.generic.level = RAW_OPEN_SMB2;
756 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
757 io.smb2.in.desired_access = 0x2019f;
758 io.smb2.in.alloc_size = 0;
759 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
760 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
761 NTCREATEX_SHARE_ACCESS_WRITE;
762 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
763 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
764 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
765 io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
766 io.smb2.in.fname = fname;
768 status = smb2_create(tree, torture, &(io.smb2));
769 CHECK_STATUS(status, NT_STATUS_OK);
771 ZERO_STRUCT(io2.smb2);
772 io2.smb2.level = RAW_LOCK_SMB2;
773 io2.smb2.in.file.handle = io.smb2.out.file.handle;
774 io2.smb2.in.lock_count = 1;
777 lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
778 SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
779 io2.smb2.in.locks = &lock[0];
780 status = smb2_lock(tree, &(io2.smb2));
781 CHECK_STATUS(status, NT_STATUS_OK);
783 ZERO_STRUCT(io1.smb2);
784 io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
785 io1.smb2.in.desired_access = 0x20196;
786 io1.smb2.in.alloc_size = 0;
787 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
788 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
789 NTCREATEX_SHARE_ACCESS_WRITE;
790 io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
791 io1.smb2.in.create_options = 0;
792 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
793 io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
794 io1.smb2.in.fname = fname;
796 status = smb2_create(tree, torture, &(io1.smb2));
797 CHECK_STATUS(status, NT_STATUS_OK);
799 smb2_util_close(tree, io.smb2.out.file.handle);
800 smb2_util_close(tree, io1.smb2.out.file.handle);
801 smb2_util_unlink(tree, fname);
802 smb2_deltree(tree, DNAME);
807 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
809 static bool test_smb2_open_multi(struct torture_context *torture,
810 struct smb2_tree *tree)
812 TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
813 const char *fname = "test_oplock.dat";
817 struct smb2_tree **trees;
818 struct smb2_request **requests;
820 int i, num_files = 3;
822 int num_collision = 0;
824 if (mem_ctx == NULL) {
829 torture_comment(torture,
830 "Testing SMB2 Open with multiple connections\n");
831 trees = talloc_array(mem_ctx, struct smb2_tree *, num_files);
832 requests = talloc_array(mem_ctx, struct smb2_request *, num_files);
833 ios = talloc_array(mem_ctx, union smb_open, num_files);
834 if ((torture->ev == NULL) || (trees == NULL) || (requests == NULL) ||
836 torture_comment(torture, ("talloc failed\n"));
841 tree->session->transport->options.request_timeout = 60;
843 for (i=0; i<num_files; i++) {
844 if (!torture_smb2_connection(torture, &(trees[i]))) {
845 torture_comment(torture,
846 "Could not open %d'th connection\n", i);
850 trees[i]->session->transport->options.request_timeout = 60;
854 smb2_util_unlink(tree, fname);
859 ZERO_STRUCT(io.smb2);
860 io.generic.level = RAW_OPEN_SMB2;
861 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
862 io.smb2.in.alloc_size = 0;
863 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
864 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
865 NTCREATEX_SHARE_ACCESS_WRITE|
866 NTCREATEX_SHARE_ACCESS_DELETE;
867 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
868 io.smb2.in.create_options = 0;
869 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
870 io.smb2.in.security_flags = 0;
871 io.smb2.in.fname = fname;
872 io.smb2.in.create_flags = 0;
874 for (i=0; i<num_files; i++) {
876 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
877 if (requests[i] == NULL) {
878 torture_comment(torture,
879 "could not send %d'th request\n", i);
885 torture_comment(torture, "waiting for replies\n");
887 bool unreplied = false;
888 for (i=0; i<num_files; i++) {
889 if (requests[i] == NULL) {
892 if (requests[i]->state < SMB2_REQUEST_DONE) {
896 status = smb2_create_recv(requests[i], mem_ctx,
899 torture_comment(torture,
900 "File %d returned status %s\n", i,
903 if (NT_STATUS_IS_OK(status)) {
907 if (NT_STATUS_EQUAL(status,
908 NT_STATUS_OBJECT_NAME_COLLISION)) {
918 if (event_loop_once(torture->ev) != 0) {
919 torture_comment(torture, "event_loop_once failed\n");
925 if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
929 talloc_free(mem_ctx);
930 smb2_deltree(tree, fname);
936 test opening for delete on a read-only attribute file.
939 static bool test_smb2_open_for_delete(struct torture_context *torture,
940 struct smb2_tree *tree)
943 union smb_fileinfo finfo;
944 const char *fname = DNAME "\\torture_open_for_delete.txt";
946 struct smb2_handle h, h1;
949 torture_comment(torture,
950 "Checking SMB2_OPEN for delete on a readonly file.\n");
951 smb2_util_unlink(tree, fname);
952 smb2_deltree(tree, fname);
954 status = torture_smb2_testdir(tree, DNAME, &h);
955 CHECK_STATUS(status, NT_STATUS_OK);
957 /* reasonable default parameters */
958 ZERO_STRUCT(io.smb2);
959 io.generic.level = RAW_OPEN_SMB2;
960 io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
961 io.smb2.in.alloc_size = 0;
962 io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
963 io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY;
964 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
965 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
966 io.smb2.in.create_options = 0;
967 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
968 io.smb2.in.security_flags = 0;
969 io.smb2.in.fname = fname;
971 /* Create the readonly file. */
973 status = smb2_create(tree, torture, &(io.smb2));
974 CHECK_STATUS(status, NT_STATUS_OK);
975 h1 = io.smb2.out.file.handle;
977 CHECK_VAL(io.smb2.out.oplock_level, 0);
978 io.smb2.in.create_options = 0;
979 CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
980 CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
981 smb2_util_close(tree, h1);
983 /* Now try and open for delete only - should succeed. */
984 io.smb2.in.desired_access = SEC_STD_DELETE;
985 io.smb2.in.file_attributes = 0;
986 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
987 NTCREATEX_SHARE_ACCESS_WRITE |
988 NTCREATEX_SHARE_ACCESS_DELETE;
989 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
990 status = smb2_create(tree, torture, &(io.smb2));
991 CHECK_STATUS(status, NT_STATUS_OK);
993 smb2_util_unlink(tree, fname);
995 smb2_util_close(tree, h1);
996 smb2_util_unlink(tree, fname);
997 smb2_deltree(tree, DNAME);
1003 test SMB2 open with a leading slash on the path.
1004 Trying to create a directory with a leading slash
1005 should give NT_STATUS_INVALID_PARAMETER error
1007 static bool test_smb2_leading_slash(struct torture_context *torture,
1008 struct smb2_tree *tree)
1011 const char *dnameslash = "\\"DNAME;
1015 torture_comment(torture,
1016 "Trying to create a directory with leading slash on path\n");
1017 smb2_deltree(tree, dnameslash);
1019 ZERO_STRUCT(io.smb2);
1020 io.generic.level = RAW_OPEN_SMB2;
1021 io.smb2.in.oplock_level = 0;
1022 io.smb2.in.desired_access = SEC_RIGHTS_DIR_ALL;
1023 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1024 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1025 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1026 NTCREATEX_SHARE_ACCESS_WRITE |
1027 NTCREATEX_SHARE_ACCESS_DELETE;
1028 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1029 io.smb2.in.fname = dnameslash;
1031 status = smb2_create(tree, tree, &(io.smb2));
1032 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1034 smb2_deltree(tree, dnameslash);
1040 basic testing of SMB2 read
1042 struct torture_suite *torture_smb2_create_init(void)
1044 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
1046 torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
1047 torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
1048 torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
1049 torture_suite_add_1smb2_test(suite, "OPEN", test_smb2_open);
1050 torture_suite_add_1smb2_test(suite, "BRLOCKED", test_smb2_open_brlocked);
1051 torture_suite_add_1smb2_test(suite, "MULTI", test_smb2_open_multi);
1052 torture_suite_add_1smb2_test(suite, "DELETE", test_smb2_open_for_delete);
1053 torture_suite_add_1smb2_test(suite, "LEADING-SLASH", test_smb2_leading_slash);
1055 suite->description = talloc_strdup(suite, "SMB2-CREATE tests");