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;
59 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
60 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
61 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
63 NTCREATEX_SHARE_ACCESS_DELETE|
64 NTCREATEX_SHARE_ACCESS_READ|
65 NTCREATEX_SHARE_ACCESS_WRITE;
66 io.in.create_options = 0;
69 status = smb2_create(tree, tmp_ctx, &io);
70 CHECK_STATUS(status, NT_STATUS_OK);
72 status = smb2_util_close(tree, io.out.file.handle);
73 CHECK_STATUS(status, NT_STATUS_OK);
75 io.in.create_options = 0xF0000000;
76 status = smb2_create(tree, tmp_ctx, &io);
77 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
79 io.in.create_options = 0x00100000;
80 status = smb2_create(tree, tmp_ctx, &io);
81 CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED);
83 io.in.create_options = 0xF0100000;
84 status = smb2_create(tree, tmp_ctx, &io);
85 CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED);
87 io.in.create_options = 0;
89 io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
90 status = smb2_create(tree, tmp_ctx, &io);
91 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
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_OPEN;
98 io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
99 status = smb2_create(tree, tmp_ctx, &io);
100 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
102 io.in.create_disposition = NTCREATEX_DISP_CREATE;
103 io.in.desired_access = 0x08000000;
104 status = smb2_create(tree, tmp_ctx, &io);
105 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
107 io.in.desired_access = 0x04000000;
108 status = smb2_create(tree, tmp_ctx, &io);
109 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
111 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
112 io.in.file_attributes = 0;
117 io.in.desired_access = 1<<i;
118 status = smb2_create(tree, tmp_ctx, &io);
119 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
120 NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
121 access_mask |= io.in.desired_access;
123 CHECK_STATUS(status, NT_STATUS_OK);
124 status = smb2_util_close(tree, io.out.file.handle);
125 CHECK_STATUS(status, NT_STATUS_OK);
130 CHECK_EQUAL(access_mask, 0x0df0fe00);
132 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
133 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
134 io.in.file_attributes = 0;
136 file_attributes_set = 0;
141 io.in.file_attributes = 1<<i;
142 smb2_deltree(tree, FNAME);
143 status = smb2_create(tree, tmp_ctx, &io);
144 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
145 file_attributes |= io.in.file_attributes;
146 } else if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
147 denied_mask |= io.in.file_attributes;
149 CHECK_STATUS(status, NT_STATUS_OK);
150 status = smb2_util_close(tree, io.out.file.handle);
151 CHECK_STATUS(status, NT_STATUS_OK);
152 file_attributes_set |= io.out.file_attr;
157 CHECK_EQUAL(file_attributes, 0xffff8048);
158 CHECK_EQUAL(denied_mask, 0x4000);
159 CHECK_EQUAL(file_attributes_set, 0x00001127);
161 smb2_deltree(tree, FNAME);
164 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
165 io.in.file_attributes = 0;
166 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
168 NTCREATEX_SHARE_ACCESS_READ|
169 NTCREATEX_SHARE_ACCESS_WRITE;
170 io.in.create_options = 0;
171 io.in.fname = FNAME ":stream1";
172 status = smb2_create(tree, tmp_ctx, &io);
173 CHECK_STATUS(status, NT_STATUS_OK);
175 status = smb2_util_close(tree, io.out.file.handle);
176 CHECK_STATUS(status, NT_STATUS_OK);
179 io.in.file_attributes = 0x8040;
181 NTCREATEX_SHARE_ACCESS_READ;
182 status = smb2_create(tree, tmp_ctx, &io);
183 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
186 io.in.file_attributes = 0;
187 io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
188 io.in.query_maximal_access = true;
189 status = smb2_create(tree, tmp_ctx, &io);
190 CHECK_STATUS(status, NT_STATUS_OK);
191 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
193 q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
194 q.access_information.in.file.handle = io.out.file.handle;
195 status = smb2_getinfo_file(tree, tmp_ctx, &q);
196 CHECK_STATUS(status, NT_STATUS_OK);
197 CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
199 talloc_free(tmp_ctx);
201 smb2_deltree(tree, FNAME);
208 try the various request blobs
210 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
212 struct smb2_create io;
214 TALLOC_CTX *tmp_ctx = talloc_new(tree);
216 smb2_deltree(tree, FNAME);
219 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
220 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
221 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
223 NTCREATEX_SHARE_ACCESS_DELETE|
224 NTCREATEX_SHARE_ACCESS_READ|
225 NTCREATEX_SHARE_ACCESS_WRITE;
226 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
227 NTCREATEX_OPTIONS_ASYNC_ALERT |
228 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
232 status = smb2_create(tree, tmp_ctx, &io);
233 CHECK_STATUS(status, NT_STATUS_OK);
235 status = smb2_util_close(tree, io.out.file.handle);
236 CHECK_STATUS(status, NT_STATUS_OK);
238 printf("testing alloc size\n");
239 io.in.alloc_size = 4096;
240 status = smb2_create(tree, tmp_ctx, &io);
241 CHECK_STATUS(status, NT_STATUS_OK);
242 CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
244 status = smb2_util_close(tree, io.out.file.handle);
245 CHECK_STATUS(status, NT_STATUS_OK);
247 printf("testing durable open\n");
248 io.in.durable_open = true;
249 status = smb2_create(tree, tmp_ctx, &io);
250 CHECK_STATUS(status, NT_STATUS_OK);
252 status = smb2_util_close(tree, io.out.file.handle);
253 CHECK_STATUS(status, NT_STATUS_OK);
255 printf("testing query maximal access\n");
256 io.in.query_maximal_access = true;
257 status = smb2_create(tree, tmp_ctx, &io);
258 CHECK_STATUS(status, NT_STATUS_OK);
259 CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
261 status = smb2_util_close(tree, io.out.file.handle);
262 CHECK_STATUS(status, NT_STATUS_OK);
264 printf("testing timewarp\n");
265 io.in.timewarp = 10000;
266 status = smb2_create(tree, tmp_ctx, &io);
267 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
270 printf("testing query_on_disk\n");
271 io.in.query_on_disk_id = true;
272 status = smb2_create(tree, tmp_ctx, &io);
273 CHECK_STATUS(status, NT_STATUS_OK);
275 status = smb2_util_close(tree, io.out.file.handle);
276 CHECK_STATUS(status, NT_STATUS_OK);
278 printf("testing unknown tag\n");
279 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
280 "FooO", data_blob(NULL, 0));
281 CHECK_STATUS(status, NT_STATUS_OK);
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 bad tag length\n");
290 status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
291 "xxx", data_blob(NULL, 0));
292 CHECK_STATUS(status, NT_STATUS_OK);
294 status = smb2_create(tree, tmp_ctx, &io);
295 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
297 talloc_free(tmp_ctx);
299 smb2_deltree(tree, FNAME);
305 try creating with acls
307 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
309 struct smb2_create io;
311 TALLOC_CTX *tmp_ctx = talloc_new(tree);
312 struct security_ace ace;
313 struct security_descriptor *sd, *sd2;
314 struct dom_sid *test_sid;
315 union smb_fileinfo q;
317 smb2_deltree(tree, FNAME);
320 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
321 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
322 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
324 NTCREATEX_SHARE_ACCESS_DELETE|
325 NTCREATEX_SHARE_ACCESS_READ|
326 NTCREATEX_SHARE_ACCESS_WRITE;
327 io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
328 NTCREATEX_OPTIONS_ASYNC_ALERT |
329 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
333 status = smb2_create(tree, tmp_ctx, &io);
334 CHECK_STATUS(status, NT_STATUS_OK);
336 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
337 q.query_secdesc.in.file.handle = io.out.file.handle;
338 q.query_secdesc.in.secinfo_flags =
342 status = smb2_getinfo_file(tree, tmp_ctx, &q);
343 CHECK_STATUS(status, NT_STATUS_OK);
344 sd = q.query_secdesc.out.sd;
346 status = smb2_util_close(tree, io.out.file.handle);
347 CHECK_STATUS(status, NT_STATUS_OK);
349 smb2_util_unlink(tree, FNAME);
351 printf("adding a new ACE\n");
352 test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
354 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
356 ace.access_mask = SEC_STD_ALL;
357 ace.trustee = *test_sid;
359 status = security_descriptor_dacl_add(sd, &ace);
360 CHECK_STATUS(status, NT_STATUS_OK);
362 printf("creating a file with an initial ACL\n");
365 status = smb2_create(tree, tmp_ctx, &io);
366 CHECK_STATUS(status, NT_STATUS_OK);
368 q.query_secdesc.in.file.handle = io.out.file.handle;
369 status = smb2_getinfo_file(tree, tmp_ctx, &q);
370 CHECK_STATUS(status, NT_STATUS_OK);
371 sd2 = q.query_secdesc.out.sd;
373 if (!security_acl_equal(sd->dacl, sd2->dacl)) {
374 printf("%s: security descriptors don't match!\n", __location__);
376 NDR_PRINT_DEBUG(security_descriptor, sd2);
377 printf("expected:\n");
378 NDR_PRINT_DEBUG(security_descriptor, sd);
382 talloc_free(tmp_ctx);
388 basic testing of SMB2 read
390 struct torture_suite *torture_smb2_create_init(void)
392 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
394 torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
395 torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
396 torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
398 suite->description = talloc_strdup(suite, "SMB2-CREATE tests");