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 "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)); \
39 #define CHECK_EQUAL(v, correct) do { \
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); \
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
;
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
;
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
;
66 NTCREATEX_SHARE_ACCESS_DELETE
|
67 NTCREATEX_SHARE_ACCESS_READ
|
68 NTCREATEX_SHARE_ACCESS_WRITE
;
69 io
.in
.create_options
= 0;
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
;
110 not_supported_mask
= 0;
111 invalid_parameter_mask
= 0;
112 not_a_directory_mask
= 0;
117 io
.in
.create_options
= 1<<i
;
118 if (io
.in
.create_options
& NTCREATEX_OPTIONS_DELETE_ON_CLOSE
) {
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
)) {
130 status
= smb2_util_close(tree
, io
.out
.file
.handle
);
131 CHECK_STATUS(status
, NT_STATUS_OK
);
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;
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
;
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);
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;
175 invalid_parameter_mask
= 0;
177 file_attributes_set
= 0;
181 io
.in
.file_attributes
= 1<<i
;
182 if (io
.in
.file_attributes
& FILE_ATTRIBUTE_ENCRYPTED
) {
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
)) {
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
);
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
));
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
);
230 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
231 io
.in
.file_attributes
= 0;
232 io
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
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
);
245 io
.in
.file_attributes
= 0x8040;
247 NTCREATEX_SHARE_ACCESS_READ
;
248 status
= smb2_create(tree
, tmp_ctx
, &io
);
249 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
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
);
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
;
287 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
289 smb2_deltree(tree
, FNAME
);
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
;
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
|
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
);
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
);
378 try creating with acls
380 static bool test_create_acl(struct torture_context
*torture
, struct smb2_tree
*tree
)
382 struct smb2_create io
;
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
);
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
;
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
|
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
=
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
;
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");
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__
);
449 NDR_PRINT_DEBUG(security_descriptor
, sd2
);
450 printf("expected:\n");
451 NDR_PRINT_DEBUG(security_descriptor
, sd
);
455 talloc_free(tmp_ctx
);
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");