/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- test_create_gentest
- test_create_blob
- test_create_acl
- torture_smb2_create_init
1 /*
2 Unix SMB/CIFS implementation.
3
4 SMB2 create test suite
5
6 Copyright (C) Andrew Tridgell 2008
7
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.
12
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.
17
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/>.
20 */
21
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"
29
30 #define FNAME "test_create.dat"
31
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)
38
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)
45
46 /*
47 test some interesting combinations found by gentest
48 */
49 static bool test_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
/* [<][>][^][v][top][bottom][index][help] */
50 {
51 struct smb2_create io;
52 NTSTATUS status;
53 TALLOC_CTX *tmp_ctx = talloc_new(tree);
54 uint32_t access_mask, file_attributes_set;
55 uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
56 uint32_t not_a_directory_mask, unexpected_mask;
57 union smb_fileinfo q;
58
59 ZERO_STRUCT(io);
60 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
61 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
62 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
63 io.in.share_access =
64 NTCREATEX_SHARE_ACCESS_DELETE|
65 NTCREATEX_SHARE_ACCESS_READ|
66 NTCREATEX_SHARE_ACCESS_WRITE;
67 io.in.create_options = 0;
68 io.in.fname = FNAME;
69
70 status = smb2_create(tree, tmp_ctx, &io);
71 CHECK_STATUS(status, NT_STATUS_OK);
72
73 status = smb2_util_close(tree, io.out.file.handle);
74 CHECK_STATUS(status, NT_STATUS_OK);
75
76 io.in.create_options = 0xF0000000;
77 status = smb2_create(tree, tmp_ctx, &io);
78 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
79
80 io.in.create_options = 0;
81
82 io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
83 status = smb2_create(tree, tmp_ctx, &io);
84 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
85
86 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
87 status = smb2_create(tree, tmp_ctx, &io);
88 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
89
90 io.in.create_disposition = NTCREATEX_DISP_OPEN;
91 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
92 status = smb2_create(tree, tmp_ctx, &io);
93 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
94
95 io.in.create_disposition = NTCREATEX_DISP_CREATE;
96 io.in.desired_access = 0x08000000;
97 status = smb2_create(tree, tmp_ctx, &io);
98 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
99
100 io.in.desired_access = 0x04000000;
101 status = smb2_create(tree, tmp_ctx, &io);
102 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
103
104 io.in.file_attributes = 0;
105 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
106 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
107 ok_mask = 0;
108 not_supported_mask = 0;
109 invalid_parameter_mask = 0;
110 not_a_directory_mask = 0;
111 unexpected_mask = 0;
112 {
113 int i;
114 for (i=0;i<32;i++) {
115 io.in.create_options = 1<<i;
116 if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
117 continue;
118 }
119 status = smb2_create(tree, tmp_ctx, &io);
120 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
121 not_supported_mask |= 1<<i;
122 } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
123 invalid_parameter_mask |= 1<<i;
124 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
125 not_a_directory_mask |= 1<<i;
126 } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
127 ok_mask |= 1<<i;
128 status = smb2_util_close(tree, io.out.file.handle);
129 CHECK_STATUS(status, NT_STATUS_OK);
130 } else {
131 unexpected_mask |= 1<<i;
132 printf("create option 0x%08x returned %s\n", 1<<i, nt_errstr(status));
133 }
134 }
135 }
136 io.in.create_options = 0;
137
138 CHECK_EQUAL(ok_mask, 0x00efcf7e);
139 CHECK_EQUAL(not_a_directory_mask, 0x00000001);
140 CHECK_EQUAL(not_supported_mask, 0x00102080);
141 CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
142 CHECK_EQUAL(unexpected_mask, 0x00000000);
143
144 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
145 io.in.file_attributes = 0;
146 access_mask = 0;
147 {
148 int i;
149 for (i=0;i<32;i++) {
150 io.in.desired_access = 1<<i;
151 status = smb2_create(tree, tmp_ctx, &io);
152 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
153 NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
154 access_mask |= io.in.desired_access;
155 } else {
156 CHECK_STATUS(status, NT_STATUS_OK);
157 status = smb2_util_close(tree, io.out.file.handle);
158 CHECK_STATUS(status, NT_STATUS_OK);
159 }
160 }
161 }
162
163 CHECK_EQUAL(access_mask, 0x0df0fe00);
164
165 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
166 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
167 io.in.file_attributes = 0;
168 ok_mask = 0;
169 invalid_parameter_mask = 0;
170 unexpected_mask = 0;
171 file_attributes_set = 0;
172 {
173 int i;
174 for (i=0;i<32;i++) {
175 io.in.file_attributes = 1<<i;
176 if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
177 continue;
178 }
179 smb2_deltree(tree, FNAME);
180 status = smb2_create(tree, tmp_ctx, &io);
181 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
182 invalid_parameter_mask |= 1<<i;
183 } else if (NT_STATUS_IS_OK(status)) {
184 uint32_t expected;
185 ok_mask |= 1<<i;
186
187 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
188 CHECK_EQUAL(io.out.file_attr, expected);
189 file_attributes_set |= io.out.file_attr;
190
191 status = smb2_util_close(tree, io.out.file.handle);
192 CHECK_STATUS(status, NT_STATUS_OK);
193 } else {
194 unexpected_mask |= 1<<i;
195 printf("file attribute 0x%08x returned %s\n", 1<<i, nt_errstr(status));
196 }
197 }
198 }
199
200 CHECK_EQUAL(ok_mask, 0x00003fb7);
201 CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
202 CHECK_EQUAL(unexpected_mask, 0x00000000);
203 CHECK_EQUAL(file_attributes_set, 0x00001127);
204
205 smb2_deltree(tree, FNAME);
206
207 /*
208 * Standalone servers doesn't support encryption
209 */
210 io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
211 status = smb2_create(tree, tmp_ctx, &io);
212 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
213 printf("FILE_ATTRIBUTE_ENCRYPTED returned %s\n", nt_errstr(status));
214 } else {
215 CHECK_STATUS(status, NT_STATUS_OK);
216 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
217 status = smb2_util_close(tree, io.out.file.handle);
218 CHECK_STATUS(status, NT_STATUS_OK);
219 }
220
221 smb2_deltree(tree, FNAME);
222
223 ZERO_STRUCT(io);
224 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
225 io.in.file_attributes = 0;
226 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
227 io.in.share_access =
228 NTCREATEX_SHARE_ACCESS_READ|
229 NTCREATEX_SHARE_ACCESS_WRITE;
230 io.in.create_options = 0;
231 io.in.fname = FNAME ":stream1";
232 status = smb2_create(tree, tmp_ctx, &io);
233 CHECK_STATUS(status, NT_STATUS_OK);
234
235 status = smb2_util_close(tree, io.out.file.handle);
236 CHECK_STATUS(status, NT_STATUS_OK);
237
238 io.in.fname = FNAME;
239 io.in.file_attributes = 0x8040;
240 io.in.share_access =
241 NTCREATEX_SHARE_ACCESS_READ;
242 status = smb2_create(tree, tmp_ctx, &io);
243 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
244
245 io.in.fname = FNAME;
246 io.in.file_attributes = 0;
247 io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
248 io.in.query_maximal_access = true;
249 status = smb2_create(tree, tmp_ctx, &io);
250 CHECK_STATUS(status, NT_STATUS_OK);
251 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
252
253 q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
254 q.access_information.in.file.handle = io.out.file.handle;
255 status = smb2_getinfo_file(tree, tmp_ctx, &q);
256 CHECK_STATUS(status, NT_STATUS_OK);
257 CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
258
259 io.in.file_attributes = 0;
260 io.in.desired_access = 0;
261 io.in.query_maximal_access = false;
262 io.in.share_access = 0;
263 status = smb2_create(tree, tmp_ctx, &io);
264 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
265
266 talloc_free(tmp_ctx);
267
268 smb2_deltree(tree, FNAME);
269
270 return true;
271 }
272
273
274 /*
275 try the various request blobs
276 */
277 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
/* [<][>][^][v][top][bottom][index][help] */
278 {
279 struct smb2_create io;
280 NTSTATUS status;
281 TALLOC_CTX *tmp_ctx = talloc_new(tree);
282
283 smb2_deltree(tree, FNAME);
284
285 ZERO_STRUCT(io);
286 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
287 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
288 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
289 io.in.share_access =
290 NTCREATEX_SHARE_ACCESS_DELETE|
291 NTCREATEX_SHARE_ACCESS_READ|
292 NTCREATEX_SHARE_ACCESS_WRITE;
293 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
294 NTCREATEX_OPTIONS_ASYNC_ALERT |
295 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
296 0x00200000;
297 io.in.fname = FNAME;
298
299 status = smb2_create(tree, tmp_ctx, &io);
300 CHECK_STATUS(status, NT_STATUS_OK);
301
302 status = smb2_util_close(tree, io.out.file.handle);
303 CHECK_STATUS(status, NT_STATUS_OK);
304
305 printf("testing alloc size\n");
306 io.in.alloc_size = 4096;
307 status = smb2_create(tree, tmp_ctx, &io);
308 CHECK_STATUS(status, NT_STATUS_OK);
309 CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
310
311 status = smb2_util_close(tree, io.out.file.handle);
312 CHECK_STATUS(status, NT_STATUS_OK);
313
314 printf("testing durable open\n");
315 io.in.durable_open = true;
316 status = smb2_create(tree, tmp_ctx, &io);
317 CHECK_STATUS(status, NT_STATUS_OK);
318
319 status = smb2_util_close(tree, io.out.file.handle);
320 CHECK_STATUS(status, NT_STATUS_OK);
321
322 printf("testing query maximal access\n");
323 io.in.query_maximal_access = true;
324 status = smb2_create(tree, tmp_ctx, &io);
325 CHECK_STATUS(status, NT_STATUS_OK);
326 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
327
328 status = smb2_util_close(tree, io.out.file.handle);
329 CHECK_STATUS(status, NT_STATUS_OK);
330
331 printf("testing timewarp\n");
332 io.in.timewarp = 10000;
333 status = smb2_create(tree, tmp_ctx, &io);
334 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
335 io.in.timewarp = 0;
336
337 printf("testing query_on_disk\n");
338 io.in.query_on_disk_id = true;
339 status = smb2_create(tree, tmp_ctx, &io);
340 CHECK_STATUS(status, NT_STATUS_OK);
341
342 status = smb2_util_close(tree, io.out.file.handle);
343 CHECK_STATUS(status, NT_STATUS_OK);
344
345 printf("testing unknown tag\n");
346 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
347 "FooO", data_blob(NULL, 0));
348 CHECK_STATUS(status, NT_STATUS_OK);
349
350 status = smb2_create(tree, tmp_ctx, &io);
351 CHECK_STATUS(status, NT_STATUS_OK);
352
353 status = smb2_util_close(tree, io.out.file.handle);
354 CHECK_STATUS(status, NT_STATUS_OK);
355
356 printf("testing bad tag length\n");
357 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
358 "xxx", data_blob(NULL, 0));
359 CHECK_STATUS(status, NT_STATUS_OK);
360
361 status = smb2_create(tree, tmp_ctx, &io);
362 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
363
364 talloc_free(tmp_ctx);
365
366 smb2_deltree(tree, FNAME);
367
368 return true;
369 }
370
371 /*
372 try creating with acls
373 */
374 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
/* [<][>][^][v][top][bottom][index][help] */
375 {
376 struct smb2_create io;
377 NTSTATUS status;
378 TALLOC_CTX *tmp_ctx = talloc_new(tree);
379 struct security_ace ace;
380 struct security_descriptor *sd, *sd2;
381 struct dom_sid *test_sid;
382 union smb_fileinfo q;
383
384 smb2_deltree(tree, FNAME);
385
386 ZERO_STRUCT(io);
387 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
388 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
389 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
390 io.in.share_access =
391 NTCREATEX_SHARE_ACCESS_DELETE|
392 NTCREATEX_SHARE_ACCESS_READ|
393 NTCREATEX_SHARE_ACCESS_WRITE;
394 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
395 NTCREATEX_OPTIONS_ASYNC_ALERT |
396 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
397 0x00200000;
398 io.in.fname = FNAME;
399
400 status = smb2_create(tree, tmp_ctx, &io);
401 CHECK_STATUS(status, NT_STATUS_OK);
402
403 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
404 q.query_secdesc.in.file.handle = io.out.file.handle;
405 q.query_secdesc.in.secinfo_flags =
406 SECINFO_OWNER |
407 SECINFO_GROUP |
408 SECINFO_DACL;
409 status = smb2_getinfo_file(tree, tmp_ctx, &q);
410 CHECK_STATUS(status, NT_STATUS_OK);
411 sd = q.query_secdesc.out.sd;
412
413 status = smb2_util_close(tree, io.out.file.handle);
414 CHECK_STATUS(status, NT_STATUS_OK);
415
416 smb2_util_unlink(tree, FNAME);
417
418 printf("adding a new ACE\n");
419 test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
420
421 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
422 ace.flags = 0;
423 ace.access_mask = SEC_STD_ALL;
424 ace.trustee = *test_sid;
425
426 status = security_descriptor_dacl_add(sd, &ace);
427 CHECK_STATUS(status, NT_STATUS_OK);
428
429 printf("creating a file with an initial ACL\n");
430
431 io.in.sec_desc = sd;
432 status = smb2_create(tree, tmp_ctx, &io);
433 CHECK_STATUS(status, NT_STATUS_OK);
434
435 q.query_secdesc.in.file.handle = io.out.file.handle;
436 status = smb2_getinfo_file(tree, tmp_ctx, &q);
437 CHECK_STATUS(status, NT_STATUS_OK);
438 sd2 = q.query_secdesc.out.sd;
439
440 if (!security_acl_equal(sd->dacl, sd2->dacl)) {
441 printf("%s: security descriptors don't match!\n", __location__);
442 printf("got:\n");
443 NDR_PRINT_DEBUG(security_descriptor, sd2);
444 printf("expected:\n");
445 NDR_PRINT_DEBUG(security_descriptor, sd);
446 return false;
447 }
448
449 talloc_free(tmp_ctx);
450
451 return true;
452 }
453
454 /*
455 basic testing of SMB2 read
456 */
457 struct torture_suite *torture_smb2_create_init(void)
/* [<][>][^][v][top][bottom][index][help] */
458 {
459 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
460
461 torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
462 torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
463 torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
464
465 suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
466
467 return suite;
468 }