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, file_attributes_set, denied_mask;
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 file_attributes_set = 0;
175 io.in.file_attributes = 1<<i;
176 smb2_deltree(tree, FNAME);
177 status = smb2_create(tree, tmp_ctx, &io);
178 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
179 file_attributes |= io.in.file_attributes;
180 } else if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
181 denied_mask |= io.in.file_attributes;
183 CHECK_STATUS(status, NT_STATUS_OK);
184 status = smb2_util_close(tree, io.out.file.handle);
185 CHECK_STATUS(status, NT_STATUS_OK);
186 file_attributes_set |= io.out.file_attr;
191 CHECK_EQUAL(file_attributes, 0xffff8048);
192 CHECK_EQUAL(denied_mask, 0x4000);
193 CHECK_EQUAL(file_attributes_set, 0x00001127);
195 smb2_deltree(tree, FNAME);
198 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
199 io.in.file_attributes = 0;
200 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
202 NTCREATEX_SHARE_ACCESS_READ|
203 NTCREATEX_SHARE_ACCESS_WRITE;
204 io.in.create_options = 0;
205 io.in.fname = FNAME ":stream1";
206 status = smb2_create(tree, tmp_ctx, &io);
207 CHECK_STATUS(status, NT_STATUS_OK);
209 status = smb2_util_close(tree, io.out.file.handle);
210 CHECK_STATUS(status, NT_STATUS_OK);
213 io.in.file_attributes = 0x8040;
215 NTCREATEX_SHARE_ACCESS_READ;
216 status = smb2_create(tree, tmp_ctx, &io);
217 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
220 io.in.file_attributes = 0;
221 io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
222 io.in.query_maximal_access = true;
223 status = smb2_create(tree, tmp_ctx, &io);
224 CHECK_STATUS(status, NT_STATUS_OK);
225 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
227 q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
228 q.access_information.in.file.handle = io.out.file.handle;
229 status = smb2_getinfo_file(tree, tmp_ctx, &q);
230 CHECK_STATUS(status, NT_STATUS_OK);
231 CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
233 talloc_free(tmp_ctx);
235 smb2_deltree(tree, FNAME);
242 try the various request blobs
244 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
246 struct smb2_create io;
248 TALLOC_CTX *tmp_ctx = talloc_new(tree);
250 smb2_deltree(tree, FNAME);
253 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
254 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
255 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
257 NTCREATEX_SHARE_ACCESS_DELETE|
258 NTCREATEX_SHARE_ACCESS_READ|
259 NTCREATEX_SHARE_ACCESS_WRITE;
260 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
261 NTCREATEX_OPTIONS_ASYNC_ALERT |
262 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
266 status = smb2_create(tree, tmp_ctx, &io);
267 CHECK_STATUS(status, NT_STATUS_OK);
269 status = smb2_util_close(tree, io.out.file.handle);
270 CHECK_STATUS(status, NT_STATUS_OK);
272 printf("testing alloc size\n");
273 io.in.alloc_size = 4096;
274 status = smb2_create(tree, tmp_ctx, &io);
275 CHECK_STATUS(status, NT_STATUS_OK);
276 CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
278 status = smb2_util_close(tree, io.out.file.handle);
279 CHECK_STATUS(status, NT_STATUS_OK);
281 printf("testing durable open\n");
282 io.in.durable_open = true;
283 status = smb2_create(tree, tmp_ctx, &io);
284 CHECK_STATUS(status, NT_STATUS_OK);
286 status = smb2_util_close(tree, io.out.file.handle);
287 CHECK_STATUS(status, NT_STATUS_OK);
289 printf("testing query maximal access\n");
290 io.in.query_maximal_access = true;
291 status = smb2_create(tree, tmp_ctx, &io);
292 CHECK_STATUS(status, NT_STATUS_OK);
293 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
295 status = smb2_util_close(tree, io.out.file.handle);
296 CHECK_STATUS(status, NT_STATUS_OK);
298 printf("testing timewarp\n");
299 io.in.timewarp = 10000;
300 status = smb2_create(tree, tmp_ctx, &io);
301 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
304 printf("testing query_on_disk\n");
305 io.in.query_on_disk_id = true;
306 status = smb2_create(tree, tmp_ctx, &io);
307 CHECK_STATUS(status, NT_STATUS_OK);
309 status = smb2_util_close(tree, io.out.file.handle);
310 CHECK_STATUS(status, NT_STATUS_OK);
312 printf("testing unknown tag\n");
313 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
314 "FooO", data_blob(NULL, 0));
315 CHECK_STATUS(status, NT_STATUS_OK);
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 bad tag length\n");
324 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
325 "xxx", data_blob(NULL, 0));
326 CHECK_STATUS(status, NT_STATUS_OK);
328 status = smb2_create(tree, tmp_ctx, &io);
329 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
331 talloc_free(tmp_ctx);
333 smb2_deltree(tree, FNAME);
339 try creating with acls
341 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
343 struct smb2_create io;
345 TALLOC_CTX *tmp_ctx = talloc_new(tree);
346 struct security_ace ace;
347 struct security_descriptor *sd, *sd2;
348 struct dom_sid *test_sid;
349 union smb_fileinfo q;
351 smb2_deltree(tree, FNAME);
354 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
355 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
356 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
358 NTCREATEX_SHARE_ACCESS_DELETE|
359 NTCREATEX_SHARE_ACCESS_READ|
360 NTCREATEX_SHARE_ACCESS_WRITE;
361 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
362 NTCREATEX_OPTIONS_ASYNC_ALERT |
363 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
367 status = smb2_create(tree, tmp_ctx, &io);
368 CHECK_STATUS(status, NT_STATUS_OK);
370 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
371 q.query_secdesc.in.file.handle = io.out.file.handle;
372 q.query_secdesc.in.secinfo_flags =
376 status = smb2_getinfo_file(tree, tmp_ctx, &q);
377 CHECK_STATUS(status, NT_STATUS_OK);
378 sd = q.query_secdesc.out.sd;
380 status = smb2_util_close(tree, io.out.file.handle);
381 CHECK_STATUS(status, NT_STATUS_OK);
383 smb2_util_unlink(tree, FNAME);
385 printf("adding a new ACE\n");
386 test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
388 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
390 ace.access_mask = SEC_STD_ALL;
391 ace.trustee = *test_sid;
393 status = security_descriptor_dacl_add(sd, &ace);
394 CHECK_STATUS(status, NT_STATUS_OK);
396 printf("creating a file with an initial ACL\n");
399 status = smb2_create(tree, tmp_ctx, &io);
400 CHECK_STATUS(status, NT_STATUS_OK);
402 q.query_secdesc.in.file.handle = io.out.file.handle;
403 status = smb2_getinfo_file(tree, tmp_ctx, &q);
404 CHECK_STATUS(status, NT_STATUS_OK);
405 sd2 = q.query_secdesc.out.sd;
407 if (!security_acl_equal(sd->dacl, sd2->dacl)) {
408 printf("%s: security descriptors don't match!\n", __location__);
410 NDR_PRINT_DEBUG(security_descriptor, sd2);
411 printf("expected:\n");
412 NDR_PRINT_DEBUG(security_descriptor, sd);
416 talloc_free(tmp_ctx);
422 basic testing of SMB2 read
424 struct torture_suite *torture_smb2_create_init(void)
426 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
428 torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
429 torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
430 torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
432 suite->description = talloc_strdup(suite, "SMB2-CREATE tests");