2 Unix SMB/CIFS implementation.
4 test suite for SMB2 sharemodes
6 Copyright (C) Christof Schmitt 2017
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "libcli/security/security.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "lib/util/smb_strtox.h"
31 #define BASEDIRHOLD "sharemode_hold_test"
33 struct hold_sharemode_info
{
34 const char *sharemode
;
36 struct smb2_handle handle
;
37 } hold_sharemode_table
[] = {
40 .filename
= BASEDIRHOLD
"\\N",
44 .filename
= BASEDIRHOLD
"\\R",
48 .filename
= BASEDIRHOLD
"\\W",
52 .filename
= BASEDIRHOLD
"\\D",
56 .filename
= BASEDIRHOLD
"\\RW",
60 .filename
= BASEDIRHOLD
"\\RD",
64 .filename
= BASEDIRHOLD
"\\WD",
68 .filename
= BASEDIRHOLD
"\\RWD",
72 static void signal_handler(struct tevent_context
*ev
,
73 struct tevent_signal
*se
,
79 struct torture_context
*tctx
= private_data
;
81 torture_comment(tctx
, "Received signal %d\n", signum
);
85 * Used for manual testing of sharemodes - especially interaction with
86 * other filesystems (such as NFS and local access). The scenario is
87 * that this test holds files open and then concurrent access to the same
88 * files outside of Samba can be tested.
90 bool torture_smb2_hold_sharemode(struct torture_context
*tctx
)
92 struct tevent_context
*ev
= tctx
->ev
;
93 struct smb2_tree
*tree
= NULL
;
94 struct smb2_handle dir_handle
;
95 struct tevent_signal
*s
;
100 if (!torture_smb2_connection(tctx
, &tree
)) {
101 torture_comment(tctx
, "Initializing smb2 connection failed.\n");
105 s
= tevent_add_signal(ev
, tctx
, SIGINT
, 0, signal_handler
, tctx
);
106 torture_assert_not_null_goto(tctx
, s
, ret
, done
,
107 "Error registering signal handler.");
109 torture_comment(tctx
, "Setting up open files with sharemodes in %s\n",
112 status
= torture_smb2_testdir(tree
, BASEDIRHOLD
, &dir_handle
);
113 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
114 "Error creating directory.");
116 for (i
= 0; i
< ARRAY_SIZE(hold_sharemode_table
); i
++) {
117 struct hold_sharemode_info
*info
= &hold_sharemode_table
[i
];
118 struct smb2_create create
= { 0 };
120 create
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
121 create
.in
.alloc_size
= 0;
122 create
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
123 create
.in
.share_access
=
124 smb2_util_share_access(info
->sharemode
);
125 create
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
126 create
.in
.create_options
= 0;
127 create
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
128 create
.in
.security_flags
= 0;
129 create
.in
.fname
= info
->filename
;
130 create
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
131 create
.in
.oplock_level
= SMB2_OPLOCK_LEVEL_NONE
;
133 torture_comment(tctx
, "opening %s\n", info
->filename
);
135 status
= smb2_create(tree
, tctx
, &create
);
137 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
138 "CREATE file failed\n");
140 info
->handle
= create
.out
.file
.handle
;
143 torture_comment(tctx
, "Waiting for SIGINT (ctrl-c)\n");
144 tevent_loop_wait(ev
);
146 torture_comment(tctx
, "Closing and deleting files\n");
148 for (i
= 0; i
< ARRAY_SIZE(hold_sharemode_table
); i
++) {
149 struct hold_sharemode_info
*info
= &hold_sharemode_table
[i
];
151 union smb_setfileinfo sfinfo
= { };
153 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
154 sfinfo
.generic
.level
= RAW_SFILEINFO_DISPOSITION_INFORMATION
;
155 sfinfo
.generic
.in
.file
.handle
= info
->handle
;
156 status
= smb2_setinfo_file(tree
, &sfinfo
);
157 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
160 status
= smb2_util_close(tree
, info
->handle
);
161 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
162 torture_comment(tctx
, "File %s not found, could have "
163 "been deleted outside of SMB\n",
167 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
172 smb2_deltree(tree
, BASEDIRHOLD
);
177 * Used for manual testing of sharemodes, especially interaction with
178 * file systems that can enforce sharemodes. The scenario here is that
179 * a file is already open outside of Samba with a sharemode and this
180 * can be used to test accessing the same file from Samba.
182 bool torture_smb2_check_sharemode(struct torture_context
*tctx
)
184 const char *sharemode_string
, *access_string
, *filename
, *operation
;
185 uint32_t sharemode
, access
;
186 struct smb2_tree
*tree
;
187 struct smb2_create create
= { 0 };
192 sharemode_string
= torture_setting_string(tctx
, "sharemode", "RWD");
193 sharemode
= smb2_util_share_access(sharemode_string
);
195 access_string
= torture_setting_string(tctx
, "access", "0xf01ff");
196 access
= smb_strtoul(access_string
, NULL
, 0, &error
, SMB_STR_STANDARD
);
198 torture_comment(tctx
, "Initializing access failed.\n");
202 filename
= torture_setting_string(tctx
, "filename", "testfile");
203 operation
= torture_setting_string(tctx
, "operation", "WD");
205 if (!torture_smb2_connection(tctx
, &tree
)) {
206 torture_comment(tctx
, "Initializing smb2 connection failed.\n");
210 create
.in
.desired_access
= access
;
211 create
.in
.alloc_size
= 0;
212 create
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
213 create
.in
.share_access
= sharemode
;
214 create
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
215 create
.in
.create_options
= 0;
216 create
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
217 create
.in
.security_flags
= 0;
218 create
.in
.fname
= filename
;
219 create
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
220 create
.in
.oplock_level
= SMB2_OPLOCK_LEVEL_NONE
;
222 status
= smb2_create(tree
, tctx
, &create
);
223 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
226 if (strchr(operation
, 'R')) {
227 struct smb2_read read
= { 0 };
229 read
.in
.file
.handle
= create
.out
.file
.handle
;
233 status
= smb2_read(tree
, tctx
, &read
);
234 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
238 if (strchr(operation
, 'W')) {
240 status
= smb2_util_write(tree
, create
.out
.file
.handle
,
241 &buf
, 0, sizeof(buf
));
242 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
246 if (strchr(operation
, 'D')) {
247 union smb_setfileinfo sfinfo
= { };
249 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
250 sfinfo
.generic
.level
= RAW_SFILEINFO_DISPOSITION_INFORMATION
;
251 sfinfo
.generic
.in
.file
.handle
= create
.out
.file
.handle
;
253 status
= smb2_setinfo_file(tree
, &sfinfo
);
254 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
257 status
= smb2_util_close(tree
, create
.out
.file
.handle
);
258 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
266 struct sharemode_info
{
267 const char *sharemode
;
268 uint32_t access_mask
;
270 } sharemode_table
[] = {
273 * Basic tests, check each permission bit against every
274 * possible sharemode combination.
277 { "R", SEC_FILE_READ_DATA
, true, },
278 { "R", SEC_FILE_WRITE_DATA
, false, },
279 { "R", SEC_FILE_APPEND_DATA
, false, },
280 { "R", SEC_FILE_READ_EA
, true, },
281 { "R", SEC_FILE_WRITE_EA
, true, },
282 { "R", SEC_FILE_EXECUTE
, true, },
283 { "R", SEC_FILE_READ_ATTRIBUTE
, true, },
284 { "R", SEC_FILE_WRITE_ATTRIBUTE
, true, },
285 { "R", SEC_STD_DELETE
, false, },
286 { "R", SEC_STD_READ_CONTROL
, true, },
287 { "R", SEC_STD_WRITE_DAC
, true, },
288 { "R", SEC_STD_WRITE_OWNER
, true, },
289 { "R", SEC_STD_SYNCHRONIZE
, true, },
291 { "W", SEC_FILE_READ_DATA
, false },
292 { "W", SEC_FILE_WRITE_DATA
, true, },
293 { "W", SEC_FILE_APPEND_DATA
, true, },
294 { "W", SEC_FILE_READ_EA
, true, },
295 { "W", SEC_FILE_WRITE_EA
, true, },
296 { "W", SEC_FILE_EXECUTE
, false, },
297 { "W", SEC_FILE_READ_ATTRIBUTE
, true, },
298 { "W", SEC_FILE_WRITE_ATTRIBUTE
, true, },
299 { "W", SEC_STD_DELETE
, false, },
300 { "W", SEC_STD_READ_CONTROL
, true, },
301 { "W", SEC_STD_WRITE_DAC
, true, },
302 { "W", SEC_STD_WRITE_OWNER
, true, },
303 { "W", SEC_STD_SYNCHRONIZE
, true, },
305 { "D", SEC_FILE_READ_DATA
, false },
306 { "D", SEC_FILE_WRITE_DATA
, false },
307 { "D", SEC_FILE_APPEND_DATA
, false },
308 { "D", SEC_FILE_READ_EA
, true, },
309 { "D", SEC_FILE_WRITE_EA
, true, },
310 { "D", SEC_FILE_EXECUTE
, false, },
311 { "D", SEC_FILE_READ_ATTRIBUTE
, true, },
312 { "D", SEC_FILE_WRITE_ATTRIBUTE
, true, },
313 { "D", SEC_STD_DELETE
, true, },
314 { "D", SEC_STD_READ_CONTROL
, true, },
315 { "D", SEC_STD_WRITE_DAC
, true, },
316 { "D", SEC_STD_WRITE_OWNER
, true, },
317 { "D", SEC_STD_SYNCHRONIZE
, true, },
319 { "RW", SEC_FILE_READ_DATA
, true, },
320 { "RW", SEC_FILE_WRITE_DATA
, true, },
321 { "RW", SEC_FILE_APPEND_DATA
, true, },
322 { "RW", SEC_FILE_READ_EA
, true, },
323 { "RW", SEC_FILE_WRITE_EA
, true, },
324 { "RW", SEC_FILE_EXECUTE
, true, },
325 { "RW", SEC_FILE_READ_ATTRIBUTE
, true, },
326 { "RW", SEC_FILE_WRITE_ATTRIBUTE
, true, },
327 { "RW", SEC_STD_DELETE
, false, },
328 { "RW", SEC_STD_READ_CONTROL
, true, },
329 { "RW", SEC_STD_WRITE_DAC
, true, },
330 { "RW", SEC_STD_WRITE_OWNER
, true, },
331 { "RW", SEC_STD_SYNCHRONIZE
, true, },
333 { "RD", SEC_FILE_READ_DATA
, true, },
334 { "RD", SEC_FILE_WRITE_DATA
, false, },
335 { "RD", SEC_FILE_APPEND_DATA
, false, },
336 { "RD", SEC_FILE_READ_EA
, true, },
337 { "RD", SEC_FILE_WRITE_EA
, true, },
338 { "RD", SEC_FILE_EXECUTE
, true, },
339 { "RD", SEC_FILE_READ_ATTRIBUTE
, true, },
340 { "RD", SEC_FILE_WRITE_ATTRIBUTE
, true, },
341 { "RD", SEC_STD_DELETE
, true, },
342 { "RD", SEC_STD_READ_CONTROL
, true, },
343 { "RD", SEC_STD_WRITE_DAC
, true, },
344 { "RD", SEC_STD_WRITE_OWNER
, true, },
345 { "RD", SEC_STD_SYNCHRONIZE
, true, },
347 { "WD", SEC_FILE_READ_DATA
, false },
348 { "WD", SEC_FILE_WRITE_DATA
, true, },
349 { "WD", SEC_FILE_APPEND_DATA
, true, },
350 { "WD", SEC_FILE_READ_EA
, true },
351 { "WD", SEC_FILE_WRITE_EA
, true, },
352 { "WD", SEC_FILE_EXECUTE
, false },
353 { "WD", SEC_FILE_READ_ATTRIBUTE
, true, },
354 { "WD", SEC_FILE_WRITE_ATTRIBUTE
, true, },
355 { "WD", SEC_STD_DELETE
, true, },
356 { "WD", SEC_STD_READ_CONTROL
, true, },
357 { "WD", SEC_STD_WRITE_DAC
, true, },
358 { "WD", SEC_STD_WRITE_OWNER
, true, },
359 { "WD", SEC_STD_SYNCHRONIZE
, true, },
361 { "RWD", SEC_FILE_READ_DATA
, true },
362 { "RWD", SEC_FILE_WRITE_DATA
, true, },
363 { "RWD", SEC_FILE_APPEND_DATA
, true, },
364 { "RWD", SEC_FILE_READ_EA
, true },
365 { "RWD", SEC_FILE_WRITE_EA
, true, },
366 { "RWD", SEC_FILE_EXECUTE
, true, },
367 { "RWD", SEC_FILE_READ_ATTRIBUTE
, true, },
368 { "RWD", SEC_FILE_WRITE_ATTRIBUTE
, true, },
369 { "RWD", SEC_STD_DELETE
, true, },
370 { "RWD", SEC_STD_READ_CONTROL
, true, },
371 { "RWD", SEC_STD_WRITE_DAC
, true, },
372 { "RWD", SEC_STD_WRITE_OWNER
, true, },
373 { "RWD", SEC_STD_SYNCHRONIZE
, true, },
376 * Some more interesting cases. Always request READ or WRITE
377 * access, as that will trigger the opening of a file
378 * description in Samba. This especially useful for file
379 * systems that enforce share modes on open file descriptors.
382 { "R", SEC_FILE_READ_DATA
, true, },
383 { "R", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
, false, },
384 { "R", SEC_FILE_READ_DATA
|SEC_FILE_APPEND_DATA
, false, },
385 { "R", SEC_FILE_READ_DATA
|SEC_FILE_READ_EA
, true, },
386 { "R", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_EA
, true, },
387 { "R", SEC_FILE_READ_DATA
|SEC_FILE_EXECUTE
, true, },
388 { "R", SEC_FILE_READ_DATA
|SEC_FILE_READ_ATTRIBUTE
, true, },
389 { "R", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_ATTRIBUTE
, true, },
390 { "R", SEC_FILE_READ_DATA
|SEC_STD_DELETE
, false, },
391 { "R", SEC_FILE_READ_DATA
|SEC_STD_READ_CONTROL
, true, },
392 { "R", SEC_FILE_READ_DATA
|SEC_STD_WRITE_DAC
, true, },
393 { "R", SEC_FILE_READ_DATA
|SEC_STD_WRITE_OWNER
, true, },
394 { "R", SEC_FILE_READ_DATA
|SEC_STD_SYNCHRONIZE
, true, },
396 { "W", SEC_FILE_WRITE_DATA
|SEC_FILE_READ_DATA
, false, },
397 { "W", SEC_FILE_WRITE_DATA
, true, },
398 { "W", SEC_FILE_WRITE_DATA
|SEC_FILE_APPEND_DATA
, true, },
399 { "W", SEC_FILE_WRITE_DATA
|SEC_FILE_READ_EA
, true, },
400 { "W", SEC_FILE_WRITE_DATA
|SEC_FILE_WRITE_EA
, true, },
401 { "W", SEC_FILE_WRITE_DATA
|SEC_FILE_EXECUTE
, false, },
402 { "W", SEC_FILE_WRITE_DATA
|SEC_FILE_READ_ATTRIBUTE
, true, },
403 { "W", SEC_FILE_WRITE_DATA
|SEC_FILE_WRITE_ATTRIBUTE
, true, },
404 { "W", SEC_FILE_WRITE_DATA
|SEC_STD_DELETE
, false, },
405 { "W", SEC_FILE_WRITE_DATA
|SEC_STD_READ_CONTROL
, true, },
406 { "W", SEC_FILE_WRITE_DATA
|SEC_STD_WRITE_DAC
, true, },
407 { "W", SEC_FILE_WRITE_DATA
|SEC_STD_WRITE_OWNER
, true, },
408 { "W", SEC_FILE_WRITE_DATA
|SEC_STD_SYNCHRONIZE
, true, },
410 { "RW", SEC_FILE_READ_DATA
, true, },
411 { "RW", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
, true, },
412 { "RW", SEC_FILE_READ_DATA
|SEC_FILE_APPEND_DATA
, true, },
413 { "RW", SEC_FILE_READ_DATA
|SEC_FILE_READ_EA
, true, },
414 { "RW", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_EA
, true, },
415 { "RW", SEC_FILE_READ_DATA
|SEC_FILE_EXECUTE
, true, },
416 { "RW", SEC_FILE_READ_DATA
|SEC_FILE_READ_ATTRIBUTE
, true, },
417 { "RW", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_ATTRIBUTE
, true, },
418 { "RW", SEC_FILE_READ_DATA
|SEC_STD_DELETE
, false, },
419 { "RW", SEC_FILE_READ_DATA
|SEC_STD_READ_CONTROL
, true, },
420 { "RW", SEC_FILE_READ_DATA
|SEC_STD_WRITE_DAC
, true, },
421 { "RW", SEC_FILE_READ_DATA
|SEC_STD_WRITE_OWNER
, true, },
422 { "RW", SEC_FILE_READ_DATA
|SEC_STD_SYNCHRONIZE
, true, },
424 { "RD", SEC_FILE_READ_DATA
, true, },
425 { "RD", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
, false, },
426 { "RD", SEC_FILE_READ_DATA
|SEC_FILE_APPEND_DATA
, false, },
427 { "RD", SEC_FILE_READ_DATA
|SEC_FILE_READ_EA
, true },
428 { "RD", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_EA
, true, },
429 { "RD", SEC_FILE_READ_DATA
|SEC_FILE_EXECUTE
, true, },
430 { "RD", SEC_FILE_READ_DATA
|SEC_FILE_READ_ATTRIBUTE
, true, },
431 { "RD", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_ATTRIBUTE
, true, },
432 { "RD", SEC_FILE_READ_DATA
|SEC_STD_DELETE
, true, },
433 { "RD", SEC_FILE_READ_DATA
|SEC_STD_READ_CONTROL
, true, },
434 { "RD", SEC_FILE_READ_DATA
|SEC_STD_WRITE_DAC
, true, },
435 { "RD", SEC_FILE_READ_DATA
|SEC_STD_WRITE_OWNER
, true, },
436 { "RD", SEC_FILE_READ_DATA
|SEC_STD_SYNCHRONIZE
, true, },
438 { "WD", SEC_FILE_WRITE_DATA
|SEC_FILE_READ_DATA
, false },
439 { "WD", SEC_FILE_WRITE_DATA
, true, },
440 { "WD", SEC_FILE_WRITE_DATA
|SEC_FILE_APPEND_DATA
, true, },
441 { "WD", SEC_FILE_WRITE_DATA
|SEC_FILE_READ_EA
, true },
442 { "WD", SEC_FILE_WRITE_DATA
|SEC_FILE_WRITE_EA
, true, },
443 { "WD", SEC_FILE_WRITE_DATA
|SEC_FILE_EXECUTE
, false },
444 { "WD", SEC_FILE_WRITE_DATA
|SEC_FILE_READ_ATTRIBUTE
, true, },
445 { "WD", SEC_FILE_WRITE_DATA
|SEC_FILE_WRITE_ATTRIBUTE
, true, },
446 { "WD", SEC_FILE_WRITE_DATA
|SEC_STD_DELETE
, true, },
447 { "WD", SEC_FILE_WRITE_DATA
|SEC_STD_READ_CONTROL
, true, },
448 { "WD", SEC_FILE_WRITE_DATA
|SEC_STD_WRITE_DAC
, true, },
449 { "WD", SEC_FILE_WRITE_DATA
|SEC_STD_WRITE_OWNER
, true, },
450 { "WD", SEC_FILE_WRITE_DATA
|SEC_STD_SYNCHRONIZE
, true, },
452 { "RWD", SEC_FILE_READ_DATA
, true },
453 { "RWD", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
, true, },
454 { "RWD", SEC_FILE_READ_DATA
|SEC_FILE_APPEND_DATA
, true, },
455 { "RWD", SEC_FILE_READ_DATA
|SEC_FILE_READ_EA
, true, },
456 { "RWD", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_EA
, true, },
457 { "RWD", SEC_FILE_READ_DATA
|SEC_FILE_EXECUTE
, true, },
458 { "RWD", SEC_FILE_READ_DATA
|SEC_FILE_READ_ATTRIBUTE
, true, },
459 { "RWD", SEC_FILE_READ_DATA
|SEC_FILE_WRITE_ATTRIBUTE
, true, },
460 { "RWD", SEC_FILE_READ_DATA
|SEC_STD_DELETE
, true, },
461 { "RWD", SEC_FILE_READ_DATA
|SEC_STD_READ_CONTROL
, true, },
462 { "RWD", SEC_FILE_READ_DATA
|SEC_STD_WRITE_DAC
, true, },
463 { "RWD", SEC_FILE_READ_DATA
|SEC_STD_WRITE_OWNER
, true, },
464 { "RWD", SEC_FILE_READ_DATA
|SEC_STD_SYNCHRONIZE
, true, },
468 * Test conflicting sharemodes through SMB2: First open takes a
469 * sharemode, second open with potentially conflicting access.
471 static bool test_smb2_sharemode_access(struct torture_context
*tctx
,
472 struct smb2_tree
*tree1
,
473 struct smb2_tree
*tree2
)
475 const char *fname
= "test_sharemode";
480 for (i
= 0; i
< ARRAY_SIZE(sharemode_table
); i
++) {
481 struct sharemode_info
*info
= &sharemode_table
[i
];
482 struct smb2_create create1
= { 0 }, create2
= { 0 };
483 NTSTATUS expected_status
;
485 torture_comment(tctx
, "index %3d, sharemode %3s, "
486 "access mask 0x%06x\n",
487 i
, info
->sharemode
, info
->access_mask
);
489 create1
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
490 create1
.in
.alloc_size
= 0;
491 create1
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
492 create1
.in
.share_access
=
493 smb2_util_share_access(info
->sharemode
);
494 create1
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
495 create1
.in
.create_options
= 0;
496 create1
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
497 create1
.in
.fname
= fname
;
498 create1
.in
.security_flags
= 0;
499 create1
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
500 create1
.in
.oplock_level
= SMB2_OPLOCK_LEVEL_NONE
;
502 status
= smb2_create(tree1
, tctx
, &create1
);
504 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
505 "CREATE file failed\n");
507 create2
.in
.desired_access
= info
->access_mask
;
508 create2
.in
.alloc_size
= 0;
509 create2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
510 create2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
511 NTCREATEX_SHARE_ACCESS_WRITE
|
512 NTCREATEX_SHARE_ACCESS_DELETE
;
513 create2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
514 create2
.in
.create_options
= 0;
515 create2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
516 create2
.in
.fname
= fname
;
517 create2
.in
.security_flags
= 0;
518 create2
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
519 create2
.in
.oplock_level
= SMB2_OPLOCK_LEVEL_NONE
;
521 status
= smb2_create(tree2
, tctx
, &create2
);
522 expected_status
= info
->expect_ok
?
523 NT_STATUS_OK
: NT_STATUS_SHARING_VIOLATION
;
524 torture_assert_ntstatus_equal_goto(tctx
, status
,
525 expected_status
, ret
,
526 done
, "Unexpected status on "
529 status
= smb2_util_close(tree1
, create1
.out
.file
.handle
);
530 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
534 if (info
->expect_ok
) {
535 status
= smb2_util_close(tree2
, create2
.out
.file
.handle
);
536 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
543 smb2_util_unlink(tree1
, fname
);
548 * Test conflicting sharemodes through SMB2: First open file with
549 * different access masks, second open requests potentially conflicting
552 static bool test_smb2_access_sharemode(struct torture_context
*tctx
,
553 struct smb2_tree
*tree1
,
554 struct smb2_tree
*tree2
)
556 const char *fname
= "test_sharemode";
561 for (i
= 0; i
< ARRAY_SIZE(sharemode_table
); i
++) {
562 struct sharemode_info
*info
= &sharemode_table
[i
];
563 struct smb2_create create1
= { 0 }, create2
= { 0 };
564 NTSTATUS expected_status
;
566 torture_comment(tctx
, "index %3d, access mask 0x%06x, "
568 i
, info
->access_mask
, info
->sharemode
);
570 create1
.in
.desired_access
= info
->access_mask
;
571 create1
.in
.alloc_size
= 0;
572 create1
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
573 create1
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
574 NTCREATEX_SHARE_ACCESS_WRITE
|
575 NTCREATEX_SHARE_ACCESS_DELETE
;
576 create1
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
577 create1
.in
.create_options
= 0;
578 create1
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
579 create1
.in
.fname
= fname
;
580 create1
.in
.security_flags
= 0;
581 create1
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
582 create1
.in
.oplock_level
= SMB2_OPLOCK_LEVEL_NONE
;
584 status
= smb2_create(tree1
, tctx
, &create1
);
586 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
587 "CREATE file failed\n");
589 create2
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
590 create2
.in
.alloc_size
= 0;
591 create2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
592 create2
.in
.share_access
=
593 smb2_util_share_access(info
->sharemode
);
594 create2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
595 create2
.in
.create_options
= 0;
596 create2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
597 create2
.in
.fname
= fname
;
598 create2
.in
.security_flags
= 0;
599 create2
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
600 create2
.in
.oplock_level
= SMB2_OPLOCK_LEVEL_NONE
;
602 status
= smb2_create(tree2
, tctx
, &create2
);
604 expected_status
= info
->expect_ok
?
605 NT_STATUS_OK
: NT_STATUS_SHARING_VIOLATION
;
606 torture_assert_ntstatus_equal_goto(tctx
, status
,
607 expected_status
, ret
,
608 done
, "Unexpected status on "
611 status
= smb2_util_close(tree1
, create1
.out
.file
.handle
);
612 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
616 if (info
->expect_ok
) {
617 status
= smb2_util_close(tree2
, create2
.out
.file
.handle
);
618 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
625 smb2_util_unlink(tree1
, fname
);
630 * Test initial stat open with share nothing doesn't trigger SHARING_VIOLTION
633 static bool test_smb2_bug14375(struct torture_context
*tctx
,
634 struct smb2_tree
*tree
)
636 const char *fname
= "test_bug14375";
637 struct smb2_create cr1
= {};
638 struct smb2_create cr2
= {};
639 struct smb2_create cr3
= {};
643 smb2_util_unlink(tree
, fname
);
645 cr1
= (struct smb2_create
) {
646 .in
.desired_access
= SEC_FILE_READ_ATTRIBUTE
,
647 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
648 .in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
,
649 .in
.create_disposition
= NTCREATEX_DISP_CREATE
,
650 .in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
,
654 status
= smb2_create(tree
, tctx
, &cr1
);
655 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
656 "CREATE file failed\n");
658 cr2
= (struct smb2_create
) {
659 .in
.desired_access
= SEC_FILE_READ_DATA
,
660 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
661 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
662 .in
.create_disposition
= NTCREATEX_DISP_OPEN
,
663 .in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
,
667 status
= smb2_create(tree
, tctx
, &cr2
);
668 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
669 "CREATE file failed\n");
671 cr3
= (struct smb2_create
) {
672 .in
.desired_access
= SEC_FILE_READ_DATA
,
673 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
674 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
675 .in
.create_disposition
= NTCREATEX_DISP_OPEN
,
676 .in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
,
680 status
= smb2_create(tree
, tctx
, &cr3
);
681 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
682 "CREATE file failed\n");
684 status
= smb2_util_close(tree
, cr1
.out
.file
.handle
);
685 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
686 "CLOSE file failed\n");
687 status
= smb2_util_close(tree
, cr2
.out
.file
.handle
);
688 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
689 "CLOSE file failed\n");
690 status
= smb2_util_close(tree
, cr3
.out
.file
.handle
);
691 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
692 "CLOSE file failed\n");
694 cr1
= (struct smb2_create
) {
695 .in
.desired_access
= SEC_FILE_READ_DATA
,
696 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
697 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
698 .in
.create_disposition
= NTCREATEX_DISP_OPEN
,
699 .in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
,
703 status
= smb2_create(tree
, tctx
, &cr1
);
704 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
705 "CREATE file failed\n");
707 cr2
= (struct smb2_create
) {
708 .in
.desired_access
= SEC_FILE_READ_ATTRIBUTE
,
709 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
710 .in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
,
711 .in
.create_disposition
= NTCREATEX_DISP_OPEN
,
712 .in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
,
716 status
= smb2_create(tree
, tctx
, &cr2
);
717 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
718 "CREATE file failed\n");
720 cr3
= (struct smb2_create
) {
721 .in
.desired_access
= SEC_FILE_READ_DATA
,
722 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
723 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
724 .in
.create_disposition
= NTCREATEX_DISP_OPEN
,
725 .in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
,
729 status
= smb2_create(tree
, tctx
, &cr3
);
730 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
731 "CREATE file failed\n");
734 smb2_util_close(tree
, cr1
.out
.file
.handle
);
735 smb2_util_close(tree
, cr2
.out
.file
.handle
);
736 smb2_util_close(tree
, cr3
.out
.file
.handle
);
737 smb2_util_unlink(tree
, fname
);
741 struct torture_suite
*torture_smb2_sharemode_init(TALLOC_CTX
*ctx
)
743 struct torture_suite
*suite
= torture_suite_create(ctx
, "sharemode");
745 torture_suite_add_2smb2_test(suite
, "sharemode-access",
746 test_smb2_sharemode_access
);
747 torture_suite_add_2smb2_test(suite
, "access-sharemode",
748 test_smb2_access_sharemode
);
749 torture_suite_add_1smb2_test(suite
, "bug14375",
752 suite
->description
= talloc_strdup(suite
, "SMB2-SHAREMODE tests");