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/smb2/proto.h"
27 #include "param/param.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "libcli/security/security.h"
31 #define FNAME "test_create.dat"
33 #define CHECK_STATUS(status, correct) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 printf("(%s) Incorrect status %s - should be %s\n", \
36 __location__, nt_errstr(status), nt_errstr(correct)); \
40 #define CHECK_EQUAL(v, correct) do { \
42 printf("(%s) Incorrect value for %s 0x%08llx - should be 0x%08llx\n", \
43 __location__, #v, (unsigned long long)v, (unsigned long long)correct); \
48 test some interesting combinations found by gentest
50 static bool test_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
52 struct smb2_create io;
54 TALLOC_CTX *tmp_ctx = talloc_new(tree);
55 uint32_t access_mask, file_attributes_set;
56 uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
57 uint32_t not_a_directory_mask, unexpected_mask;
61 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
62 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
63 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
65 NTCREATEX_SHARE_ACCESS_DELETE|
66 NTCREATEX_SHARE_ACCESS_READ|
67 NTCREATEX_SHARE_ACCESS_WRITE;
68 io.in.create_options = 0;
71 status = smb2_create(tree, tmp_ctx, &io);
72 CHECK_STATUS(status, NT_STATUS_OK);
74 status = smb2_util_close(tree, io.out.file.handle);
75 CHECK_STATUS(status, NT_STATUS_OK);
77 io.in.create_options = 0xF0000000;
78 status = smb2_create(tree, tmp_ctx, &io);
79 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
81 io.in.create_options = 0;
83 io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
84 status = smb2_create(tree, tmp_ctx, &io);
85 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
87 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
88 status = smb2_create(tree, tmp_ctx, &io);
89 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
91 io.in.create_disposition = NTCREATEX_DISP_OPEN;
92 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
93 status = smb2_create(tree, tmp_ctx, &io);
94 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
96 io.in.create_disposition = NTCREATEX_DISP_CREATE;
97 io.in.desired_access = 0x08000000;
98 status = smb2_create(tree, tmp_ctx, &io);
99 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
101 io.in.desired_access = 0x04000000;
102 status = smb2_create(tree, tmp_ctx, &io);
103 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
105 io.in.file_attributes = 0;
106 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
107 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
109 not_supported_mask = 0;
110 invalid_parameter_mask = 0;
111 not_a_directory_mask = 0;
116 io.in.create_options = 1<<i;
117 if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
120 status = smb2_create(tree, tmp_ctx, &io);
121 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
122 not_supported_mask |= 1<<i;
123 } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
124 invalid_parameter_mask |= 1<<i;
125 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
126 not_a_directory_mask |= 1<<i;
127 } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
129 status = smb2_util_close(tree, io.out.file.handle);
130 CHECK_STATUS(status, NT_STATUS_OK);
132 unexpected_mask |= 1<<i;
133 printf("create option 0x%08x returned %s\n", 1<<i, nt_errstr(status));
137 io.in.create_options = 0;
139 CHECK_EQUAL(ok_mask, 0x00efcf7e);
140 CHECK_EQUAL(not_a_directory_mask, 0x00000001);
141 CHECK_EQUAL(not_supported_mask, 0x00102080);
142 CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
143 CHECK_EQUAL(unexpected_mask, 0x00000000);
145 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
146 io.in.file_attributes = 0;
151 io.in.desired_access = 1<<i;
152 status = smb2_create(tree, tmp_ctx, &io);
153 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
154 NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
155 access_mask |= io.in.desired_access;
157 CHECK_STATUS(status, NT_STATUS_OK);
158 status = smb2_util_close(tree, io.out.file.handle);
159 CHECK_STATUS(status, NT_STATUS_OK);
164 CHECK_EQUAL(access_mask, 0x0df0fe00);
166 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
167 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
168 io.in.file_attributes = 0;
170 invalid_parameter_mask = 0;
172 file_attributes_set = 0;
176 io.in.file_attributes = 1<<i;
177 if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
180 smb2_deltree(tree, FNAME);
181 status = smb2_create(tree, tmp_ctx, &io);
182 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
183 invalid_parameter_mask |= 1<<i;
184 } else if (NT_STATUS_IS_OK(status)) {
188 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
189 CHECK_EQUAL(io.out.file_attr, expected);
190 file_attributes_set |= io.out.file_attr;
192 status = smb2_util_close(tree, io.out.file.handle);
193 CHECK_STATUS(status, NT_STATUS_OK);
195 unexpected_mask |= 1<<i;
196 printf("file attribute 0x%08x returned %s\n", 1<<i, nt_errstr(status));
201 CHECK_EQUAL(ok_mask, 0x00003fb7);
202 CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
203 CHECK_EQUAL(unexpected_mask, 0x00000000);
204 CHECK_EQUAL(file_attributes_set, 0x00001127);
206 smb2_deltree(tree, FNAME);
209 * Standalone servers doesn't support encryption
211 io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
212 status = smb2_create(tree, tmp_ctx, &io);
213 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
214 printf("FILE_ATTRIBUTE_ENCRYPTED returned %s\n", nt_errstr(status));
216 CHECK_STATUS(status, NT_STATUS_OK);
217 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
218 status = smb2_util_close(tree, io.out.file.handle);
219 CHECK_STATUS(status, NT_STATUS_OK);
222 smb2_deltree(tree, FNAME);
225 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
226 io.in.file_attributes = 0;
227 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
229 NTCREATEX_SHARE_ACCESS_READ|
230 NTCREATEX_SHARE_ACCESS_WRITE;
231 io.in.create_options = 0;
232 io.in.fname = FNAME ":stream1";
233 status = smb2_create(tree, tmp_ctx, &io);
234 CHECK_STATUS(status, NT_STATUS_OK);
236 status = smb2_util_close(tree, io.out.file.handle);
237 CHECK_STATUS(status, NT_STATUS_OK);
240 io.in.file_attributes = 0x8040;
242 NTCREATEX_SHARE_ACCESS_READ;
243 status = smb2_create(tree, tmp_ctx, &io);
244 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
247 io.in.file_attributes = 0;
248 io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
249 io.in.query_maximal_access = true;
250 status = smb2_create(tree, tmp_ctx, &io);
251 CHECK_STATUS(status, NT_STATUS_OK);
252 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
254 q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
255 q.access_information.in.file.handle = io.out.file.handle;
256 status = smb2_getinfo_file(tree, tmp_ctx, &q);
257 CHECK_STATUS(status, NT_STATUS_OK);
258 CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
260 io.in.file_attributes = 0;
261 io.in.desired_access = 0;
262 io.in.query_maximal_access = false;
263 io.in.share_access = 0;
264 status = smb2_create(tree, tmp_ctx, &io);
265 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
267 talloc_free(tmp_ctx);
269 smb2_deltree(tree, FNAME);
276 try the various request blobs
278 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
280 struct smb2_create io;
282 TALLOC_CTX *tmp_ctx = talloc_new(tree);
284 smb2_deltree(tree, FNAME);
287 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
288 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
289 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
291 NTCREATEX_SHARE_ACCESS_DELETE|
292 NTCREATEX_SHARE_ACCESS_READ|
293 NTCREATEX_SHARE_ACCESS_WRITE;
294 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
295 NTCREATEX_OPTIONS_ASYNC_ALERT |
296 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
300 status = smb2_create(tree, tmp_ctx, &io);
301 CHECK_STATUS(status, NT_STATUS_OK);
303 status = smb2_util_close(tree, io.out.file.handle);
304 CHECK_STATUS(status, NT_STATUS_OK);
306 printf("testing alloc size\n");
307 io.in.alloc_size = 4096;
308 status = smb2_create(tree, tmp_ctx, &io);
309 CHECK_STATUS(status, NT_STATUS_OK);
310 CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
312 status = smb2_util_close(tree, io.out.file.handle);
313 CHECK_STATUS(status, NT_STATUS_OK);
315 printf("testing durable open\n");
316 io.in.durable_open = true;
317 status = smb2_create(tree, tmp_ctx, &io);
318 CHECK_STATUS(status, NT_STATUS_OK);
320 status = smb2_util_close(tree, io.out.file.handle);
321 CHECK_STATUS(status, NT_STATUS_OK);
323 printf("testing query maximal access\n");
324 io.in.query_maximal_access = true;
325 status = smb2_create(tree, tmp_ctx, &io);
326 CHECK_STATUS(status, NT_STATUS_OK);
327 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
329 status = smb2_util_close(tree, io.out.file.handle);
330 CHECK_STATUS(status, NT_STATUS_OK);
332 printf("testing timewarp\n");
333 io.in.timewarp = 10000;
334 status = smb2_create(tree, tmp_ctx, &io);
335 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
338 printf("testing query_on_disk\n");
339 io.in.query_on_disk_id = true;
340 status = smb2_create(tree, tmp_ctx, &io);
341 CHECK_STATUS(status, NT_STATUS_OK);
343 status = smb2_util_close(tree, io.out.file.handle);
344 CHECK_STATUS(status, NT_STATUS_OK);
346 printf("testing unknown tag\n");
347 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
348 "FooO", data_blob(NULL, 0));
349 CHECK_STATUS(status, NT_STATUS_OK);
351 status = smb2_create(tree, tmp_ctx, &io);
352 CHECK_STATUS(status, NT_STATUS_OK);
354 status = smb2_util_close(tree, io.out.file.handle);
355 CHECK_STATUS(status, NT_STATUS_OK);
357 printf("testing bad tag length\n");
358 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
359 "xxx", data_blob(NULL, 0));
360 CHECK_STATUS(status, NT_STATUS_OK);
362 status = smb2_create(tree, tmp_ctx, &io);
363 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
365 talloc_free(tmp_ctx);
367 smb2_deltree(tree, FNAME);
373 try creating with acls
375 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
377 struct smb2_create io;
379 TALLOC_CTX *tmp_ctx = talloc_new(tree);
380 struct security_ace ace;
381 struct security_descriptor *sd, *sd2;
382 struct dom_sid *test_sid;
383 union smb_fileinfo q;
385 smb2_deltree(tree, FNAME);
388 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
389 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
390 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
392 NTCREATEX_SHARE_ACCESS_DELETE|
393 NTCREATEX_SHARE_ACCESS_READ|
394 NTCREATEX_SHARE_ACCESS_WRITE;
395 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
396 NTCREATEX_OPTIONS_ASYNC_ALERT |
397 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
401 status = smb2_create(tree, tmp_ctx, &io);
402 CHECK_STATUS(status, NT_STATUS_OK);
404 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
405 q.query_secdesc.in.file.handle = io.out.file.handle;
406 q.query_secdesc.in.secinfo_flags =
410 status = smb2_getinfo_file(tree, tmp_ctx, &q);
411 CHECK_STATUS(status, NT_STATUS_OK);
412 sd = q.query_secdesc.out.sd;
414 status = smb2_util_close(tree, io.out.file.handle);
415 CHECK_STATUS(status, NT_STATUS_OK);
417 smb2_util_unlink(tree, FNAME);
419 printf("adding a new ACE\n");
420 test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
422 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
424 ace.access_mask = SEC_STD_ALL;
425 ace.trustee = *test_sid;
427 status = security_descriptor_dacl_add(sd, &ace);
428 CHECK_STATUS(status, NT_STATUS_OK);
430 printf("creating a file with an initial ACL\n");
433 status = smb2_create(tree, tmp_ctx, &io);
434 CHECK_STATUS(status, NT_STATUS_OK);
436 q.query_secdesc.in.file.handle = io.out.file.handle;
437 status = smb2_getinfo_file(tree, tmp_ctx, &q);
438 CHECK_STATUS(status, NT_STATUS_OK);
439 sd2 = q.query_secdesc.out.sd;
441 if (!security_acl_equal(sd->dacl, sd2->dacl)) {
442 printf("%s: security descriptors don't match!\n", __location__);
444 NDR_PRINT_DEBUG(security_descriptor, sd2);
445 printf("expected:\n");
446 NDR_PRINT_DEBUG(security_descriptor, sd);
450 talloc_free(tmp_ctx);
456 basic testing of SMB2 read
458 struct torture_suite *torture_smb2_create_init(void)
460 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
462 torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
463 torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
464 torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
466 suite->description = talloc_strdup(suite, "SMB2-CREATE tests");