Line data Source code
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 "libcli/smb/smbXcli_base.h"
26 : #include "torture/torture.h"
27 : #include "torture/util.h"
28 : #include "torture/smb2/proto.h"
29 : #include "librpc/gen_ndr/ndr_security.h"
30 : #include "libcli/security/security.h"
31 :
32 : #include "system/filesys.h"
33 : #include "auth/credentials/credentials.h"
34 : #include "lib/cmdline/cmdline.h"
35 : #include "librpc/gen_ndr/security.h"
36 : #include "lib/events/events.h"
37 :
38 : #define FNAME "test_create.dat"
39 : #define DNAME "smb2_open"
40 :
41 : #define CHECK_STATUS(status, correct) do { \
42 : if (!NT_STATUS_EQUAL(status, correct)) { \
43 : torture_result(tctx, TORTURE_FAIL, \
44 : "(%s) Incorrect status %s - should be %s\n", \
45 : __location__, nt_errstr(status), nt_errstr(correct)); \
46 : return false; \
47 : }} while (0)
48 :
49 : #define CHECK_EQUAL(v, correct) do { \
50 : if (v != correct) { \
51 : torture_result(tctx, TORTURE_FAIL, \
52 : "(%s) Incorrect value for %s 0x%08llx - " \
53 : "should be 0x%08llx\n", \
54 : __location__, #v, \
55 : (unsigned long long)v, \
56 : (unsigned long long)correct); \
57 : return false; \
58 : }} while (0)
59 :
60 : #define CHECK_TIME(t, field) do { \
61 : time_t t1, t2; \
62 : finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
63 : finfo.all_info.in.file.handle = h1; \
64 : status = smb2_getinfo_file(tree, tctx, &finfo); \
65 : CHECK_STATUS(status, NT_STATUS_OK); \
66 : t1 = t & ~1; \
67 : t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
68 : if (abs(t1-t2) > 2) { \
69 : torture_result(tctx, TORTURE_FAIL, \
70 : "(%s) wrong time for field %s %s - %s\n", \
71 : __location__, #field, \
72 : timestring(tctx, t1), \
73 : timestring(tctx, t2)); \
74 : dump_all_info(tctx, &finfo); \
75 : ret = false; \
76 : }} while (0)
77 :
78 : #define CHECK_NTTIME(t, field) do { \
79 : NTTIME t2; \
80 : finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
81 : finfo.all_info.in.file.handle = h1; \
82 : status = smb2_getinfo_file(tree, tctx, &finfo); \
83 : CHECK_STATUS(status, NT_STATUS_OK); \
84 : t2 = finfo.all_info.out.field; \
85 : if (llabs((int64_t)(t-t2)) > 20000) { \
86 : torture_result(tctx, TORTURE_FAIL, \
87 : "(%s) wrong time for field %s %s - %s\n", \
88 : __location__, #field, \
89 : nt_time_string(tctx, t), \
90 : nt_time_string(tctx, t2)); \
91 : dump_all_info(tctx, &finfo); \
92 : ret = false; \
93 : }} while (0)
94 :
95 : #define CHECK_ALL_INFO(v, field) do { \
96 : finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
97 : finfo.all_info.in.file.handle = h1; \
98 : status = smb2_getinfo_file(tree, tctx, &finfo); \
99 : CHECK_STATUS(status, NT_STATUS_OK); \
100 : if ((v) != (finfo.all_info.out.field)) { \
101 : torture_result(tctx, TORTURE_FAIL, \
102 : "(%s) wrong value for field %s 0x%x - 0x%x\n", \
103 : __location__, #field, (int)v,\
104 : (int)(finfo.all_info.out.field)); \
105 : dump_all_info(tctx, &finfo); \
106 : ret = false; \
107 : }} while (0)
108 :
109 : #define CHECK_VAL(v, correct) do { \
110 : if ((v) != (correct)) { \
111 : torture_result(tctx, TORTURE_FAIL, \
112 : "(%s) wrong value for %s 0x%x - should be 0x%x\n", \
113 : __location__, #v, (int)(v), (int)correct); \
114 : ret = false; \
115 : }} while (0)
116 :
117 : #define SET_ATTRIB(sattrib) do { \
118 : union smb_setfileinfo sfinfo; \
119 : ZERO_STRUCT(sfinfo.basic_info.in); \
120 : sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
121 : sfinfo.basic_info.in.file.handle = h1; \
122 : sfinfo.basic_info.in.attrib = sattrib; \
123 : status = smb2_setinfo_file(tree, &sfinfo); \
124 : if (!NT_STATUS_IS_OK(status)) { \
125 : torture_comment(tctx, \
126 : "(%s) Failed to set attrib 0x%x on %s\n", \
127 : __location__, (unsigned int)(sattrib), fname); \
128 : }} while (0)
129 :
130 : /*
131 : test some interesting combinations found by gentest
132 : */
133 6 : static bool test_create_gentest(struct torture_context *tctx, struct smb2_tree *tree)
134 : {
135 0 : struct smb2_create io;
136 0 : NTSTATUS status;
137 0 : uint32_t access_mask, file_attributes_set;
138 0 : uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
139 0 : uint32_t not_a_directory_mask, unexpected_mask;
140 0 : union smb_fileinfo q;
141 :
142 6 : ZERO_STRUCT(io);
143 6 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
144 6 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
145 6 : io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
146 6 : io.in.share_access =
147 : NTCREATEX_SHARE_ACCESS_DELETE|
148 : NTCREATEX_SHARE_ACCESS_READ|
149 : NTCREATEX_SHARE_ACCESS_WRITE;
150 6 : io.in.create_options = 0;
151 6 : io.in.fname = FNAME;
152 :
153 6 : status = smb2_create(tree, tctx, &io);
154 6 : CHECK_STATUS(status, NT_STATUS_OK);
155 :
156 6 : status = smb2_util_close(tree, io.out.file.handle);
157 6 : CHECK_STATUS(status, NT_STATUS_OK);
158 :
159 6 : io.in.create_options = 0xF0000000;
160 6 : status = smb2_create(tree, tctx, &io);
161 6 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
162 :
163 6 : io.in.create_options = 0;
164 :
165 6 : io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
166 6 : status = smb2_create(tree, tctx, &io);
167 6 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
168 :
169 1 : io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
170 1 : status = smb2_create(tree, tctx, &io);
171 1 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
172 :
173 1 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
174 1 : io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
175 1 : status = smb2_create(tree, tctx, &io);
176 1 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
177 :
178 1 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
179 1 : io.in.desired_access = 0x08000000;
180 1 : status = smb2_create(tree, tctx, &io);
181 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
182 :
183 1 : io.in.desired_access = 0x04000000;
184 1 : status = smb2_create(tree, tctx, &io);
185 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
186 :
187 1 : io.in.file_attributes = 0;
188 1 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
189 1 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
190 1 : ok_mask = 0;
191 1 : not_supported_mask = 0;
192 1 : invalid_parameter_mask = 0;
193 1 : not_a_directory_mask = 0;
194 1 : unexpected_mask = 0;
195 : {
196 0 : int i;
197 33 : for (i=0;i<32;i++) {
198 32 : io.in.create_options = (uint32_t)1<<i;
199 32 : if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
200 1 : continue;
201 : }
202 31 : status = smb2_create(tree, tctx, &io);
203 31 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
204 3 : not_supported_mask |= 1<<i;
205 28 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
206 8 : invalid_parameter_mask |= 1<<i;
207 20 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
208 1 : not_a_directory_mask |= 1<<i;
209 19 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
210 19 : ok_mask |= 1<<i;
211 19 : status = smb2_util_close(tree, io.out.file.handle);
212 19 : CHECK_STATUS(status, NT_STATUS_OK);
213 : } else {
214 0 : unexpected_mask |= 1<<i;
215 0 : torture_comment(tctx,
216 : "create option 0x%08x returned %s\n",
217 : 1<<i, nt_errstr(status));
218 : }
219 : }
220 : }
221 1 : io.in.create_options = 0;
222 :
223 1 : CHECK_EQUAL(ok_mask, 0x00efcf7e);
224 1 : CHECK_EQUAL(not_a_directory_mask, 0x00000001);
225 1 : CHECK_EQUAL(not_supported_mask, 0x00102080);
226 1 : CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
227 1 : CHECK_EQUAL(unexpected_mask, 0x00000000);
228 :
229 1 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
230 1 : io.in.file_attributes = 0;
231 1 : access_mask = 0;
232 : {
233 0 : int i;
234 33 : for (i=0;i<32;i++) {
235 32 : io.in.desired_access = (uint32_t)1<<i;
236 32 : status = smb2_create(tree, tctx, &io);
237 32 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
238 19 : NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
239 13 : access_mask |= io.in.desired_access;
240 : } else {
241 19 : CHECK_STATUS(status, NT_STATUS_OK);
242 19 : status = smb2_util_close(tree, io.out.file.handle);
243 19 : CHECK_STATUS(status, NT_STATUS_OK);
244 : }
245 : }
246 : }
247 :
248 1 : if (TARGET_IS_WIN7(tctx)) {
249 0 : CHECK_EQUAL(access_mask, 0x0de0fe00);
250 1 : } else if (torture_setting_bool(tctx, "samba4", false)) {
251 1 : CHECK_EQUAL(access_mask, 0x0cf0fe00);
252 : } else {
253 0 : CHECK_EQUAL(access_mask, 0x0df0fe00);
254 : }
255 :
256 1 : io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
257 1 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
258 1 : io.in.file_attributes = 0;
259 1 : ok_mask = 0;
260 1 : invalid_parameter_mask = 0;
261 1 : unexpected_mask = 0;
262 1 : file_attributes_set = 0;
263 : {
264 0 : int i;
265 33 : for (i=0;i<32;i++) {
266 32 : io.in.file_attributes = (uint32_t)1<<i;
267 32 : if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
268 1 : continue;
269 : }
270 31 : smb2_deltree(tree, FNAME);
271 31 : status = smb2_create(tree, tctx, &io);
272 31 : if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
273 19 : invalid_parameter_mask |= 1<<i;
274 12 : } else if (NT_STATUS_IS_OK(status)) {
275 0 : uint32_t expected;
276 12 : ok_mask |= 1<<i;
277 :
278 12 : expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
279 12 : io.out.file_attr &= ~FILE_ATTRIBUTE_NONINDEXED;
280 12 : CHECK_EQUAL(io.out.file_attr, expected);
281 12 : file_attributes_set |= io.out.file_attr;
282 :
283 12 : status = smb2_util_close(tree, io.out.file.handle);
284 12 : CHECK_STATUS(status, NT_STATUS_OK);
285 : } else {
286 0 : unexpected_mask |= 1<<i;
287 0 : torture_comment(tctx,
288 : "file attribute 0x%08x returned %s\n",
289 : 1<<i, nt_errstr(status));
290 : }
291 : }
292 : }
293 :
294 1 : CHECK_EQUAL(ok_mask, 0x00003fb7);
295 1 : CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
296 1 : CHECK_EQUAL(unexpected_mask, 0x00000000);
297 1 : CHECK_EQUAL(file_attributes_set, 0x00001127);
298 :
299 1 : smb2_deltree(tree, FNAME);
300 :
301 : /*
302 : * Standalone servers doesn't support encryption
303 : */
304 1 : io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
305 1 : status = smb2_create(tree, tctx, &io);
306 1 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
307 1 : torture_comment(tctx,
308 : "FILE_ATTRIBUTE_ENCRYPTED returned %s\n",
309 : nt_errstr(status));
310 : } else {
311 0 : CHECK_STATUS(status, NT_STATUS_OK);
312 0 : CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
313 0 : status = smb2_util_close(tree, io.out.file.handle);
314 0 : CHECK_STATUS(status, NT_STATUS_OK);
315 : }
316 :
317 1 : smb2_deltree(tree, FNAME);
318 :
319 1 : ZERO_STRUCT(io);
320 1 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
321 1 : io.in.file_attributes = 0;
322 1 : io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
323 1 : io.in.share_access =
324 : NTCREATEX_SHARE_ACCESS_READ|
325 : NTCREATEX_SHARE_ACCESS_WRITE;
326 1 : io.in.create_options = 0;
327 1 : io.in.fname = FNAME ":stream1";
328 1 : status = smb2_create(tree, tctx, &io);
329 1 : CHECK_STATUS(status, NT_STATUS_OK);
330 :
331 1 : status = smb2_util_close(tree, io.out.file.handle);
332 1 : CHECK_STATUS(status, NT_STATUS_OK);
333 :
334 1 : io.in.fname = FNAME;
335 1 : io.in.file_attributes = 0x8040;
336 1 : io.in.share_access =
337 : NTCREATEX_SHARE_ACCESS_READ;
338 1 : status = smb2_create(tree, tctx, &io);
339 1 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
340 :
341 1 : io.in.fname = FNAME;
342 1 : io.in.file_attributes = 0;
343 1 : io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
344 1 : io.in.query_maximal_access = true;
345 1 : status = smb2_create(tree, tctx, &io);
346 1 : CHECK_STATUS(status, NT_STATUS_OK);
347 1 : CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
348 :
349 1 : q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
350 1 : q.access_information.in.file.handle = io.out.file.handle;
351 1 : status = smb2_getinfo_file(tree, tctx, &q);
352 1 : CHECK_STATUS(status, NT_STATUS_OK);
353 1 : CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
354 :
355 1 : io.in.file_attributes = 0;
356 1 : io.in.desired_access = 0;
357 1 : io.in.query_maximal_access = false;
358 1 : io.in.share_access = 0;
359 1 : status = smb2_create(tree, tctx, &io);
360 1 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
361 :
362 1 : smb2_deltree(tree, FNAME);
363 :
364 1 : return true;
365 : }
366 :
367 :
368 : /*
369 : try the various request blobs
370 : */
371 6 : static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tree)
372 : {
373 0 : struct smb2_create io;
374 0 : NTSTATUS status;
375 :
376 6 : smb2_deltree(tree, FNAME);
377 :
378 6 : ZERO_STRUCT(io);
379 6 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
380 6 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
381 6 : io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
382 6 : io.in.share_access =
383 : NTCREATEX_SHARE_ACCESS_DELETE|
384 : NTCREATEX_SHARE_ACCESS_READ|
385 : NTCREATEX_SHARE_ACCESS_WRITE;
386 6 : io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
387 : NTCREATEX_OPTIONS_ASYNC_ALERT |
388 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
389 : 0x00200000;
390 6 : io.in.fname = FNAME;
391 :
392 6 : status = smb2_create(tree, tctx, &io);
393 6 : CHECK_STATUS(status, NT_STATUS_OK);
394 :
395 6 : status = smb2_util_close(tree, io.out.file.handle);
396 6 : CHECK_STATUS(status, NT_STATUS_OK);
397 :
398 6 : torture_comment(tctx, "Testing alloc size\n");
399 : /* FIXME We use 1M cause that's the rounded size of Samba.
400 : * We should ask the server for the cluster size and calculate it
401 : * correctly. */
402 6 : io.in.alloc_size = 0x00100000;
403 6 : status = smb2_create(tree, tctx, &io);
404 6 : CHECK_STATUS(status, NT_STATUS_OK);
405 6 : CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
406 :
407 6 : status = smb2_util_close(tree, io.out.file.handle);
408 6 : CHECK_STATUS(status, NT_STATUS_OK);
409 :
410 6 : torture_comment(tctx, "Testing durable open\n");
411 6 : io.in.durable_open = true;
412 6 : status = smb2_create(tree, tctx, &io);
413 6 : CHECK_STATUS(status, NT_STATUS_OK);
414 :
415 6 : status = smb2_util_close(tree, io.out.file.handle);
416 6 : CHECK_STATUS(status, NT_STATUS_OK);
417 :
418 6 : torture_comment(tctx, "Testing query maximal access\n");
419 6 : io.in.query_maximal_access = true;
420 6 : status = smb2_create(tree, tctx, &io);
421 6 : CHECK_STATUS(status, NT_STATUS_OK);
422 6 : CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
423 :
424 6 : status = smb2_util_close(tree, io.out.file.handle);
425 6 : CHECK_STATUS(status, NT_STATUS_OK);
426 :
427 6 : torture_comment(tctx, "Testing timewarp\n");
428 6 : io.in.timewarp = 10000;
429 6 : status = smb2_create(tree, tctx, &io);
430 6 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
431 1 : io.in.timewarp = 0;
432 :
433 1 : torture_comment(tctx, "Testing query_on_disk\n");
434 1 : io.in.query_on_disk_id = true;
435 1 : status = smb2_create(tree, tctx, &io);
436 1 : CHECK_STATUS(status, NT_STATUS_OK);
437 :
438 1 : status = smb2_util_close(tree, io.out.file.handle);
439 1 : CHECK_STATUS(status, NT_STATUS_OK);
440 :
441 1 : torture_comment(tctx, "Testing unknown tag\n");
442 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
443 : "FooO", data_blob(NULL, 0));
444 1 : CHECK_STATUS(status, NT_STATUS_OK);
445 :
446 1 : status = smb2_create(tree, tctx, &io);
447 1 : CHECK_STATUS(status, NT_STATUS_OK);
448 :
449 1 : status = smb2_util_close(tree, io.out.file.handle);
450 1 : CHECK_STATUS(status, NT_STATUS_OK);
451 :
452 1 : torture_comment(tctx, "Testing bad tag length 0\n");
453 1 : ZERO_STRUCT(io.in.blobs);
454 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
455 : "x", data_blob(NULL, 0));
456 1 : CHECK_STATUS(status, NT_STATUS_OK);
457 1 : status = smb2_create(tree, tctx, &io);
458 1 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
459 :
460 1 : torture_comment(tctx, "Testing bad tag length 1\n");
461 1 : ZERO_STRUCT(io.in.blobs);
462 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
463 : "x", data_blob(NULL, 0));
464 1 : CHECK_STATUS(status, NT_STATUS_OK);
465 1 : status = smb2_create(tree, tctx, &io);
466 1 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
467 :
468 1 : torture_comment(tctx, "Testing bad tag length 2\n");
469 1 : ZERO_STRUCT(io.in.blobs);
470 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
471 : "xx", data_blob(NULL, 0));
472 1 : CHECK_STATUS(status, NT_STATUS_OK);
473 1 : status = smb2_create(tree, tctx, &io);
474 1 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
475 :
476 1 : torture_comment(tctx, "Testing bad tag length 3\n");
477 1 : ZERO_STRUCT(io.in.blobs);
478 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
479 : "xxx", data_blob(NULL, 0));
480 1 : CHECK_STATUS(status, NT_STATUS_OK);
481 1 : status = smb2_create(tree, tctx, &io);
482 1 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
483 :
484 1 : torture_comment(tctx, "Testing tag length 4\n");
485 1 : ZERO_STRUCT(io.in.blobs);
486 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
487 : "xxxx", data_blob(NULL, 0));
488 1 : CHECK_STATUS(status, NT_STATUS_OK);
489 1 : status = smb2_create(tree, tctx, &io);
490 1 : CHECK_STATUS(status, NT_STATUS_OK);
491 :
492 1 : torture_comment(tctx, "Testing tag length 5\n");
493 1 : ZERO_STRUCT(io.in.blobs);
494 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
495 : "xxxxx", data_blob(NULL, 0));
496 1 : CHECK_STATUS(status, NT_STATUS_OK);
497 1 : status = smb2_create(tree, tctx, &io);
498 1 : CHECK_STATUS(status, NT_STATUS_OK);
499 :
500 1 : torture_comment(tctx, "Testing tag length 6\n");
501 1 : ZERO_STRUCT(io.in.blobs);
502 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
503 : "xxxxxx", data_blob(NULL, 0));
504 1 : CHECK_STATUS(status, NT_STATUS_OK);
505 1 : status = smb2_create(tree, tctx, &io);
506 1 : CHECK_STATUS(status, NT_STATUS_OK);
507 :
508 1 : torture_comment(tctx, "Testing tag length 7\n");
509 1 : ZERO_STRUCT(io.in.blobs);
510 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
511 : "xxxxxxx", data_blob(NULL, 0));
512 1 : CHECK_STATUS(status, NT_STATUS_OK);
513 1 : status = smb2_create(tree, tctx, &io);
514 1 : CHECK_STATUS(status, NT_STATUS_OK);
515 :
516 1 : torture_comment(tctx, "Testing tag length 8\n");
517 1 : ZERO_STRUCT(io.in.blobs);
518 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
519 : "xxxxxxxx", data_blob(NULL, 0));
520 1 : CHECK_STATUS(status, NT_STATUS_OK);
521 1 : status = smb2_create(tree, tctx, &io);
522 1 : CHECK_STATUS(status, NT_STATUS_OK);
523 :
524 1 : torture_comment(tctx, "Testing tag length 16\n");
525 1 : ZERO_STRUCT(io.in.blobs);
526 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
527 : "xxxxxxxxxxxxxxxx", data_blob(NULL, 0));
528 1 : CHECK_STATUS(status, NT_STATUS_OK);
529 1 : status = smb2_create(tree, tctx, &io);
530 1 : CHECK_STATUS(status, NT_STATUS_OK);
531 :
532 1 : torture_comment(tctx, "Testing tag length 17\n");
533 1 : ZERO_STRUCT(io.in.blobs);
534 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
535 : "xxxxxxxxxxxxxxxxx", data_blob(NULL, 0));
536 1 : CHECK_STATUS(status, NT_STATUS_OK);
537 1 : status = smb2_create(tree, tctx, &io);
538 1 : CHECK_STATUS(status, NT_STATUS_OK);
539 :
540 1 : torture_comment(tctx, "Testing tag length 34\n");
541 1 : ZERO_STRUCT(io.in.blobs);
542 1 : status = smb2_create_blob_add(tctx, &io.in.blobs,
543 : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
544 : data_blob(NULL, 0));
545 1 : CHECK_STATUS(status, NT_STATUS_OK);
546 1 : status = smb2_create(tree, tctx, &io);
547 1 : CHECK_STATUS(status, NT_STATUS_OK);
548 :
549 1 : smb2_deltree(tree, FNAME);
550 :
551 1 : return true;
552 : }
553 :
554 : #define FAIL_UNLESS(__cond) \
555 : do { \
556 : if (__cond) {} else { \
557 : torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \
558 : __location__, #__cond); \
559 : ret = false; goto done; \
560 : } \
561 : } while(0)
562 :
563 : /*
564 : try creating with acls
565 : */
566 12 : static bool test_create_acl_ext(struct torture_context *tctx, struct smb2_tree *tree, bool test_dir)
567 : {
568 12 : bool ret = true;
569 0 : struct smb2_create io;
570 0 : NTSTATUS status;
571 0 : struct security_ace ace;
572 0 : struct security_descriptor *sd;
573 0 : struct dom_sid *test_sid;
574 12 : union smb_fileinfo q = {};
575 12 : uint32_t attrib =
576 : FILE_ATTRIBUTE_HIDDEN |
577 : FILE_ATTRIBUTE_SYSTEM |
578 : (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
579 12 : NTSTATUS (*delete_func)(struct smb2_tree *, const char *) =
580 12 : test_dir ? smb2_util_rmdir : smb2_util_unlink;
581 :
582 12 : ZERO_STRUCT(ace);
583 :
584 12 : smb2_deltree(tree, FNAME);
585 :
586 12 : ZERO_STRUCT(io);
587 12 : io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
588 12 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
589 12 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
590 12 : io.in.share_access =
591 : NTCREATEX_SHARE_ACCESS_DELETE |
592 : NTCREATEX_SHARE_ACCESS_READ |
593 : NTCREATEX_SHARE_ACCESS_WRITE;
594 12 : io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT | 0x00200000 |
595 : (test_dir ? NTCREATEX_OPTIONS_DIRECTORY :
596 : (NTCREATEX_OPTIONS_NON_DIRECTORY_FILE));
597 :
598 12 : io.in.fname = FNAME;
599 :
600 12 : torture_comment(tctx, "basic create\n");
601 :
602 12 : status = smb2_create(tree, tctx, &io);
603 12 : CHECK_STATUS(status, NT_STATUS_OK);
604 :
605 12 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
606 12 : q.query_secdesc.in.file.handle = io.out.file.handle;
607 12 : q.query_secdesc.in.secinfo_flags =
608 : SECINFO_OWNER |
609 : SECINFO_GROUP |
610 : SECINFO_DACL;
611 12 : status = smb2_getinfo_file(tree, tctx, &q);
612 12 : CHECK_STATUS(status, NT_STATUS_OK);
613 12 : sd = q.query_secdesc.out.sd;
614 :
615 12 : status = smb2_util_close(tree, io.out.file.handle);
616 12 : CHECK_STATUS(status, NT_STATUS_OK);
617 12 : status = delete_func(tree, FNAME);
618 12 : CHECK_STATUS(status, NT_STATUS_OK);
619 :
620 12 : torture_comment(tctx, "adding a new ACE\n");
621 12 : test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS);
622 :
623 12 : ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
624 12 : ace.flags = 0;
625 12 : ace.access_mask = SEC_STD_ALL;
626 12 : ace.trustee = *test_sid;
627 :
628 12 : status = security_descriptor_dacl_add(sd, &ace);
629 12 : CHECK_STATUS(status, NT_STATUS_OK);
630 :
631 12 : torture_comment(tctx, "creating a file with an initial ACL\n");
632 :
633 12 : io.in.sec_desc = sd;
634 12 : status = smb2_create(tree, tctx, &io);
635 12 : CHECK_STATUS(status, NT_STATUS_OK);
636 :
637 12 : FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
638 :
639 12 : status = smb2_util_close(tree, io.out.file.handle);
640 12 : CHECK_STATUS(status, NT_STATUS_OK);
641 12 : status = delete_func(tree, FNAME);
642 12 : CHECK_STATUS(status, NT_STATUS_OK);
643 :
644 12 : torture_comment(tctx, "creating with attributes\n");
645 :
646 12 : io.in.sec_desc = NULL;
647 12 : io.in.file_attributes = attrib;
648 12 : status = smb2_create(tree, tctx, &io);
649 12 : CHECK_STATUS(status, NT_STATUS_OK);
650 :
651 12 : FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
652 :
653 11 : status = smb2_util_close(tree, io.out.file.handle);
654 11 : CHECK_STATUS(status, NT_STATUS_OK);
655 11 : status = delete_func(tree, FNAME);
656 11 : CHECK_STATUS(status, NT_STATUS_OK);
657 :
658 11 : torture_comment(tctx, "creating with attributes and ACL\n");
659 :
660 11 : io.in.sec_desc = sd;
661 11 : io.in.file_attributes = attrib;
662 11 : status = smb2_create(tree, tctx, &io);
663 11 : CHECK_STATUS(status, NT_STATUS_OK);
664 :
665 11 : FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
666 11 : FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
667 :
668 11 : status = smb2_util_close(tree, io.out.file.handle);
669 11 : CHECK_STATUS(status, NT_STATUS_OK);
670 11 : status = delete_func(tree, FNAME);
671 11 : CHECK_STATUS(status, NT_STATUS_OK);
672 :
673 11 : torture_comment(tctx, "creating with attributes, ACL and owner\n");
674 11 : sd = security_descriptor_dacl_create(tctx,
675 : 0, SID_WORLD, SID_BUILTIN_USERS,
676 : SID_WORLD,
677 : SEC_ACE_TYPE_ACCESS_ALLOWED,
678 : SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
679 : 0,
680 : NULL);
681 :
682 11 : io.in.sec_desc = sd;
683 11 : io.in.file_attributes = attrib;
684 11 : status = smb2_create(tree, tctx, &io);
685 11 : CHECK_STATUS(status, NT_STATUS_OK);
686 :
687 11 : FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
688 11 : FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
689 :
690 12 : done:
691 12 : status = smb2_util_close(tree, io.out.file.handle);
692 12 : CHECK_STATUS(status, NT_STATUS_OK);
693 12 : status = delete_func(tree, FNAME);
694 12 : CHECK_STATUS(status, NT_STATUS_OK);
695 :
696 12 : return ret;
697 : }
698 :
699 : /*
700 : test SMB2 open
701 : */
702 6 : static bool test_smb2_open(struct torture_context *tctx,
703 : struct smb2_tree *tree)
704 : {
705 0 : union smb_open io;
706 0 : union smb_fileinfo finfo;
707 6 : const char *fname = DNAME "\\torture_ntcreatex.txt";
708 6 : const char *dname = DNAME "\\torture_ntcreatex.dir";
709 0 : NTSTATUS status;
710 6 : struct smb2_handle h = {{0}};
711 6 : struct smb2_handle h1 = {{0}};
712 6 : bool ret = true;
713 0 : size_t i;
714 0 : struct {
715 : uint32_t create_disp;
716 : bool with_file;
717 : NTSTATUS correct_status;
718 6 : } open_funcs[] = {
719 : { NTCREATEX_DISP_SUPERSEDE, true, NT_STATUS_OK },
720 : { NTCREATEX_DISP_SUPERSEDE, false, NT_STATUS_OK },
721 : { NTCREATEX_DISP_OPEN, true, NT_STATUS_OK },
722 : { NTCREATEX_DISP_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
723 : { NTCREATEX_DISP_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
724 : { NTCREATEX_DISP_CREATE, false, NT_STATUS_OK },
725 : { NTCREATEX_DISP_OPEN_IF, true, NT_STATUS_OK },
726 : { NTCREATEX_DISP_OPEN_IF, false, NT_STATUS_OK },
727 : { NTCREATEX_DISP_OVERWRITE, true, NT_STATUS_OK },
728 : { NTCREATEX_DISP_OVERWRITE, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
729 : { NTCREATEX_DISP_OVERWRITE_IF, true, NT_STATUS_OK },
730 : { NTCREATEX_DISP_OVERWRITE_IF, false, NT_STATUS_OK },
731 : { 6, true, NT_STATUS_INVALID_PARAMETER },
732 : { 6, false, NT_STATUS_INVALID_PARAMETER },
733 : };
734 :
735 6 : torture_comment(tctx, "Checking SMB2 Open\n");
736 :
737 6 : smb2_util_unlink(tree, fname);
738 6 : smb2_util_rmdir(tree, dname);
739 :
740 6 : status = torture_smb2_testdir(tree, DNAME, &h);
741 6 : CHECK_STATUS(status, NT_STATUS_OK);
742 :
743 6 : ZERO_STRUCT(io.smb2);
744 : /* reasonable default parameters */
745 6 : io.generic.level = RAW_OPEN_SMB2;
746 6 : io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
747 6 : io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
748 6 : io.smb2.in.alloc_size = 1024*1024;
749 6 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
750 6 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
751 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
752 6 : io.smb2.in.create_options = 0;
753 6 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
754 6 : io.smb2.in.security_flags = 0;
755 6 : io.smb2.in.fname = fname;
756 :
757 : /* test the create disposition */
758 90 : for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
759 84 : if (open_funcs[i].with_file) {
760 42 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
761 42 : status= smb2_create(tree, tctx, &(io.smb2));
762 42 : if (!NT_STATUS_IS_OK(status)) {
763 0 : torture_comment(tctx,
764 : "Failed to create file %s status %s %zu\n",
765 : fname, nt_errstr(status), i);
766 :
767 0 : ret = false;
768 0 : goto done;
769 : }
770 42 : smb2_util_close(tree, io.smb2.out.file.handle);
771 : }
772 84 : io.smb2.in.create_disposition = open_funcs[i].create_disp;
773 84 : status = smb2_create(tree, tctx, &(io.smb2));
774 84 : if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
775 0 : torture_comment(tctx,
776 : "(%s) incorrect status %s should be %s (i=%zu "
777 : "with_file=%d open_disp=%d)\n",
778 : __location__, nt_errstr(status),
779 : nt_errstr(open_funcs[i].correct_status),
780 0 : i, (int)open_funcs[i].with_file,
781 0 : (int)open_funcs[i].create_disp);
782 :
783 0 : ret = false;
784 0 : goto done;
785 : }
786 84 : if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
787 66 : smb2_util_close(tree, io.smb2.out.file.handle);
788 66 : smb2_util_unlink(tree, fname);
789 : }
790 : }
791 :
792 : /* basic field testing */
793 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
794 :
795 6 : status = smb2_create(tree, tctx, &(io.smb2));
796 6 : CHECK_STATUS(status, NT_STATUS_OK);
797 6 : h1 = io.smb2.out.file.handle;
798 :
799 6 : CHECK_VAL(io.smb2.out.oplock_level, 0);
800 6 : CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
801 6 : CHECK_NTTIME(io.smb2.out.create_time, create_time);
802 6 : CHECK_NTTIME(io.smb2.out.access_time, access_time);
803 6 : CHECK_NTTIME(io.smb2.out.write_time, write_time);
804 6 : CHECK_NTTIME(io.smb2.out.change_time, change_time);
805 6 : CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
806 6 : CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
807 6 : CHECK_ALL_INFO(io.smb2.out.size, size);
808 :
809 : /* check fields when the file already existed */
810 6 : smb2_util_close(tree, h1);
811 6 : smb2_util_unlink(tree, fname);
812 :
813 6 : status = smb2_create_complex_file(tctx, tree, fname, &h1);
814 6 : CHECK_STATUS(status, NT_STATUS_OK);
815 :
816 1 : smb2_util_close(tree, h1);
817 :
818 1 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
819 1 : status = smb2_create(tree, tctx, &(io.smb2));
820 1 : CHECK_STATUS(status, NT_STATUS_OK);
821 1 : h1 = io.smb2.out.file.handle;
822 :
823 1 : CHECK_VAL(io.smb2.out.oplock_level, 0);
824 1 : CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_EXISTED);
825 1 : CHECK_NTTIME(io.smb2.out.create_time, create_time);
826 1 : CHECK_NTTIME(io.smb2.out.access_time, access_time);
827 1 : CHECK_NTTIME(io.smb2.out.write_time, write_time);
828 1 : CHECK_NTTIME(io.smb2.out.change_time, change_time);
829 1 : CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
830 1 : CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
831 1 : CHECK_ALL_INFO(io.smb2.out.size, size);
832 1 : smb2_util_close(tree, h1);
833 1 : smb2_util_unlink(tree, fname);
834 :
835 : /* create a directory */
836 1 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
837 1 : io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
838 1 : io.smb2.in.alloc_size = 0;
839 1 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
840 1 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
841 1 : io.smb2.in.create_options = 0;
842 1 : io.smb2.in.fname = dname;
843 1 : fname = dname;
844 :
845 1 : smb2_util_rmdir(tree, fname);
846 1 : smb2_util_unlink(tree, fname);
847 :
848 1 : io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
849 1 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
850 1 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
851 1 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
852 : NTCREATEX_SHARE_ACCESS_WRITE;
853 1 : status = smb2_create(tree, tctx, &(io.smb2));
854 1 : CHECK_STATUS(status, NT_STATUS_OK);
855 1 : h1 = io.smb2.out.file.handle;
856 :
857 1 : CHECK_VAL(io.smb2.out.oplock_level, 0);
858 1 : CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
859 1 : CHECK_NTTIME(io.smb2.out.create_time, create_time);
860 1 : CHECK_NTTIME(io.smb2.out.access_time, access_time);
861 1 : CHECK_NTTIME(io.smb2.out.write_time, write_time);
862 1 : CHECK_NTTIME(io.smb2.out.change_time, change_time);
863 1 : CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
864 1 : CHECK_VAL(io.smb2.out.file_attr & ~FILE_ATTRIBUTE_NONINDEXED,
865 : FILE_ATTRIBUTE_DIRECTORY);
866 1 : CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
867 1 : CHECK_ALL_INFO(io.smb2.out.size, size);
868 1 : CHECK_VAL(io.smb2.out.size, 0);
869 1 : smb2_util_unlink(tree, fname);
870 :
871 1 : done:
872 1 : smb2_util_close(tree, h1);
873 1 : smb2_util_unlink(tree, fname);
874 1 : smb2_deltree(tree, DNAME);
875 1 : return ret;
876 : }
877 :
878 : /*
879 : test with an already opened and byte range locked file
880 : */
881 :
882 6 : static bool test_smb2_open_brlocked(struct torture_context *tctx,
883 : struct smb2_tree *tree)
884 : {
885 0 : union smb_open io, io1;
886 0 : union smb_lock io2;
887 0 : struct smb2_lock_element lock[1];
888 6 : const char *fname = DNAME "\\torture_ntcreatex.txt";
889 0 : NTSTATUS status;
890 6 : bool ret = true;
891 0 : struct smb2_handle h;
892 6 : char b = 42;
893 :
894 6 : torture_comment(tctx,
895 : "Testing SMB2 open with a byte range locked file\n");
896 :
897 6 : smb2_util_unlink(tree, fname);
898 :
899 6 : status = torture_smb2_testdir(tree, DNAME, &h);
900 6 : CHECK_STATUS(status, NT_STATUS_OK);
901 :
902 6 : ZERO_STRUCT(io.smb2);
903 6 : io.generic.level = RAW_OPEN_SMB2;
904 6 : io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
905 6 : io.smb2.in.desired_access = 0x2019f;
906 6 : io.smb2.in.alloc_size = 0;
907 6 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
908 6 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
909 : NTCREATEX_SHARE_ACCESS_WRITE;
910 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
911 6 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
912 6 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
913 6 : io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
914 6 : io.smb2.in.fname = fname;
915 :
916 6 : status = smb2_create(tree, tctx, &(io.smb2));
917 6 : CHECK_STATUS(status, NT_STATUS_OK);
918 :
919 6 : status = smb2_util_write(tree, io.smb2.out.file.handle, &b, 0, 1);
920 6 : CHECK_STATUS(status, NT_STATUS_OK);
921 :
922 6 : ZERO_STRUCT(io2.smb2);
923 6 : io2.smb2.level = RAW_LOCK_SMB2;
924 6 : io2.smb2.in.file.handle = io.smb2.out.file.handle;
925 6 : io2.smb2.in.lock_count = 1;
926 :
927 6 : ZERO_STRUCT(lock);
928 6 : lock[0].offset = 0;
929 6 : lock[0].length = 1;
930 6 : lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
931 : SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
932 6 : io2.smb2.in.locks = &lock[0];
933 6 : status = smb2_lock(tree, &(io2.smb2));
934 6 : CHECK_STATUS(status, NT_STATUS_OK);
935 :
936 6 : ZERO_STRUCT(io1.smb2);
937 6 : io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
938 6 : io1.smb2.in.desired_access = 0x20196;
939 6 : io1.smb2.in.alloc_size = 0;
940 6 : io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
941 6 : io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
942 : NTCREATEX_SHARE_ACCESS_WRITE;
943 6 : io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
944 6 : io1.smb2.in.create_options = 0;
945 6 : io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
946 6 : io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
947 6 : io1.smb2.in.fname = fname;
948 :
949 6 : status = smb2_create(tree, tctx, &(io1.smb2));
950 6 : CHECK_STATUS(status, NT_STATUS_OK);
951 :
952 6 : smb2_util_close(tree, io.smb2.out.file.handle);
953 6 : smb2_util_close(tree, io1.smb2.out.file.handle);
954 6 : smb2_util_unlink(tree, fname);
955 6 : smb2_deltree(tree, DNAME);
956 :
957 6 : return ret;
958 : }
959 :
960 : /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
961 :
962 6 : static bool test_smb2_open_multi(struct torture_context *tctx,
963 : struct smb2_tree *tree)
964 : {
965 6 : const char *fname = "test_oplock.dat";
966 0 : NTSTATUS status;
967 6 : bool ret = true;
968 0 : union smb_open io;
969 0 : struct smb2_tree **trees;
970 0 : struct smb2_request **requests;
971 0 : union smb_open *ios;
972 6 : int i, num_files = 3;
973 6 : int num_ok = 0;
974 6 : int num_collision = 0;
975 :
976 6 : torture_comment(tctx,
977 : "Testing SMB2 Open with multiple connections\n");
978 6 : trees = talloc_array(tctx, struct smb2_tree *, num_files);
979 6 : requests = talloc_array(tctx, struct smb2_request *, num_files);
980 6 : ios = talloc_array(tctx, union smb_open, num_files);
981 6 : if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
982 : (ios == NULL)) {
983 0 : torture_comment(tctx, ("talloc failed\n"));
984 0 : ret = false;
985 0 : goto done;
986 : }
987 :
988 6 : tree->session->transport->options.request_timeout = 60;
989 :
990 24 : for (i=0; i<num_files; i++) {
991 18 : if (!torture_smb2_connection(tctx, &(trees[i]))) {
992 0 : torture_comment(tctx,
993 : "Could not open %d'th connection\n", i);
994 0 : ret = false;
995 0 : goto done;
996 : }
997 18 : trees[i]->session->transport->options.request_timeout = 60;
998 : }
999 :
1000 : /* cleanup */
1001 6 : smb2_util_unlink(tree, fname);
1002 :
1003 : /*
1004 : base ntcreatex parms
1005 : */
1006 6 : ZERO_STRUCT(io.smb2);
1007 6 : io.generic.level = RAW_OPEN_SMB2;
1008 6 : io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1009 6 : io.smb2.in.alloc_size = 0;
1010 6 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1011 6 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1012 : NTCREATEX_SHARE_ACCESS_WRITE|
1013 : NTCREATEX_SHARE_ACCESS_DELETE;
1014 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1015 6 : io.smb2.in.create_options = 0;
1016 6 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1017 6 : io.smb2.in.security_flags = 0;
1018 6 : io.smb2.in.fname = fname;
1019 6 : io.smb2.in.create_flags = 0;
1020 :
1021 24 : for (i=0; i<num_files; i++) {
1022 18 : ios[i] = io;
1023 18 : requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
1024 18 : if (requests[i] == NULL) {
1025 0 : torture_comment(tctx,
1026 : "could not send %d'th request\n", i);
1027 0 : ret = false;
1028 0 : goto done;
1029 : }
1030 : }
1031 :
1032 6 : torture_comment(tctx, "waiting for replies\n");
1033 72 : while (1) {
1034 78 : bool unreplied = false;
1035 114 : for (i=0; i<num_files; i++) {
1036 108 : if (requests[i] == NULL) {
1037 18 : continue;
1038 : }
1039 90 : if (requests[i]->state < SMB2_REQUEST_DONE) {
1040 72 : unreplied = true;
1041 72 : break;
1042 : }
1043 18 : status = smb2_create_recv(requests[i], tctx,
1044 18 : &(ios[i].smb2));
1045 :
1046 18 : torture_comment(tctx,
1047 : "File %d returned status %s\n", i,
1048 : nt_errstr(status));
1049 :
1050 18 : if (NT_STATUS_IS_OK(status)) {
1051 6 : num_ok += 1;
1052 : }
1053 :
1054 18 : if (NT_STATUS_EQUAL(status,
1055 : NT_STATUS_OBJECT_NAME_COLLISION)) {
1056 12 : num_collision += 1;
1057 : }
1058 :
1059 18 : requests[i] = NULL;
1060 : }
1061 78 : if (!unreplied) {
1062 6 : break;
1063 : }
1064 :
1065 72 : if (tevent_loop_once(tctx->ev) != 0) {
1066 0 : torture_comment(tctx, "tevent_loop_once failed\n");
1067 0 : ret = false;
1068 0 : goto done;
1069 : }
1070 : }
1071 :
1072 6 : if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1073 0 : ret = false;
1074 : }
1075 6 : done:
1076 6 : smb2_deltree(tree, fname);
1077 :
1078 6 : return ret;
1079 : }
1080 :
1081 : /*
1082 : test opening for delete on a read-only attribute file.
1083 : */
1084 :
1085 6 : static bool test_smb2_open_for_delete(struct torture_context *tctx,
1086 : struct smb2_tree *tree)
1087 : {
1088 0 : union smb_open io;
1089 0 : union smb_fileinfo finfo;
1090 6 : const char *fname = DNAME "\\torture_open_for_delete.txt";
1091 0 : NTSTATUS status;
1092 0 : struct smb2_handle h, h1;
1093 6 : bool ret = true;
1094 :
1095 6 : torture_comment(tctx,
1096 : "Checking SMB2_OPEN for delete on a readonly file.\n");
1097 6 : smb2_util_unlink(tree, fname);
1098 6 : smb2_deltree(tree, fname);
1099 :
1100 6 : status = torture_smb2_testdir(tree, DNAME, &h);
1101 6 : CHECK_STATUS(status, NT_STATUS_OK);
1102 :
1103 : /* reasonable default parameters */
1104 6 : ZERO_STRUCT(io.smb2);
1105 6 : io.generic.level = RAW_OPEN_SMB2;
1106 6 : io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1107 6 : io.smb2.in.alloc_size = 0;
1108 6 : io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1109 6 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY;
1110 6 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1111 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1112 6 : io.smb2.in.create_options = 0;
1113 6 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1114 6 : io.smb2.in.security_flags = 0;
1115 6 : io.smb2.in.fname = fname;
1116 :
1117 : /* Create the readonly file. */
1118 :
1119 6 : status = smb2_create(tree, tctx, &(io.smb2));
1120 6 : CHECK_STATUS(status, NT_STATUS_OK);
1121 6 : h1 = io.smb2.out.file.handle;
1122 :
1123 6 : CHECK_VAL(io.smb2.out.oplock_level, 0);
1124 6 : io.smb2.in.create_options = 0;
1125 6 : CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
1126 6 : CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
1127 6 : smb2_util_close(tree, h1);
1128 :
1129 : /* Now try and open for delete only - should succeed. */
1130 6 : io.smb2.in.desired_access = SEC_STD_DELETE;
1131 6 : io.smb2.in.file_attributes = 0;
1132 6 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1133 : NTCREATEX_SHARE_ACCESS_WRITE |
1134 : NTCREATEX_SHARE_ACCESS_DELETE;
1135 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1136 6 : status = smb2_create(tree, tctx, &(io.smb2));
1137 6 : CHECK_STATUS(status, NT_STATUS_OK);
1138 6 : smb2_util_close(tree, io.smb2.out.file.handle);
1139 :
1140 : /* Clear readonly flag to allow file deletion */
1141 6 : io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1142 : SEC_FILE_WRITE_ATTRIBUTE;
1143 6 : status = smb2_create(tree, tctx, &(io.smb2));
1144 6 : CHECK_STATUS(status, NT_STATUS_OK);
1145 6 : h1 = io.smb2.out.file.handle;
1146 6 : SET_ATTRIB(FILE_ATTRIBUTE_ARCHIVE);
1147 6 : smb2_util_close(tree, h1);
1148 :
1149 6 : smb2_util_close(tree, h);
1150 6 : smb2_util_unlink(tree, fname);
1151 6 : smb2_deltree(tree, DNAME);
1152 :
1153 6 : return ret;
1154 : }
1155 :
1156 : /*
1157 : test SMB2 open with a leading slash on the path.
1158 : Trying to create a directory with a leading slash
1159 : should give NT_STATUS_INVALID_PARAMETER error
1160 : */
1161 6 : static bool test_smb2_leading_slash(struct torture_context *tctx,
1162 : struct smb2_tree *tree)
1163 : {
1164 0 : union smb_open io;
1165 6 : const char *dnameslash = "\\"DNAME;
1166 0 : NTSTATUS status;
1167 6 : bool ret = true;
1168 :
1169 6 : torture_comment(tctx,
1170 : "Trying to create a directory with leading slash on path\n");
1171 6 : smb2_deltree(tree, dnameslash);
1172 :
1173 6 : ZERO_STRUCT(io.smb2);
1174 6 : io.generic.level = RAW_OPEN_SMB2;
1175 6 : io.smb2.in.oplock_level = 0;
1176 6 : io.smb2.in.desired_access = SEC_RIGHTS_DIR_ALL;
1177 6 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1178 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1179 6 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1180 : NTCREATEX_SHARE_ACCESS_WRITE |
1181 : NTCREATEX_SHARE_ACCESS_DELETE;
1182 6 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1183 6 : io.smb2.in.fname = dnameslash;
1184 :
1185 6 : status = smb2_create(tree, tree, &(io.smb2));
1186 6 : CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1187 :
1188 6 : smb2_deltree(tree, dnameslash);
1189 6 : return ret;
1190 : }
1191 :
1192 : /*
1193 : test SMB2 open with an invalid impersonation level.
1194 : Should give NT_STATUS_BAD_IMPERSONATION_LEVEL error
1195 : */
1196 6 : static bool test_smb2_impersonation_level(struct torture_context *tctx,
1197 : struct smb2_tree *tree)
1198 : {
1199 0 : union smb_open io;
1200 6 : const char *fname = DNAME "\\torture_invalid_impersonation_level.txt";
1201 0 : NTSTATUS status;
1202 0 : struct smb2_handle h;
1203 6 : bool ret = true;
1204 :
1205 6 : torture_comment(tctx,
1206 : "Testing SMB2 open with an invalid impersonation level.\n");
1207 :
1208 6 : smb2_util_unlink(tree, fname);
1209 6 : smb2_util_rmdir(tree, DNAME);
1210 :
1211 6 : status = torture_smb2_testdir(tree, DNAME, &h);
1212 6 : CHECK_STATUS(status, NT_STATUS_OK);
1213 :
1214 6 : ZERO_STRUCT(io.smb2);
1215 6 : io.generic.level = RAW_OPEN_SMB2;
1216 6 : io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1217 6 : io.smb2.in.alloc_size = 0;
1218 6 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1219 6 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1220 : NTCREATEX_SHARE_ACCESS_WRITE|
1221 : NTCREATEX_SHARE_ACCESS_DELETE;
1222 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1223 6 : io.smb2.in.create_options = 0;
1224 6 : io.smb2.in.impersonation_level = 0x12345678;
1225 6 : io.smb2.in.security_flags = 0;
1226 6 : io.smb2.in.fname = fname;
1227 6 : io.smb2.in.create_flags = 0;
1228 :
1229 6 : status = smb2_create(tree, tree, &(io.smb2));
1230 6 : CHECK_STATUS(status, NT_STATUS_BAD_IMPERSONATION_LEVEL);
1231 :
1232 5 : smb2_util_close(tree, h);
1233 5 : smb2_util_unlink(tree, fname);
1234 5 : smb2_deltree(tree, DNAME);
1235 5 : return ret;
1236 : }
1237 :
1238 6 : static bool test_create_acl_file(struct torture_context *tctx,
1239 : struct smb2_tree *tree)
1240 : {
1241 6 : torture_comment(tctx, "Testing nttrans create with sec_desc on files\n");
1242 :
1243 6 : return test_create_acl_ext(tctx, tree, false);
1244 : }
1245 :
1246 6 : static bool test_create_acl_dir(struct torture_context *tctx,
1247 : struct smb2_tree *tree)
1248 : {
1249 6 : torture_comment(tctx, "Testing nttrans create with sec_desc on directories\n");
1250 :
1251 6 : return test_create_acl_ext(tctx, tree, true);
1252 : }
1253 :
1254 : #define CHECK_ACCESS_FLAGS(_fh, flags) do { \
1255 : union smb_fileinfo _q; \
1256 : _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
1257 : _q.access_information.in.file.handle = (_fh); \
1258 : status = smb2_getinfo_file(tree, tctx, &_q); \
1259 : CHECK_STATUS(status, NT_STATUS_OK); \
1260 : if (_q.access_information.out.access_flags != (flags)) { \
1261 : torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
1262 : __location__, _q.access_information.out.access_flags, (flags)); \
1263 : ret = false; \
1264 : goto done; \
1265 : } \
1266 : } while (0)
1267 :
1268 : /*
1269 : * Test creating a file with a NULL DACL.
1270 : */
1271 6 : static bool test_create_null_dacl(struct torture_context *tctx,
1272 : struct smb2_tree *tree)
1273 : {
1274 0 : NTSTATUS status;
1275 0 : struct smb2_create io;
1276 6 : const char *fname = "nulldacl.txt";
1277 6 : bool ret = true;
1278 0 : struct smb2_handle handle;
1279 0 : union smb_fileinfo q;
1280 0 : union smb_setfileinfo s;
1281 6 : struct security_descriptor *sd = security_descriptor_initialise(tctx);
1282 0 : struct security_acl dacl;
1283 :
1284 6 : torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n");
1285 :
1286 6 : smb2_util_unlink(tree, fname);
1287 :
1288 6 : ZERO_STRUCT(io);
1289 6 : io.level = RAW_OPEN_SMB2;
1290 6 : io.in.create_flags = 0;
1291 6 : io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC
1292 : | SEC_STD_WRITE_OWNER;
1293 6 : io.in.create_options = 0;
1294 6 : io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1295 6 : io.in.share_access =
1296 : NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1297 6 : io.in.alloc_size = 0;
1298 6 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1299 6 : io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
1300 6 : io.in.security_flags = 0;
1301 6 : io.in.fname = fname;
1302 6 : io.in.sec_desc = sd;
1303 : /* XXX create_options ? */
1304 6 : io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
1305 : NTCREATEX_OPTIONS_ASYNC_ALERT |
1306 : NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
1307 : 0x00200000;
1308 :
1309 6 : torture_comment(tctx, "creating a file with a empty sd\n");
1310 6 : status = smb2_create(tree, tctx, &io);
1311 6 : CHECK_STATUS(status, NT_STATUS_OK);
1312 6 : handle = io.out.file.handle;
1313 :
1314 6 : torture_comment(tctx, "get the original sd\n");
1315 6 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1316 6 : q.query_secdesc.in.file.handle = handle;
1317 6 : q.query_secdesc.in.secinfo_flags =
1318 : SECINFO_OWNER |
1319 : SECINFO_GROUP |
1320 : SECINFO_DACL;
1321 6 : status = smb2_getinfo_file(tree, tctx, &q);
1322 6 : CHECK_STATUS(status, NT_STATUS_OK);
1323 :
1324 : /*
1325 : * Testing the created DACL,
1326 : * the server should add the inherited DACL
1327 : * when SEC_DESC_DACL_PRESENT isn't specified
1328 : */
1329 6 : if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
1330 0 : ret = false;
1331 0 : torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
1332 : }
1333 6 : if (q.query_secdesc.out.sd->dacl == NULL) {
1334 0 : ret = false;
1335 0 : torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
1336 : }
1337 :
1338 6 : torture_comment(tctx, "set NULL DACL\n");
1339 6 : sd->type |= SEC_DESC_DACL_PRESENT;
1340 :
1341 6 : s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1342 6 : s.set_secdesc.in.file.handle = handle;
1343 6 : s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1344 6 : s.set_secdesc.in.sd = sd;
1345 6 : status = smb2_setinfo_file(tree, &s);
1346 6 : CHECK_STATUS(status, NT_STATUS_OK);
1347 :
1348 6 : torture_comment(tctx, "get the sd\n");
1349 6 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1350 6 : q.query_secdesc.in.file.handle = handle;
1351 6 : q.query_secdesc.in.secinfo_flags =
1352 : SECINFO_OWNER |
1353 : SECINFO_GROUP |
1354 : SECINFO_DACL;
1355 6 : status = smb2_getinfo_file(tree, tctx, &q);
1356 6 : CHECK_STATUS(status, NT_STATUS_OK);
1357 :
1358 : /* Testing the modified DACL */
1359 6 : if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
1360 0 : ret = false;
1361 0 : torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
1362 : }
1363 6 : if (q.query_secdesc.out.sd->dacl != NULL) {
1364 0 : ret = false;
1365 0 : torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
1366 : }
1367 :
1368 6 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1369 :
1370 6 : torture_comment(tctx, "try open for read control\n");
1371 6 : io.in.desired_access = SEC_STD_READ_CONTROL;
1372 6 : status = smb2_create(tree, tctx, &io);
1373 6 : CHECK_STATUS(status, NT_STATUS_OK);
1374 6 : CHECK_ACCESS_FLAGS(io.out.file.handle,
1375 : SEC_STD_READ_CONTROL);
1376 6 : smb2_util_close(tree, io.out.file.handle);
1377 :
1378 6 : torture_comment(tctx, "try open for write\n");
1379 6 : io.in.desired_access = SEC_FILE_WRITE_DATA;
1380 6 : status = smb2_create(tree, tctx, &io);
1381 6 : CHECK_STATUS(status, NT_STATUS_OK);
1382 6 : CHECK_ACCESS_FLAGS(io.out.file.handle,
1383 : SEC_FILE_WRITE_DATA);
1384 6 : smb2_util_close(tree, io.out.file.handle);
1385 :
1386 6 : torture_comment(tctx, "try open for read\n");
1387 6 : io.in.desired_access = SEC_FILE_READ_DATA;
1388 6 : status = smb2_create(tree, tctx, &io);
1389 6 : CHECK_STATUS(status, NT_STATUS_OK);
1390 6 : CHECK_ACCESS_FLAGS(io.out.file.handle,
1391 : SEC_FILE_READ_DATA);
1392 6 : smb2_util_close(tree, io.out.file.handle);
1393 :
1394 6 : torture_comment(tctx, "try open for generic write\n");
1395 6 : io.in.desired_access = SEC_GENERIC_WRITE;
1396 6 : status = smb2_create(tree, tctx, &io);
1397 6 : CHECK_STATUS(status, NT_STATUS_OK);
1398 6 : CHECK_ACCESS_FLAGS(io.out.file.handle,
1399 : SEC_RIGHTS_FILE_WRITE);
1400 6 : smb2_util_close(tree, io.out.file.handle);
1401 :
1402 6 : torture_comment(tctx, "try open for generic read\n");
1403 6 : io.in.desired_access = SEC_GENERIC_READ;
1404 6 : status = smb2_create(tree, tctx, &io);
1405 6 : CHECK_STATUS(status, NT_STATUS_OK);
1406 6 : CHECK_ACCESS_FLAGS(io.out.file.handle,
1407 : SEC_RIGHTS_FILE_READ);
1408 6 : smb2_util_close(tree, io.out.file.handle);
1409 :
1410 6 : torture_comment(tctx, "set DACL with 0 aces\n");
1411 6 : ZERO_STRUCT(dacl);
1412 6 : dacl.revision = SECURITY_ACL_REVISION_NT4;
1413 6 : dacl.num_aces = 0;
1414 6 : sd->dacl = &dacl;
1415 :
1416 6 : s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1417 6 : s.set_secdesc.in.file.handle = handle;
1418 6 : s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1419 6 : s.set_secdesc.in.sd = sd;
1420 6 : status = smb2_setinfo_file(tree, &s);
1421 6 : CHECK_STATUS(status, NT_STATUS_OK);
1422 :
1423 6 : torture_comment(tctx, "get the sd\n");
1424 6 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1425 6 : q.query_secdesc.in.file.handle = handle;
1426 6 : q.query_secdesc.in.secinfo_flags =
1427 : SECINFO_OWNER |
1428 : SECINFO_GROUP |
1429 : SECINFO_DACL;
1430 6 : status = smb2_getinfo_file(tree, tctx, &q);
1431 6 : CHECK_STATUS(status, NT_STATUS_OK);
1432 :
1433 : /* Testing the modified DACL */
1434 6 : if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
1435 0 : ret = false;
1436 0 : torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
1437 : }
1438 6 : if (q.query_secdesc.out.sd->dacl == NULL) {
1439 0 : ret = false;
1440 0 : torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
1441 : }
1442 6 : if (q.query_secdesc.out.sd->dacl->num_aces != 0) {
1443 0 : torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n",
1444 0 : q.query_secdesc.out.sd->dacl->num_aces);
1445 0 : ret = false;
1446 0 : goto done;
1447 : }
1448 :
1449 6 : torture_comment(tctx, "try open for read control\n");
1450 6 : io.in.desired_access = SEC_STD_READ_CONTROL;
1451 6 : status = smb2_create(tree, tctx, &io);
1452 6 : CHECK_STATUS(status, NT_STATUS_OK);
1453 6 : CHECK_ACCESS_FLAGS(io.out.file.handle,
1454 : SEC_STD_READ_CONTROL);
1455 6 : smb2_util_close(tree, io.out.file.handle);
1456 :
1457 6 : torture_comment(tctx, "try open for write => access_denied\n");
1458 6 : io.in.desired_access = SEC_FILE_WRITE_DATA;
1459 6 : status = smb2_create(tree, tctx, &io);
1460 6 : if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1461 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1462 : } else {
1463 6 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1464 : }
1465 :
1466 6 : torture_comment(tctx, "try open for read => access_denied\n");
1467 6 : io.in.desired_access = SEC_FILE_READ_DATA;
1468 6 : status = smb2_create(tree, tctx, &io);
1469 6 : if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1470 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1471 : } else {
1472 6 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1473 : }
1474 :
1475 6 : torture_comment(tctx, "try open for generic write => access_denied\n");
1476 6 : io.in.desired_access = SEC_GENERIC_WRITE;
1477 6 : status = smb2_create(tree, tctx, &io);
1478 6 : if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1479 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1480 : } else {
1481 6 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1482 : }
1483 :
1484 6 : torture_comment(tctx, "try open for generic read => access_denied\n");
1485 6 : io.in.desired_access = SEC_GENERIC_READ;
1486 6 : status = smb2_create(tree, tctx, &io);
1487 6 : if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1488 0 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1489 : } else {
1490 6 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1491 : }
1492 :
1493 6 : torture_comment(tctx, "set empty sd\n");
1494 6 : sd->type &= ~SEC_DESC_DACL_PRESENT;
1495 6 : sd->dacl = NULL;
1496 :
1497 6 : s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1498 6 : s.set_secdesc.in.file.handle = handle;
1499 6 : s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1500 6 : s.set_secdesc.in.sd = sd;
1501 6 : status = smb2_setinfo_file(tree, &s);
1502 6 : CHECK_STATUS(status, NT_STATUS_OK);
1503 :
1504 6 : torture_comment(tctx, "get the sd\n");
1505 6 : q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1506 6 : q.query_secdesc.in.file.handle = handle;
1507 6 : q.query_secdesc.in.secinfo_flags =
1508 : SECINFO_OWNER |
1509 : SECINFO_GROUP |
1510 : SECINFO_DACL;
1511 6 : status = smb2_getinfo_file(tree, tctx, &q);
1512 6 : CHECK_STATUS(status, NT_STATUS_OK);
1513 :
1514 : /* Testing the modified DACL */
1515 6 : if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
1516 0 : ret = false;
1517 0 : torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
1518 : }
1519 6 : if (q.query_secdesc.out.sd->dacl != NULL) {
1520 0 : ret = false;
1521 0 : torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
1522 : }
1523 6 : done:
1524 6 : smb2_util_close(tree, handle);
1525 6 : smb2_util_unlink(tree, fname);
1526 6 : smb2_tdis(tree);
1527 6 : smb2_logoff(tree->session);
1528 6 : return ret;
1529 : }
1530 :
1531 : /*
1532 : test SMB2 mkdir with OPEN_IF on the same name twice.
1533 : Must use 2 connections to hit the race.
1534 : */
1535 :
1536 6 : static bool test_mkdir_dup(struct torture_context *tctx,
1537 : struct smb2_tree *tree)
1538 : {
1539 6 : const char *fname = "mkdir_dup";
1540 0 : NTSTATUS status;
1541 6 : bool ret = true;
1542 0 : union smb_open io;
1543 0 : struct smb2_tree **trees;
1544 0 : struct smb2_request **requests;
1545 0 : union smb_open *ios;
1546 6 : int i, num_files = 2;
1547 6 : int num_ok = 0;
1548 6 : int num_created = 0;
1549 6 : int num_existed = 0;
1550 :
1551 6 : torture_comment(tctx,
1552 : "Testing SMB2 Create Directory with multiple connections\n");
1553 6 : trees = talloc_array(tctx, struct smb2_tree *, num_files);
1554 6 : requests = talloc_array(tctx, struct smb2_request *, num_files);
1555 6 : ios = talloc_array(tctx, union smb_open, num_files);
1556 6 : if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
1557 : (ios == NULL)) {
1558 0 : torture_fail(tctx, ("talloc failed\n"));
1559 : ret = false;
1560 : goto done;
1561 : }
1562 :
1563 6 : tree->session->transport->options.request_timeout = 60;
1564 :
1565 18 : for (i=0; i<num_files; i++) {
1566 12 : if (!torture_smb2_connection(tctx, &(trees[i]))) {
1567 0 : torture_fail(tctx,
1568 : talloc_asprintf(tctx,
1569 : "Could not open %d'th connection\n", i));
1570 : ret = false;
1571 : goto done;
1572 : }
1573 12 : trees[i]->session->transport->options.request_timeout = 60;
1574 : }
1575 :
1576 : /* cleanup */
1577 6 : smb2_util_unlink(tree, fname);
1578 6 : smb2_util_rmdir(tree, fname);
1579 :
1580 : /*
1581 : base ntcreatex parms
1582 : */
1583 6 : ZERO_STRUCT(io.smb2);
1584 6 : io.generic.level = RAW_OPEN_SMB2;
1585 6 : io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1586 6 : io.smb2.in.alloc_size = 0;
1587 6 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1588 6 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1589 : NTCREATEX_SHARE_ACCESS_WRITE|
1590 : NTCREATEX_SHARE_ACCESS_DELETE;
1591 6 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1592 6 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1593 6 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1594 6 : io.smb2.in.security_flags = 0;
1595 6 : io.smb2.in.fname = fname;
1596 6 : io.smb2.in.create_flags = 0;
1597 :
1598 18 : for (i=0; i<num_files; i++) {
1599 12 : ios[i] = io;
1600 12 : requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
1601 12 : if (requests[i] == NULL) {
1602 0 : torture_fail(tctx,
1603 : talloc_asprintf(tctx,
1604 : "could not send %d'th request\n", i));
1605 : ret = false;
1606 : goto done;
1607 : }
1608 : }
1609 :
1610 6 : torture_comment(tctx, "waiting for replies\n");
1611 48 : while (1) {
1612 54 : bool unreplied = false;
1613 74 : for (i=0; i<num_files; i++) {
1614 68 : if (requests[i] == NULL) {
1615 8 : continue;
1616 : }
1617 60 : if (requests[i]->state < SMB2_REQUEST_DONE) {
1618 48 : unreplied = true;
1619 48 : break;
1620 : }
1621 12 : status = smb2_create_recv(requests[i], tctx,
1622 12 : &(ios[i].smb2));
1623 :
1624 12 : if (NT_STATUS_IS_OK(status)) {
1625 12 : num_ok += 1;
1626 :
1627 12 : if (ios[i].smb2.out.create_action ==
1628 : NTCREATEX_ACTION_CREATED) {
1629 6 : num_created++;
1630 : }
1631 12 : if (ios[i].smb2.out.create_action ==
1632 : NTCREATEX_ACTION_EXISTED) {
1633 6 : num_existed++;
1634 : }
1635 : } else {
1636 0 : torture_fail(tctx,
1637 : talloc_asprintf(tctx,
1638 : "File %d returned status %s\n", i,
1639 : nt_errstr(status)));
1640 : }
1641 :
1642 :
1643 12 : requests[i] = NULL;
1644 : }
1645 54 : if (!unreplied) {
1646 6 : break;
1647 : }
1648 :
1649 48 : if (tevent_loop_once(tctx->ev) != 0) {
1650 0 : torture_fail(tctx, "tevent_loop_once failed\n");
1651 : ret = false;
1652 : goto done;
1653 : }
1654 : }
1655 :
1656 6 : if (num_ok != 2) {
1657 0 : torture_fail(tctx,
1658 : talloc_asprintf(tctx,
1659 : "num_ok == %d\n", num_ok));
1660 : ret = false;
1661 : }
1662 6 : if (num_created != 1) {
1663 0 : torture_fail(tctx,
1664 : talloc_asprintf(tctx,
1665 : "num_created == %d\n", num_created));
1666 : ret = false;
1667 : }
1668 6 : if (num_existed != 1) {
1669 0 : torture_fail(tctx,
1670 : talloc_asprintf(tctx,
1671 : "num_existed == %d\n", num_existed));
1672 : ret = false;
1673 : }
1674 6 : done:
1675 6 : smb2_deltree(tree, fname);
1676 :
1677 6 : return ret;
1678 : }
1679 :
1680 : /*
1681 : test directory creation with an initial allocation size > 0
1682 : */
1683 6 : static bool test_dir_alloc_size(struct torture_context *tctx,
1684 : struct smb2_tree *tree)
1685 : {
1686 6 : bool ret = true;
1687 6 : const char *dname = DNAME "\\torture_alloc_size.dir";
1688 0 : NTSTATUS status;
1689 0 : struct smb2_create c;
1690 6 : struct smb2_handle h1 = {{0}}, h2;
1691 :
1692 6 : torture_comment(tctx, "Checking initial allocation size on directories\n");
1693 :
1694 6 : smb2_deltree(tree, dname);
1695 :
1696 6 : status = torture_smb2_testdir(tree, DNAME, &h1);
1697 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
1698 :
1699 6 : ZERO_STRUCT(c);
1700 6 : c.in.create_disposition = NTCREATEX_DISP_CREATE;
1701 6 : c.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1702 6 : c.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1703 6 : c.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1704 6 : c.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1705 6 : c.in.fname = dname;
1706 : /*
1707 : * An insanely large value so we can check the value is
1708 : * ignored: Samba either returns 0 (current behaviour), or,
1709 : * once vfswrap_get_alloc_size() is fixed to allow retrieving
1710 : * the allocated size for directories, returns
1711 : * smb_roundup(..., stat.st_size) which would be 1 MB by
1712 : * default.
1713 : *
1714 : * Windows returns 0 for empty directories, once directories
1715 : * have a few entries it starts replying with values > 0.
1716 : */
1717 6 : c.in.alloc_size = 1024*1024*1024;
1718 :
1719 6 : status = smb2_create(tree, tctx, &c);
1720 6 : h2 = c.out.file.handle;
1721 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1722 : "dir create with initial alloc size failed");
1723 :
1724 6 : smb2_util_close(tree, h2);
1725 :
1726 6 : torture_comment(tctx, "Got directory alloc size: %ju\n", (uintmax_t)c.out.alloc_size);
1727 :
1728 : /*
1729 : * See above for the rational for this test
1730 : */
1731 6 : if (c.out.alloc_size > 1024*1024) {
1732 0 : torture_fail_goto(tctx, done, talloc_asprintf(tctx, "bad alloc size: %ju",
1733 : (uintmax_t)c.out.alloc_size));
1734 : }
1735 :
1736 6 : done:
1737 6 : if (!smb2_util_handle_empty(h1)) {
1738 6 : smb2_util_close(tree, h1);
1739 : }
1740 6 : smb2_deltree(tree, DNAME);
1741 6 : return ret;
1742 : }
1743 :
1744 1 : static bool test_twrp_write(struct torture_context *tctx, struct smb2_tree *tree)
1745 : {
1746 0 : struct smb2_create io;
1747 1 : struct smb2_handle h1 = {{0}};
1748 0 : NTSTATUS status;
1749 1 : bool ret = true;
1750 1 : char *p = NULL;
1751 0 : struct tm tm;
1752 0 : time_t t;
1753 0 : uint64_t nttime;
1754 1 : const char *file = NULL;
1755 1 : const char *snapshot = NULL;
1756 0 : uint32_t expected_access;
1757 0 : union smb_fileinfo getinfo;
1758 0 : union smb_setfileinfo setinfo;
1759 1 : struct security_descriptor *sd = NULL, *sd_orig = NULL;
1760 1 : const char *owner_sid = NULL;
1761 0 : struct create_disps_tests {
1762 : const char *file;
1763 : uint32_t create_disposition;
1764 : uint32_t create_options;
1765 : NTSTATUS expected_status;
1766 : };
1767 1 : struct create_disps_tests *cd_test = NULL;
1768 :
1769 1 : file = torture_setting_string(tctx, "twrp_file", NULL);
1770 1 : if (file == NULL) {
1771 0 : torture_skip(tctx, "missing 'twrp_file' option\n");
1772 : }
1773 :
1774 1 : snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
1775 1 : if (snapshot == NULL) {
1776 0 : torture_skip(tctx, "missing 'twrp_snapshot' option\n");
1777 : }
1778 :
1779 1 : torture_comment(tctx, "Testing timewarp (%s) (%s)\n", file, snapshot);
1780 :
1781 1 : setenv("TZ", "GMT", 1);
1782 :
1783 : /* strptime does not set tm.tm_isdst but mktime assumes DST is in
1784 : * effect if it is greater than 1. */
1785 1 : ZERO_STRUCT(tm);
1786 :
1787 1 : p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
1788 1 : torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
1789 1 : torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
1790 :
1791 1 : t = mktime(&tm);
1792 1 : unix_to_nt_time(&nttime, t);
1793 :
1794 1 : io = (struct smb2_create) {
1795 : .in.desired_access = SEC_FILE_READ_DATA,
1796 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
1797 : .in.create_disposition = NTCREATEX_DISP_OPEN,
1798 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
1799 : .in.fname = file,
1800 : .in.query_maximal_access = true,
1801 : .in.timewarp = nttime,
1802 : };
1803 :
1804 1 : status = smb2_create(tree, tctx, &io);
1805 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1806 : "smb2_create\n");
1807 1 : smb2_util_close(tree, io.out.file.handle);
1808 :
1809 1 : expected_access = SEC_RIGHTS_FILE_ALL &
1810 : ~(SEC_FILE_EXECUTE | SEC_DIR_DELETE_CHILD);
1811 :
1812 1 : torture_assert_int_equal_goto(tctx,
1813 : io.out.maximal_access & expected_access,
1814 : expected_access,
1815 : ret, done, "Bad access\n");
1816 :
1817 : {
1818 : /*
1819 : * Test create dispositions
1820 : */
1821 1 : struct create_disps_tests cd_tests[] = {
1822 : {
1823 : .file = file,
1824 : .create_disposition = NTCREATEX_DISP_OPEN,
1825 : .expected_status = NT_STATUS_OK,
1826 : },
1827 : {
1828 : .file = file,
1829 : .create_disposition = NTCREATEX_DISP_OPEN_IF,
1830 : .expected_status = NT_STATUS_OK,
1831 : },
1832 : {
1833 : .file = file,
1834 : .create_disposition = NTCREATEX_DISP_OVERWRITE,
1835 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1836 : },
1837 : {
1838 : .file = file,
1839 : .create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
1840 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1841 : },
1842 : {
1843 : .file = file,
1844 : .create_disposition = NTCREATEX_DISP_SUPERSEDE,
1845 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1846 : },
1847 : {
1848 : .file = "newfile",
1849 : .create_disposition = NTCREATEX_DISP_OPEN_IF,
1850 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1851 : },
1852 : {
1853 : .file = "newfile",
1854 : .create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
1855 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1856 : },
1857 : {
1858 : .file = "newfile",
1859 : .create_disposition = NTCREATEX_DISP_CREATE,
1860 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1861 : },
1862 : {
1863 : .file = "newfile",
1864 : .create_disposition = NTCREATEX_DISP_SUPERSEDE,
1865 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1866 : },
1867 : {
1868 : .file = "newdir",
1869 : .create_disposition = NTCREATEX_DISP_OPEN_IF,
1870 : .create_options = NTCREATEX_OPTIONS_DIRECTORY,
1871 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1872 : },
1873 : {
1874 : .file = "newdir",
1875 : .create_disposition = NTCREATEX_DISP_CREATE,
1876 : .create_options = NTCREATEX_OPTIONS_DIRECTORY,
1877 : .expected_status = NT_STATUS_MEDIA_WRITE_PROTECTED,
1878 : },
1879 : {
1880 : .file = NULL,
1881 : },
1882 : };
1883 :
1884 12 : for (cd_test = &cd_tests[0]; cd_test->file != NULL; cd_test++) {
1885 11 : io = (struct smb2_create) {
1886 11 : .in.fname = cd_test->file,
1887 11 : .in.create_disposition = cd_test->create_disposition,
1888 11 : .in.create_options = cd_test->create_options,
1889 :
1890 : .in.desired_access = SEC_FILE_READ_DATA,
1891 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
1892 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
1893 : .in.timewarp = nttime,
1894 : };
1895 :
1896 11 : status = smb2_create(tree, tctx, &io);
1897 11 : torture_assert_ntstatus_equal_goto(
1898 : tctx, status, cd_test->expected_status, ret, done,
1899 : "Bad status\n");
1900 : }
1901 : }
1902 :
1903 1 : io = (struct smb2_create) {
1904 : .in.desired_access = expected_access,
1905 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
1906 : .in.create_disposition = NTCREATEX_DISP_OPEN,
1907 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
1908 : .in.fname = file,
1909 : .in.timewarp = nttime,
1910 : };
1911 :
1912 1 : status = smb2_create(tree, tctx, &io);
1913 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1914 : "smb2_create\n");
1915 1 : h1 = io.out.file.handle;
1916 :
1917 1 : status = smb2_util_write(tree, h1, "123", 0, 3);
1918 1 : torture_assert_ntstatus_equal_goto(tctx, status,
1919 : NT_STATUS_MEDIA_WRITE_PROTECTED,
1920 : ret, done, "smb2_create\n");
1921 :
1922 : /*
1923 : * Verify access mask
1924 : */
1925 :
1926 1 : ZERO_STRUCT(getinfo);
1927 1 : getinfo.generic.level = RAW_FILEINFO_ACCESS_INFORMATION;
1928 1 : getinfo.generic.in.file.handle = h1;
1929 :
1930 1 : status = smb2_getinfo_file(tree, tree, &getinfo);
1931 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1932 : "smb2_getinfo_file\n");
1933 :
1934 1 : torture_assert_int_equal_goto(
1935 : tctx,
1936 : getinfo.access_information.out.access_flags,
1937 : expected_access,
1938 : ret, done,
1939 : "Bad access mask\n");
1940 :
1941 : /*
1942 : * Check we can't set various things
1943 : */
1944 :
1945 1 : ZERO_STRUCT(getinfo);
1946 1 : getinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1947 1 : getinfo.query_secdesc.in.file.handle = h1;
1948 1 : getinfo.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1949 :
1950 1 : status = smb2_getinfo_file(tree, tctx, &getinfo);
1951 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1952 : "smb2_getinfo_file\n");
1953 :
1954 1 : sd_orig = getinfo.query_secdesc.out.sd;
1955 1 : owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1956 :
1957 1 : sd = security_descriptor_dacl_create(tctx,
1958 : 0, NULL, NULL,
1959 : owner_sid,
1960 : SEC_ACE_TYPE_ACCESS_ALLOWED,
1961 : SEC_FILE_WRITE_DATA,
1962 : 0,
1963 : NULL);
1964 :
1965 : /* Try to set ACL */
1966 :
1967 1 : ZERO_STRUCT(setinfo);
1968 1 : setinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1969 1 : setinfo.set_secdesc.in.file.handle = h1;
1970 1 : setinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1971 1 : setinfo.set_secdesc.in.sd = sd;
1972 :
1973 1 : status = smb2_setinfo_file(tree, &setinfo);
1974 1 : torture_assert_ntstatus_equal_goto(
1975 : tctx,
1976 : status,
1977 : NT_STATUS_MEDIA_WRITE_PROTECTED,
1978 : ret, done,
1979 : "smb2_setinfo_file\n");
1980 :
1981 : /* Try to delete */
1982 :
1983 1 : ZERO_STRUCT(setinfo);
1984 1 : setinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
1985 1 : setinfo.disposition_info.in.delete_on_close = 1;
1986 1 : setinfo.generic.in.file.handle = h1;
1987 :
1988 1 : status = smb2_setinfo_file(tree, &setinfo);
1989 1 : torture_assert_ntstatus_equal_goto(
1990 : tctx,
1991 : status,
1992 : NT_STATUS_MEDIA_WRITE_PROTECTED,
1993 : ret, done,
1994 : "smb2_setinfo_file\n");
1995 :
1996 1 : ZERO_STRUCT(setinfo);
1997 1 : setinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1998 1 : setinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1999 1 : setinfo.generic.in.file.handle = h1;
2000 :
2001 1 : status = smb2_setinfo_file(tree, &setinfo);
2002 1 : torture_assert_ntstatus_equal_goto(
2003 : tctx,
2004 : status,
2005 : NT_STATUS_MEDIA_WRITE_PROTECTED,
2006 : ret, done,
2007 : "smb2_setinfo_file\n");
2008 :
2009 : /* Try to truncate */
2010 :
2011 1 : ZERO_STRUCT(setinfo);
2012 1 : setinfo.generic.level = SMB_SFILEINFO_END_OF_FILE_INFORMATION;
2013 1 : setinfo.generic.in.file.handle = h1;
2014 1 : setinfo.end_of_file_info.in.size = 0x100000;
2015 :
2016 1 : status = smb2_setinfo_file(tree, &setinfo);
2017 1 : torture_assert_ntstatus_equal_goto(
2018 : tctx,
2019 : status,
2020 : NT_STATUS_MEDIA_WRITE_PROTECTED,
2021 : ret, done,
2022 : "smb2_setinfo_file\n");
2023 :
2024 : /* Try to set a hardlink */
2025 :
2026 1 : ZERO_STRUCT(setinfo);
2027 1 : setinfo.generic.level = RAW_SFILEINFO_LINK_INFORMATION;
2028 1 : setinfo.generic.in.file.handle = h1;
2029 1 : setinfo.link_information.in.new_name = "hardlink";
2030 :
2031 1 : status = smb2_setinfo_file(tree, &setinfo);
2032 1 : torture_assert_ntstatus_equal_goto(
2033 : tctx,
2034 : status,
2035 : NT_STATUS_NOT_SAME_DEVICE,
2036 : ret, done,
2037 : "smb2_setinfo_file\n");
2038 :
2039 : /* Try to rename */
2040 :
2041 1 : ZERO_STRUCT(setinfo);
2042 1 : setinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
2043 1 : setinfo.rename_information.in.file.handle = h1;
2044 1 : setinfo.rename_information.in.new_name = "renamed";
2045 :
2046 1 : status = smb2_setinfo_file(tree, &setinfo);
2047 1 : torture_assert_ntstatus_equal_goto(
2048 : tctx,
2049 : status,
2050 : NT_STATUS_NOT_SAME_DEVICE,
2051 : ret, done,
2052 : "smb2_setinfo_file\n");
2053 :
2054 1 : smb2_util_close(tree, h1);
2055 1 : ZERO_STRUCT(h1);
2056 :
2057 1 : done:
2058 1 : if (!smb2_util_handle_empty(h1)) {
2059 0 : smb2_util_close(tree, h1);
2060 : }
2061 1 : return ret;
2062 : }
2063 :
2064 1 : static bool test_twrp_stream(struct torture_context *tctx,
2065 : struct smb2_tree *tree)
2066 : {
2067 0 : struct smb2_create io;
2068 0 : NTSTATUS status;
2069 1 : bool ret = true;
2070 1 : char *p = NULL;
2071 0 : struct tm tm;
2072 0 : time_t t;
2073 0 : uint64_t nttime;
2074 1 : const char *file = NULL;
2075 1 : const char *stream = NULL;
2076 1 : const char *snapshot = NULL;
2077 0 : int stream_size;
2078 1 : char *path = NULL;
2079 1 : uint8_t *buf = NULL;
2080 1 : struct smb2_handle h1 = {{0}};
2081 0 : struct smb2_read r;
2082 :
2083 1 : file = torture_setting_string(tctx, "twrp_file", NULL);
2084 1 : if (file == NULL) {
2085 0 : torture_skip(tctx, "missing 'twrp_file' option\n");
2086 : }
2087 :
2088 1 : stream = torture_setting_string(tctx, "twrp_stream", NULL);
2089 1 : if (stream == NULL) {
2090 0 : torture_skip(tctx, "missing 'twrp_stream' option\n");
2091 : }
2092 :
2093 1 : snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
2094 1 : if (snapshot == NULL) {
2095 0 : torture_skip(tctx, "missing 'twrp_snapshot' option\n");
2096 : }
2097 :
2098 1 : stream_size = torture_setting_int(tctx, "twrp_stream_size", 0);
2099 1 : if (stream_size == 0) {
2100 0 : torture_skip(tctx, "missing 'twrp_stream_size' option\n");
2101 : }
2102 :
2103 1 : torture_comment(tctx, "Testing timewarp on stream (%s) (%s)\n",
2104 : file, snapshot);
2105 :
2106 1 : path = talloc_asprintf(tree, "%s:%s", file, stream);
2107 1 : torture_assert_not_null_goto(tctx, path, ret, done, "path\n");
2108 :
2109 1 : buf = talloc_zero_array(tree, uint8_t, stream_size);
2110 1 : torture_assert_not_null_goto(tctx, buf, ret, done, "buf\n");
2111 :
2112 1 : setenv("TZ", "GMT", 1);
2113 :
2114 : /* strptime does not set tm.tm_isdst but mktime assumes DST is in
2115 : * effect if it is greater than 1. */
2116 1 : ZERO_STRUCT(tm);
2117 :
2118 1 : p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
2119 1 : torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
2120 1 : torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
2121 :
2122 1 : t = mktime(&tm);
2123 1 : unix_to_nt_time(&nttime, t);
2124 :
2125 1 : io = (struct smb2_create) {
2126 : .in.desired_access = SEC_FILE_READ_DATA,
2127 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2128 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2129 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2130 : .in.fname = path,
2131 : .in.timewarp = nttime,
2132 : };
2133 :
2134 1 : status = smb2_create(tree, tctx, &io);
2135 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2136 : "smb2_create\n");
2137 1 : h1 = io.out.file.handle;
2138 :
2139 1 : r = (struct smb2_read) {
2140 : .in.file.handle = h1,
2141 : .in.length = stream_size,
2142 : .in.offset = 0,
2143 : };
2144 :
2145 1 : status = smb2_read(tree, tree, &r);
2146 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2147 : "smb2_create\n");
2148 :
2149 1 : smb2_util_close(tree, h1);
2150 :
2151 1 : done:
2152 1 : return ret;
2153 : }
2154 :
2155 1 : static bool test_twrp_openroot(struct torture_context *tctx, struct smb2_tree *tree)
2156 : {
2157 0 : struct smb2_create io;
2158 0 : NTSTATUS status;
2159 1 : bool ret = true;
2160 1 : char *p = NULL;
2161 0 : struct tm tm;
2162 0 : time_t t;
2163 0 : uint64_t nttime;
2164 1 : const char *snapshot = NULL;
2165 :
2166 1 : snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
2167 1 : if (snapshot == NULL) {
2168 0 : torture_skip(tctx, "missing 'twrp_snapshot' option\n");
2169 : }
2170 :
2171 1 : torture_comment(tctx, "Testing open of root of "
2172 : "share with timewarp (%s)\n",
2173 : snapshot);
2174 :
2175 1 : setenv("TZ", "GMT", 1);
2176 :
2177 : /* strptime does not set tm.tm_isdst but mktime assumes DST is in
2178 : * effect if it is greater than 1. */
2179 1 : ZERO_STRUCT(tm);
2180 :
2181 1 : p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
2182 1 : torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
2183 1 : torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
2184 :
2185 1 : t = mktime(&tm);
2186 1 : unix_to_nt_time(&nttime, t);
2187 :
2188 1 : io = (struct smb2_create) {
2189 : .in.desired_access = SEC_FILE_READ_DATA,
2190 : .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2191 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2192 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2193 : .in.fname = "",
2194 : .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2195 : .in.timewarp = nttime,
2196 : };
2197 :
2198 1 : status = smb2_create(tree, tctx, &io);
2199 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2200 : "smb2_create\n");
2201 1 : smb2_util_close(tree, io.out.file.handle);
2202 :
2203 1 : done:
2204 1 : return ret;
2205 : }
2206 :
2207 1 : static bool test_twrp_listdir(struct torture_context *tctx,
2208 : struct smb2_tree *tree)
2209 : {
2210 0 : struct smb2_create create;
2211 1 : struct smb2_handle h = {{0}};
2212 0 : struct smb2_find find;
2213 0 : unsigned int count;
2214 0 : union smb_search_data *d;
2215 1 : char *p = NULL;
2216 0 : struct tm tm;
2217 0 : time_t t;
2218 0 : uint64_t nttime;
2219 1 : const char *snapshot = NULL;
2220 0 : uint64_t normal_fileid;
2221 0 : uint64_t snapshot_fileid;
2222 0 : NTSTATUS status;
2223 1 : bool ret = true;
2224 :
2225 1 : snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
2226 1 : if (snapshot == NULL) {
2227 0 : torture_fail(tctx, "missing 'twrp_snapshot' option\n");
2228 : }
2229 :
2230 1 : torture_comment(tctx, "Testing File-Ids of directory listing "
2231 : "with timewarp (%s)\n",
2232 : snapshot);
2233 :
2234 1 : setenv("TZ", "GMT", 1);
2235 :
2236 : /* strptime does not set tm.tm_isdst but mktime assumes DST is in
2237 : * effect if it is greater than 1. */
2238 1 : ZERO_STRUCT(tm);
2239 :
2240 1 : p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
2241 1 : torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
2242 1 : torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
2243 :
2244 1 : t = mktime(&tm);
2245 1 : unix_to_nt_time(&nttime, t);
2246 :
2247 : /*
2248 : * 1: Query the file's File-Id
2249 : */
2250 1 : create = (struct smb2_create) {
2251 : .in.desired_access = SEC_FILE_READ_DATA,
2252 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2253 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2254 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2255 : .in.fname = "subdir/hardlink",
2256 : .in.query_on_disk_id = true,
2257 : };
2258 :
2259 1 : status = smb2_create(tree, tctx, &create);
2260 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2261 : "test file could not be created\n");
2262 1 : smb2_util_close(tree, create.out.file.handle);
2263 1 : normal_fileid = BVAL(&create.out.on_disk_id, 0);
2264 :
2265 : /*
2266 : * 2: check directory listing of the file returns same File-Id
2267 : */
2268 :
2269 1 : create = (struct smb2_create) {
2270 : .in.desired_access = SEC_DIR_LIST,
2271 : .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2272 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2273 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2274 : .in.fname = "subdir",
2275 : .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2276 : };
2277 :
2278 1 : status = smb2_create(tree, tctx, &create);
2279 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2280 : "smb2_create\n");
2281 1 : h = create.out.file.handle;
2282 :
2283 1 : find = (struct smb2_find) {
2284 : .in.file.handle = h,
2285 : .in.pattern = "*",
2286 : .in.max_response_size = 0x1000,
2287 : .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
2288 : };
2289 :
2290 1 : status = smb2_find_level(tree, tree, &find, &count, &d);
2291 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2292 : "smb2_find_level failed\n");
2293 :
2294 1 : smb2_util_close(tree, h);
2295 :
2296 1 : torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
2297 1 : torture_assert_str_equal_goto(tctx,
2298 : d[2].id_both_directory_info.name.s,
2299 : "hardlink",
2300 : ret, done, "bad name");
2301 1 : torture_assert_u64_equal_goto(tctx,
2302 : d[2].id_both_directory_info.file_id,
2303 : normal_fileid,
2304 : ret, done, "bad fileid\n");
2305 :
2306 : /*
2307 : * 3: Query File-Id of snapshot of the file and check the File-Id is
2308 : * different compared to the basefile
2309 : */
2310 :
2311 1 : create = (struct smb2_create) {
2312 : .in.desired_access = SEC_FILE_READ_DATA,
2313 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2314 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2315 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2316 : .in.fname = "subdir/hardlink",
2317 : .in.query_on_disk_id = true,
2318 : .in.timewarp = nttime,
2319 : };
2320 :
2321 1 : status = smb2_create(tree, tctx, &create);
2322 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2323 : "test file could not be created\n");
2324 1 : smb2_util_close(tree, create.out.file.handle);
2325 :
2326 1 : snapshot_fileid = BVAL(&create.out.on_disk_id, 0);
2327 :
2328 : /*
2329 : * 4: List directory of the snapshot and check the File-Id returned here
2330 : * is the same as in 3.
2331 : */
2332 :
2333 1 : create = (struct smb2_create) {
2334 : .in.desired_access = SEC_DIR_LIST,
2335 : .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2336 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2337 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2338 : .in.fname = "subdir",
2339 : .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2340 : .in.timewarp = nttime,
2341 : };
2342 :
2343 1 : status = smb2_create(tree, tctx, &create);
2344 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2345 : "smb2_create\n");
2346 1 : h = create.out.file.handle;
2347 :
2348 1 : find = (struct smb2_find) {
2349 : .in.file.handle = h,
2350 : .in.pattern = "*",
2351 : .in.max_response_size = 0x1000,
2352 : .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
2353 : };
2354 :
2355 1 : status = smb2_find_level(tree, tree, &find, &count, &d);
2356 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2357 : "smb2_find_level failed\n");
2358 1 : smb2_util_close(tree, h);
2359 :
2360 1 : torture_assert_int_equal_goto(tctx, count, 3, ret, done, "Bad count\n");
2361 1 : torture_assert_str_equal_goto(tctx,
2362 : d[2].id_both_directory_info.name.s,
2363 : "hardlink",
2364 : ret, done, "bad name");
2365 1 : torture_assert_u64_equal_goto(tctx,
2366 : snapshot_fileid,
2367 : d[2].id_both_directory_info.file_id,
2368 : ret, done, "bad fileid\n");
2369 :
2370 1 : done:
2371 1 : return ret;
2372 : }
2373 :
2374 2 : static bool test_fileid(struct torture_context *tctx,
2375 : struct smb2_tree *tree)
2376 : {
2377 2 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
2378 2 : const char *fname = DNAME "\\foo";
2379 2 : const char *sname = DNAME "\\foo:bar";
2380 0 : struct smb2_handle testdirh;
2381 0 : struct smb2_handle h1;
2382 0 : struct smb2_create create;
2383 0 : union smb_fileinfo finfo;
2384 0 : union smb_setfileinfo sinfo;
2385 0 : struct smb2_find f;
2386 0 : unsigned int count;
2387 0 : union smb_search_data *d;
2388 0 : uint64_t expected_fileid;
2389 0 : uint64_t returned_fileid;
2390 0 : NTSTATUS status;
2391 2 : bool ret = true;
2392 :
2393 2 : smb2_deltree(tree, DNAME);
2394 :
2395 2 : status = torture_smb2_testdir(tree, DNAME, &testdirh);
2396 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2397 : "torture_smb2_testdir failed\n");
2398 :
2399 : /*
2400 : * Initial create with QFID
2401 : */
2402 2 : create = (struct smb2_create) {
2403 : .in.desired_access = SEC_FILE_ALL,
2404 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2405 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2406 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2407 : .in.fname = fname,
2408 : .in.query_on_disk_id = true,
2409 : };
2410 :
2411 2 : status = smb2_create(tree, tctx, &create);
2412 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2413 : "test file could not be created\n");
2414 2 : h1 = create.out.file.handle;
2415 2 : expected_fileid = BVAL(&create.out.on_disk_id, 0);
2416 :
2417 : /*
2418 : * Getinfo the File-ID on the just opened handle
2419 : */
2420 2 : finfo = (union smb_fileinfo) {
2421 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2422 : .generic.in.file.handle = h1,
2423 : };
2424 :
2425 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2426 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2427 : "torture_smb2_testdir\n");
2428 2 : smb2_util_close(tree, h1);
2429 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2430 : expected_fileid,
2431 : ret, done, "bad fileid\n");
2432 :
2433 : /*
2434 : * Open existing with QFID
2435 : */
2436 2 : create = (struct smb2_create) {
2437 : .in.desired_access = SEC_FILE_ALL,
2438 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2439 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2440 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2441 : .in.fname = fname,
2442 : .in.query_on_disk_id = true,
2443 : };
2444 :
2445 2 : status = smb2_create(tree, tctx, &create);
2446 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2447 : "test file could not be created\n");
2448 2 : h1 = create.out.file.handle;
2449 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2450 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2451 : ret, done, "bad fileid\n");
2452 :
2453 : /*
2454 : * Getinfo the File-ID on the just opened handle
2455 : */
2456 2 : finfo = (union smb_fileinfo) {
2457 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2458 : .generic.in.file.handle = h1,
2459 : };
2460 :
2461 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2462 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2463 : "torture_smb2_testdir\n");
2464 2 : smb2_util_close(tree, h1);
2465 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2466 : expected_fileid,
2467 : ret, done, "bad fileid\n");
2468 :
2469 : /*
2470 : * Overwrite with QFID
2471 : */
2472 2 : create = (struct smb2_create) {
2473 : .in.desired_access = SEC_FILE_ALL,
2474 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2475 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2476 : .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
2477 : .in.fname = fname,
2478 : .in.query_on_disk_id = true,
2479 : };
2480 :
2481 2 : status = smb2_create(tree, tctx, &create);
2482 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2483 : "test file could not be created\n");
2484 2 : h1 = create.out.file.handle;
2485 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2486 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2487 : ret, done, "bad fileid\n");
2488 :
2489 : /*
2490 : * Getinfo the File-ID on the open with overwrite handle
2491 : */
2492 2 : finfo = (union smb_fileinfo) {
2493 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2494 : .generic.in.file.handle = h1,
2495 : };
2496 :
2497 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2498 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2499 : "torture_smb2_testdir\n");
2500 2 : smb2_util_close(tree, h1);
2501 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2502 : expected_fileid,
2503 : ret, done, "bad fileid\n");
2504 :
2505 : /*
2506 : * Do some modifications on the basefile (IO, setinfo), verifying
2507 : * File-ID after each step.
2508 : */
2509 2 : create = (struct smb2_create) {
2510 : .in.desired_access = SEC_FILE_ALL,
2511 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2512 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2513 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2514 : .in.fname = fname,
2515 : .in.query_on_disk_id = true,
2516 : };
2517 :
2518 2 : status = smb2_create(tree, tctx, &create);
2519 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2520 : "test file could not be created\n");
2521 2 : h1 = create.out.file.handle;
2522 :
2523 2 : status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
2524 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2525 : "smb2_util_write failed\n");
2526 :
2527 2 : finfo = (union smb_fileinfo) {
2528 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2529 : .generic.in.file.handle = h1,
2530 : };
2531 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2532 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2533 : "smb2_getinfo_file failed\n");
2534 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2535 : expected_fileid,
2536 : ret, done, "bad fileid\n");
2537 :
2538 2 : sinfo = (union smb_setfileinfo) {
2539 : .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
2540 : .basic_info.in.file.handle = h1,
2541 : };
2542 2 : unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
2543 :
2544 2 : status = smb2_setinfo_file(tree, &sinfo);
2545 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2546 : "smb2_setinfo_file failed\n");
2547 :
2548 2 : finfo = (union smb_fileinfo) {
2549 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2550 : .generic.in.file.handle = h1,
2551 : };
2552 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2553 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2554 : "smb2_getinfo_file failed\n");
2555 2 : smb2_util_close(tree, h1);
2556 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2557 : expected_fileid,
2558 : ret, done, "bad fileid\n");
2559 :
2560 : /*
2561 : * Create stream, check the stream's File-ID, should be the same as the
2562 : * base file (sic!, tested against Windows).
2563 : */
2564 2 : create = (struct smb2_create) {
2565 : .in.desired_access = SEC_FILE_ALL,
2566 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2567 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2568 : .in.create_disposition = NTCREATEX_DISP_CREATE,
2569 : .in.fname = sname,
2570 : .in.query_on_disk_id = true,
2571 : };
2572 :
2573 2 : status = smb2_create(tree, tctx, &create);
2574 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2575 : "test file could not be created\n");
2576 2 : h1 = create.out.file.handle;
2577 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2578 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2579 : ret, done, "bad fileid\n");
2580 :
2581 : /*
2582 : * Getinfo the File-ID on the created stream
2583 : */
2584 2 : finfo = (union smb_fileinfo) {
2585 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2586 : .generic.in.file.handle = h1,
2587 : };
2588 :
2589 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2590 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2591 : "smb2_getinfo_file failed\n");
2592 2 : smb2_util_close(tree, h1);
2593 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2594 : expected_fileid,
2595 : ret, done, "bad fileid\n");
2596 :
2597 : /*
2598 : * Open stream, check the stream's File-ID, should be the same as the
2599 : * base file (sic!, tested against Windows).
2600 : */
2601 2 : create = (struct smb2_create) {
2602 : .in.desired_access = SEC_FILE_ALL,
2603 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2604 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2605 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2606 : .in.fname = sname,
2607 : .in.query_on_disk_id = true,
2608 : };
2609 :
2610 2 : status = smb2_create(tree, tctx, &create);
2611 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2612 : "test file could not be created\n");
2613 2 : h1 = create.out.file.handle;
2614 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2615 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2616 : ret, done, "bad fileid\n");
2617 :
2618 : /*
2619 : * Getinfo the File-ID on the opened stream
2620 : */
2621 2 : finfo = (union smb_fileinfo) {
2622 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2623 : .generic.in.file.handle = h1,
2624 : };
2625 :
2626 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2627 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2628 : "smb2_getinfo_file failed\n");
2629 2 : smb2_util_close(tree, h1);
2630 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2631 : expected_fileid,
2632 : ret, done, "bad fileid\n");
2633 :
2634 : /*
2635 : * Overwrite stream, check the stream's File-ID, should be the same as
2636 : * the base file (sic!, tested against Windows).
2637 : */
2638 2 : create = (struct smb2_create) {
2639 : .in.desired_access = SEC_FILE_ALL,
2640 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2641 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2642 : .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
2643 : .in.fname = sname,
2644 : .in.query_on_disk_id = true,
2645 : };
2646 :
2647 2 : status = smb2_create(tree, tctx, &create);
2648 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2649 : "test file could not be created\n");
2650 2 : h1 = create.out.file.handle;
2651 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2652 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2653 : ret, done, "bad fileid\n");
2654 :
2655 : /*
2656 : * Getinfo the File-ID on the overwritten stream
2657 : */
2658 2 : finfo = (union smb_fileinfo) {
2659 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2660 : .generic.in.file.handle = h1,
2661 : };
2662 :
2663 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2664 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2665 : "smb2_getinfo_file failed\n");
2666 2 : smb2_util_close(tree, h1);
2667 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2668 : expected_fileid,
2669 : ret, done, "bad fileid\n");
2670 :
2671 : /*
2672 : * Do some modifications on the stream (IO, setinfo), verifying File-ID
2673 : * after each step.
2674 : */
2675 2 : create = (struct smb2_create) {
2676 : .in.desired_access = SEC_FILE_ALL,
2677 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2678 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2679 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2680 : .in.fname = sname,
2681 : .in.query_on_disk_id = true,
2682 : };
2683 :
2684 2 : status = smb2_create(tree, tctx, &create);
2685 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2686 : "test file could not be created\n");
2687 2 : h1 = create.out.file.handle;
2688 :
2689 2 : status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
2690 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2691 : "smb2_util_write failed\n");
2692 :
2693 2 : finfo = (union smb_fileinfo) {
2694 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2695 : .generic.in.file.handle = h1,
2696 : };
2697 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2698 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2699 : "smb2_getinfo_file failed\n");
2700 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2701 : expected_fileid,
2702 : ret, done, "bad fileid\n");
2703 :
2704 2 : sinfo = (union smb_setfileinfo) {
2705 : .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
2706 : .basic_info.in.file.handle = h1,
2707 : };
2708 2 : unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
2709 :
2710 2 : status = smb2_setinfo_file(tree, &sinfo);
2711 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2712 : "smb2_setinfo_file failed\n");
2713 :
2714 2 : finfo = (union smb_fileinfo) {
2715 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2716 : .generic.in.file.handle = h1,
2717 : };
2718 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2719 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2720 : "smb2_getinfo_file failed\n");
2721 2 : smb2_util_close(tree, h1);
2722 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2723 : expected_fileid,
2724 : ret, done, "bad fileid\n");
2725 :
2726 : /*
2727 : * Final open of the basefile with QFID
2728 : */
2729 2 : create = (struct smb2_create) {
2730 : .in.desired_access = SEC_FILE_ALL,
2731 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2732 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2733 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2734 : .in.fname = fname,
2735 : .in.query_on_disk_id = true,
2736 : };
2737 :
2738 2 : status = smb2_create(tree, tctx, &create);
2739 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2740 : "test file could not be created\n");
2741 2 : h1 = create.out.file.handle;
2742 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2743 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2744 : ret, done, "bad fileid\n");
2745 :
2746 : /*
2747 : * Final Getinfo checking File-ID
2748 : */
2749 2 : finfo = (union smb_fileinfo) {
2750 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2751 : .generic.in.file.handle = h1,
2752 : };
2753 :
2754 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2755 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2756 : "torture_smb2_testdir\n");
2757 2 : smb2_util_close(tree, h1);
2758 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2759 : expected_fileid,
2760 : ret, done, "bad fileid\n");
2761 :
2762 : /*
2763 : * Final list directory, verifying the operations on basefile and stream
2764 : * didn't modify the base file metadata.
2765 : */
2766 2 : f = (struct smb2_find) {
2767 : .in.file.handle = testdirh,
2768 : .in.pattern = "foo",
2769 : .in.max_response_size = 0x1000,
2770 : .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
2771 : .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
2772 : };
2773 :
2774 2 : status = smb2_find_level(tree, tree, &f, &count, &d);
2775 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2776 : "smb2_find_level failed\n");
2777 2 : torture_assert_u64_equal_goto(tctx,
2778 : d->id_both_directory_info.file_id,
2779 : expected_fileid,
2780 : ret, done, "bad fileid\n");
2781 :
2782 2 : done:
2783 2 : smb2_util_close(tree, testdirh);
2784 2 : smb2_deltree(tree, DNAME);
2785 2 : talloc_free(mem_ctx);
2786 2 : return ret;
2787 : }
2788 :
2789 2 : static bool test_fileid_dir(struct torture_context *tctx,
2790 : struct smb2_tree *tree)
2791 : {
2792 2 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
2793 2 : const char *dname = DNAME "\\foo";
2794 2 : const char *sname = DNAME "\\foo:bar";
2795 0 : struct smb2_handle testdirh;
2796 0 : struct smb2_handle h1;
2797 0 : struct smb2_create create;
2798 0 : union smb_fileinfo finfo;
2799 0 : union smb_setfileinfo sinfo;
2800 0 : struct smb2_find f;
2801 0 : unsigned int count;
2802 0 : union smb_search_data *d;
2803 0 : uint64_t expected_fileid;
2804 0 : uint64_t returned_fileid;
2805 0 : NTSTATUS status;
2806 2 : bool ret = true;
2807 :
2808 2 : smb2_deltree(tree, DNAME);
2809 :
2810 2 : status = torture_smb2_testdir(tree, DNAME, &testdirh);
2811 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2812 : "torture_smb2_testdir failed\n");
2813 :
2814 : /*
2815 : * Initial directory create with QFID
2816 : */
2817 2 : create = (struct smb2_create) {
2818 : .in.desired_access = SEC_FILE_ALL,
2819 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2820 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
2821 : .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2822 : .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2823 : .in.fname = dname,
2824 : .in.query_on_disk_id = true,
2825 : };
2826 :
2827 2 : status = smb2_create(tree, tctx, &create);
2828 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2829 : "test file could not be created\n");
2830 2 : h1 = create.out.file.handle;
2831 2 : expected_fileid = BVAL(&create.out.on_disk_id, 0);
2832 :
2833 : /*
2834 : * Getinfo the File-ID on the just opened handle
2835 : */
2836 2 : finfo = (union smb_fileinfo) {
2837 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2838 : .generic.in.file.handle = h1,
2839 : };
2840 :
2841 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2842 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2843 : "torture_smb2_testdir\n");
2844 2 : smb2_util_close(tree, h1);
2845 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2846 : expected_fileid,
2847 : ret, done, "bad fileid\n");
2848 :
2849 : /*
2850 : * Open existing directory with QFID
2851 : */
2852 2 : create = (struct smb2_create) {
2853 : .in.desired_access = SEC_FILE_ALL,
2854 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2855 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2856 : .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2857 : .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2858 : .in.fname = dname,
2859 : .in.query_on_disk_id = true,
2860 : };
2861 :
2862 2 : status = smb2_create(tree, tctx, &create);
2863 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2864 : "test file could not be created\n");
2865 2 : h1 = create.out.file.handle;
2866 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2867 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2868 : ret, done, "bad fileid\n");
2869 :
2870 : /*
2871 : * Getinfo the File-ID on the just opened handle
2872 : */
2873 2 : finfo = (union smb_fileinfo) {
2874 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2875 : .generic.in.file.handle = h1,
2876 : };
2877 :
2878 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2879 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2880 : "torture_smb2_testdir\n");
2881 2 : smb2_util_close(tree, h1);
2882 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2883 : expected_fileid,
2884 : ret, done, "bad fileid\n");
2885 :
2886 : /*
2887 : * Create stream, check the stream's File-ID, should be the same as the
2888 : * base file (sic!, tested against Windows).
2889 : */
2890 2 : create = (struct smb2_create) {
2891 : .in.desired_access = SEC_FILE_ALL,
2892 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2893 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2894 : .in.create_disposition = NTCREATEX_DISP_CREATE,
2895 : .in.fname = sname,
2896 : .in.query_on_disk_id = true,
2897 : };
2898 :
2899 2 : status = smb2_create(tree, tctx, &create);
2900 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2901 : "test file could not be created\n");
2902 2 : h1 = create.out.file.handle;
2903 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2904 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2905 : ret, done, "bad fileid\n");
2906 :
2907 : /*
2908 : * Getinfo the File-ID on the created stream
2909 : */
2910 2 : finfo = (union smb_fileinfo) {
2911 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2912 : .generic.in.file.handle = h1,
2913 : };
2914 :
2915 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2916 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2917 : "smb2_getinfo_file failed\n");
2918 2 : smb2_util_close(tree, h1);
2919 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2920 : expected_fileid,
2921 : ret, done, "bad fileid\n");
2922 :
2923 : /*
2924 : * Open stream, check the stream's File-ID, should be the same as the
2925 : * base file (sic!, tested against Windows).
2926 : */
2927 2 : create = (struct smb2_create) {
2928 : .in.desired_access = SEC_FILE_ALL,
2929 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2930 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2931 : .in.create_disposition = NTCREATEX_DISP_OPEN,
2932 : .in.fname = sname,
2933 : .in.query_on_disk_id = true,
2934 : };
2935 :
2936 2 : status = smb2_create(tree, tctx, &create);
2937 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2938 : "test file could not be created\n");
2939 2 : h1 = create.out.file.handle;
2940 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2941 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2942 : ret, done, "bad fileid\n");
2943 :
2944 : /*
2945 : * Getinfo the File-ID on the opened stream
2946 : */
2947 2 : finfo = (union smb_fileinfo) {
2948 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2949 : .generic.in.file.handle = h1,
2950 : };
2951 :
2952 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2953 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2954 : "smb2_getinfo_file failed\n");
2955 2 : smb2_util_close(tree, h1);
2956 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2957 : expected_fileid,
2958 : ret, done, "bad fileid\n");
2959 :
2960 : /*
2961 : * Overwrite stream, check the stream's File-ID, should be the same as
2962 : * the base file (sic!, tested against Windows).
2963 : */
2964 2 : create = (struct smb2_create) {
2965 : .in.desired_access = SEC_FILE_ALL,
2966 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
2967 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
2968 : .in.create_disposition = NTCREATEX_DISP_OVERWRITE,
2969 : .in.fname = sname,
2970 : .in.query_on_disk_id = true,
2971 : };
2972 :
2973 2 : status = smb2_create(tree, tctx, &create);
2974 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2975 : "test file could not be created\n");
2976 2 : h1 = create.out.file.handle;
2977 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
2978 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
2979 : ret, done, "bad fileid\n");
2980 :
2981 : /*
2982 : * Getinfo the File-ID on the overwritten stream
2983 : */
2984 2 : finfo = (union smb_fileinfo) {
2985 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
2986 : .generic.in.file.handle = h1,
2987 : };
2988 :
2989 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
2990 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2991 : "smb2_getinfo_file failed\n");
2992 2 : smb2_util_close(tree, h1);
2993 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
2994 : expected_fileid,
2995 : ret, done, "bad fileid\n");
2996 :
2997 : /*
2998 : * Do some modifications on the stream (IO, setinfo), verifying File-ID
2999 : * after each step.
3000 : */
3001 2 : create = (struct smb2_create) {
3002 : .in.desired_access = SEC_FILE_ALL,
3003 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3004 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3005 : .in.create_disposition = NTCREATEX_DISP_OPEN,
3006 : .in.fname = sname,
3007 : .in.query_on_disk_id = true,
3008 : };
3009 :
3010 2 : status = smb2_create(tree, tctx, &create);
3011 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3012 : "test file could not be created\n");
3013 2 : h1 = create.out.file.handle;
3014 :
3015 2 : status = smb2_util_write(tree, h1, "foo", 0, strlen("foo"));
3016 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3017 : "smb2_util_write failed\n");
3018 :
3019 2 : finfo = (union smb_fileinfo) {
3020 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
3021 : .generic.in.file.handle = h1,
3022 : };
3023 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
3024 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3025 : "smb2_getinfo_file failed\n");
3026 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
3027 : expected_fileid,
3028 : ret, done, "bad fileid\n");
3029 :
3030 2 : sinfo = (union smb_setfileinfo) {
3031 : .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
3032 : .basic_info.in.file.handle = h1,
3033 : };
3034 2 : unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL));
3035 :
3036 2 : status = smb2_setinfo_file(tree, &sinfo);
3037 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3038 : "smb2_setinfo_file failed\n");
3039 :
3040 2 : finfo = (union smb_fileinfo) {
3041 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
3042 : .generic.in.file.handle = h1,
3043 : };
3044 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
3045 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3046 : "smb2_getinfo_file failed\n");
3047 2 : smb2_util_close(tree, h1);
3048 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
3049 : expected_fileid,
3050 : ret, done, "bad fileid\n");
3051 :
3052 : /*
3053 : * Final open of the directory with QFID
3054 : */
3055 2 : create = (struct smb2_create) {
3056 : .in.desired_access = SEC_FILE_ALL,
3057 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3058 : .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
3059 : .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
3060 : .in.create_disposition = NTCREATEX_DISP_OPEN,
3061 : .in.fname = dname,
3062 : .in.query_on_disk_id = true,
3063 : };
3064 :
3065 2 : status = smb2_create(tree, tctx, &create);
3066 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3067 : "test file could not be created\n");
3068 2 : h1 = create.out.file.handle;
3069 2 : returned_fileid = BVAL(&create.out.on_disk_id, 0);
3070 2 : torture_assert_u64_equal_goto(tctx, returned_fileid, expected_fileid,
3071 : ret, done, "bad fileid\n");
3072 :
3073 : /*
3074 : * Final Getinfo checking File-ID
3075 : */
3076 2 : finfo = (union smb_fileinfo) {
3077 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
3078 : .generic.in.file.handle = h1,
3079 : };
3080 :
3081 2 : status = smb2_getinfo_file(tree, tctx, &finfo);
3082 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3083 : "torture_smb2_testdir\n");
3084 2 : smb2_util_close(tree, h1);
3085 2 : torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id,
3086 : expected_fileid,
3087 : ret, done, "bad fileid\n");
3088 :
3089 : /*
3090 : * Final list directory, verifying the operations on basefile and stream
3091 : * didn't modify the base file metadata.
3092 : */
3093 2 : f = (struct smb2_find) {
3094 : .in.file.handle = testdirh,
3095 : .in.pattern = "foo",
3096 : .in.max_response_size = 0x1000,
3097 : .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
3098 : .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART,
3099 : };
3100 :
3101 2 : status = smb2_find_level(tree, tree, &f, &count, &d);
3102 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3103 : "smb2_find_level failed\n");
3104 2 : torture_assert_u64_equal_goto(tctx,
3105 : d->id_both_directory_info.file_id,
3106 : expected_fileid,
3107 : ret, done, "bad fileid\n");
3108 :
3109 2 : done:
3110 2 : smb2_util_close(tree, testdirh);
3111 2 : smb2_deltree(tree, DNAME);
3112 2 : talloc_free(mem_ctx);
3113 2 : return ret;
3114 : }
3115 :
3116 4 : static bool test_fileid_unique_object(
3117 : struct torture_context *tctx,
3118 : struct smb2_tree *tree,
3119 : unsigned int num_objs,
3120 : bool create_dirs)
3121 4 : {
3122 4 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
3123 4 : char *fname = NULL;
3124 0 : struct smb2_handle testdirh;
3125 0 : struct smb2_handle h1;
3126 0 : struct smb2_create create;
3127 0 : unsigned int i;
3128 4 : uint64_t fileid_array[num_objs];
3129 0 : NTSTATUS status;
3130 4 : bool ret = true;
3131 :
3132 4 : smb2_deltree(tree, DNAME);
3133 :
3134 4 : status = torture_smb2_testdir(tree, DNAME, &testdirh);
3135 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3136 : "test_fileid_unique failed\n");
3137 4 : smb2_util_close(tree, testdirh);
3138 :
3139 : /* Create num_obj files as rapidly as we can. */
3140 404 : for (i = 0; i < num_objs; i++) {
3141 400 : fname = talloc_asprintf(mem_ctx,
3142 : "%s\\testfile.%u",
3143 : DNAME,
3144 : i);
3145 400 : torture_assert_goto(tctx,
3146 : fname != NULL,
3147 : ret,
3148 : done,
3149 : "talloc failed\n");
3150 :
3151 400 : create = (struct smb2_create) {
3152 : .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
3153 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3154 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3155 : .in.create_disposition = NTCREATEX_DISP_CREATE,
3156 : .in.fname = fname,
3157 : };
3158 :
3159 400 : if (create_dirs) {
3160 200 : create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3161 200 : create.in.create_options = FILE_DIRECTORY_FILE;
3162 : }
3163 :
3164 400 : status = smb2_create(tree, tctx, &create);
3165 400 : if (!NT_STATUS_IS_OK(status)) {
3166 0 : torture_fail(tctx,
3167 : talloc_asprintf(tctx,
3168 : "test file %s could not be created\n",
3169 : fname));
3170 : TALLOC_FREE(fname);
3171 : ret = false;
3172 : goto done;
3173 : }
3174 :
3175 400 : h1 = create.out.file.handle;
3176 400 : smb2_util_close(tree, h1);
3177 400 : TALLOC_FREE(fname);
3178 : }
3179 :
3180 : /*
3181 : * Get the file ids.
3182 : */
3183 404 : for (i = 0; i < num_objs; i++) {
3184 0 : union smb_fileinfo finfo;
3185 :
3186 400 : fname = talloc_asprintf(mem_ctx,
3187 : "%s\\testfile.%u",
3188 : DNAME,
3189 : i);
3190 400 : torture_assert_goto(tctx,
3191 : fname != NULL,
3192 : ret,
3193 : done,
3194 : "talloc failed\n");
3195 :
3196 400 : create = (struct smb2_create) {
3197 : .in.desired_access = SEC_FILE_READ_ATTRIBUTE,
3198 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3199 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3200 : .in.create_disposition = NTCREATEX_DISP_OPEN,
3201 : .in.fname = fname,
3202 : };
3203 :
3204 400 : if (create_dirs) {
3205 200 : create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3206 200 : create.in.create_options = FILE_DIRECTORY_FILE;
3207 : }
3208 :
3209 400 : status = smb2_create(tree, tctx, &create);
3210 400 : if (!NT_STATUS_IS_OK(status)) {
3211 0 : torture_fail(tctx,
3212 : talloc_asprintf(tctx,
3213 : "test file %s could not "
3214 : "be opened: %s\n",
3215 : fname,
3216 : nt_errstr(status)));
3217 : TALLOC_FREE(fname);
3218 : ret = false;
3219 : goto done;
3220 : }
3221 :
3222 400 : h1 = create.out.file.handle;
3223 :
3224 400 : finfo = (union smb_fileinfo) {
3225 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
3226 : .generic.in.file.handle = h1,
3227 : };
3228 :
3229 400 : status = smb2_getinfo_file(tree, tctx, &finfo);
3230 400 : if (!NT_STATUS_IS_OK(status)) {
3231 0 : torture_fail(tctx,
3232 : talloc_asprintf(tctx,
3233 : "failed to get fileid for "
3234 : "test file %s: %s\n",
3235 : fname,
3236 : nt_errstr(status)));
3237 : TALLOC_FREE(fname);
3238 : ret = false;
3239 : goto done;
3240 : }
3241 400 : smb2_util_close(tree, h1);
3242 :
3243 400 : fileid_array[i] = finfo.all_info2.out.file_id;
3244 400 : TALLOC_FREE(fname);
3245 : }
3246 :
3247 : /* All returned fileids must be unique. 100 is small so brute force. */
3248 400 : for (i = 0; i < num_objs - 1; i++) {
3249 0 : unsigned int j;
3250 20196 : for (j = i + 1; j < num_objs; j++) {
3251 19800 : if (fileid_array[i] == fileid_array[j]) {
3252 0 : torture_fail(tctx,
3253 : talloc_asprintf(tctx,
3254 : "fileid %u == fileid %u (0x%"PRIu64")\n",
3255 : i,
3256 : j,
3257 : fileid_array[i]));
3258 : ret = false;
3259 : goto done;
3260 : }
3261 : }
3262 : }
3263 :
3264 4 : done:
3265 :
3266 4 : smb2_util_close(tree, testdirh);
3267 4 : smb2_deltree(tree, DNAME);
3268 4 : talloc_free(mem_ctx);
3269 4 : return ret;
3270 : }
3271 :
3272 2 : static bool test_fileid_unique(
3273 : struct torture_context *tctx,
3274 : struct smb2_tree *tree)
3275 : {
3276 2 : return test_fileid_unique_object(tctx, tree, 100, false);
3277 : }
3278 :
3279 2 : static bool test_fileid_unique_dir(
3280 : struct torture_context *tctx,
3281 : struct smb2_tree *tree)
3282 : {
3283 2 : return test_fileid_unique_object(tctx, tree, 100, true);
3284 : }
3285 :
3286 6 : static bool test_dosattr_tmp_dir(struct torture_context *tctx,
3287 : struct smb2_tree *tree)
3288 : {
3289 6 : bool ret = true;
3290 0 : NTSTATUS status;
3291 0 : struct smb2_create c;
3292 6 : struct smb2_handle h1 = {{0}};
3293 6 : const char *fname = DNAME;
3294 :
3295 6 : smb2_deltree(tree, fname);
3296 6 : smb2_util_rmdir(tree, fname);
3297 :
3298 6 : c = (struct smb2_create) {
3299 : .in.desired_access = SEC_RIGHTS_DIR_ALL,
3300 : .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
3301 : .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
3302 : .in.share_access = NTCREATEX_SHARE_ACCESS_READ |
3303 : NTCREATEX_SHARE_ACCESS_WRITE |
3304 : NTCREATEX_SHARE_ACCESS_DELETE,
3305 : .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
3306 : .in.fname = DNAME,
3307 : };
3308 :
3309 6 : status = smb2_create(tree, tctx, &c);
3310 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3311 : "smb2_create\n");
3312 6 : h1 = c.out.file.handle;
3313 :
3314 : /* Try to set temporary attribute on directory */
3315 6 : SET_ATTRIB(FILE_ATTRIBUTE_TEMPORARY);
3316 :
3317 6 : torture_assert_ntstatus_equal_goto(tctx, status,
3318 : NT_STATUS_INVALID_PARAMETER,
3319 : ret, done,
3320 : "Unexpected setinfo result\n");
3321 :
3322 6 : done:
3323 6 : if (!smb2_util_handle_empty(h1)) {
3324 6 : smb2_util_close(tree, h1);
3325 : }
3326 6 : smb2_util_unlink(tree, fname);
3327 6 : smb2_deltree(tree, fname);
3328 :
3329 6 : return ret;
3330 : }
3331 :
3332 : /*
3333 : test opening quota fakefile handle and returned attributes
3334 : */
3335 6 : static bool test_smb2_open_quota_fake_file(struct torture_context *tctx,
3336 : struct smb2_tree *tree)
3337 : {
3338 6 : const char *fname = "$Extend\\$Quota:$Q:$INDEX_ALLOCATION";
3339 0 : struct smb2_create create;
3340 6 : struct smb2_handle h = {{0}};
3341 0 : NTSTATUS status;
3342 6 : bool ret = true;
3343 :
3344 6 : create = (struct smb2_create) {
3345 : .in.desired_access = SEC_RIGHTS_FILE_READ,
3346 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3347 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3348 : .in.create_disposition = NTCREATEX_DISP_OPEN,
3349 : .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
3350 : .in.fname = fname,
3351 : };
3352 :
3353 6 : status = smb2_create(tree, tree, &create);
3354 6 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3355 : "smb2_create failed\n");
3356 5 : h = create.out.file.handle;
3357 :
3358 5 : torture_assert_u64_equal_goto(tctx,
3359 : create.out.file_attr,
3360 : FILE_ATTRIBUTE_HIDDEN
3361 : | FILE_ATTRIBUTE_SYSTEM
3362 : | FILE_ATTRIBUTE_DIRECTORY
3363 : | FILE_ATTRIBUTE_ARCHIVE,
3364 : ret,
3365 : done,
3366 : "Wrong attributes\n");
3367 :
3368 5 : torture_assert_u64_equal_goto(tctx,
3369 : create.out.create_time, 0,
3370 : ret,
3371 : done,
3372 : "create_time is not 0\n");
3373 5 : torture_assert_u64_equal_goto(tctx,
3374 : create.out.access_time, 0,
3375 : ret,
3376 : done,
3377 : "access_time is not 0\n");
3378 5 : torture_assert_u64_equal_goto(tctx,
3379 : create.out.write_time, 0,
3380 : ret,
3381 : done,
3382 : "write_time is not 0\n");
3383 5 : torture_assert_u64_equal_goto(tctx,
3384 : create.out.change_time, 0,
3385 : ret,
3386 : done,
3387 : "change_time is not 0\n");
3388 :
3389 5 : done:
3390 6 : smb2_util_close(tree, h);
3391 6 : return ret;
3392 : }
3393 :
3394 : /**
3395 : Find Maximum Path Length
3396 : */
3397 0 : static bool generate_path(const size_t len,
3398 : char *buffer,
3399 : const size_t buf_len)
3400 : {
3401 : size_t i;
3402 :
3403 0 : if (len >= buf_len) {
3404 0 : return false;
3405 : }
3406 :
3407 0 : for (i = 0; i < len ; i++) {
3408 0 : buffer[i] = (char)(i % 10) + 48;
3409 : }
3410 0 : buffer[i] = '\0';
3411 0 : return true;
3412 : }
3413 :
3414 6 : static bool test_path_length_test(struct torture_context *tctx,
3415 : struct smb2_tree *tree)
3416 : {
3417 6 : const size_t max_name = 2048;
3418 6 : char *name = talloc_array(tctx, char, max_name);
3419 6 : struct smb2_handle fh = {{0}};
3420 6 : size_t length = 128;
3421 6 : size_t max_file_name = 0;
3422 6 : size_t max_path_length = 0;
3423 6 : char *path_ok = NULL;
3424 6 : char *path_next = NULL;
3425 6 : char *topdir = NULL;
3426 6 : bool is_interactive = torture_setting_bool(tctx, "interactive", false);
3427 0 : NTSTATUS status;
3428 6 : bool ret = true;
3429 :
3430 6 : if (!is_interactive) {
3431 6 : torture_result(tctx, TORTURE_SKIP,
3432 : "Interactive Test: Skipping... "
3433 : "(enable with --interactive)\n");
3434 6 : return ret;
3435 : }
3436 :
3437 0 : torture_comment(tctx, "Testing filename and path lengths\n");
3438 :
3439 : /* Find Longest File Name */
3440 0 : for (length = 128; length < max_name; length++) {
3441 0 : if (!generate_path(length, name, max_name)) {
3442 0 : torture_result(tctx, TORTURE_FAIL,
3443 : "Failed to generate path.");
3444 0 : return false;
3445 : }
3446 :
3447 0 : status = torture_smb2_testfile(tree, name, &fh);
3448 0 : if (!NT_STATUS_IS_OK(status)) {
3449 0 : break;
3450 : }
3451 :
3452 0 : smb2_util_close(tree, fh);
3453 0 : smb2_util_unlink(tree, name);
3454 :
3455 0 : max_file_name = length;
3456 : }
3457 :
3458 0 : torture_assert_int_not_equal_goto(tctx, length, max_name, ret, done,
3459 : "Name too big\n");
3460 :
3461 0 : torture_comment(tctx, "Max file name length: %zu\n", max_file_name);
3462 :
3463 : /* Remove one char that caused the failure above */
3464 0 : name[max_file_name] = '\0';
3465 :
3466 0 : path_ok = talloc_strdup(tree, name);
3467 0 : torture_assert_not_null_goto(tctx, path_ok, ret, done,
3468 : "talloc_strdup failed\n");
3469 :
3470 0 : topdir = talloc_strdup(tree, name);
3471 0 : torture_assert_not_null_goto(tctx, topdir, ret, done,
3472 : "talloc_strdup failed\n");
3473 :
3474 0 : status = smb2_util_mkdir(tree, path_ok);
3475 0 : if (!NT_STATUS_IS_OK(status)) {
3476 0 : torture_comment(tctx, "mkdir [%s] failed: %s\n",
3477 : path_ok, nt_errstr(status));
3478 0 : torture_result(tctx, TORTURE_FAIL, "Initial mkdir failed");
3479 0 : return false;
3480 : }
3481 :
3482 0 : while (true) {
3483 0 : path_next = talloc_asprintf(tctx, "%s\\%s", path_ok, name);
3484 0 : torture_assert_not_null_goto(tctx, path_next, ret, done,
3485 : "talloc_asprintf failed\n");
3486 :
3487 0 : status = smb2_util_mkdir(tree, path_next);
3488 0 : if (!NT_STATUS_IS_OK(status)) {
3489 0 : break;
3490 : }
3491 :
3492 0 : path_ok = path_next;
3493 : }
3494 :
3495 0 : for (length = 1; length < max_name; length++) {
3496 0 : if (!generate_path(length, name, max_name)) {
3497 0 : torture_result(tctx, TORTURE_FAIL,
3498 : "Failed to generate path.");
3499 0 : return false;
3500 : }
3501 :
3502 0 : path_next = talloc_asprintf(tctx, "%s\\%s", path_ok, name);
3503 0 : torture_assert_not_null_goto(tctx, path_next, ret, done,
3504 : "talloc_asprintf failed\n");
3505 :
3506 0 : status = torture_smb2_testfile(tree, path_next, &fh);
3507 0 : if (!NT_STATUS_IS_OK(status)) {
3508 0 : break;
3509 : }
3510 0 : smb2_util_close(tree, fh);
3511 0 : path_ok = path_next;
3512 : }
3513 :
3514 0 : max_path_length = talloc_array_length(path_ok);
3515 :
3516 0 : torture_comment(tctx, "Max path name length: %zu\n", max_path_length);
3517 :
3518 0 : done:
3519 0 : return ret;
3520 : }
3521 :
3522 : /*
3523 : basic testing of SMB2 read
3524 : */
3525 2354 : struct torture_suite *torture_smb2_create_init(TALLOC_CTX *ctx)
3526 : {
3527 2354 : struct torture_suite *suite = torture_suite_create(ctx, "create");
3528 :
3529 2354 : torture_suite_add_1smb2_test(suite, "gentest", test_create_gentest);
3530 2354 : torture_suite_add_1smb2_test(suite, "blob", test_create_blob);
3531 2354 : torture_suite_add_1smb2_test(suite, "open", test_smb2_open);
3532 2354 : torture_suite_add_1smb2_test(suite, "brlocked", test_smb2_open_brlocked);
3533 2354 : torture_suite_add_1smb2_test(suite, "multi", test_smb2_open_multi);
3534 2354 : torture_suite_add_1smb2_test(suite, "delete", test_smb2_open_for_delete);
3535 2354 : torture_suite_add_1smb2_test(suite, "leading-slash", test_smb2_leading_slash);
3536 2354 : torture_suite_add_1smb2_test(suite, "impersonation", test_smb2_impersonation_level);
3537 2354 : torture_suite_add_1smb2_test(suite, "aclfile", test_create_acl_file);
3538 2354 : torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir);
3539 2354 : torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl);
3540 2354 : torture_suite_add_1smb2_test(suite, "mkdir-dup", test_mkdir_dup);
3541 2354 : torture_suite_add_1smb2_test(suite, "dir-alloc-size", test_dir_alloc_size);
3542 2354 : torture_suite_add_1smb2_test(suite, "dosattr_tmp_dir", test_dosattr_tmp_dir);
3543 2354 : torture_suite_add_1smb2_test(suite, "quota-fake-file", test_smb2_open_quota_fake_file);
3544 2354 : torture_suite_add_1smb2_test(suite, "path-length", test_path_length_test);
3545 2354 : torture_suite_add_1smb2_test(suite, "bench-path-contention-shared", test_smb2_bench_path_contention_shared);
3546 :
3547 2354 : suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
3548 :
3549 2354 : return suite;
3550 : }
3551 :
3552 2354 : struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx)
3553 : {
3554 2354 : struct torture_suite *suite = torture_suite_create(ctx, "twrp");
3555 :
3556 2354 : torture_suite_add_1smb2_test(suite, "write", test_twrp_write);
3557 2354 : torture_suite_add_1smb2_test(suite, "stream", test_twrp_stream);
3558 2354 : torture_suite_add_1smb2_test(suite, "openroot", test_twrp_openroot);
3559 2354 : torture_suite_add_1smb2_test(suite, "listdir", test_twrp_listdir);
3560 :
3561 2354 : suite->description = talloc_strdup(suite, "SMB2-TWRP tests");
3562 :
3563 2354 : return suite;
3564 : }
3565 :
3566 : /*
3567 : basic testing of SMB2 File-IDs
3568 : */
3569 2354 : struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx)
3570 : {
3571 2354 : struct torture_suite *suite = torture_suite_create(ctx, "fileid");
3572 :
3573 2354 : torture_suite_add_1smb2_test(suite, "fileid", test_fileid);
3574 2354 : torture_suite_add_1smb2_test(suite, "fileid-dir", test_fileid_dir);
3575 2354 : torture_suite_add_1smb2_test(suite, "unique", test_fileid_unique);
3576 2354 : torture_suite_add_1smb2_test(suite, "unique-dir", test_fileid_unique_dir);
3577 :
3578 2354 : suite->description = talloc_strdup(suite, "SMB2-FILEID tests");
3579 :
3580 2354 : return suite;
3581 : }
3582 :
3583 2 : static bool test_no_stream(struct torture_context *tctx,
3584 : struct smb2_tree *tree)
3585 : {
3586 0 : struct smb2_create c;
3587 0 : NTSTATUS status;
3588 2 : bool ret = true;
3589 2 : const char *names[] = {
3590 : "test_no_stream::$DATA",
3591 : "test_no_stream::foooooooooooo",
3592 : "test_no_stream:stream",
3593 : "test_no_stream:stream:$DATA",
3594 : NULL
3595 : };
3596 0 : int i;
3597 :
3598 10 : for (i = 0; names[i] != NULL; i++) {
3599 8 : c = (struct smb2_create) {
3600 : .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED,
3601 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
3602 : .in.create_disposition = NTCREATEX_DISP_OPEN,
3603 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
3604 8 : .in.fname = names[i],
3605 : };
3606 :
3607 8 : status = smb2_create(tree, tctx, &c);
3608 8 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
3609 0 : torture_comment(
3610 : tctx, "Expected NT_STATUS_OBJECT_NAME_INVALID, "
3611 : "got %s, name: '%s'\n",
3612 : nt_errstr(status), names[i]);
3613 0 : torture_fail_goto(tctx, done, "Bad create result\n");
3614 : }
3615 : }
3616 2 : done:
3617 2 : return ret;
3618 : }
3619 :
3620 2354 : struct torture_suite *torture_smb2_create_no_streams_init(TALLOC_CTX *ctx)
3621 : {
3622 2354 : struct torture_suite *suite = torture_suite_create(ctx, "create_no_streams");
3623 :
3624 2354 : torture_suite_add_1smb2_test(suite, "no_stream", test_no_stream);
3625 :
3626 2354 : suite->description = talloc_strdup(suite, "SMB2-CREATE stream test on share without streams support");
3627 :
3628 2354 : return suite;
3629 : }
|