lib: tevent: Use system <tevent.h>, not internal header path (except in self-test).
[Samba.git] / source4 / torture / smb2 / sharemode.c
blobd1ad22e477de9df0dd5b1e7a64ebbd74147471b4
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 <tevent.h>
30 #define BASEDIRHOLD "sharemode_hold_test"
32 struct hold_sharemode_info {
33 const char *sharemode;
34 const char *filename;
35 struct smb2_handle handle;
36 } hold_sharemode_table[] = {
37 { "", BASEDIRHOLD "\\N" },
38 { "R", BASEDIRHOLD "\\R" },
39 { "W", BASEDIRHOLD "\\W" },
40 { "D", BASEDIRHOLD "\\D" },
41 { "RW", BASEDIRHOLD "\\RW" },
42 { "RD", BASEDIRHOLD "\\RD" },
43 { "WD", BASEDIRHOLD "\\WD" },
44 { "RWD", BASEDIRHOLD "\\RWD" },
47 static void signal_handler(struct tevent_context *ev,
48 struct tevent_signal *se,
49 int signum,
50 int count,
51 void *siginfo,
52 void *private_data)
54 struct torture_context *tctx = private_data;
56 torture_comment(tctx, "Received signal %d\n", signum);
60 * Used for manual testing of sharemodes - especially interaction with
61 * other filesystems (such as NFS and local access). The scenario is
62 * that this test holds files open and then concurrent access to the same
63 * files outside of Samba can be tested.
65 bool torture_smb2_hold_sharemode(struct torture_context *tctx)
67 struct tevent_context *ev = tctx->ev;
68 struct smb2_tree *tree = NULL;
69 struct smb2_handle dir_handle;
70 struct tevent_signal *s;
71 NTSTATUS status;
72 bool ret = true;
73 int i;
75 if (!torture_smb2_connection(tctx, &tree)) {
76 torture_comment(tctx, "Initializing smb2 connection failed.\n");
77 return false;
80 s = tevent_add_signal(ev, tctx, SIGINT, 0, signal_handler, tctx);
81 torture_assert_not_null_goto(tctx, s, ret, done,
82 "Error registering signal handler.");
84 torture_comment(tctx, "Setting up open files with sharemodes in %s\n",
85 BASEDIRHOLD);
87 status = torture_smb2_testdir(tree, BASEDIRHOLD, &dir_handle);
88 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
89 "Error creating directory.");
91 for (i = 0; i < ARRAY_SIZE(hold_sharemode_table); i++) {
92 struct hold_sharemode_info *info = &hold_sharemode_table[i];
93 struct smb2_create create = { };
95 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
96 create.in.alloc_size = 0;
97 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
98 create.in.share_access =
99 smb2_util_share_access(info->sharemode);
100 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
101 create.in.create_options = 0;
102 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
103 create.in.security_flags = 0;
104 create.in.fname = info->filename;
105 create.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
106 create.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
108 torture_comment(tctx, "opening %s\n", info->filename);
110 status = smb2_create(tree, tctx, &create);
112 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
113 "CREATE file failed\n");
115 info->handle = create.out.file.handle;
118 torture_comment(tctx, "Waiting for SIGINT (ctrl-c)\n");
119 tevent_loop_wait(ev);
121 torture_comment(tctx, "Closing and deleting files\n");
123 for (i = 0; i < ARRAY_SIZE(hold_sharemode_table); i++) {
124 struct hold_sharemode_info *info = &hold_sharemode_table[i];
126 union smb_setfileinfo sfinfo = { };
128 sfinfo.disposition_info.in.delete_on_close = 1;
129 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
130 sfinfo.generic.in.file.handle = info->handle;
131 status = smb2_setinfo_file(tree, &sfinfo);
132 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
133 "SETINFO failed\n");
135 status = smb2_util_close(tree, info->handle);
136 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
137 torture_comment(tctx, "File %s not found, could have "
138 "been deleted outside of SMB\n",
139 info->filename);
140 continue;
142 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
143 "CLOSE failed\n");
146 done:
147 smb2_deltree(tree, BASEDIRHOLD);
148 return ret;
152 * Used for manual testing of sharemodes, especially interaction with
153 * file systems that can enforce sharemodes. The scenario here is that
154 * a file is already open outside of Samba with a sharemode and this
155 * can be used to test accessing the same file from Samba.
157 bool torture_smb2_check_sharemode(struct torture_context *tctx)
159 const char *sharemode_string, *access_string, *filename, *operation;
160 uint32_t sharemode, access;
161 struct smb2_tree *tree;
162 struct smb2_create create = { };
163 NTSTATUS status;
164 bool ret = true;
166 sharemode_string = torture_setting_string(tctx, "sharemode", "RWD");
167 sharemode = smb2_util_share_access(sharemode_string);
169 access_string = torture_setting_string(tctx, "access", "0xf01ff");
170 access = strtoul(access_string, NULL, 0);
172 filename = torture_setting_string(tctx, "filename", "testfile");
173 operation = torture_setting_string(tctx, "operation", "WD");
175 if (!torture_smb2_connection(tctx, &tree)) {
176 torture_comment(tctx, "Initializing smb2 connection failed.\n");
177 return false;
180 create.in.desired_access = access;
181 create.in.alloc_size = 0;
182 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
183 create.in.share_access = sharemode;
184 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
185 create.in.create_options = 0;
186 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
187 create.in.security_flags = 0;
188 create.in.fname = filename;
189 create.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
190 create.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
192 status = smb2_create(tree, tctx, &create);
193 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
194 "CREATE failed\n");
196 if (strchr(operation, 'R')) {
197 struct smb2_read read = { 0 };
199 read.in.file.handle = create.out.file.handle;
200 read.in.offset = 0;
201 read.in.length = 1;
203 status = smb2_read(tree, tctx, &read);
204 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
205 "READ failed\n");
208 if (strchr(operation, 'W')) {
209 char buf[1];
210 status = smb2_util_write(tree, create.out.file.handle,
211 &buf, 0, sizeof(buf));
212 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
213 "WRITE failed\n");
216 if (strchr(operation, 'D')) {
217 union smb_setfileinfo sfinfo = { };
219 sfinfo.disposition_info.in.delete_on_close = 1;
220 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
221 sfinfo.generic.in.file.handle = create.out.file.handle;
223 status = smb2_setinfo_file(tree, &sfinfo);
224 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
225 "SETINFO failed\n");
227 status = smb2_util_close(tree, create.out.file.handle);
228 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
229 "CLOSE failed\n");
232 done:
233 return ret;
236 struct sharemode_info {
237 const char *sharemode;
238 uint32_t access_mask;
239 bool expect_ok;
240 } sharemode_table[] = {
243 * Basic tests, check each permission bit against every
244 * possible sharemode combination.
247 { "R", SEC_FILE_READ_DATA, true, },
248 { "R", SEC_FILE_WRITE_DATA, false, },
249 { "R", SEC_FILE_APPEND_DATA, false, },
250 { "R", SEC_FILE_READ_EA, true, },
251 { "R", SEC_FILE_WRITE_EA, true, },
252 { "R", SEC_FILE_EXECUTE, true, },
253 { "R", SEC_FILE_READ_ATTRIBUTE, true, },
254 { "R", SEC_FILE_WRITE_ATTRIBUTE, true, },
255 { "R", SEC_STD_DELETE, false, },
256 { "R", SEC_STD_READ_CONTROL, true, },
257 { "R", SEC_STD_WRITE_DAC, true, },
258 { "R", SEC_STD_WRITE_OWNER, true, },
259 { "R", SEC_STD_SYNCHRONIZE, true, },
261 { "W", SEC_FILE_READ_DATA, false },
262 { "W", SEC_FILE_WRITE_DATA, true, },
263 { "W", SEC_FILE_APPEND_DATA, true, },
264 { "W", SEC_FILE_READ_EA, true, },
265 { "W", SEC_FILE_WRITE_EA, true, },
266 { "W", SEC_FILE_EXECUTE, false, },
267 { "W", SEC_FILE_READ_ATTRIBUTE, true, },
268 { "W", SEC_FILE_WRITE_ATTRIBUTE, true, },
269 { "W", SEC_STD_DELETE, false, },
270 { "W", SEC_STD_READ_CONTROL, true, },
271 { "W", SEC_STD_WRITE_DAC, true, },
272 { "W", SEC_STD_WRITE_OWNER, true, },
273 { "W", SEC_STD_SYNCHRONIZE, true, },
275 { "D", SEC_FILE_READ_DATA, false },
276 { "D", SEC_FILE_WRITE_DATA, false },
277 { "D", SEC_FILE_APPEND_DATA, false },
278 { "D", SEC_FILE_READ_EA, true, },
279 { "D", SEC_FILE_WRITE_EA, true, },
280 { "D", SEC_FILE_EXECUTE, false, },
281 { "D", SEC_FILE_READ_ATTRIBUTE, true, },
282 { "D", SEC_FILE_WRITE_ATTRIBUTE, true, },
283 { "D", SEC_STD_DELETE, true, },
284 { "D", SEC_STD_READ_CONTROL, true, },
285 { "D", SEC_STD_WRITE_DAC, true, },
286 { "D", SEC_STD_WRITE_OWNER, true, },
287 { "D", SEC_STD_SYNCHRONIZE, true, },
289 { "RW", SEC_FILE_READ_DATA, true, },
290 { "RW", SEC_FILE_WRITE_DATA, true, },
291 { "RW", SEC_FILE_APPEND_DATA, true, },
292 { "RW", SEC_FILE_READ_EA, true, },
293 { "RW", SEC_FILE_WRITE_EA, true, },
294 { "RW", SEC_FILE_EXECUTE, true, },
295 { "RW", SEC_FILE_READ_ATTRIBUTE, true, },
296 { "RW", SEC_FILE_WRITE_ATTRIBUTE, true, },
297 { "RW", SEC_STD_DELETE, false, },
298 { "RW", SEC_STD_READ_CONTROL, true, },
299 { "RW", SEC_STD_WRITE_DAC, true, },
300 { "RW", SEC_STD_WRITE_OWNER, true, },
301 { "RW", SEC_STD_SYNCHRONIZE, true, },
303 { "RD", SEC_FILE_READ_DATA, true, },
304 { "RD", SEC_FILE_WRITE_DATA, false, },
305 { "RD", SEC_FILE_APPEND_DATA, false, },
306 { "RD", SEC_FILE_READ_EA, true, },
307 { "RD", SEC_FILE_WRITE_EA, true, },
308 { "RD", SEC_FILE_EXECUTE, true, },
309 { "RD", SEC_FILE_READ_ATTRIBUTE, true, },
310 { "RD", SEC_FILE_WRITE_ATTRIBUTE, true, },
311 { "RD", SEC_STD_DELETE, true, },
312 { "RD", SEC_STD_READ_CONTROL, true, },
313 { "RD", SEC_STD_WRITE_DAC, true, },
314 { "RD", SEC_STD_WRITE_OWNER, true, },
315 { "RD", SEC_STD_SYNCHRONIZE, true, },
317 { "WD", SEC_FILE_READ_DATA, false },
318 { "WD", SEC_FILE_WRITE_DATA, true, },
319 { "WD", SEC_FILE_APPEND_DATA, true, },
320 { "WD", SEC_FILE_READ_EA, true },
321 { "WD", SEC_FILE_WRITE_EA, true, },
322 { "WD", SEC_FILE_EXECUTE, false },
323 { "WD", SEC_FILE_READ_ATTRIBUTE, true, },
324 { "WD", SEC_FILE_WRITE_ATTRIBUTE, true, },
325 { "WD", SEC_STD_DELETE, true, },
326 { "WD", SEC_STD_READ_CONTROL, true, },
327 { "WD", SEC_STD_WRITE_DAC, true, },
328 { "WD", SEC_STD_WRITE_OWNER, true, },
329 { "WD", SEC_STD_SYNCHRONIZE, true, },
331 { "RWD", SEC_FILE_READ_DATA, true },
332 { "RWD", SEC_FILE_WRITE_DATA, true, },
333 { "RWD", SEC_FILE_APPEND_DATA, true, },
334 { "RWD", SEC_FILE_READ_EA, true },
335 { "RWD", SEC_FILE_WRITE_EA, true, },
336 { "RWD", SEC_FILE_EXECUTE, true, },
337 { "RWD", SEC_FILE_READ_ATTRIBUTE, true, },
338 { "RWD", SEC_FILE_WRITE_ATTRIBUTE, true, },
339 { "RWD", SEC_STD_DELETE, true, },
340 { "RWD", SEC_STD_READ_CONTROL, true, },
341 { "RWD", SEC_STD_WRITE_DAC, true, },
342 { "RWD", SEC_STD_WRITE_OWNER, true, },
343 { "RWD", SEC_STD_SYNCHRONIZE, true, },
346 * Some more interesting cases. Always request READ or WRITE
347 * access, as that will trigger the opening of a file
348 * description in Samba. This especially useful for file
349 * systems that enforce share modes on open file descriptors.
352 { "R", SEC_FILE_READ_DATA, true, },
353 { "R", SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA, false, },
354 { "R", SEC_FILE_READ_DATA|SEC_FILE_APPEND_DATA, false, },
355 { "R", SEC_FILE_READ_DATA|SEC_FILE_READ_EA, true, },
356 { "R", SEC_FILE_READ_DATA|SEC_FILE_WRITE_EA, true, },
357 { "R", SEC_FILE_READ_DATA|SEC_FILE_EXECUTE, true, },
358 { "R", SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE, true, },
359 { "R", SEC_FILE_READ_DATA|SEC_FILE_WRITE_ATTRIBUTE, true, },
360 { "R", SEC_FILE_READ_DATA|SEC_STD_DELETE, false, },
361 { "R", SEC_FILE_READ_DATA|SEC_STD_READ_CONTROL, true, },
362 { "R", SEC_FILE_READ_DATA|SEC_STD_WRITE_DAC, true, },
363 { "R", SEC_FILE_READ_DATA|SEC_STD_WRITE_OWNER, true, },
364 { "R", SEC_FILE_READ_DATA|SEC_STD_SYNCHRONIZE, true, },
366 { "W", SEC_FILE_WRITE_DATA|SEC_FILE_READ_DATA, false, },
367 { "W", SEC_FILE_WRITE_DATA, true, },
368 { "W", SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA, true, },
369 { "W", SEC_FILE_WRITE_DATA|SEC_FILE_READ_EA, true, },
370 { "W", SEC_FILE_WRITE_DATA|SEC_FILE_WRITE_EA, true, },
371 { "W", SEC_FILE_WRITE_DATA|SEC_FILE_EXECUTE, false, },
372 { "W", SEC_FILE_WRITE_DATA|SEC_FILE_READ_ATTRIBUTE, true, },
373 { "W", SEC_FILE_WRITE_DATA|SEC_FILE_WRITE_ATTRIBUTE, true, },
374 { "W", SEC_FILE_WRITE_DATA|SEC_STD_DELETE, false, },
375 { "W", SEC_FILE_WRITE_DATA|SEC_STD_READ_CONTROL, true, },
376 { "W", SEC_FILE_WRITE_DATA|SEC_STD_WRITE_DAC, true, },
377 { "W", SEC_FILE_WRITE_DATA|SEC_STD_WRITE_OWNER, true, },
378 { "W", SEC_FILE_WRITE_DATA|SEC_STD_SYNCHRONIZE, true, },
380 { "RW", SEC_FILE_READ_DATA, true, },
381 { "RW", SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA, true, },
382 { "RW", SEC_FILE_READ_DATA|SEC_FILE_APPEND_DATA, true, },
383 { "RW", SEC_FILE_READ_DATA|SEC_FILE_READ_EA, true, },
384 { "RW", SEC_FILE_READ_DATA|SEC_FILE_WRITE_EA, true, },
385 { "RW", SEC_FILE_READ_DATA|SEC_FILE_EXECUTE, true, },
386 { "RW", SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE, true, },
387 { "RW", SEC_FILE_READ_DATA|SEC_FILE_WRITE_ATTRIBUTE, true, },
388 { "RW", SEC_FILE_READ_DATA|SEC_STD_DELETE, false, },
389 { "RW", SEC_FILE_READ_DATA|SEC_STD_READ_CONTROL, true, },
390 { "RW", SEC_FILE_READ_DATA|SEC_STD_WRITE_DAC, true, },
391 { "RW", SEC_FILE_READ_DATA|SEC_STD_WRITE_OWNER, true, },
392 { "RW", SEC_FILE_READ_DATA|SEC_STD_SYNCHRONIZE, true, },
394 { "RD", SEC_FILE_READ_DATA, true, },
395 { "RD", SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA, false, },
396 { "RD", SEC_FILE_READ_DATA|SEC_FILE_APPEND_DATA, false, },
397 { "RD", SEC_FILE_READ_DATA|SEC_FILE_READ_EA, true },
398 { "RD", SEC_FILE_READ_DATA|SEC_FILE_WRITE_EA, true, },
399 { "RD", SEC_FILE_READ_DATA|SEC_FILE_EXECUTE, true, },
400 { "RD", SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE, true, },
401 { "RD", SEC_FILE_READ_DATA|SEC_FILE_WRITE_ATTRIBUTE, true, },
402 { "RD", SEC_FILE_READ_DATA|SEC_STD_DELETE, true, },
403 { "RD", SEC_FILE_READ_DATA|SEC_STD_READ_CONTROL, true, },
404 { "RD", SEC_FILE_READ_DATA|SEC_STD_WRITE_DAC, true, },
405 { "RD", SEC_FILE_READ_DATA|SEC_STD_WRITE_OWNER, true, },
406 { "RD", SEC_FILE_READ_DATA|SEC_STD_SYNCHRONIZE, true, },
408 { "WD", SEC_FILE_WRITE_DATA|SEC_FILE_READ_DATA, false },
409 { "WD", SEC_FILE_WRITE_DATA, true, },
410 { "WD", SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA, true, },
411 { "WD", SEC_FILE_WRITE_DATA|SEC_FILE_READ_EA, true },
412 { "WD", SEC_FILE_WRITE_DATA|SEC_FILE_WRITE_EA, true, },
413 { "WD", SEC_FILE_WRITE_DATA|SEC_FILE_EXECUTE, false },
414 { "WD", SEC_FILE_WRITE_DATA|SEC_FILE_READ_ATTRIBUTE, true, },
415 { "WD", SEC_FILE_WRITE_DATA|SEC_FILE_WRITE_ATTRIBUTE, true, },
416 { "WD", SEC_FILE_WRITE_DATA|SEC_STD_DELETE, true, },
417 { "WD", SEC_FILE_WRITE_DATA|SEC_STD_READ_CONTROL, true, },
418 { "WD", SEC_FILE_WRITE_DATA|SEC_STD_WRITE_DAC, true, },
419 { "WD", SEC_FILE_WRITE_DATA|SEC_STD_WRITE_OWNER, true, },
420 { "WD", SEC_FILE_WRITE_DATA|SEC_STD_SYNCHRONIZE, true, },
422 { "RWD", SEC_FILE_READ_DATA, true },
423 { "RWD", SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA, true, },
424 { "RWD", SEC_FILE_READ_DATA|SEC_FILE_APPEND_DATA, true, },
425 { "RWD", SEC_FILE_READ_DATA|SEC_FILE_READ_EA, true, },
426 { "RWD", SEC_FILE_READ_DATA|SEC_FILE_WRITE_EA, true, },
427 { "RWD", SEC_FILE_READ_DATA|SEC_FILE_EXECUTE, true, },
428 { "RWD", SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE, true, },
429 { "RWD", SEC_FILE_READ_DATA|SEC_FILE_WRITE_ATTRIBUTE, true, },
430 { "RWD", SEC_FILE_READ_DATA|SEC_STD_DELETE, true, },
431 { "RWD", SEC_FILE_READ_DATA|SEC_STD_READ_CONTROL, true, },
432 { "RWD", SEC_FILE_READ_DATA|SEC_STD_WRITE_DAC, true, },
433 { "RWD", SEC_FILE_READ_DATA|SEC_STD_WRITE_OWNER, true, },
434 { "RWD", SEC_FILE_READ_DATA|SEC_STD_SYNCHRONIZE, true, },
438 * Test conflicting sharemodes through SMB2: First open takes a
439 * sharemode, second open with potentially conflicting access.
441 static bool test_smb2_sharemode_access(struct torture_context *tctx,
442 struct smb2_tree *tree)
444 const char *fname = "test_sharemode";
445 NTSTATUS status;
446 bool ret = true;
447 int i;
449 for (i = 0; i < ARRAY_SIZE(sharemode_table); i++) {
450 struct sharemode_info *info = &sharemode_table[i];
451 struct smb2_create create1 = { }, create2 = { };
452 NTSTATUS expected_status;
454 torture_comment(tctx, "index %3d, sharemode %3s, "
455 "access mask 0x%06x\n",
456 i, info->sharemode, info->access_mask);
458 create1.in.desired_access = SEC_RIGHTS_FILE_ALL;
459 create1.in.alloc_size = 0;
460 create1.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
461 create1.in.share_access =
462 smb2_util_share_access(info->sharemode);
463 create1.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
464 create1.in.create_options = 0;
465 create1.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
466 create1.in.fname = fname;
467 create1.in.security_flags = 0;
468 create1.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
469 create1.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
471 status = smb2_create(tree, tctx, &create1);
473 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
474 "CREATE file failed\n");
476 create2.in.desired_access = info->access_mask;
477 create2.in.alloc_size = 0;
478 create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
479 create2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
480 NTCREATEX_SHARE_ACCESS_WRITE |
481 NTCREATEX_SHARE_ACCESS_DELETE;
482 create2.in.create_disposition = NTCREATEX_DISP_OPEN;
483 create2.in.create_options = 0;
484 create2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
485 create2.in.fname = fname;
486 create2.in.security_flags = 0;
487 create2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
488 create2.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
490 status = smb2_create(tree, tctx, &create2);
491 expected_status = info->expect_ok ?
492 NT_STATUS_OK : NT_STATUS_SHARING_VIOLATION;
493 torture_assert_ntstatus_equal_goto(tctx, status,
494 expected_status, ret,
495 done, "Unexpected status on "
496 "second create.\n");
498 status = smb2_util_close(tree, create1.out.file.handle);
499 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
500 "Failed to close "
501 "first handle.\n");
503 if (info->expect_ok) {
504 status = smb2_util_close(tree, create2.out.file.handle);
505 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
506 "Failed to close "
507 "second handle.\n");
511 done:
512 smb2_util_unlink(tree, fname);
513 return ret;
517 * Test conflicting sharemodes through SMB2: First open file with
518 * different access masks, second open requests potentially conflict
519 * sharemode.
521 static bool test_smb2_access_sharemode(struct torture_context *tctx,
522 struct smb2_tree *tree)
524 const char *fname = "test_sharemode";
525 NTSTATUS status;
526 bool ret = true;
527 int i;
529 for (i = 0; i < ARRAY_SIZE(sharemode_table); i++) {
530 struct sharemode_info *info = &sharemode_table[i];
531 struct smb2_create create1 = { }, create2 = { };
532 NTSTATUS expected_status;
534 torture_comment(tctx, "index %3d, access mask 0x%06x, "
535 "sharemode %3s\n",
536 i, info->access_mask, info->sharemode);
538 create1.in.desired_access = info->access_mask;
539 create1.in.alloc_size = 0;
540 create1.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
541 create1.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
542 NTCREATEX_SHARE_ACCESS_WRITE |
543 NTCREATEX_SHARE_ACCESS_DELETE;
544 create1.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
545 create1.in.create_options = 0;
546 create1.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
547 create1.in.fname = fname;
548 create1.in.security_flags = 0;
549 create1.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
550 create1.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
552 status = smb2_create(tree, tctx, &create1);
554 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
555 "CREATE file failed\n");
557 create2.in.desired_access = SEC_RIGHTS_FILE_ALL;
558 create2.in.alloc_size = 0;
559 create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
560 create2.in.share_access =
561 smb2_util_share_access(info->sharemode);
562 create2.in.create_disposition = NTCREATEX_DISP_OPEN;
563 create2.in.create_options = 0;
564 create2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
565 create2.in.fname = fname;
566 create2.in.security_flags = 0;
567 create2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
568 create2.in.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
570 status = smb2_create(tree, tctx, &create2);
572 expected_status = info->expect_ok ?
573 NT_STATUS_OK : NT_STATUS_SHARING_VIOLATION;
574 torture_assert_ntstatus_equal_goto(tctx, status,
575 expected_status, ret,
576 done, "Unexpected status on "
577 "second create.\n");
579 status = smb2_util_close(tree, create1.out.file.handle);
580 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
581 "Failed to close "
582 "first handle.\n");
584 if (info->expect_ok) {
585 status = smb2_util_close(tree, create2.out.file.handle);
586 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
587 "Failed to close "
588 "second handle.\n");
592 done:
593 smb2_util_unlink(tree, fname);
594 return ret;
597 struct torture_suite *torture_smb2_sharemode_init(TALLOC_CTX *ctx)
599 struct torture_suite *suite = torture_suite_create(ctx, "sharemode");
601 torture_suite_add_1smb2_test(suite, "sharemode-access",
602 test_smb2_sharemode_access);
603 torture_suite_add_1smb2_test(suite, "access-sharemode",
604 test_smb2_access_sharemode);
606 suite->description = talloc_strdup(suite, "SMB2-SHAREMODE tests");
608 return suite;