2 Unix SMB/CIFS implementation.
4 test security descriptor operations
6 Copyright (C) Andrew Tridgell 2004
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 "torture/torture.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/libcli.h"
26 #include "librpc/gen_ndr/lsa.h"
27 #include "libcli/smb2/smb2.h"
28 #include "libcli/util/clilsa.h"
29 #include "libcli/security/security.h"
30 #include "torture/util.h"
31 #include "librpc/gen_ndr/ndr_security.h"
32 #include "torture/raw/proto.h"
34 #define BASEDIR "\\testsd"
36 #define CHECK_STATUS(status, correct) do { \
37 if (!NT_STATUS_EQUAL(status, correct)) { \
39 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
40 __location__, nt_errstr(status), nt_errstr(correct)); \
44 #define FAIL_UNLESS(__cond) \
46 if (__cond) {} else { \
48 torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \
49 __location__, #__cond); \
54 #define CHECK_SECURITY_DESCRIPTOR(_sd1, _sd2) do { \
55 if (!security_descriptor_equal(_sd1, _sd2)) { \
56 torture_warning(tctx, "%s: security descriptors don't match!\n", __location__); \
57 torture_warning(tctx, "got:\n"); \
58 NDR_PRINT_DEBUG(security_descriptor, _sd1); \
59 torture_warning(tctx, "expected:\n"); \
60 NDR_PRINT_DEBUG(security_descriptor, _sd2); \
66 * Helper function to verify a security descriptor, by querying
67 * and comparing against the passed in sd.
68 * Copied to smb2_util_verify_sd() for SMB2.
70 static bool verify_sd(TALLOC_CTX *tctx, struct smbcli_state *cli,
71 int fnum, struct security_descriptor *sd)
75 union smb_fileinfo q = {};
78 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
79 q.query_secdesc.in.file.fnum = fnum;
80 q.query_secdesc.in.secinfo_flags =
84 status = smb_raw_fileinfo(cli->tree, tctx, &q);
85 CHECK_STATUS(status, NT_STATUS_OK);
87 /* More work is needed if we're going to check this bit. */
88 sd->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
90 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
98 * Helper function to verify attributes, by querying
99 * and comparing against the passed attrib.
100 * Copied to smb2_util_verify_attrib() for SMB2.
102 static bool verify_attrib(TALLOC_CTX *tctx, struct smbcli_state *cli,
103 int fnum, uint32_t attrib)
107 union smb_fileinfo q2 = {};
110 q2.standard.level = RAW_FILEINFO_STANDARD;
111 q2.standard.in.file.fnum = fnum;
112 status = smb_raw_fileinfo(cli->tree, tctx, &q2);
113 CHECK_STATUS(status, NT_STATUS_OK);
115 q2.standard.out.attrib &= ~FILE_ATTRIBUTE_ARCHIVE;
117 if (q2.standard.out.attrib != attrib) {
118 torture_warning(tctx, "%s: attributes don't match! "
119 "got %x, expected %x\n", __location__,
120 (uint32_t)q2.standard.out.attrib,
131 * Test setting and removing a DACL.
132 * Test copied to torture_smb2_setinfo() for SMB2.
134 static bool test_sd(struct torture_context *tctx, struct smbcli_state *cli)
138 const char *fname = BASEDIR "\\sd.txt";
141 union smb_fileinfo q;
142 union smb_setfileinfo set;
143 struct security_ace ace = {};
144 struct security_descriptor *sd;
145 const struct dom_sid *test_sid;
147 if (!torture_setup_dir(cli, BASEDIR))
150 torture_comment(tctx, "TESTING SETFILEINFO EA_SET\n");
152 io.generic.level = RAW_OPEN_NTCREATEX;
153 io.ntcreatex.in.root_fid.fnum = 0;
154 io.ntcreatex.in.flags = 0;
155 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
156 io.ntcreatex.in.create_options = 0;
157 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
158 io.ntcreatex.in.share_access =
159 NTCREATEX_SHARE_ACCESS_READ |
160 NTCREATEX_SHARE_ACCESS_WRITE;
161 io.ntcreatex.in.alloc_size = 0;
162 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
163 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
164 io.ntcreatex.in.security_flags = 0;
165 io.ntcreatex.in.fname = fname;
166 status = smb_raw_open(cli->tree, tctx, &io);
167 CHECK_STATUS(status, NT_STATUS_OK);
168 fnum = io.ntcreatex.out.file.fnum;
170 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
171 q.query_secdesc.in.file.fnum = fnum;
172 q.query_secdesc.in.secinfo_flags =
176 status = smb_raw_fileinfo(cli->tree, tctx, &q);
177 CHECK_STATUS(status, NT_STATUS_OK);
178 sd = q.query_secdesc.out.sd;
180 torture_comment(tctx, "add a new ACE to the DACL\n");
182 test_sid = &global_sid_Authenticated_Users;
184 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
186 ace.access_mask = SEC_STD_ALL;
187 ace.trustee = *test_sid;
189 status = security_descriptor_dacl_add(sd, &ace);
190 CHECK_STATUS(status, NT_STATUS_OK);
192 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
193 set.set_secdesc.in.file.fnum = fnum;
194 set.set_secdesc.in.secinfo_flags = q.query_secdesc.in.secinfo_flags;
195 set.set_secdesc.in.sd = sd;
197 status = smb_raw_setfileinfo(cli->tree, &set);
198 CHECK_STATUS(status, NT_STATUS_OK);
199 FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
201 torture_comment(tctx, "remove it again\n");
203 status = security_descriptor_dacl_del(sd, test_sid);
204 CHECK_STATUS(status, NT_STATUS_OK);
206 status = smb_raw_setfileinfo(cli->tree, &set);
207 CHECK_STATUS(status, NT_STATUS_OK);
208 FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
211 smbcli_close(cli->tree, fnum);
212 smb_raw_exit(cli->session);
213 smbcli_deltree(cli->tree, BASEDIR);
220 test using nttrans create to create a file with an initial acl set
221 Test copied to test_create_acl() for SMB2.
223 static bool test_nttrans_create_ext(struct torture_context *tctx,
224 struct smbcli_state *cli, bool test_dir)
228 const char *fname = BASEDIR "\\acl2.txt";
231 union smb_fileinfo q = {};
232 struct security_ace ace;
233 struct security_descriptor *sd;
234 const struct dom_sid *test_sid;
236 FILE_ATTRIBUTE_HIDDEN |
237 FILE_ATTRIBUTE_SYSTEM |
238 (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
239 NTSTATUS (*delete_func)(struct smbcli_tree *, const char *) =
240 test_dir ? smbcli_rmdir : smbcli_unlink;
244 if (!torture_setup_dir(cli, BASEDIR))
247 io.generic.level = RAW_OPEN_NTTRANS_CREATE;
248 io.ntcreatex.in.root_fid.fnum = 0;
249 io.ntcreatex.in.flags = 0;
250 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
251 io.ntcreatex.in.create_options =
252 test_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
253 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
254 io.ntcreatex.in.share_access =
255 NTCREATEX_SHARE_ACCESS_READ |
256 NTCREATEX_SHARE_ACCESS_WRITE;
257 io.ntcreatex.in.alloc_size = 0;
258 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
259 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
260 io.ntcreatex.in.security_flags = 0;
261 io.ntcreatex.in.fname = fname;
262 io.ntcreatex.in.sec_desc = NULL;
263 io.ntcreatex.in.ea_list = NULL;
265 torture_comment(tctx, "basic create\n");
267 status = smb_raw_open(cli->tree, tctx, &io);
268 CHECK_STATUS(status, NT_STATUS_OK);
269 fnum = io.ntcreatex.out.file.fnum;
271 torture_comment(tctx, "querying ACL\n");
273 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
274 q.query_secdesc.in.file.fnum = fnum;
275 q.query_secdesc.in.secinfo_flags =
279 status = smb_raw_fileinfo(cli->tree, tctx, &q);
280 CHECK_STATUS(status, NT_STATUS_OK);
281 sd = q.query_secdesc.out.sd;
283 status = smbcli_close(cli->tree, fnum);
284 CHECK_STATUS(status, NT_STATUS_OK);
286 status = delete_func(cli->tree, fname);
287 CHECK_STATUS(status, NT_STATUS_OK);
289 torture_comment(tctx, "adding a new ACE\n");
290 test_sid = &global_sid_Authenticated_Users;
292 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
294 ace.access_mask = SEC_STD_ALL;
295 ace.trustee = *test_sid;
297 status = security_descriptor_dacl_add(sd, &ace);
298 CHECK_STATUS(status, NT_STATUS_OK);
300 torture_comment(tctx, "creating with an initial ACL\n");
302 io.ntcreatex.in.sec_desc = sd;
303 status = smb_raw_open(cli->tree, tctx, &io);
304 CHECK_STATUS(status, NT_STATUS_OK);
305 fnum = io.ntcreatex.out.file.fnum;
307 FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
309 status = smbcli_close(cli->tree, fnum);
310 CHECK_STATUS(status, NT_STATUS_OK);
311 status = delete_func(cli->tree, fname);
312 CHECK_STATUS(status, NT_STATUS_OK);
314 torture_comment(tctx, "creating with attributes\n");
316 io.ntcreatex.in.sec_desc = NULL;
317 io.ntcreatex.in.file_attr = attrib;
318 status = smb_raw_open(cli->tree, tctx, &io);
319 CHECK_STATUS(status, NT_STATUS_OK);
320 fnum = io.ntcreatex.out.file.fnum;
322 FAIL_UNLESS(verify_attrib(tctx, cli, fnum, attrib));
324 status = smbcli_close(cli->tree, fnum);
325 CHECK_STATUS(status, NT_STATUS_OK);
327 status = delete_func(cli->tree, fname);
328 CHECK_STATUS(status, NT_STATUS_OK);
330 torture_comment(tctx, "creating with attributes and ACL\n");
332 io.ntcreatex.in.sec_desc = sd;
333 io.ntcreatex.in.file_attr = attrib;
334 status = smb_raw_open(cli->tree, tctx, &io);
335 CHECK_STATUS(status, NT_STATUS_OK);
336 fnum = io.ntcreatex.out.file.fnum;
338 FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
339 FAIL_UNLESS(verify_attrib(tctx, cli, fnum, attrib));
341 status = smbcli_close(cli->tree, fnum);
342 CHECK_STATUS(status, NT_STATUS_OK);
343 status = delete_func(cli->tree, fname);
344 CHECK_STATUS(status, NT_STATUS_OK);
347 smbcli_close(cli->tree, fnum);
348 smb_raw_exit(cli->session);
349 smbcli_deltree(cli->tree, BASEDIR);
354 test using nttrans create to create a file and directory with an initial acl
357 static bool test_nttrans_create_ext_owner(
358 struct torture_context *tctx,
359 struct smbcli_state *cli, bool test_dir)
363 const char *fname = BASEDIR "\\foo.txt";
366 struct security_ace ace;
367 struct security_descriptor *sd;
369 FILE_ATTRIBUTE_HIDDEN |
370 FILE_ATTRIBUTE_SYSTEM |
371 (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
372 NTSTATUS (*delete_func)(struct smbcli_tree *, const char *) =
373 test_dir ? smbcli_rmdir : smbcli_unlink;
377 smbcli_deltree(cli->tree, BASEDIR);
379 if (!torture_setup_dir(cli, BASEDIR))
382 io.generic.level = RAW_OPEN_NTTRANS_CREATE;
383 io.ntcreatex.in.root_fid.fnum = 0;
384 io.ntcreatex.in.flags = 0;
385 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
386 io.ntcreatex.in.create_options =
387 test_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
388 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
389 io.ntcreatex.in.share_access =
390 NTCREATEX_SHARE_ACCESS_READ |
391 NTCREATEX_SHARE_ACCESS_WRITE;
392 io.ntcreatex.in.alloc_size = 0;
393 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
394 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
395 io.ntcreatex.in.security_flags = 0;
396 io.ntcreatex.in.fname = fname;
397 io.ntcreatex.in.sec_desc = NULL;
398 io.ntcreatex.in.ea_list = NULL;
400 torture_comment(tctx, "creating with attributes, ACL and owner\n");
402 sd = security_descriptor_dacl_create(tctx,
403 0, SID_WORLD, SID_BUILTIN_USERS,
405 SEC_ACE_TYPE_ACCESS_ALLOWED,
406 SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
410 io.ntcreatex.in.sec_desc = sd;
411 io.ntcreatex.in.file_attr = attrib;
412 status = smb_raw_open(cli->tree, tctx, &io);
413 CHECK_STATUS(status, NT_STATUS_OK);
414 fnum = io.ntcreatex.out.file.fnum;
416 FAIL_UNLESS(verify_sd(tctx, cli, fnum, sd));
417 FAIL_UNLESS(verify_attrib(tctx, cli, fnum, attrib));
419 status = smbcli_close(cli->tree, fnum);
420 CHECK_STATUS(status, NT_STATUS_OK);
421 status = delete_func(cli->tree, fname);
422 CHECK_STATUS(status, NT_STATUS_OK);
425 smbcli_close(cli->tree, fnum);
426 smb_raw_exit(cli->session);
427 smbcli_deltree(cli->tree, BASEDIR);
431 static bool test_nttrans_create_file(struct torture_context *tctx,
432 struct smbcli_state *cli)
434 torture_comment(tctx, "Testing nttrans create with sec_desc on files\n");
436 return test_nttrans_create_ext(tctx, cli, false);
439 static bool test_nttrans_create_dir(struct torture_context *tctx,
440 struct smbcli_state *cli)
442 torture_comment(tctx, "Testing nttrans create with sec_desc on directories\n");
444 return test_nttrans_create_ext(tctx, cli, true);
447 static bool test_nttrans_create_owner_file(struct torture_context *tctx,
448 struct smbcli_state *cli)
450 torture_comment(tctx, "Testing nttrans create with sec_desc with owner on file\n");
452 return test_nttrans_create_ext_owner(tctx, cli, false);
455 static bool test_nttrans_create_owner_dir(struct torture_context *tctx,
456 struct smbcli_state *cli)
458 torture_comment(tctx, "Testing nttrans create with sec_desc with owner on directory\n");
460 return test_nttrans_create_ext_owner(tctx, cli, true);
463 #define CHECK_ACCESS_FLAGS(_fnum, flags) do { \
464 union smb_fileinfo _q; \
465 _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
466 _q.access_information.in.file.fnum = (_fnum); \
467 status = smb_raw_fileinfo(cli->tree, tctx, &_q); \
468 CHECK_STATUS(status, NT_STATUS_OK); \
469 if (_q.access_information.out.access_flags != (flags)) { \
471 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
472 __location__, _q.access_information.out.access_flags, (flags)); \
478 test using NTTRANS CREATE to create a file with a null ACL set
479 Test copied to test_create_null_dacl() for SMB2.
481 static bool test_nttrans_create_null_dacl(struct torture_context *tctx,
482 struct smbcli_state *cli)
486 const char *fname = BASEDIR "\\nulldacl.txt";
489 union smb_fileinfo q;
490 union smb_setfileinfo s;
491 struct security_descriptor *sd = security_descriptor_initialise(tctx);
492 struct security_acl dacl;
494 if (!torture_setup_dir(cli, BASEDIR))
497 torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n");
499 io.generic.level = RAW_OPEN_NTTRANS_CREATE;
500 io.ntcreatex.in.root_fid.fnum = 0;
501 io.ntcreatex.in.flags = 0;
502 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC
503 | SEC_STD_WRITE_OWNER;
504 io.ntcreatex.in.create_options = 0;
505 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
506 io.ntcreatex.in.share_access =
507 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
508 io.ntcreatex.in.alloc_size = 0;
509 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
510 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
511 io.ntcreatex.in.security_flags = 0;
512 io.ntcreatex.in.fname = fname;
513 io.ntcreatex.in.sec_desc = sd;
514 io.ntcreatex.in.ea_list = NULL;
516 torture_comment(tctx, "creating a file with a empty sd\n");
517 status = smb_raw_open(cli->tree, tctx, &io);
518 CHECK_STATUS(status, NT_STATUS_OK);
519 fnum = io.ntcreatex.out.file.fnum;
521 torture_comment(tctx, "get the original sd\n");
522 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
523 q.query_secdesc.in.file.fnum = fnum;
524 q.query_secdesc.in.secinfo_flags =
528 status = smb_raw_fileinfo(cli->tree, tctx, &q);
529 CHECK_STATUS(status, NT_STATUS_OK);
532 * Testing the created DACL,
533 * the server should add the inherited DACL
534 * when SEC_DESC_DACL_PRESENT isn't specified
536 if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
538 torture_result(tctx, TORTURE_FAIL, "DACL_PRESENT flag not set by the server!\n");
541 if (q.query_secdesc.out.sd->dacl == NULL) {
543 torture_result(tctx, TORTURE_FAIL, "no DACL has been created on the server!\n");
547 torture_comment(tctx, "set NULL DACL\n");
548 sd->type |= SEC_DESC_DACL_PRESENT;
550 s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
551 s.set_secdesc.in.file.fnum = fnum;
552 s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
553 s.set_secdesc.in.sd = sd;
554 status = smb_raw_setfileinfo(cli->tree, &s);
555 CHECK_STATUS(status, NT_STATUS_OK);
557 torture_comment(tctx, "get the sd\n");
558 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
559 q.query_secdesc.in.file.fnum = fnum;
560 q.query_secdesc.in.secinfo_flags =
564 status = smb_raw_fileinfo(cli->tree, tctx, &q);
565 CHECK_STATUS(status, NT_STATUS_OK);
567 /* Testing the modified DACL */
568 if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
570 torture_result(tctx, TORTURE_FAIL, "DACL_PRESENT flag not set by the server!\n");
573 if (q.query_secdesc.out.sd->dacl != NULL) {
575 torture_result(tctx, TORTURE_FAIL, "DACL has been created on the server!\n");
579 torture_comment(tctx, "try open for read control\n");
580 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL;
581 status = smb_raw_open(cli->tree, tctx, &io);
582 CHECK_STATUS(status, NT_STATUS_OK);
583 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
584 SEC_STD_READ_CONTROL | SEC_FILE_READ_ATTRIBUTE);
585 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
587 torture_comment(tctx, "try open for write\n");
588 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
589 status = smb_raw_open(cli->tree, tctx, &io);
590 CHECK_STATUS(status, NT_STATUS_OK);
591 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
592 SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
593 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
595 torture_comment(tctx, "try open for read\n");
596 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
597 status = smb_raw_open(cli->tree, tctx, &io);
598 CHECK_STATUS(status, NT_STATUS_OK);
599 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
600 SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE);
601 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
603 torture_comment(tctx, "try open for generic write\n");
604 io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
605 status = smb_raw_open(cli->tree, tctx, &io);
606 CHECK_STATUS(status, NT_STATUS_OK);
607 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
608 SEC_RIGHTS_FILE_WRITE | SEC_FILE_READ_ATTRIBUTE);
609 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
611 torture_comment(tctx, "try open for generic read\n");
612 io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
613 status = smb_raw_open(cli->tree, tctx, &io);
614 CHECK_STATUS(status, NT_STATUS_OK);
615 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
616 SEC_RIGHTS_FILE_READ | SEC_FILE_READ_ATTRIBUTE);
617 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
619 torture_comment(tctx, "set DACL with 0 aces\n");
621 dacl.revision = SECURITY_ACL_REVISION_NT4;
625 s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
626 s.set_secdesc.in.file.fnum = fnum;
627 s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
628 s.set_secdesc.in.sd = sd;
629 status = smb_raw_setfileinfo(cli->tree, &s);
630 CHECK_STATUS(status, NT_STATUS_OK);
632 torture_comment(tctx, "get the sd\n");
633 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
634 q.query_secdesc.in.file.fnum = fnum;
635 q.query_secdesc.in.secinfo_flags =
639 status = smb_raw_fileinfo(cli->tree, tctx, &q);
640 CHECK_STATUS(status, NT_STATUS_OK);
642 /* Testing the modified DACL */
643 if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
645 torture_result(tctx, TORTURE_FAIL, "DACL_PRESENT flag not set by the server!\n");
648 if (q.query_secdesc.out.sd->dacl == NULL) {
650 torture_result(tctx, TORTURE_FAIL, "no DACL has been created on the server!\n");
653 if (q.query_secdesc.out.sd->dacl->num_aces != 0) {
655 torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n",
656 q.query_secdesc.out.sd->dacl->num_aces);
660 torture_comment(tctx, "try open for read control\n");
661 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL;
662 status = smb_raw_open(cli->tree, tctx, &io);
663 CHECK_STATUS(status, NT_STATUS_OK);
664 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
665 SEC_STD_READ_CONTROL | SEC_FILE_READ_ATTRIBUTE);
666 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
668 torture_comment(tctx, "try open for write => access_denied\n");
669 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
670 status = smb_raw_open(cli->tree, tctx, &io);
671 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
673 torture_comment(tctx, "try open for read => access_denied\n");
674 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
675 status = smb_raw_open(cli->tree, tctx, &io);
676 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
678 torture_comment(tctx, "try open for generic write => access_denied\n");
679 io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
680 status = smb_raw_open(cli->tree, tctx, &io);
681 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
683 torture_comment(tctx, "try open for generic read => access_denied\n");
684 io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
685 status = smb_raw_open(cli->tree, tctx, &io);
686 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
688 torture_comment(tctx, "set empty sd\n");
689 sd->type &= ~SEC_DESC_DACL_PRESENT;
692 s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
693 s.set_secdesc.in.file.fnum = fnum;
694 s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
695 s.set_secdesc.in.sd = sd;
696 status = smb_raw_setfileinfo(cli->tree, &s);
697 CHECK_STATUS(status, NT_STATUS_OK);
699 torture_comment(tctx, "get the sd\n");
700 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
701 q.query_secdesc.in.file.fnum = fnum;
702 q.query_secdesc.in.secinfo_flags =
706 status = smb_raw_fileinfo(cli->tree, tctx, &q);
707 CHECK_STATUS(status, NT_STATUS_OK);
709 /* Testing the modified DACL */
710 if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
712 torture_result(tctx, TORTURE_FAIL, "DACL_PRESENT flag not set by the server!\n");
715 if (q.query_secdesc.out.sd->dacl != NULL) {
717 torture_result(tctx, TORTURE_FAIL, "DACL has been created on the server!\n");
721 smbcli_close(cli->tree, fnum);
722 smb_raw_exit(cli->session);
723 smbcli_deltree(cli->tree, BASEDIR);
728 test the behaviour of the well known SID_CREATOR_OWNER sid, and some generic
730 Test copied to smb2/acls.c for SMB2.
732 static bool test_creator_sid(struct torture_context *tctx,
733 struct smbcli_state *cli)
737 const char *fname = BASEDIR "\\creator.txt";
740 union smb_fileinfo q;
741 union smb_setfileinfo set;
742 struct security_descriptor *sd, *sd_orig, *sd2;
743 const char *owner_sid;
745 if (!torture_setup_dir(cli, BASEDIR))
748 torture_comment(tctx, "TESTING SID_CREATOR_OWNER\n");
750 io.generic.level = RAW_OPEN_NTCREATEX;
751 io.ntcreatex.in.root_fid.fnum = 0;
752 io.ntcreatex.in.flags = 0;
753 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER;
754 io.ntcreatex.in.create_options = 0;
755 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
756 io.ntcreatex.in.share_access =
757 NTCREATEX_SHARE_ACCESS_READ |
758 NTCREATEX_SHARE_ACCESS_WRITE;
759 io.ntcreatex.in.alloc_size = 0;
760 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
761 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
762 io.ntcreatex.in.security_flags = 0;
763 io.ntcreatex.in.fname = fname;
764 status = smb_raw_open(cli->tree, tctx, &io);
765 CHECK_STATUS(status, NT_STATUS_OK);
766 fnum = io.ntcreatex.out.file.fnum;
768 torture_comment(tctx, "get the original sd\n");
769 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
770 q.query_secdesc.in.file.fnum = fnum;
771 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
772 status = smb_raw_fileinfo(cli->tree, tctx, &q);
773 CHECK_STATUS(status, NT_STATUS_OK);
774 sd_orig = q.query_secdesc.out.sd;
776 owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
778 torture_comment(tctx, "set a sec desc allowing no write by CREATOR_OWNER\n");
779 sd = security_descriptor_dacl_create(tctx,
782 SEC_ACE_TYPE_ACCESS_ALLOWED,
783 SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
787 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
788 set.set_secdesc.in.file.fnum = fnum;
789 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
790 set.set_secdesc.in.sd = sd;
792 status = smb_raw_setfileinfo(cli->tree, &set);
793 CHECK_STATUS(status, NT_STATUS_OK);
795 torture_comment(tctx, "try open for write\n");
796 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
797 status = smb_raw_open(cli->tree, tctx, &io);
798 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
800 torture_comment(tctx, "try open for read\n");
801 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
802 status = smb_raw_open(cli->tree, tctx, &io);
803 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
805 torture_comment(tctx, "try open for generic write\n");
806 io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
807 status = smb_raw_open(cli->tree, tctx, &io);
808 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
810 torture_comment(tctx, "try open for generic read\n");
811 io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
812 status = smb_raw_open(cli->tree, tctx, &io);
813 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
815 torture_comment(tctx, "set a sec desc allowing no write by owner\n");
816 sd = security_descriptor_dacl_create(tctx,
819 SEC_ACE_TYPE_ACCESS_ALLOWED,
820 SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
824 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
825 set.set_secdesc.in.file.fnum = fnum;
826 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
827 set.set_secdesc.in.sd = sd;
828 status = smb_raw_setfileinfo(cli->tree, &set);
829 CHECK_STATUS(status, NT_STATUS_OK);
831 torture_comment(tctx, "check that sd has been mapped correctly\n");
832 status = smb_raw_fileinfo(cli->tree, tctx, &q);
833 CHECK_STATUS(status, NT_STATUS_OK);
834 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
836 torture_comment(tctx, "try open for write\n");
837 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
838 status = smb_raw_open(cli->tree, tctx, &io);
839 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
841 torture_comment(tctx, "try open for read\n");
842 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
843 status = smb_raw_open(cli->tree, tctx, &io);
844 CHECK_STATUS(status, NT_STATUS_OK);
845 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
847 SEC_FILE_READ_ATTRIBUTE);
848 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
850 torture_comment(tctx, "try open for generic write\n");
851 io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
852 status = smb_raw_open(cli->tree, tctx, &io);
853 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
855 torture_comment(tctx, "try open for generic read\n");
856 io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
857 status = smb_raw_open(cli->tree, tctx, &io);
858 CHECK_STATUS(status, NT_STATUS_OK);
859 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
860 SEC_RIGHTS_FILE_READ);
861 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
863 torture_comment(tctx, "set a sec desc allowing generic read by owner\n");
864 sd = security_descriptor_dacl_create(tctx,
867 SEC_ACE_TYPE_ACCESS_ALLOWED,
868 SEC_GENERIC_READ | SEC_STD_ALL,
872 set.set_secdesc.in.sd = sd;
873 status = smb_raw_setfileinfo(cli->tree, &set);
874 CHECK_STATUS(status, NT_STATUS_OK);
876 torture_comment(tctx, "check that generic read has been mapped correctly\n");
877 sd2 = security_descriptor_dacl_create(tctx,
880 SEC_ACE_TYPE_ACCESS_ALLOWED,
881 SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
885 status = smb_raw_fileinfo(cli->tree, tctx, &q);
886 CHECK_STATUS(status, NT_STATUS_OK);
887 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
889 torture_comment(tctx, "try open for write\n");
890 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
891 status = smb_raw_open(cli->tree, tctx, &io);
892 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
894 torture_comment(tctx, "try open for read\n");
895 io.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
896 status = smb_raw_open(cli->tree, tctx, &io);
897 CHECK_STATUS(status, NT_STATUS_OK);
898 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
900 SEC_FILE_READ_ATTRIBUTE);
901 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
903 torture_comment(tctx, "try open for generic write\n");
904 io.ntcreatex.in.access_mask = SEC_GENERIC_WRITE;
905 status = smb_raw_open(cli->tree, tctx, &io);
906 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
908 torture_comment(tctx, "try open for generic read\n");
909 io.ntcreatex.in.access_mask = SEC_GENERIC_READ;
910 status = smb_raw_open(cli->tree, tctx, &io);
911 CHECK_STATUS(status, NT_STATUS_OK);
912 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, SEC_RIGHTS_FILE_READ);
913 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
916 torture_comment(tctx, "put back original sd\n");
917 set.set_secdesc.in.sd = sd_orig;
918 status = smb_raw_setfileinfo(cli->tree, &set);
919 CHECK_STATUS(status, NT_STATUS_OK);
923 smbcli_close(cli->tree, fnum);
924 smb_raw_exit(cli->session);
925 smbcli_deltree(cli->tree, BASEDIR);
931 test the mapping of the SEC_GENERIC_xx bits to SEC_STD_xx and
933 Test copied to smb2/acls.c for SMB2.
935 static bool test_generic_bits(struct torture_context *tctx,
936 struct smbcli_state *cli)
940 const char *fname = BASEDIR "\\generic.txt";
943 union smb_fileinfo q;
944 union smb_setfileinfo set;
945 struct security_descriptor *sd, *sd_orig, *sd2;
946 const char *owner_sid;
949 uint32_t specific_bits;
950 } file_mappings[] = {
952 { SEC_GENERIC_READ, SEC_RIGHTS_FILE_READ },
953 { SEC_GENERIC_WRITE, SEC_RIGHTS_FILE_WRITE },
954 { SEC_GENERIC_EXECUTE, SEC_RIGHTS_FILE_EXECUTE },
955 { SEC_GENERIC_ALL, SEC_RIGHTS_FILE_ALL },
956 { SEC_FILE_READ_DATA, SEC_FILE_READ_DATA },
957 { SEC_FILE_READ_ATTRIBUTE, SEC_FILE_READ_ATTRIBUTE }
961 uint32_t specific_bits;
964 { SEC_GENERIC_READ, SEC_RIGHTS_DIR_READ },
965 { SEC_GENERIC_WRITE, SEC_RIGHTS_DIR_WRITE },
966 { SEC_GENERIC_EXECUTE, SEC_RIGHTS_DIR_EXECUTE },
967 { SEC_GENERIC_ALL, SEC_RIGHTS_DIR_ALL }
969 bool has_restore_privilege;
970 bool has_take_ownership_privilege;
972 if (!torture_setup_dir(cli, BASEDIR))
975 torture_comment(tctx, "TESTING FILE GENERIC BITS\n");
977 io.generic.level = RAW_OPEN_NTCREATEX;
978 io.ntcreatex.in.root_fid.fnum = 0;
979 io.ntcreatex.in.flags = 0;
980 io.ntcreatex.in.access_mask =
981 SEC_STD_READ_CONTROL |
984 io.ntcreatex.in.create_options = 0;
985 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
986 io.ntcreatex.in.share_access =
987 NTCREATEX_SHARE_ACCESS_READ |
988 NTCREATEX_SHARE_ACCESS_WRITE;
989 io.ntcreatex.in.alloc_size = 0;
990 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
991 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
992 io.ntcreatex.in.security_flags = 0;
993 io.ntcreatex.in.fname = fname;
994 status = smb_raw_open(cli->tree, tctx, &io);
995 CHECK_STATUS(status, NT_STATUS_OK);
996 fnum = io.ntcreatex.out.file.fnum;
998 torture_comment(tctx, "get the original sd\n");
999 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1000 q.query_secdesc.in.file.fnum = fnum;
1001 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1002 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1003 CHECK_STATUS(status, NT_STATUS_OK);
1004 sd_orig = q.query_secdesc.out.sd;
1006 owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1008 status = torture_check_privilege(cli,
1010 sec_privilege_name(SEC_PRIV_RESTORE));
1011 has_restore_privilege = NT_STATUS_IS_OK(status);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 torture_warning(tctx, "torture_check_privilege - %s\n",
1016 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
1018 status = torture_check_privilege(cli,
1020 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
1021 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
1022 if (!NT_STATUS_IS_OK(status)) {
1023 torture_warning(tctx, "torture_check_privilege - %s\n",
1026 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
1028 for (i=0;i<ARRAY_SIZE(file_mappings);i++) {
1029 uint32_t expected_mask =
1031 SEC_STD_READ_CONTROL |
1032 SEC_FILE_READ_ATTRIBUTE |
1034 uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
1036 if (has_restore_privilege) {
1037 expected_mask_anon |= SEC_STD_DELETE;
1040 torture_comment(tctx, "Testing generic bits 0x%08x\n",
1041 file_mappings[i].gen_bits);
1042 sd = security_descriptor_dacl_create(tctx,
1045 SEC_ACE_TYPE_ACCESS_ALLOWED,
1046 file_mappings[i].gen_bits,
1050 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1051 set.set_secdesc.in.file.fnum = fnum;
1052 set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1053 set.set_secdesc.in.sd = sd;
1055 status = smb_raw_setfileinfo(cli->tree, &set);
1056 CHECK_STATUS(status, NT_STATUS_OK);
1058 sd2 = security_descriptor_dacl_create(tctx,
1061 SEC_ACE_TYPE_ACCESS_ALLOWED,
1062 file_mappings[i].specific_bits,
1066 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1067 CHECK_STATUS(status, NT_STATUS_OK);
1068 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1070 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1071 status = smb_raw_open(cli->tree, tctx, &io);
1072 CHECK_STATUS(status, NT_STATUS_OK);
1073 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
1074 expected_mask | file_mappings[i].specific_bits);
1075 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1077 if (!has_take_ownership_privilege) {
1081 torture_comment(tctx, "Testing generic bits 0x%08x (anonymous)\n",
1082 file_mappings[i].gen_bits);
1083 sd = security_descriptor_dacl_create(tctx,
1084 0, SID_NT_ANONYMOUS, NULL,
1086 SEC_ACE_TYPE_ACCESS_ALLOWED,
1087 file_mappings[i].gen_bits,
1091 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1092 set.set_secdesc.in.file.fnum = fnum;
1093 set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1094 set.set_secdesc.in.sd = sd;
1096 status = smb_raw_setfileinfo(cli->tree, &set);
1097 CHECK_STATUS(status, NT_STATUS_OK);
1099 sd2 = security_descriptor_dacl_create(tctx,
1100 0, SID_NT_ANONYMOUS, NULL,
1102 SEC_ACE_TYPE_ACCESS_ALLOWED,
1103 file_mappings[i].specific_bits,
1107 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1108 CHECK_STATUS(status, NT_STATUS_OK);
1109 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1111 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1112 status = smb_raw_open(cli->tree, tctx, &io);
1113 CHECK_STATUS(status, NT_STATUS_OK);
1114 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
1115 expected_mask_anon | file_mappings[i].specific_bits);
1116 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1119 torture_comment(tctx, "put back original sd\n");
1120 set.set_secdesc.in.sd = sd_orig;
1121 status = smb_raw_setfileinfo(cli->tree, &set);
1122 CHECK_STATUS(status, NT_STATUS_OK);
1124 smbcli_close(cli->tree, fnum);
1125 smbcli_unlink(cli->tree, fname);
1128 torture_comment(tctx, "TESTING DIR GENERIC BITS\n");
1130 io.generic.level = RAW_OPEN_NTCREATEX;
1131 io.ntcreatex.in.root_fid.fnum = 0;
1132 io.ntcreatex.in.flags = 0;
1133 io.ntcreatex.in.access_mask =
1134 SEC_STD_READ_CONTROL |
1136 SEC_STD_WRITE_OWNER;
1137 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1138 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1139 io.ntcreatex.in.share_access =
1140 NTCREATEX_SHARE_ACCESS_READ |
1141 NTCREATEX_SHARE_ACCESS_WRITE;
1142 io.ntcreatex.in.alloc_size = 0;
1143 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1144 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1145 io.ntcreatex.in.security_flags = 0;
1146 io.ntcreatex.in.fname = fname;
1147 status = smb_raw_open(cli->tree, tctx, &io);
1148 CHECK_STATUS(status, NT_STATUS_OK);
1149 fnum = io.ntcreatex.out.file.fnum;
1151 torture_comment(tctx, "get the original sd\n");
1152 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1153 q.query_secdesc.in.file.fnum = fnum;
1154 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1155 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1156 CHECK_STATUS(status, NT_STATUS_OK);
1157 sd_orig = q.query_secdesc.out.sd;
1159 owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1161 status = torture_check_privilege(cli,
1163 sec_privilege_name(SEC_PRIV_RESTORE));
1164 has_restore_privilege = NT_STATUS_IS_OK(status);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 torture_warning(tctx, "torture_check_privilege - %s\n",
1169 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
1171 status = torture_check_privilege(cli,
1173 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
1174 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
1175 if (!NT_STATUS_IS_OK(status)) {
1176 torture_warning(tctx, "torture_check_privilege - %s\n",
1179 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
1181 for (i=0;i<ARRAY_SIZE(dir_mappings);i++) {
1182 uint32_t expected_mask =
1184 SEC_STD_READ_CONTROL |
1185 SEC_FILE_READ_ATTRIBUTE |
1187 uint32_t expected_mask_anon = SEC_FILE_READ_ATTRIBUTE;
1189 if (has_restore_privilege) {
1190 expected_mask_anon |= SEC_STD_DELETE;
1193 torture_comment(tctx, "Testing generic bits 0x%08x\n",
1194 file_mappings[i].gen_bits);
1195 sd = security_descriptor_dacl_create(tctx,
1198 SEC_ACE_TYPE_ACCESS_ALLOWED,
1199 dir_mappings[i].gen_bits,
1203 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1204 set.set_secdesc.in.file.fnum = fnum;
1205 set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1206 set.set_secdesc.in.sd = sd;
1208 status = smb_raw_setfileinfo(cli->tree, &set);
1209 CHECK_STATUS(status, NT_STATUS_OK);
1211 sd2 = security_descriptor_dacl_create(tctx,
1214 SEC_ACE_TYPE_ACCESS_ALLOWED,
1215 dir_mappings[i].specific_bits,
1219 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1220 CHECK_STATUS(status, NT_STATUS_OK);
1221 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1223 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1224 status = smb_raw_open(cli->tree, tctx, &io);
1225 CHECK_STATUS(status, NT_STATUS_OK);
1226 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
1227 expected_mask | dir_mappings[i].specific_bits);
1228 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1230 if (!has_take_ownership_privilege) {
1234 torture_comment(tctx, "Testing generic bits 0x%08x (anonymous)\n",
1235 file_mappings[i].gen_bits);
1236 sd = security_descriptor_dacl_create(tctx,
1237 0, SID_NT_ANONYMOUS, NULL,
1239 SEC_ACE_TYPE_ACCESS_ALLOWED,
1240 file_mappings[i].gen_bits,
1244 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1245 set.set_secdesc.in.file.fnum = fnum;
1246 set.set_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1247 set.set_secdesc.in.sd = sd;
1249 status = smb_raw_setfileinfo(cli->tree, &set);
1250 CHECK_STATUS(status, NT_STATUS_OK);
1252 sd2 = security_descriptor_dacl_create(tctx,
1253 0, SID_NT_ANONYMOUS, NULL,
1255 SEC_ACE_TYPE_ACCESS_ALLOWED,
1256 file_mappings[i].specific_bits,
1260 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1261 CHECK_STATUS(status, NT_STATUS_OK);
1262 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1264 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1265 status = smb_raw_open(cli->tree, tctx, &io);
1266 CHECK_STATUS(status, NT_STATUS_OK);
1267 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum,
1268 expected_mask_anon | dir_mappings[i].specific_bits);
1269 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1272 torture_comment(tctx, "put back original sd\n");
1273 set.set_secdesc.in.sd = sd_orig;
1274 status = smb_raw_setfileinfo(cli->tree, &set);
1275 CHECK_STATUS(status, NT_STATUS_OK);
1277 smbcli_close(cli->tree, fnum);
1278 smbcli_unlink(cli->tree, fname);
1281 smbcli_close(cli->tree, fnum);
1282 smb_raw_exit(cli->session);
1283 smbcli_deltree(cli->tree, BASEDIR);
1289 see what access bits the owner of a file always gets
1290 Test copied to smb2/acls.c for SMB2.
1292 static bool test_owner_bits(struct torture_context *tctx,
1293 struct smbcli_state *cli)
1297 const char *fname = BASEDIR "\\test_owner_bits.txt";
1300 union smb_fileinfo q;
1301 union smb_setfileinfo set;
1302 struct security_descriptor *sd, *sd_orig;
1303 const char *owner_sid;
1304 bool has_restore_privilege;
1305 bool has_take_ownership_privilege;
1306 uint32_t expected_bits;
1308 if (!torture_setup_dir(cli, BASEDIR))
1311 torture_comment(tctx, "TESTING FILE OWNER BITS\n");
1313 io.generic.level = RAW_OPEN_NTCREATEX;
1314 io.ntcreatex.in.root_fid.fnum = 0;
1315 io.ntcreatex.in.flags = 0;
1316 io.ntcreatex.in.access_mask =
1317 SEC_STD_READ_CONTROL |
1319 SEC_STD_WRITE_OWNER;
1320 io.ntcreatex.in.create_options = 0;
1321 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1322 io.ntcreatex.in.share_access =
1323 NTCREATEX_SHARE_ACCESS_READ |
1324 NTCREATEX_SHARE_ACCESS_WRITE;
1325 io.ntcreatex.in.alloc_size = 0;
1326 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1327 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1328 io.ntcreatex.in.security_flags = 0;
1329 io.ntcreatex.in.fname = fname;
1330 status = smb_raw_open(cli->tree, tctx, &io);
1331 CHECK_STATUS(status, NT_STATUS_OK);
1332 fnum = io.ntcreatex.out.file.fnum;
1334 torture_comment(tctx, "get the original sd\n");
1335 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1336 q.query_secdesc.in.file.fnum = fnum;
1337 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1338 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1339 CHECK_STATUS(status, NT_STATUS_OK);
1340 sd_orig = q.query_secdesc.out.sd;
1342 owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1344 status = torture_check_privilege(cli,
1346 sec_privilege_name(SEC_PRIV_RESTORE));
1347 has_restore_privilege = NT_STATUS_IS_OK(status);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 torture_warning(tctx, "torture_check_privilege - %s\n", nt_errstr(status));
1351 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
1353 status = torture_check_privilege(cli,
1355 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
1356 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 torture_warning(tctx, "torture_check_privilege - %s\n", nt_errstr(status));
1360 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
1362 sd = security_descriptor_dacl_create(tctx,
1365 SEC_ACE_TYPE_ACCESS_ALLOWED,
1366 SEC_FILE_WRITE_DATA,
1370 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1371 set.set_secdesc.in.file.fnum = fnum;
1372 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1373 set.set_secdesc.in.sd = sd;
1375 status = smb_raw_setfileinfo(cli->tree, &set);
1376 CHECK_STATUS(status, NT_STATUS_OK);
1378 expected_bits = SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE;
1380 for (i=0;i<16;i++) {
1381 uint32_t bit = (1<<i);
1382 io.ntcreatex.in.access_mask = bit;
1383 status = smb_raw_open(cli->tree, tctx, &io);
1384 if (expected_bits & bit) {
1385 if (!NT_STATUS_IS_OK(status)) {
1386 torture_warning(tctx, "failed with access mask 0x%08x of expected 0x%08x\n",
1387 bit, expected_bits);
1389 CHECK_STATUS(status, NT_STATUS_OK);
1390 CHECK_ACCESS_FLAGS(io.ntcreatex.out.file.fnum, bit | SEC_FILE_READ_ATTRIBUTE);
1391 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1393 if (NT_STATUS_IS_OK(status)) {
1394 torture_warning(tctx, "open succeeded with access mask 0x%08x of "
1395 "expected 0x%08x - should fail\n",
1396 bit, expected_bits);
1398 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1402 torture_comment(tctx, "put back original sd\n");
1403 set.set_secdesc.in.sd = sd_orig;
1404 status = smb_raw_setfileinfo(cli->tree, &set);
1405 CHECK_STATUS(status, NT_STATUS_OK);
1408 smbcli_close(cli->tree, fnum);
1409 smbcli_unlink(cli->tree, fname);
1410 smb_raw_exit(cli->session);
1411 smbcli_deltree(cli->tree, BASEDIR);
1418 test the inheritance of ACL flags onto new files and directories
1419 Test copied to smb2/acls.c for SMB2.
1421 static bool test_inheritance(struct torture_context *tctx,
1422 struct smbcli_state *cli)
1426 const char *dname = BASEDIR "\\inheritance";
1427 const char *fname1 = BASEDIR "\\inheritance\\testfile";
1428 const char *fname2 = BASEDIR "\\inheritance\\testdir";
1430 int fnum=0, fnum2, i;
1431 union smb_fileinfo q;
1432 union smb_setfileinfo set;
1433 struct security_descriptor *sd, *sd2, *sd_orig=NULL, *sd_def1, *sd_def2;
1434 const char *owner_sid, *group_sid;
1435 const struct dom_sid *creator_owner;
1437 uint32_t parent_flags;
1438 uint32_t file_flags;
1447 SEC_ACE_FLAG_OBJECT_INHERIT,
1449 SEC_ACE_FLAG_OBJECT_INHERIT |
1450 SEC_ACE_FLAG_INHERIT_ONLY,
1453 SEC_ACE_FLAG_CONTAINER_INHERIT,
1455 SEC_ACE_FLAG_CONTAINER_INHERIT,
1458 SEC_ACE_FLAG_OBJECT_INHERIT |
1459 SEC_ACE_FLAG_CONTAINER_INHERIT,
1461 SEC_ACE_FLAG_OBJECT_INHERIT |
1462 SEC_ACE_FLAG_CONTAINER_INHERIT,
1465 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
1470 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1471 SEC_ACE_FLAG_OBJECT_INHERIT,
1476 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1477 SEC_ACE_FLAG_CONTAINER_INHERIT,
1482 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1483 SEC_ACE_FLAG_CONTAINER_INHERIT |
1484 SEC_ACE_FLAG_OBJECT_INHERIT,
1489 SEC_ACE_FLAG_INHERIT_ONLY,
1494 SEC_ACE_FLAG_INHERIT_ONLY |
1495 SEC_ACE_FLAG_OBJECT_INHERIT,
1497 SEC_ACE_FLAG_OBJECT_INHERIT |
1498 SEC_ACE_FLAG_INHERIT_ONLY,
1501 SEC_ACE_FLAG_INHERIT_ONLY |
1502 SEC_ACE_FLAG_CONTAINER_INHERIT,
1504 SEC_ACE_FLAG_CONTAINER_INHERIT,
1507 SEC_ACE_FLAG_INHERIT_ONLY |
1508 SEC_ACE_FLAG_CONTAINER_INHERIT |
1509 SEC_ACE_FLAG_OBJECT_INHERIT,
1511 SEC_ACE_FLAG_CONTAINER_INHERIT |
1512 SEC_ACE_FLAG_OBJECT_INHERIT,
1515 SEC_ACE_FLAG_INHERIT_ONLY |
1516 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT,
1521 SEC_ACE_FLAG_INHERIT_ONLY |
1522 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1523 SEC_ACE_FLAG_OBJECT_INHERIT,
1528 SEC_ACE_FLAG_INHERIT_ONLY |
1529 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1530 SEC_ACE_FLAG_CONTAINER_INHERIT,
1535 SEC_ACE_FLAG_INHERIT_ONLY |
1536 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT |
1537 SEC_ACE_FLAG_CONTAINER_INHERIT |
1538 SEC_ACE_FLAG_OBJECT_INHERIT,
1544 if (!torture_setup_dir(cli, BASEDIR))
1547 torture_comment(tctx, "TESTING ACL INHERITANCE\n");
1549 io.generic.level = RAW_OPEN_NTCREATEX;
1550 io.ntcreatex.in.root_fid.fnum = 0;
1551 io.ntcreatex.in.flags = 0;
1552 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1553 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1554 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1555 io.ntcreatex.in.share_access = 0;
1556 io.ntcreatex.in.alloc_size = 0;
1557 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1558 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1559 io.ntcreatex.in.security_flags = 0;
1560 io.ntcreatex.in.fname = dname;
1562 status = smb_raw_open(cli->tree, tctx, &io);
1563 CHECK_STATUS(status, NT_STATUS_OK);
1564 fnum = io.ntcreatex.out.file.fnum;
1566 torture_comment(tctx, "get the original sd\n");
1567 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1568 q.query_secdesc.in.file.fnum = fnum;
1569 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP;
1570 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1571 CHECK_STATUS(status, NT_STATUS_OK);
1572 sd_orig = q.query_secdesc.out.sd;
1574 owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
1575 group_sid = dom_sid_string(tctx, sd_orig->group_sid);
1577 torture_comment(tctx, "owner_sid is %s\n", owner_sid);
1578 torture_comment(tctx, "group_sid is %s\n", group_sid);
1580 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1582 if (torture_setting_bool(tctx, "samba4", false)) {
1583 /* the default ACL in Samba4 includes the group and
1584 other permissions */
1585 sd_def1 = security_descriptor_dacl_create(tctx,
1588 SEC_ACE_TYPE_ACCESS_ALLOWED,
1589 SEC_RIGHTS_FILE_ALL,
1592 SEC_ACE_TYPE_ACCESS_ALLOWED,
1593 SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE,
1596 SEC_ACE_TYPE_ACCESS_ALLOWED,
1597 SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE,
1600 SEC_ACE_TYPE_ACCESS_ALLOWED,
1601 SEC_RIGHTS_FILE_ALL,
1606 * The Windows Default ACL for a new file, when there is no ACL to be
1607 * inherited: FullControl for the owner and SYSTEM.
1609 sd_def1 = security_descriptor_dacl_create(tctx,
1612 SEC_ACE_TYPE_ACCESS_ALLOWED,
1613 SEC_RIGHTS_FILE_ALL,
1616 SEC_ACE_TYPE_ACCESS_ALLOWED,
1617 SEC_RIGHTS_FILE_ALL,
1623 * Use this in the case the system being tested does not add an ACE for
1626 sd_def2 = security_descriptor_dacl_create(tctx,
1629 SEC_ACE_TYPE_ACCESS_ALLOWED,
1630 SEC_RIGHTS_FILE_ALL,
1634 creator_owner = dom_sid_parse_talloc(tctx, SID_CREATOR_OWNER);
1636 for (i=0;i<ARRAY_SIZE(test_flags);i++) {
1637 sd = security_descriptor_dacl_create(tctx,
1640 SEC_ACE_TYPE_ACCESS_ALLOWED,
1641 SEC_FILE_WRITE_DATA,
1642 test_flags[i].parent_flags,
1644 SEC_ACE_TYPE_ACCESS_ALLOWED,
1645 SEC_FILE_ALL | SEC_STD_ALL,
1648 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1649 set.set_secdesc.in.file.fnum = fnum;
1650 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1651 set.set_secdesc.in.sd = sd;
1652 status = smb_raw_setfileinfo(cli->tree, &set);
1653 CHECK_STATUS(status, NT_STATUS_OK);
1655 io.ntcreatex.in.fname = fname1;
1656 io.ntcreatex.in.create_options = 0;
1657 status = smb_raw_open(cli->tree, tctx, &io);
1658 CHECK_STATUS(status, NT_STATUS_OK);
1659 fnum2 = io.ntcreatex.out.file.fnum;
1661 q.query_secdesc.in.file.fnum = fnum2;
1662 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1663 CHECK_STATUS(status, NT_STATUS_OK);
1665 smbcli_close(cli->tree, fnum2);
1666 smbcli_unlink(cli->tree, fname1);
1668 if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
1669 if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def1) &&
1670 !security_descriptor_equal(q.query_secdesc.out.sd, sd_def2)) {
1671 torture_warning(tctx, "Expected default sd "
1673 NDR_PRINT_DEBUG(security_descriptor, sd_def1);
1674 torture_warning(tctx, "at %d - got:\n", i);
1675 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1680 if (q.query_secdesc.out.sd->dacl == NULL ||
1681 q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1682 q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1683 !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1684 sd_orig->owner_sid)) {
1686 torture_warning(tctx, "Bad sd in child file at %d\n", i);
1687 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1691 if (q.query_secdesc.out.sd->dacl->aces[0].flags !=
1692 test_flags[i].file_flags) {
1693 torture_warning(tctx, "incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1694 q.query_secdesc.out.sd->dacl->aces[0].flags,
1695 test_flags[i].file_flags,
1696 test_flags[i].parent_flags,
1702 io.ntcreatex.in.fname = fname2;
1703 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1704 status = smb_raw_open(cli->tree, tctx, &io);
1705 CHECK_STATUS(status, NT_STATUS_OK);
1706 fnum2 = io.ntcreatex.out.file.fnum;
1708 q.query_secdesc.in.file.fnum = fnum2;
1709 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1710 CHECK_STATUS(status, NT_STATUS_OK);
1712 smbcli_close(cli->tree, fnum2);
1713 smbcli_rmdir(cli->tree, fname2);
1715 if (!(test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1716 (!(test_flags[i].parent_flags & SEC_ACE_FLAG_OBJECT_INHERIT) ||
1717 (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT))) {
1718 if (!security_descriptor_equal(q.query_secdesc.out.sd, sd_def1) &&
1719 !security_descriptor_equal(q.query_secdesc.out.sd, sd_def2)) {
1720 torture_warning(tctx, "Expected default sd for dir at %d:\n", i);
1721 NDR_PRINT_DEBUG(security_descriptor, sd_def1);
1722 torture_warning(tctx, "got:\n");
1723 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1728 if ((test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) &&
1729 (test_flags[i].parent_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
1730 if (q.query_secdesc.out.sd->dacl == NULL ||
1731 q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1732 q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1733 !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1734 sd_orig->owner_sid) ||
1735 q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1736 torture_warning(tctx, "(CI & NP) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1737 test_flags[i].dir_flags,
1738 test_flags[i].parent_flags, i);
1739 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1740 torture_comment(tctx, "FYI, here is the parent sd:\n");
1741 NDR_PRINT_DEBUG(security_descriptor, sd);
1745 } else if (test_flags[i].parent_flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
1746 if (q.query_secdesc.out.sd->dacl == NULL ||
1747 q.query_secdesc.out.sd->dacl->num_aces != 2 ||
1748 q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1749 !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1750 sd_orig->owner_sid) ||
1751 q.query_secdesc.out.sd->dacl->aces[1].access_mask != SEC_FILE_WRITE_DATA ||
1752 !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[1].trustee,
1754 q.query_secdesc.out.sd->dacl->aces[0].flags != 0 ||
1755 q.query_secdesc.out.sd->dacl->aces[1].flags !=
1756 (test_flags[i].dir_flags | SEC_ACE_FLAG_INHERIT_ONLY)) {
1757 torture_warning(tctx, "(CI) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1758 test_flags[i].dir_flags,
1759 test_flags[i].parent_flags, i);
1760 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1761 torture_comment(tctx, "FYI, here is the parent sd:\n");
1762 NDR_PRINT_DEBUG(security_descriptor, sd);
1767 if (q.query_secdesc.out.sd->dacl == NULL ||
1768 q.query_secdesc.out.sd->dacl->num_aces != 1 ||
1769 q.query_secdesc.out.sd->dacl->aces[0].access_mask != SEC_FILE_WRITE_DATA ||
1770 !dom_sid_equal(&q.query_secdesc.out.sd->dacl->aces[0].trustee,
1772 q.query_secdesc.out.sd->dacl->aces[0].flags != test_flags[i].dir_flags) {
1773 torture_warning(tctx, "(0) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1774 test_flags[i].dir_flags,
1775 test_flags[i].parent_flags, i);
1776 NDR_PRINT_DEBUG(security_descriptor, q.query_secdesc.out.sd);
1777 torture_comment(tctx, "FYI, here is the parent sd:\n");
1778 NDR_PRINT_DEBUG(security_descriptor, sd);
1785 torture_comment(tctx, "Testing access checks on inherited create with %s\n", fname1);
1786 sd = security_descriptor_dacl_create(tctx,
1789 SEC_ACE_TYPE_ACCESS_ALLOWED,
1790 SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1791 SEC_ACE_FLAG_OBJECT_INHERIT,
1793 SEC_ACE_TYPE_ACCESS_ALLOWED,
1794 SEC_FILE_ALL | SEC_STD_ALL,
1797 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1798 set.set_secdesc.in.file.fnum = fnum;
1799 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1800 set.set_secdesc.in.sd = sd;
1801 status = smb_raw_setfileinfo(cli->tree, &set);
1802 CHECK_STATUS(status, NT_STATUS_OK);
1804 /* Check DACL we just set. */
1805 torture_comment(tctx, "checking new sd\n");
1806 q.query_secdesc.in.file.fnum = fnum;
1807 q.query_secdesc.in.secinfo_flags = SECINFO_DACL;
1808 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1809 CHECK_STATUS(status, NT_STATUS_OK);
1810 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
1812 io.ntcreatex.in.fname = fname1;
1813 io.ntcreatex.in.create_options = 0;
1814 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1815 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1816 status = smb_raw_open(cli->tree, tctx, &io);
1817 CHECK_STATUS(status, NT_STATUS_OK);
1818 fnum2 = io.ntcreatex.out.file.fnum;
1819 CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
1821 q.query_secdesc.in.file.fnum = fnum2;
1822 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
1823 status = smb_raw_fileinfo(cli->tree, tctx, &q);
1824 CHECK_STATUS(status, NT_STATUS_OK);
1825 smbcli_close(cli->tree, fnum2);
1827 sd2 = security_descriptor_dacl_create(tctx,
1830 SEC_ACE_TYPE_ACCESS_ALLOWED,
1831 SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
1834 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
1836 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1837 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1838 status = smb_raw_open(cli->tree, tctx, &io);
1839 if (NT_STATUS_IS_OK(status)) {
1840 torture_warning(tctx, "failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1842 fnum2 = io.ntcreatex.out.file.fnum;
1843 CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
1844 smbcli_close(cli->tree, fnum2);
1846 if (TARGET_IS_WIN7(tctx)) {
1847 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1849 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1853 torture_comment(tctx, "trying without execute\n");
1854 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1855 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL & ~SEC_FILE_EXECUTE;
1856 status = smb_raw_open(cli->tree, tctx, &io);
1857 if (TARGET_IS_WIN7(tctx)) {
1858 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1860 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1863 torture_comment(tctx, "and with full permissions again\n");
1864 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1865 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1866 status = smb_raw_open(cli->tree, tctx, &io);
1867 if (TARGET_IS_WIN7(tctx)) {
1868 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1870 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1873 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1874 status = smb_raw_open(cli->tree, tctx, &io);
1875 CHECK_STATUS(status, NT_STATUS_OK);
1876 fnum2 = io.ntcreatex.out.file.fnum;
1877 CHECK_ACCESS_FLAGS(fnum2, SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
1878 smbcli_close(cli->tree, fnum2);
1880 torture_comment(tctx, "put back original sd\n");
1881 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1882 set.set_secdesc.in.file.fnum = fnum;
1883 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1884 set.set_secdesc.in.sd = sd_orig;
1885 status = smb_raw_setfileinfo(cli->tree, &set);
1886 CHECK_STATUS(status, NT_STATUS_OK);
1888 smbcli_close(cli->tree, fnum);
1890 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1891 status = smb_raw_open(cli->tree, tctx, &io);
1892 if (TARGET_IS_WIN7(tctx)) {
1893 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1895 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1898 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
1899 status = smb_raw_open(cli->tree, tctx, &io);
1900 CHECK_STATUS(status, NT_STATUS_OK);
1901 fnum2 = io.ntcreatex.out.file.fnum;
1902 CHECK_ACCESS_FLAGS(fnum2, SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE);
1903 smbcli_close(cli->tree, fnum2);
1906 if (sd_orig != NULL) {
1907 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1908 set.set_secdesc.in.file.fnum = fnum;
1909 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1910 set.set_secdesc.in.sd = sd_orig;
1911 status = smb_raw_setfileinfo(cli->tree, &set);
1914 smbcli_close(cli->tree, fnum);
1915 smbcli_unlink(cli->tree, fname1);
1916 smbcli_rmdir(cli->tree, dname);
1917 smb_raw_exit(cli->session);
1918 smbcli_deltree(cli->tree, BASEDIR);
1921 torture_result(tctx,
1922 TORTURE_FAIL, "(%s) test_inheritance\n",
1929 static bool test_inheritance_flags(struct torture_context *tctx,
1930 struct smbcli_state *cli)
1934 const char *dname = BASEDIR "\\inheritance";
1935 const char *fname1 = BASEDIR "\\inheritance\\testfile";
1937 int fnum=0, fnum2, i, j;
1938 union smb_fileinfo q;
1939 union smb_setfileinfo set;
1940 struct security_descriptor *sd, *sd2, *sd_orig=NULL;
1941 const char *owner_sid;
1943 uint32_t parent_set_sd_type; /* 3 options */
1944 uint32_t parent_set_ace_inherit; /* 1 option */
1945 uint32_t parent_get_sd_type;
1946 uint32_t parent_get_ace_inherit;
1947 uint32_t child_get_sd_type;
1948 uint32_t child_get_ace_inherit;
1949 } tflags[16] = {{0}}; /* 2^4 */
1951 for (i = 0; i < 15; i++) {
1952 torture_comment(tctx, "i=%d:", i);
1954 ZERO_STRUCT(tflags[i]);
1957 tflags[i].parent_set_sd_type |=
1958 SEC_DESC_DACL_AUTO_INHERITED;
1959 torture_comment(tctx, "AUTO_INHERITED, ");
1962 tflags[i].parent_set_sd_type |=
1963 SEC_DESC_DACL_AUTO_INHERIT_REQ;
1964 torture_comment(tctx, "AUTO_INHERIT_REQ, ");
1967 tflags[i].parent_set_sd_type |=
1968 SEC_DESC_DACL_PROTECTED;
1969 tflags[i].parent_get_sd_type |=
1970 SEC_DESC_DACL_PROTECTED;
1971 torture_comment(tctx, "PROTECTED, ");
1974 tflags[i].parent_set_ace_inherit |=
1975 SEC_ACE_FLAG_INHERITED_ACE;
1976 tflags[i].parent_get_ace_inherit |=
1977 SEC_ACE_FLAG_INHERITED_ACE;
1978 torture_comment(tctx, "INHERITED, ");
1981 if ((tflags[i].parent_set_sd_type &
1982 (SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ)) ==
1983 (SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ)) {
1984 tflags[i].parent_get_sd_type |=
1985 SEC_DESC_DACL_AUTO_INHERITED;
1986 tflags[i].child_get_sd_type |=
1987 SEC_DESC_DACL_AUTO_INHERITED;
1988 tflags[i].child_get_ace_inherit |=
1989 SEC_ACE_FLAG_INHERITED_ACE;
1990 torture_comment(tctx, " ... parent is AUTO INHERITED");
1993 if (tflags[i].parent_set_ace_inherit &
1994 SEC_ACE_FLAG_INHERITED_ACE) {
1995 tflags[i].parent_get_ace_inherit =
1996 SEC_ACE_FLAG_INHERITED_ACE;
1997 torture_comment(tctx, " ... parent ACE is INHERITED");
2000 torture_comment(tctx, "\n");
2003 if (!torture_setup_dir(cli, BASEDIR))
2006 torture_comment(tctx, "TESTING ACL INHERITANCE FLAGS\n");
2010 io.generic.level = RAW_OPEN_NTCREATEX;
2011 io.ntcreatex.in.root_fid.fnum = 0;
2012 io.ntcreatex.in.flags = 0;
2013 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2014 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2015 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
2016 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
2017 io.ntcreatex.in.alloc_size = 0;
2018 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2019 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2020 io.ntcreatex.in.security_flags = 0;
2021 io.ntcreatex.in.fname = dname;
2023 torture_comment(tctx, "creating initial directory %s\n", dname);
2024 status = smb_raw_open(cli->tree, tctx, &io);
2025 CHECK_STATUS(status, NT_STATUS_OK);
2026 fnum = io.ntcreatex.out.file.fnum;
2028 torture_comment(tctx, "getting original sd\n");
2029 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2030 q.query_secdesc.in.file.fnum = fnum;
2031 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2032 status = smb_raw_fileinfo(cli->tree, tctx, &q);
2033 CHECK_STATUS(status, NT_STATUS_OK);
2034 sd_orig = q.query_secdesc.out.sd;
2036 owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2037 torture_comment(tctx, "owner_sid is %s\n", owner_sid);
2039 for (i=0; i < ARRAY_SIZE(tflags); i++) {
2040 torture_comment(tctx, "setting a new sd on directory, pass #%d\n", i);
2042 sd = security_descriptor_dacl_create(tctx,
2043 tflags[i].parent_set_sd_type,
2046 SEC_ACE_TYPE_ACCESS_ALLOWED,
2047 SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
2048 SEC_ACE_FLAG_OBJECT_INHERIT |
2049 SEC_ACE_FLAG_CONTAINER_INHERIT |
2050 tflags[i].parent_set_ace_inherit,
2052 SEC_ACE_TYPE_ACCESS_ALLOWED,
2053 SEC_FILE_ALL | SEC_STD_ALL,
2056 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2057 set.set_secdesc.in.file.fnum = fnum;
2058 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2059 set.set_secdesc.in.sd = sd;
2060 status = smb_raw_setfileinfo(cli->tree, &set);
2061 CHECK_STATUS(status, NT_STATUS_OK);
2064 * Check DACL we just set, except change the bits to what they
2067 torture_comment(tctx, " checking new sd\n");
2069 /* REQ bit should always be false. */
2070 sd->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
2072 if ((tflags[i].parent_get_sd_type & SEC_DESC_DACL_AUTO_INHERITED) == 0)
2073 sd->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
2075 q.query_secdesc.in.file.fnum = fnum;
2076 q.query_secdesc.in.secinfo_flags = SECINFO_DACL;
2077 status = smb_raw_fileinfo(cli->tree, tctx, &q);
2078 CHECK_STATUS(status, NT_STATUS_OK);
2079 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd);
2082 torture_comment(tctx, " creating file %s\n", fname1);
2083 io.ntcreatex.in.fname = fname1;
2084 io.ntcreatex.in.create_options = 0;
2085 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2086 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2087 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2088 status = smb_raw_open(cli->tree, tctx, &io);
2089 CHECK_STATUS(status, NT_STATUS_OK);
2090 fnum2 = io.ntcreatex.out.file.fnum;
2091 CHECK_ACCESS_FLAGS(fnum2, SEC_RIGHTS_FILE_ALL);
2093 q.query_secdesc.in.file.fnum = fnum2;
2094 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2095 status = smb_raw_fileinfo(cli->tree, tctx, &q);
2096 CHECK_STATUS(status, NT_STATUS_OK);
2098 torture_comment(tctx, " checking sd on file %s\n", fname1);
2099 sd2 = security_descriptor_dacl_create(tctx,
2100 tflags[i].child_get_sd_type,
2103 SEC_ACE_TYPE_ACCESS_ALLOWED,
2104 SEC_FILE_WRITE_DATA | SEC_STD_WRITE_DAC,
2105 tflags[i].child_get_ace_inherit,
2107 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
2110 * Set new sd on file ... prove that the bits have nothing to
2111 * do with the parents bits when manually setting an ACL. The
2112 * _AUTO_INHERITED bit comes directly from the ACL set.
2114 for (j = 0; j < ARRAY_SIZE(tflags); j++) {
2115 torture_comment(tctx, " setting new file sd, pass #%d\n", j);
2117 /* Change sd type. */
2118 sd2->type &= ~(SEC_DESC_DACL_AUTO_INHERITED |
2119 SEC_DESC_DACL_AUTO_INHERIT_REQ |
2120 SEC_DESC_DACL_PROTECTED);
2121 sd2->type |= tflags[j].parent_set_sd_type;
2123 sd2->dacl->aces[0].flags &=
2124 ~SEC_ACE_FLAG_INHERITED_ACE;
2125 sd2->dacl->aces[0].flags |=
2126 tflags[j].parent_set_ace_inherit;
2128 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2129 set.set_secdesc.in.file.fnum = fnum2;
2130 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2131 set.set_secdesc.in.sd = sd2;
2132 status = smb_raw_setfileinfo(cli->tree, &set);
2133 CHECK_STATUS(status, NT_STATUS_OK);
2135 /* Check DACL we just set. */
2136 sd2->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
2137 if ((tflags[j].parent_get_sd_type & SEC_DESC_DACL_AUTO_INHERITED) == 0)
2138 sd2->type &= ~SEC_DESC_DACL_AUTO_INHERITED;
2140 q.query_secdesc.in.file.fnum = fnum2;
2141 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2142 status = smb_raw_fileinfo(cli->tree, tctx, &q);
2143 CHECK_STATUS(status, NT_STATUS_OK);
2145 CHECK_SECURITY_DESCRIPTOR(q.query_secdesc.out.sd, sd2);
2148 smbcli_close(cli->tree, fnum2);
2149 smbcli_unlink(cli->tree, fname1);
2153 smbcli_close(cli->tree, fnum);
2154 smb_raw_exit(cli->session);
2155 smbcli_deltree(cli->tree, BASEDIR);
2158 torture_result(tctx,
2159 TORTURE_FAIL, "(%s) test_inheritance_flags\n",
2167 test dynamic acl inheritance
2168 Test copied to smb2/acls.c for SMB2.
2170 static bool test_inheritance_dynamic(struct torture_context *tctx,
2171 struct smbcli_state *cli)
2175 const char *dname = BASEDIR "\\inheritance2";
2176 const char *fname1 = BASEDIR "\\inheritance2\\testfile";
2179 union smb_fileinfo q;
2180 union smb_setfileinfo set;
2181 struct security_descriptor *sd, *sd_orig=NULL;
2182 const char *owner_sid;
2184 torture_comment(tctx, "TESTING DYNAMIC ACL INHERITANCE\n");
2186 if (!torture_setup_dir(cli, BASEDIR))
2189 io.generic.level = RAW_OPEN_NTCREATEX;
2190 io.ntcreatex.in.root_fid.fnum = 0;
2191 io.ntcreatex.in.flags = 0;
2192 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2193 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2194 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
2195 io.ntcreatex.in.share_access = 0;
2196 io.ntcreatex.in.alloc_size = 0;
2197 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2198 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2199 io.ntcreatex.in.security_flags = 0;
2200 io.ntcreatex.in.fname = dname;
2202 status = smb_raw_open(cli->tree, tctx, &io);
2203 CHECK_STATUS(status, NT_STATUS_OK);
2204 fnum = io.ntcreatex.out.file.fnum;
2206 torture_comment(tctx, "get the original sd\n");
2207 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2208 q.query_secdesc.in.file.fnum = fnum;
2209 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
2210 status = smb_raw_fileinfo(cli->tree, tctx, &q);
2211 CHECK_STATUS(status, NT_STATUS_OK);
2212 sd_orig = q.query_secdesc.out.sd;
2214 owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
2216 torture_comment(tctx, "owner_sid is %s\n", owner_sid);
2218 sd = security_descriptor_dacl_create(tctx,
2221 SEC_ACE_TYPE_ACCESS_ALLOWED,
2222 SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE,
2223 SEC_ACE_FLAG_OBJECT_INHERIT,
2225 sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
2227 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2228 set.set_secdesc.in.file.fnum = fnum;
2229 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2230 set.set_secdesc.in.sd = sd;
2231 status = smb_raw_setfileinfo(cli->tree, &set);
2232 CHECK_STATUS(status, NT_STATUS_OK);
2234 torture_comment(tctx, "create a file with an inherited acl\n");
2235 io.ntcreatex.in.fname = fname1;
2236 io.ntcreatex.in.create_options = 0;
2237 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE;
2238 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2239 status = smb_raw_open(cli->tree, tctx, &io);
2240 CHECK_STATUS(status, NT_STATUS_OK);
2241 fnum2 = io.ntcreatex.out.file.fnum;
2242 smbcli_close(cli->tree, fnum2);
2244 torture_comment(tctx, "try and access file with base rights - should be OK\n");
2245 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
2246 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2247 status = smb_raw_open(cli->tree, tctx, &io);
2248 CHECK_STATUS(status, NT_STATUS_OK);
2249 fnum2 = io.ntcreatex.out.file.fnum;
2250 smbcli_close(cli->tree, fnum2);
2252 torture_comment(tctx, "try and access file with extra rights - should be denied\n");
2253 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
2254 status = smb_raw_open(cli->tree, tctx, &io);
2255 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
2257 torture_comment(tctx, "update parent sd\n");
2258 sd = security_descriptor_dacl_create(tctx,
2261 SEC_ACE_TYPE_ACCESS_ALLOWED,
2262 SEC_FILE_WRITE_DATA | SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE,
2263 SEC_ACE_FLAG_OBJECT_INHERIT,
2265 sd->type |= SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ;
2267 set.set_secdesc.in.sd = sd;
2268 status = smb_raw_setfileinfo(cli->tree, &set);
2269 CHECK_STATUS(status, NT_STATUS_OK);
2271 torture_comment(tctx, "try and access file with base rights - should be OK\n");
2272 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
2273 status = smb_raw_open(cli->tree, tctx, &io);
2274 CHECK_STATUS(status, NT_STATUS_OK);
2275 fnum2 = io.ntcreatex.out.file.fnum;
2276 smbcli_close(cli->tree, fnum2);
2279 torture_comment(tctx, "try and access now - should be OK if dynamic inheritance works\n");
2280 io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA | SEC_FILE_EXECUTE;
2281 status = smb_raw_open(cli->tree, tctx, &io);
2282 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2283 torture_comment(tctx, "Server does not have dynamic inheritance\n");
2285 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
2286 torture_comment(tctx, "Server does have dynamic inheritance\n");
2288 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
2290 smbcli_unlink(cli->tree, fname1);
2293 if (sd_orig != NULL) {
2294 torture_comment(tctx, "put back original sd\n");
2295 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2296 set.set_secdesc.in.file.fnum = fnum;
2297 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2298 set.set_secdesc.in.sd = sd_orig;
2299 status = smb_raw_setfileinfo(cli->tree, &set);
2301 smbcli_close(cli->tree, fnum);
2302 smbcli_rmdir(cli->tree, dname);
2303 smb_raw_exit(cli->session);
2304 smbcli_deltree(cli->tree, BASEDIR);
2309 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
2310 if (!(bits & desired_64)) {\
2311 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
2314 CHECK_STATUS(status, NT_STATUS_OK); \
2318 #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
2319 if (NT_STATUS_IS_OK(status)) { \
2320 if (!(granted & access)) {\
2322 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
2323 __location__, nt_errstr(status), access, granted, desired); \
2327 if (granted & access) {\
2329 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
2330 __location__, nt_errstr(status), access, granted, desired); \
2334 CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
2339 /* test what access mask is needed for getting and setting security_descriptors
2340 Test copied to smb2/acls.c for SMB2. */
2341 static bool test_sd_get_set(struct torture_context *tctx,
2342 struct smbcli_state *cli)
2347 union smb_fileinfo fi;
2348 union smb_setfileinfo si;
2349 struct security_descriptor *sd;
2350 struct security_descriptor *sd_owner = NULL;
2351 struct security_descriptor *sd_group = NULL;
2352 struct security_descriptor *sd_dacl = NULL;
2353 struct security_descriptor *sd_sacl = NULL;
2355 const char *fname = BASEDIR "\\sd_get_set.txt";
2356 uint64_t desired_64;
2357 uint32_t desired = 0, granted;
2359 #define NO_BITS_HACK (((uint64_t)1)<<32)
2360 uint64_t open_bits =
2362 SEC_FLAG_SYSTEM_SECURITY |
2363 SEC_FLAG_MAXIMUM_ALLOWED |
2367 uint64_t get_owner_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
2368 uint64_t set_owner_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
2369 uint64_t get_group_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
2370 uint64_t set_group_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_OWNER;
2371 uint64_t get_dacl_bits = SEC_MASK_GENERIC | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_READ_CONTROL;
2372 uint64_t set_dacl_bits = SEC_GENERIC_ALL | SEC_FLAG_MAXIMUM_ALLOWED | SEC_STD_WRITE_DAC;
2373 uint64_t get_sacl_bits = SEC_FLAG_SYSTEM_SECURITY;
2374 uint64_t set_sacl_bits = SEC_FLAG_SYSTEM_SECURITY;
2376 if (!torture_setup_dir(cli, BASEDIR))
2379 torture_comment(tctx, "TESTING ACCESS MASKS FOR SD GET/SET\n");
2381 /* first create a file with full access for everyone */
2382 sd = security_descriptor_dacl_create(tctx,
2383 0, SID_NT_ANONYMOUS, SID_BUILTIN_USERS,
2385 SEC_ACE_TYPE_ACCESS_ALLOWED,
2389 sd->type |= SEC_DESC_SACL_PRESENT;
2391 io.ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
2392 io.ntcreatex.in.root_fid.fnum = 0;
2393 io.ntcreatex.in.flags = 0;
2394 io.ntcreatex.in.access_mask = SEC_GENERIC_ALL;
2395 io.ntcreatex.in.create_options = 0;
2396 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2397 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
2398 io.ntcreatex.in.alloc_size = 0;
2399 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2400 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2401 io.ntcreatex.in.security_flags = 0;
2402 io.ntcreatex.in.fname = fname;
2403 io.ntcreatex.in.sec_desc = sd;
2404 io.ntcreatex.in.ea_list = NULL;
2405 status = smb_raw_open(cli->tree, tctx, &io);
2406 CHECK_STATUS(status, NT_STATUS_OK);
2407 fnum = io.ntcreatex.out.file.fnum;
2409 status = smbcli_close(cli->tree, fnum);
2410 CHECK_STATUS(status, NT_STATUS_OK);
2413 * now try each access_mask bit and no bit at all in a loop
2414 * and see what's allowed
2415 * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
2417 for (i=0; i <= 32; i++) {
2418 desired_64 = ((uint64_t)1) << i;
2419 desired = (uint32_t)desired_64;
2421 /* first open the file with the desired access */
2422 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
2423 io.ntcreatex.in.access_mask = desired;
2424 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2425 status = smb_raw_open(cli->tree, tctx, &io);
2426 CHECK_STATUS_FOR_BIT_ACTION(status, open_bits, goto next);
2427 fnum = io.ntcreatex.out.file.fnum;
2429 /* then check what access was granted */
2430 fi.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
2431 fi.access_information.in.file.fnum = fnum;
2432 status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2433 CHECK_STATUS(status, NT_STATUS_OK);
2434 granted = fi.access_information.out.access_flags;
2436 /* test the owner */
2438 fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2439 fi.query_secdesc.in.file.fnum = fnum;
2440 fi.query_secdesc.in.secinfo_flags = SECINFO_OWNER;
2441 status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2442 CHECK_STATUS_FOR_BIT(status, get_owner_bits, SEC_STD_READ_CONTROL);
2443 if (fi.query_secdesc.out.sd) {
2444 sd_owner = fi.query_secdesc.out.sd;
2445 } else if (!sd_owner) {
2448 si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2449 si.set_secdesc.in.file.fnum = fnum;
2450 si.set_secdesc.in.secinfo_flags = SECINFO_OWNER;
2451 si.set_secdesc.in.sd = sd_owner;
2452 status = smb_raw_setfileinfo(cli->tree, &si);
2453 CHECK_STATUS_FOR_BIT(status, set_owner_bits, SEC_STD_WRITE_OWNER);
2455 /* test the group */
2457 fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2458 fi.query_secdesc.in.file.fnum = fnum;
2459 fi.query_secdesc.in.secinfo_flags = SECINFO_GROUP;
2460 status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2461 CHECK_STATUS_FOR_BIT(status, get_group_bits, SEC_STD_READ_CONTROL);
2462 if (fi.query_secdesc.out.sd) {
2463 sd_group = fi.query_secdesc.out.sd;
2464 } else if (!sd_group) {
2467 si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2468 si.set_secdesc.in.file.fnum = fnum;
2469 si.set_secdesc.in.secinfo_flags = SECINFO_GROUP;
2470 si.set_secdesc.in.sd = sd_group;
2471 status = smb_raw_setfileinfo(cli->tree, &si);
2472 CHECK_STATUS_FOR_BIT(status, set_group_bits, SEC_STD_WRITE_OWNER);
2476 fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2477 fi.query_secdesc.in.file.fnum = fnum;
2478 fi.query_secdesc.in.secinfo_flags = SECINFO_DACL;
2479 status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2480 CHECK_STATUS_FOR_BIT(status, get_dacl_bits, SEC_STD_READ_CONTROL);
2481 if (fi.query_secdesc.out.sd) {
2482 sd_dacl = fi.query_secdesc.out.sd;
2483 } else if (!sd_dacl) {
2486 si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2487 si.set_secdesc.in.file.fnum = fnum;
2488 si.set_secdesc.in.secinfo_flags = SECINFO_DACL;
2489 si.set_secdesc.in.sd = sd_dacl;
2490 status = smb_raw_setfileinfo(cli->tree, &si);
2491 CHECK_STATUS_FOR_BIT(status, set_dacl_bits, SEC_STD_WRITE_DAC);
2495 fi.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
2496 fi.query_secdesc.in.file.fnum = fnum;
2497 fi.query_secdesc.in.secinfo_flags = SECINFO_SACL;
2498 status = smb_raw_fileinfo(cli->tree, tctx, &fi);
2499 CHECK_STATUS_FOR_BIT(status, get_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
2500 if (fi.query_secdesc.out.sd) {
2501 sd_sacl = fi.query_secdesc.out.sd;
2502 } else if (!sd_sacl) {
2505 si.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
2506 si.set_secdesc.in.file.fnum = fnum;
2507 si.set_secdesc.in.secinfo_flags = SECINFO_SACL;
2508 si.set_secdesc.in.sd = sd_sacl;
2509 status = smb_raw_setfileinfo(cli->tree, &si);
2510 CHECK_STATUS_FOR_BIT(status, set_sacl_bits, SEC_FLAG_SYSTEM_SECURITY);
2512 /* close the handle */
2513 status = smbcli_close(cli->tree, fnum);
2514 CHECK_STATUS(status, NT_STATUS_OK);
2520 smbcli_close(cli->tree, fnum);
2521 smbcli_unlink(cli->tree, fname);
2522 smb_raw_exit(cli->session);
2523 smbcli_deltree(cli->tree, BASEDIR);
2531 basic testing of security descriptor calls
2533 struct torture_suite *torture_raw_acls(TALLOC_CTX *mem_ctx)
2535 struct torture_suite *suite = torture_suite_create(mem_ctx, "acls");
2537 torture_suite_add_1smb_test(suite, "sd", test_sd);
2538 torture_suite_add_1smb_test(suite, "create_file", test_nttrans_create_file);
2539 torture_suite_add_1smb_test(suite, "create_dir", test_nttrans_create_dir);
2540 torture_suite_add_1smb_test(suite, "create_owner_file", test_nttrans_create_owner_file);
2541 torture_suite_add_1smb_test(suite, "create_owner_dir", test_nttrans_create_owner_dir);
2542 torture_suite_add_1smb_test(suite, "nulldacl", test_nttrans_create_null_dacl);
2543 torture_suite_add_1smb_test(suite, "creator", test_creator_sid);
2544 torture_suite_add_1smb_test(suite, "generic", test_generic_bits);
2545 torture_suite_add_1smb_test(suite, "owner", test_owner_bits);
2546 torture_suite_add_1smb_test(suite, "inheritance", test_inheritance);
2548 torture_suite_add_1smb_test(suite, "INHERITFLAGS", test_inheritance_flags);
2549 torture_suite_add_1smb_test(suite, "dynamic", test_inheritance_dynamic);
2551 /* XXX This test does not work against XP or Vista. */
2552 torture_suite_add_1smb_test(suite, "GETSET", test_sd_get_set);