WHATSNEW: Update release notes.
[Samba/bb.git] / source4 / torture / smb2 / create.c
blobfebfbe03ec4190505cfe6c10cb597927a7ecb584
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 create test suite
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/>.
22 #include "includes.h"
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 "librpc/gen_ndr/ndr_security.h"
28 #include "libcli/security/security.h"
30 #define FNAME "test_create.dat"
32 #define CHECK_STATUS(status, correct) do { \
33 if (!NT_STATUS_EQUAL(status, correct)) { \
34 printf("(%s) Incorrect status %s - should be %s\n", \
35 __location__, nt_errstr(status), nt_errstr(correct)); \
36 return false; \
37 }} while (0)
39 #define CHECK_EQUAL(v, correct) do { \
40 if (v != correct) { \
41 printf("(%s) Incorrect value for %s 0x%08llx - should be 0x%08llx\n", \
42 __location__, #v, (unsigned long long)v, (unsigned long long)correct); \
43 return false; \
44 }} while (0)
46 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
49 test some interesting combinations found by gentest
51 static bool test_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
53 struct smb2_create io;
54 NTSTATUS status;
55 TALLOC_CTX *tmp_ctx = talloc_new(tree);
56 uint32_t access_mask, file_attributes_set;
57 uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
58 uint32_t not_a_directory_mask, unexpected_mask;
59 union smb_fileinfo q;
61 ZERO_STRUCT(io);
62 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
63 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
64 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
65 io.in.share_access =
66 NTCREATEX_SHARE_ACCESS_DELETE|
67 NTCREATEX_SHARE_ACCESS_READ|
68 NTCREATEX_SHARE_ACCESS_WRITE;
69 io.in.create_options = 0;
70 io.in.fname = FNAME;
72 status = smb2_create(tree, tmp_ctx, &io);
73 CHECK_STATUS(status, NT_STATUS_OK);
75 status = smb2_util_close(tree, io.out.file.handle);
76 CHECK_STATUS(status, NT_STATUS_OK);
78 io.in.create_options = 0xF0000000;
79 status = smb2_create(tree, tmp_ctx, &io);
80 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
82 io.in.create_options = 0;
84 io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
85 status = smb2_create(tree, tmp_ctx, &io);
86 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
88 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
89 status = smb2_create(tree, tmp_ctx, &io);
90 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
92 io.in.create_disposition = NTCREATEX_DISP_OPEN;
93 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
94 status = smb2_create(tree, tmp_ctx, &io);
95 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
97 io.in.create_disposition = NTCREATEX_DISP_CREATE;
98 io.in.desired_access = 0x08000000;
99 status = smb2_create(tree, tmp_ctx, &io);
100 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
102 io.in.desired_access = 0x04000000;
103 status = smb2_create(tree, tmp_ctx, &io);
104 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
106 io.in.file_attributes = 0;
107 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
108 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
109 ok_mask = 0;
110 not_supported_mask = 0;
111 invalid_parameter_mask = 0;
112 not_a_directory_mask = 0;
113 unexpected_mask = 0;
115 int i;
116 for (i=0;i<32;i++) {
117 io.in.create_options = 1<<i;
118 if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
119 continue;
121 status = smb2_create(tree, tmp_ctx, &io);
122 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
123 not_supported_mask |= 1<<i;
124 } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
125 invalid_parameter_mask |= 1<<i;
126 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
127 not_a_directory_mask |= 1<<i;
128 } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
129 ok_mask |= 1<<i;
130 status = smb2_util_close(tree, io.out.file.handle);
131 CHECK_STATUS(status, NT_STATUS_OK);
132 } else {
133 unexpected_mask |= 1<<i;
134 printf("create option 0x%08x returned %s\n", 1<<i, nt_errstr(status));
138 io.in.create_options = 0;
140 CHECK_EQUAL(ok_mask, 0x00efcf7e);
141 CHECK_EQUAL(not_a_directory_mask, 0x00000001);
142 CHECK_EQUAL(not_supported_mask, 0x00102080);
143 CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
144 CHECK_EQUAL(unexpected_mask, 0x00000000);
146 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
147 io.in.file_attributes = 0;
148 access_mask = 0;
150 int i;
151 for (i=0;i<32;i++) {
152 io.in.desired_access = 1<<i;
153 status = smb2_create(tree, tmp_ctx, &io);
154 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
155 NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
156 access_mask |= io.in.desired_access;
157 } else {
158 CHECK_STATUS(status, NT_STATUS_OK);
159 status = smb2_util_close(tree, io.out.file.handle);
160 CHECK_STATUS(status, NT_STATUS_OK);
165 if (TARGET_IS_WIN7(torture)) {
166 CHECK_EQUAL(access_mask, 0x0de0fe00);
167 } else {
168 CHECK_EQUAL(access_mask, 0x0df0fe00);
171 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
172 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
173 io.in.file_attributes = 0;
174 ok_mask = 0;
175 invalid_parameter_mask = 0;
176 unexpected_mask = 0;
177 file_attributes_set = 0;
179 int i;
180 for (i=0;i<32;i++) {
181 io.in.file_attributes = 1<<i;
182 if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
183 continue;
185 smb2_deltree(tree, FNAME);
186 status = smb2_create(tree, tmp_ctx, &io);
187 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
188 invalid_parameter_mask |= 1<<i;
189 } else if (NT_STATUS_IS_OK(status)) {
190 uint32_t expected;
191 ok_mask |= 1<<i;
193 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
194 CHECK_EQUAL(io.out.file_attr, expected);
195 file_attributes_set |= io.out.file_attr;
197 status = smb2_util_close(tree, io.out.file.handle);
198 CHECK_STATUS(status, NT_STATUS_OK);
199 } else {
200 unexpected_mask |= 1<<i;
201 printf("file attribute 0x%08x returned %s\n", 1<<i, nt_errstr(status));
206 CHECK_EQUAL(ok_mask, 0x00003fb7);
207 CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
208 CHECK_EQUAL(unexpected_mask, 0x00000000);
209 CHECK_EQUAL(file_attributes_set, 0x00001127);
211 smb2_deltree(tree, FNAME);
214 * Standalone servers doesn't support encryption
216 io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
217 status = smb2_create(tree, tmp_ctx, &io);
218 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
219 printf("FILE_ATTRIBUTE_ENCRYPTED returned %s\n", nt_errstr(status));
220 } else {
221 CHECK_STATUS(status, NT_STATUS_OK);
222 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
223 status = smb2_util_close(tree, io.out.file.handle);
224 CHECK_STATUS(status, NT_STATUS_OK);
227 smb2_deltree(tree, FNAME);
229 ZERO_STRUCT(io);
230 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
231 io.in.file_attributes = 0;
232 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
233 io.in.share_access =
234 NTCREATEX_SHARE_ACCESS_READ|
235 NTCREATEX_SHARE_ACCESS_WRITE;
236 io.in.create_options = 0;
237 io.in.fname = FNAME ":stream1";
238 status = smb2_create(tree, tmp_ctx, &io);
239 CHECK_STATUS(status, NT_STATUS_OK);
241 status = smb2_util_close(tree, io.out.file.handle);
242 CHECK_STATUS(status, NT_STATUS_OK);
244 io.in.fname = FNAME;
245 io.in.file_attributes = 0x8040;
246 io.in.share_access =
247 NTCREATEX_SHARE_ACCESS_READ;
248 status = smb2_create(tree, tmp_ctx, &io);
249 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
251 io.in.fname = FNAME;
252 io.in.file_attributes = 0;
253 io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
254 io.in.query_maximal_access = true;
255 status = smb2_create(tree, tmp_ctx, &io);
256 CHECK_STATUS(status, NT_STATUS_OK);
257 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
259 q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
260 q.access_information.in.file.handle = io.out.file.handle;
261 status = smb2_getinfo_file(tree, tmp_ctx, &q);
262 CHECK_STATUS(status, NT_STATUS_OK);
263 CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
265 io.in.file_attributes = 0;
266 io.in.desired_access = 0;
267 io.in.query_maximal_access = false;
268 io.in.share_access = 0;
269 status = smb2_create(tree, tmp_ctx, &io);
270 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
272 talloc_free(tmp_ctx);
274 smb2_deltree(tree, FNAME);
276 return true;
281 try the various request blobs
283 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
285 struct smb2_create io;
286 NTSTATUS status;
287 TALLOC_CTX *tmp_ctx = talloc_new(tree);
289 smb2_deltree(tree, FNAME);
291 ZERO_STRUCT(io);
292 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
293 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
294 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
295 io.in.share_access =
296 NTCREATEX_SHARE_ACCESS_DELETE|
297 NTCREATEX_SHARE_ACCESS_READ|
298 NTCREATEX_SHARE_ACCESS_WRITE;
299 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
300 NTCREATEX_OPTIONS_ASYNC_ALERT |
301 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
302 0x00200000;
303 io.in.fname = FNAME;
305 status = smb2_create(tree, tmp_ctx, &io);
306 CHECK_STATUS(status, NT_STATUS_OK);
308 status = smb2_util_close(tree, io.out.file.handle);
309 CHECK_STATUS(status, NT_STATUS_OK);
311 printf("testing alloc size\n");
312 io.in.alloc_size = 4096;
313 status = smb2_create(tree, tmp_ctx, &io);
314 CHECK_STATUS(status, NT_STATUS_OK);
315 CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
317 status = smb2_util_close(tree, io.out.file.handle);
318 CHECK_STATUS(status, NT_STATUS_OK);
320 printf("testing durable open\n");
321 io.in.durable_open = true;
322 status = smb2_create(tree, tmp_ctx, &io);
323 CHECK_STATUS(status, NT_STATUS_OK);
325 status = smb2_util_close(tree, io.out.file.handle);
326 CHECK_STATUS(status, NT_STATUS_OK);
328 printf("testing query maximal access\n");
329 io.in.query_maximal_access = true;
330 status = smb2_create(tree, tmp_ctx, &io);
331 CHECK_STATUS(status, NT_STATUS_OK);
332 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
334 status = smb2_util_close(tree, io.out.file.handle);
335 CHECK_STATUS(status, NT_STATUS_OK);
337 printf("testing timewarp\n");
338 io.in.timewarp = 10000;
339 status = smb2_create(tree, tmp_ctx, &io);
340 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
341 io.in.timewarp = 0;
343 printf("testing query_on_disk\n");
344 io.in.query_on_disk_id = true;
345 status = smb2_create(tree, tmp_ctx, &io);
346 CHECK_STATUS(status, NT_STATUS_OK);
348 status = smb2_util_close(tree, io.out.file.handle);
349 CHECK_STATUS(status, NT_STATUS_OK);
351 printf("testing unknown tag\n");
352 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
353 "FooO", data_blob(NULL, 0));
354 CHECK_STATUS(status, NT_STATUS_OK);
356 status = smb2_create(tree, tmp_ctx, &io);
357 CHECK_STATUS(status, NT_STATUS_OK);
359 status = smb2_util_close(tree, io.out.file.handle);
360 CHECK_STATUS(status, NT_STATUS_OK);
362 printf("testing bad tag length\n");
363 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
364 "xxx", data_blob(NULL, 0));
365 CHECK_STATUS(status, NT_STATUS_OK);
367 status = smb2_create(tree, tmp_ctx, &io);
368 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
370 talloc_free(tmp_ctx);
372 smb2_deltree(tree, FNAME);
374 return true;
378 try creating with acls
380 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
382 struct smb2_create io;
383 NTSTATUS status;
384 TALLOC_CTX *tmp_ctx = talloc_new(tree);
385 struct security_ace ace;
386 struct security_descriptor *sd, *sd2;
387 struct dom_sid *test_sid;
388 union smb_fileinfo q;
390 smb2_deltree(tree, FNAME);
392 ZERO_STRUCT(io);
393 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
394 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
395 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
396 io.in.share_access =
397 NTCREATEX_SHARE_ACCESS_DELETE|
398 NTCREATEX_SHARE_ACCESS_READ|
399 NTCREATEX_SHARE_ACCESS_WRITE;
400 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
401 NTCREATEX_OPTIONS_ASYNC_ALERT |
402 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
403 0x00200000;
404 io.in.fname = FNAME;
406 status = smb2_create(tree, tmp_ctx, &io);
407 CHECK_STATUS(status, NT_STATUS_OK);
409 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
410 q.query_secdesc.in.file.handle = io.out.file.handle;
411 q.query_secdesc.in.secinfo_flags =
412 SECINFO_OWNER |
413 SECINFO_GROUP |
414 SECINFO_DACL;
415 status = smb2_getinfo_file(tree, tmp_ctx, &q);
416 CHECK_STATUS(status, NT_STATUS_OK);
417 sd = q.query_secdesc.out.sd;
419 status = smb2_util_close(tree, io.out.file.handle);
420 CHECK_STATUS(status, NT_STATUS_OK);
422 smb2_util_unlink(tree, FNAME);
424 printf("adding a new ACE\n");
425 test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
427 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
428 ace.flags = 0;
429 ace.access_mask = SEC_STD_ALL;
430 ace.trustee = *test_sid;
432 status = security_descriptor_dacl_add(sd, &ace);
433 CHECK_STATUS(status, NT_STATUS_OK);
435 printf("creating a file with an initial ACL\n");
437 io.in.sec_desc = sd;
438 status = smb2_create(tree, tmp_ctx, &io);
439 CHECK_STATUS(status, NT_STATUS_OK);
441 q.query_secdesc.in.file.handle = io.out.file.handle;
442 status = smb2_getinfo_file(tree, tmp_ctx, &q);
443 CHECK_STATUS(status, NT_STATUS_OK);
444 sd2 = q.query_secdesc.out.sd;
446 if (!security_acl_equal(sd->dacl, sd2->dacl)) {
447 printf("%s: security descriptors don't match!\n", __location__);
448 printf("got:\n");
449 NDR_PRINT_DEBUG(security_descriptor, sd2);
450 printf("expected:\n");
451 NDR_PRINT_DEBUG(security_descriptor, sd);
452 return false;
455 talloc_free(tmp_ctx);
457 return true;
461 basic testing of SMB2 read
463 struct torture_suite *torture_smb2_create_init(void)
465 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
467 torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
468 torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
469 torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
471 suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
473 return suite;