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); \
47
test some interesting combinations found by gentest
49
static bool test_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
51
struct smb2_create io;
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;
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;
64
NTCREATEX_SHARE_ACCESS_DELETE|
65
NTCREATEX_SHARE_ACCESS_READ|
66
NTCREATEX_SHARE_ACCESS_WRITE;
67
io.in.create_options = 0;
70
status = smb2_create(tree, tmp_ctx, &io);
71
CHECK_STATUS(status, NT_STATUS_OK);
73
status = smb2_util_close(tree, io.out.file.handle);
74
CHECK_STATUS(status, NT_STATUS_OK);
76
io.in.create_options = 0xF0000000;
77
status = smb2_create(tree, tmp_ctx, &io);
78
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
80
io.in.create_options = 0;
82
io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
83
status = smb2_create(tree, tmp_ctx, &io);
84
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
86
io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
87
status = smb2_create(tree, tmp_ctx, &io);
88
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
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);
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);
100
io.in.desired_access = 0x04000000;
101
status = smb2_create(tree, tmp_ctx, &io);
102
CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
104
io.in.file_attributes = 0;
105
io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
106
io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
108
not_supported_mask = 0;
109
invalid_parameter_mask = 0;
110
not_a_directory_mask = 0;
115
io.in.create_options = 1<<i;
116
if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
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)) {
128
status = smb2_util_close(tree, io.out.file.handle);
129
CHECK_STATUS(status, NT_STATUS_OK);
131
unexpected_mask |= 1<<i;
132
printf("create option 0x%08x returned %s\n", 1<<i, nt_errstr(status));
136
io.in.create_options = 0;
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);
144
io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
145
io.in.file_attributes = 0;
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;
156
CHECK_STATUS(status, NT_STATUS_OK);
157
status = smb2_util_close(tree, io.out.file.handle);
158
CHECK_STATUS(status, NT_STATUS_OK);
163
CHECK_EQUAL(access_mask, 0x0df0fe00);
165
io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
166
io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
167
io.in.file_attributes = 0;
169
invalid_parameter_mask = 0;
171
file_attributes_set = 0;
175
io.in.file_attributes = 1<<i;
176
if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
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)) {
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;
191
status = smb2_util_close(tree, io.out.file.handle);
192
CHECK_STATUS(status, NT_STATUS_OK);
194
unexpected_mask |= 1<<i;
195
printf("file attribute 0x%08x returned %s\n", 1<<i, nt_errstr(status));
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);
205
smb2_deltree(tree, FNAME);
208
* Standalone servers doesn't support encryption
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));
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);
221
smb2_deltree(tree, FNAME);
224
io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
225
io.in.file_attributes = 0;
226
io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
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);
235
status = smb2_util_close(tree, io.out.file.handle);
236
CHECK_STATUS(status, NT_STATUS_OK);
239
io.in.file_attributes = 0x8040;
241
NTCREATEX_SHARE_ACCESS_READ;
242
status = smb2_create(tree, tmp_ctx, &io);
243
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
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);
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);
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);
266
talloc_free(tmp_ctx);
268
smb2_deltree(tree, FNAME);
275
try the various request blobs
277
static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
279
struct smb2_create io;
281
TALLOC_CTX *tmp_ctx = talloc_new(tree);
283
smb2_deltree(tree, FNAME);
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;
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 |
299
status = smb2_create(tree, tmp_ctx, &io);
300
CHECK_STATUS(status, NT_STATUS_OK);
302
status = smb2_util_close(tree, io.out.file.handle);
303
CHECK_STATUS(status, NT_STATUS_OK);
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);
311
status = smb2_util_close(tree, io.out.file.handle);
312
CHECK_STATUS(status, NT_STATUS_OK);
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);
319
status = smb2_util_close(tree, io.out.file.handle);
320
CHECK_STATUS(status, NT_STATUS_OK);
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);
328
status = smb2_util_close(tree, io.out.file.handle);
329
CHECK_STATUS(status, NT_STATUS_OK);
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);
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);
342
status = smb2_util_close(tree, io.out.file.handle);
343
CHECK_STATUS(status, NT_STATUS_OK);
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);
350
status = smb2_create(tree, tmp_ctx, &io);
351
CHECK_STATUS(status, NT_STATUS_OK);
353
status = smb2_util_close(tree, io.out.file.handle);
354
CHECK_STATUS(status, NT_STATUS_OK);
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);
361
status = smb2_create(tree, tmp_ctx, &io);
362
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
364
talloc_free(tmp_ctx);
366
smb2_deltree(tree, FNAME);
372
try creating with acls
374
static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
376
struct smb2_create io;
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;
384
smb2_deltree(tree, FNAME);
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;
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 |
400
status = smb2_create(tree, tmp_ctx, &io);
401
CHECK_STATUS(status, NT_STATUS_OK);
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 =
409
status = smb2_getinfo_file(tree, tmp_ctx, &q);
410
CHECK_STATUS(status, NT_STATUS_OK);
411
sd = q.query_secdesc.out.sd;
413
status = smb2_util_close(tree, io.out.file.handle);
414
CHECK_STATUS(status, NT_STATUS_OK);
416
smb2_util_unlink(tree, FNAME);
418
printf("adding a new ACE\n");
419
test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
421
ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
423
ace.access_mask = SEC_STD_ALL;
424
ace.trustee = *test_sid;
426
status = security_descriptor_dacl_add(sd, &ace);
427
CHECK_STATUS(status, NT_STATUS_OK);
429
printf("creating a file with an initial ACL\n");
432
status = smb2_create(tree, tmp_ctx, &io);
433
CHECK_STATUS(status, NT_STATUS_OK);
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;
440
if (!security_acl_equal(sd->dacl, sd2->dacl)) {
441
printf("%s: security descriptors don't match!\n", __location__);
443
NDR_PRINT_DEBUG(security_descriptor, sd2);
444
printf("expected:\n");
445
NDR_PRINT_DEBUG(security_descriptor, sd);
449
talloc_free(tmp_ctx);
455
basic testing of SMB2 read
457
struct torture_suite *torture_smb2_create_init(void)
459
struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
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);
465
suite->description = talloc_strdup(suite, "SMB2-CREATE tests");