ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / smb2 / sharemode.c
blobb503378e9c382a3be51066d21742816d4ec38bb5
1 /*
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/>.
22 #include "includes.h"
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"
29 #include <tevent.h>
31 #define BASEDIRHOLD "sharemode_hold_test"
33 struct hold_sharemode_info {
34 const char *sharemode;
35 const char *filename;
36 struct smb2_handle handle;
37 } hold_sharemode_table[] = {
39 .sharemode = "",
40 .filename = BASEDIRHOLD "\\N",
43 .sharemode = "R",
44 .filename = BASEDIRHOLD "\\R",
47 .sharemode = "W",
48 .filename = BASEDIRHOLD "\\W",
51 .sharemode = "D",
52 .filename = BASEDIRHOLD "\\D",
55 .sharemode = "RW",
56 .filename = BASEDIRHOLD "\\RW",
59 .sharemode = "RD",
60 .filename = BASEDIRHOLD "\\RD",
63 .sharemode = "WD",
64 .filename = BASEDIRHOLD "\\WD",
67 .sharemode = "RWD",
68 .filename = BASEDIRHOLD "\\RWD",
72 static void signal_handler(struct tevent_context *ev,
73 struct tevent_signal *se,
74 int signum,
75 int count,
76 void *siginfo,
77 void *private_data)
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;
96 NTSTATUS status;
97 bool ret = true;
98 int i;
100 if (!torture_smb2_connection(tctx, &tree)) {
101 torture_comment(tctx, "Initializing smb2 connection failed.\n");
102 return false;
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",
110 BASEDIRHOLD);
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,
158 "SETINFO failed\n");
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",
164 info->filename);
165 continue;
167 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
168 "CLOSE failed\n");
171 done:
172 smb2_deltree(tree, BASEDIRHOLD);
173 return ret;
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 };
188 NTSTATUS status;
189 bool ret = true;
190 int error = 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);
197 if (error != 0) {
198 torture_comment(tctx, "Initializing access failed.\n");
199 return false;
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");
207 return false;
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,
224 "CREATE failed\n");
226 if (strchr(operation, 'R')) {
227 struct smb2_read read = { 0 };
229 read.in.file.handle = create.out.file.handle;
230 read.in.offset = 0;
231 read.in.length = 1;
233 status = smb2_read(tree, tctx, &read);
234 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
235 "READ failed\n");
238 if (strchr(operation, 'W')) {
239 char buf[1];
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,
243 "WRITE failed\n");
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,
255 "SETINFO failed\n");
257 status = smb2_util_close(tree, create.out.file.handle);
258 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
259 "CLOSE failed\n");
262 done:
263 return ret;
266 struct sharemode_info {
267 const char *sharemode;
268 uint32_t access_mask;
269 bool expect_ok;
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";
476 NTSTATUS status;
477 bool ret = true;
478 int i;
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 "
527 "second create.\n");
529 status = smb2_util_close(tree1, create1.out.file.handle);
530 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
531 "Failed to close "
532 "first handle.\n");
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,
537 "Failed to close "
538 "second handle.\n");
542 done:
543 smb2_util_unlink(tree1, fname);
544 return ret;
548 * Test conflicting sharemodes through SMB2: First open file with
549 * different access masks, second open requests potentially conflicting
550 * sharemode.
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";
557 NTSTATUS status;
558 bool ret = true;
559 int i;
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, "
567 "sharemode %3s\n",
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 "
609 "second create.\n");
611 status = smb2_util_close(tree1, create1.out.file.handle);
612 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
613 "Failed to close "
614 "first handle.\n");
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,
619 "Failed to close "
620 "second handle.\n");
624 done:
625 smb2_util_unlink(tree1, fname);
626 return ret;
630 * Test initial stat open with share nothing doesn't trigger SHARING_VIOLTION
631 * errors.
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 = {};
640 NTSTATUS status;
641 bool ret = true;
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,
651 .in.fname = fname,
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,
664 .in.fname = fname,
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,
677 .in.fname = fname,
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,
700 .in.fname = fname,
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,
713 .in.fname = fname,
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,
726 .in.fname = fname,
729 status = smb2_create(tree, tctx, &cr3);
730 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
731 "CREATE file failed\n");
733 done:
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);
738 return ret;
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",
750 test_smb2_bug14375);
752 suite->description = talloc_strdup(suite, "SMB2-SHAREMODE tests");
754 return suite;