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/util/clilsa.h"
28 #include "libcli/security/security.h"
29 #include "torture/util.h"
30 #include "librpc/gen_ndr/ndr_security.h"
32 #define BASEDIR "\\testsd"
34 #define CHECK_STATUS(status, correct) do { \
35 if (!NT_STATUS_EQUAL(status, correct)) { \
37 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
38 __location__, nt_errstr(status), nt_errstr(correct)); \
42 #define FAIL_UNLESS(__cond) \
44 if (__cond) {} else { \
46 torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \
47 __location__, #__cond); \
52 #define CHECK_SECURITY_DESCRIPTOR(_sd1, _sd2) do { \
53 if (!security_descriptor_equal(_sd1, _sd2)) { \
54 torture_warning(tctx, "%s: security descriptors don't match!\n", __location__); \
55 torture_warning(tctx, "got:\n"); \
56 NDR_PRINT_DEBUG(security_descriptor, _sd1); \
57 torture_warning(tctx, "expected:\n"); \
58 NDR_PRINT_DEBUG(security_descriptor, _sd2); \
64 * Helper function to verify a security descriptor, by querying
65 * and comparing against the passed in sd.
66 * Copied to smb2_util_verify_sd() for SMB2.
68 static bool verify_sd(TALLOC_CTX
*tctx
, struct smbcli_state
*cli
,
69 int fnum
, struct security_descriptor
*sd
)
73 union smb_fileinfo q
= {};
76 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
77 q
.query_secdesc
.in
.file
.fnum
= fnum
;
78 q
.query_secdesc
.in
.secinfo_flags
=
82 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
83 CHECK_STATUS(status
, NT_STATUS_OK
);
85 /* More work is needed if we're going to check this bit. */
86 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
88 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
96 * Helper function to verify attributes, by querying
97 * and comparing against the passed attrib.
98 * Copied to smb2_util_verify_attrib() for SMB2.
100 static bool verify_attrib(TALLOC_CTX
*tctx
, struct smbcli_state
*cli
,
101 int fnum
, uint32_t attrib
)
105 union smb_fileinfo q2
= {};
108 q2
.standard
.level
= RAW_FILEINFO_STANDARD
;
109 q2
.standard
.in
.file
.fnum
= fnum
;
110 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q2
);
111 CHECK_STATUS(status
, NT_STATUS_OK
);
113 q2
.standard
.out
.attrib
&= ~FILE_ATTRIBUTE_ARCHIVE
;
115 if (q2
.standard
.out
.attrib
!= attrib
) {
116 torture_warning(tctx
, "%s: attributes don't match! "
117 "got %x, expected %x\n", __location__
,
118 (uint32_t)q2
.standard
.out
.attrib
,
129 * Test setting and removing a DACL.
130 * Test copied to torture_smb2_setinfo() for SMB2.
132 static bool test_sd(struct torture_context
*tctx
, struct smbcli_state
*cli
)
136 const char *fname
= BASEDIR
"\\sd.txt";
139 union smb_fileinfo q
;
140 union smb_setfileinfo set
;
141 struct security_ace ace
;
142 struct security_descriptor
*sd
;
143 struct dom_sid
*test_sid
;
145 if (!torture_setup_dir(cli
, BASEDIR
))
148 torture_comment(tctx
, "TESTING SETFILEINFO EA_SET\n");
150 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
151 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
152 io
.ntcreatex
.in
.flags
= 0;
153 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
154 io
.ntcreatex
.in
.create_options
= 0;
155 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
156 io
.ntcreatex
.in
.share_access
=
157 NTCREATEX_SHARE_ACCESS_READ
|
158 NTCREATEX_SHARE_ACCESS_WRITE
;
159 io
.ntcreatex
.in
.alloc_size
= 0;
160 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
161 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
162 io
.ntcreatex
.in
.security_flags
= 0;
163 io
.ntcreatex
.in
.fname
= fname
;
164 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
165 CHECK_STATUS(status
, NT_STATUS_OK
);
166 fnum
= io
.ntcreatex
.out
.file
.fnum
;
168 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
169 q
.query_secdesc
.in
.file
.fnum
= fnum
;
170 q
.query_secdesc
.in
.secinfo_flags
=
174 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
175 CHECK_STATUS(status
, NT_STATUS_OK
);
176 sd
= q
.query_secdesc
.out
.sd
;
178 torture_comment(tctx
, "add a new ACE to the DACL\n");
180 test_sid
= dom_sid_parse_talloc(tctx
, SID_NT_AUTHENTICATED_USERS
);
182 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
184 ace
.access_mask
= SEC_STD_ALL
;
185 ace
.trustee
= *test_sid
;
187 status
= security_descriptor_dacl_add(sd
, &ace
);
188 CHECK_STATUS(status
, NT_STATUS_OK
);
190 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
191 set
.set_secdesc
.in
.file
.fnum
= fnum
;
192 set
.set_secdesc
.in
.secinfo_flags
= q
.query_secdesc
.in
.secinfo_flags
;
193 set
.set_secdesc
.in
.sd
= sd
;
195 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
196 CHECK_STATUS(status
, NT_STATUS_OK
);
197 FAIL_UNLESS(verify_sd(tctx
, cli
, fnum
, sd
));
199 torture_comment(tctx
, "remove it again\n");
201 status
= security_descriptor_dacl_del(sd
, test_sid
);
202 CHECK_STATUS(status
, NT_STATUS_OK
);
204 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
205 CHECK_STATUS(status
, NT_STATUS_OK
);
206 FAIL_UNLESS(verify_sd(tctx
, cli
, fnum
, sd
));
209 smbcli_close(cli
->tree
, fnum
);
210 smb_raw_exit(cli
->session
);
211 smbcli_deltree(cli
->tree
, BASEDIR
);
218 test using nttrans create to create a file with an initial acl set
219 Test copied to test_create_acl() for SMB2.
221 static bool test_nttrans_create_ext(struct torture_context
*tctx
,
222 struct smbcli_state
*cli
, bool test_dir
)
226 const char *fname
= BASEDIR
"\\acl2.txt";
229 union smb_fileinfo q
= {};
230 struct security_ace ace
;
231 struct security_descriptor
*sd
;
232 struct dom_sid
*test_sid
;
234 FILE_ATTRIBUTE_HIDDEN
|
235 FILE_ATTRIBUTE_SYSTEM
|
236 (test_dir
? FILE_ATTRIBUTE_DIRECTORY
: 0);
237 NTSTATUS (*delete_func
)(struct smbcli_tree
*, const char *) =
238 test_dir
? smbcli_rmdir
: smbcli_unlink
;
240 if (!torture_setup_dir(cli
, BASEDIR
))
243 io
.generic
.level
= RAW_OPEN_NTTRANS_CREATE
;
244 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
245 io
.ntcreatex
.in
.flags
= 0;
246 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
247 io
.ntcreatex
.in
.create_options
=
248 test_dir
? NTCREATEX_OPTIONS_DIRECTORY
: 0;
249 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
250 io
.ntcreatex
.in
.share_access
=
251 NTCREATEX_SHARE_ACCESS_READ
|
252 NTCREATEX_SHARE_ACCESS_WRITE
;
253 io
.ntcreatex
.in
.alloc_size
= 0;
254 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
255 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
256 io
.ntcreatex
.in
.security_flags
= 0;
257 io
.ntcreatex
.in
.fname
= fname
;
258 io
.ntcreatex
.in
.sec_desc
= NULL
;
259 io
.ntcreatex
.in
.ea_list
= NULL
;
261 torture_comment(tctx
, "basic create\n");
263 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
264 CHECK_STATUS(status
, NT_STATUS_OK
);
265 fnum
= io
.ntcreatex
.out
.file
.fnum
;
267 torture_comment(tctx
, "querying ACL\n");
269 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
270 q
.query_secdesc
.in
.file
.fnum
= fnum
;
271 q
.query_secdesc
.in
.secinfo_flags
=
275 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
276 CHECK_STATUS(status
, NT_STATUS_OK
);
277 sd
= q
.query_secdesc
.out
.sd
;
279 status
= smbcli_close(cli
->tree
, fnum
);
280 CHECK_STATUS(status
, NT_STATUS_OK
);
282 status
= delete_func(cli
->tree
, fname
);
283 CHECK_STATUS(status
, NT_STATUS_OK
);
285 torture_comment(tctx
, "adding a new ACE\n");
286 test_sid
= dom_sid_parse_talloc(tctx
, SID_NT_AUTHENTICATED_USERS
);
288 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
290 ace
.access_mask
= SEC_STD_ALL
;
291 ace
.trustee
= *test_sid
;
293 status
= security_descriptor_dacl_add(sd
, &ace
);
294 CHECK_STATUS(status
, NT_STATUS_OK
);
296 torture_comment(tctx
, "creating with an initial ACL\n");
298 io
.ntcreatex
.in
.sec_desc
= sd
;
299 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
300 CHECK_STATUS(status
, NT_STATUS_OK
);
301 fnum
= io
.ntcreatex
.out
.file
.fnum
;
303 FAIL_UNLESS(verify_sd(tctx
, cli
, fnum
, sd
));
305 status
= smbcli_close(cli
->tree
, fnum
);
306 CHECK_STATUS(status
, NT_STATUS_OK
);
307 status
= delete_func(cli
->tree
, fname
);
308 CHECK_STATUS(status
, NT_STATUS_OK
);
310 torture_comment(tctx
, "creating with attributes\n");
312 io
.ntcreatex
.in
.sec_desc
= NULL
;
313 io
.ntcreatex
.in
.file_attr
= attrib
;
314 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
315 CHECK_STATUS(status
, NT_STATUS_OK
);
316 fnum
= io
.ntcreatex
.out
.file
.fnum
;
318 FAIL_UNLESS(verify_attrib(tctx
, cli
, fnum
, attrib
));
320 status
= smbcli_close(cli
->tree
, fnum
);
321 CHECK_STATUS(status
, NT_STATUS_OK
);
323 status
= delete_func(cli
->tree
, fname
);
324 CHECK_STATUS(status
, NT_STATUS_OK
);
326 torture_comment(tctx
, "creating with attributes and ACL\n");
328 io
.ntcreatex
.in
.sec_desc
= sd
;
329 io
.ntcreatex
.in
.file_attr
= attrib
;
330 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
331 CHECK_STATUS(status
, NT_STATUS_OK
);
332 fnum
= io
.ntcreatex
.out
.file
.fnum
;
334 FAIL_UNLESS(verify_sd(tctx
, cli
, fnum
, sd
));
335 FAIL_UNLESS(verify_attrib(tctx
, cli
, fnum
, attrib
));
337 status
= smbcli_close(cli
->tree
, fnum
);
338 CHECK_STATUS(status
, NT_STATUS_OK
);
339 status
= delete_func(cli
->tree
, fname
);
340 CHECK_STATUS(status
, NT_STATUS_OK
);
342 torture_comment(tctx
, "creating with attributes, ACL and owner\n");
344 sd
= security_descriptor_dacl_create(tctx
,
345 0, SID_WORLD
, SID_BUILTIN_USERS
,
347 SEC_ACE_TYPE_ACCESS_ALLOWED
,
348 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
352 io
.ntcreatex
.in
.sec_desc
= sd
;
353 io
.ntcreatex
.in
.file_attr
= attrib
;
354 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
355 CHECK_STATUS(status
, NT_STATUS_OK
);
356 fnum
= io
.ntcreatex
.out
.file
.fnum
;
358 FAIL_UNLESS(verify_sd(tctx
, cli
, fnum
, sd
));
359 FAIL_UNLESS(verify_attrib(tctx
, cli
, fnum
, attrib
));
361 status
= smbcli_close(cli
->tree
, fnum
);
362 CHECK_STATUS(status
, NT_STATUS_OK
);
363 status
= delete_func(cli
->tree
, fname
);
364 CHECK_STATUS(status
, NT_STATUS_OK
);
367 smbcli_close(cli
->tree
, fnum
);
368 smb_raw_exit(cli
->session
);
369 smbcli_deltree(cli
->tree
, BASEDIR
);
373 static bool test_nttrans_create_file(struct torture_context
*tctx
,
374 struct smbcli_state
*cli
)
376 torture_comment(tctx
, "Testing nttrans create with sec_desc on files\n");
378 return test_nttrans_create_ext(tctx
, cli
, false);
381 static bool test_nttrans_create_dir(struct torture_context
*tctx
,
382 struct smbcli_state
*cli
)
384 torture_comment(tctx
, "Testing nttrans create with sec_desc on directories\n");
386 return test_nttrans_create_ext(tctx
, cli
, true);
389 #define CHECK_ACCESS_FLAGS(_fnum, flags) do { \
390 union smb_fileinfo _q; \
391 _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
392 _q.access_information.in.file.fnum = (_fnum); \
393 status = smb_raw_fileinfo(cli->tree, tctx, &_q); \
394 CHECK_STATUS(status, NT_STATUS_OK); \
395 if (_q.access_information.out.access_flags != (flags)) { \
397 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
398 __location__, _q.access_information.out.access_flags, (flags)); \
404 test using NTTRANS CREATE to create a file with a null ACL set
405 Test copied to test_create_null_dacl() for SMB2.
407 static bool test_nttrans_create_null_dacl(struct torture_context
*tctx
,
408 struct smbcli_state
*cli
)
412 const char *fname
= BASEDIR
"\\nulldacl.txt";
415 union smb_fileinfo q
;
416 union smb_setfileinfo s
;
417 struct security_descriptor
*sd
= security_descriptor_initialise(tctx
);
418 struct security_acl dacl
;
420 if (!torture_setup_dir(cli
, BASEDIR
))
423 torture_comment(tctx
, "TESTING SEC_DESC WITH A NULL DACL\n");
425 io
.generic
.level
= RAW_OPEN_NTTRANS_CREATE
;
426 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
427 io
.ntcreatex
.in
.flags
= 0;
428 io
.ntcreatex
.in
.access_mask
= SEC_STD_READ_CONTROL
| SEC_STD_WRITE_DAC
429 | SEC_STD_WRITE_OWNER
;
430 io
.ntcreatex
.in
.create_options
= 0;
431 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
432 io
.ntcreatex
.in
.share_access
=
433 NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
434 io
.ntcreatex
.in
.alloc_size
= 0;
435 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
436 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
437 io
.ntcreatex
.in
.security_flags
= 0;
438 io
.ntcreatex
.in
.fname
= fname
;
439 io
.ntcreatex
.in
.sec_desc
= sd
;
440 io
.ntcreatex
.in
.ea_list
= NULL
;
442 torture_comment(tctx
, "creating a file with a empty sd\n");
443 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
444 CHECK_STATUS(status
, NT_STATUS_OK
);
445 fnum
= io
.ntcreatex
.out
.file
.fnum
;
447 torture_comment(tctx
, "get the original sd\n");
448 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
449 q
.query_secdesc
.in
.file
.fnum
= fnum
;
450 q
.query_secdesc
.in
.secinfo_flags
=
454 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
455 CHECK_STATUS(status
, NT_STATUS_OK
);
458 * Testing the created DACL,
459 * the server should add the inherited DACL
460 * when SEC_DESC_DACL_PRESENT isn't specified
462 if (!(q
.query_secdesc
.out
.sd
->type
& SEC_DESC_DACL_PRESENT
)) {
464 torture_result(tctx
, TORTURE_FAIL
, "DACL_PRESENT flag not set by the server!\n");
467 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
) {
469 torture_result(tctx
, TORTURE_FAIL
, "no DACL has been created on the server!\n");
473 torture_comment(tctx
, "set NULL DACL\n");
474 sd
->type
|= SEC_DESC_DACL_PRESENT
;
476 s
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
477 s
.set_secdesc
.in
.file
.fnum
= fnum
;
478 s
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
479 s
.set_secdesc
.in
.sd
= sd
;
480 status
= smb_raw_setfileinfo(cli
->tree
, &s
);
481 CHECK_STATUS(status
, NT_STATUS_OK
);
483 torture_comment(tctx
, "get the sd\n");
484 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
485 q
.query_secdesc
.in
.file
.fnum
= fnum
;
486 q
.query_secdesc
.in
.secinfo_flags
=
490 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
491 CHECK_STATUS(status
, NT_STATUS_OK
);
493 /* Testing the modified DACL */
494 if (!(q
.query_secdesc
.out
.sd
->type
& SEC_DESC_DACL_PRESENT
)) {
496 torture_result(tctx
, TORTURE_FAIL
, "DACL_PRESENT flag not set by the server!\n");
499 if (q
.query_secdesc
.out
.sd
->dacl
!= NULL
) {
501 torture_result(tctx
, TORTURE_FAIL
, "DACL has been created on the server!\n");
505 torture_comment(tctx
, "try open for read control\n");
506 io
.ntcreatex
.in
.access_mask
= SEC_STD_READ_CONTROL
;
507 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
508 CHECK_STATUS(status
, NT_STATUS_OK
);
509 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
510 SEC_STD_READ_CONTROL
| SEC_FILE_READ_ATTRIBUTE
);
511 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
513 torture_comment(tctx
, "try open for write\n");
514 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
515 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
516 CHECK_STATUS(status
, NT_STATUS_OK
);
517 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
518 SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
);
519 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
521 torture_comment(tctx
, "try open for read\n");
522 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
523 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
524 CHECK_STATUS(status
, NT_STATUS_OK
);
525 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
526 SEC_FILE_READ_DATA
| SEC_FILE_READ_ATTRIBUTE
);
527 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
529 torture_comment(tctx
, "try open for generic write\n");
530 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_WRITE
;
531 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
532 CHECK_STATUS(status
, NT_STATUS_OK
);
533 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
534 SEC_RIGHTS_FILE_WRITE
| SEC_FILE_READ_ATTRIBUTE
);
535 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
537 torture_comment(tctx
, "try open for generic read\n");
538 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_READ
;
539 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
540 CHECK_STATUS(status
, NT_STATUS_OK
);
541 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
542 SEC_RIGHTS_FILE_READ
| SEC_FILE_READ_ATTRIBUTE
);
543 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
545 torture_comment(tctx
, "set DACL with 0 aces\n");
547 dacl
.revision
= SECURITY_ACL_REVISION_NT4
;
551 s
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
552 s
.set_secdesc
.in
.file
.fnum
= fnum
;
553 s
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
554 s
.set_secdesc
.in
.sd
= sd
;
555 status
= smb_raw_setfileinfo(cli
->tree
, &s
);
556 CHECK_STATUS(status
, NT_STATUS_OK
);
558 torture_comment(tctx
, "get the sd\n");
559 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
560 q
.query_secdesc
.in
.file
.fnum
= fnum
;
561 q
.query_secdesc
.in
.secinfo_flags
=
565 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
566 CHECK_STATUS(status
, NT_STATUS_OK
);
568 /* Testing the modified DACL */
569 if (!(q
.query_secdesc
.out
.sd
->type
& SEC_DESC_DACL_PRESENT
)) {
571 torture_result(tctx
, TORTURE_FAIL
, "DACL_PRESENT flag not set by the server!\n");
574 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
) {
576 torture_result(tctx
, TORTURE_FAIL
, "no DACL has been created on the server!\n");
579 if (q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 0) {
581 torture_result(tctx
, TORTURE_FAIL
, "DACL has %u aces!\n",
582 q
.query_secdesc
.out
.sd
->dacl
->num_aces
);
586 torture_comment(tctx
, "try open for read control\n");
587 io
.ntcreatex
.in
.access_mask
= SEC_STD_READ_CONTROL
;
588 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
589 CHECK_STATUS(status
, NT_STATUS_OK
);
590 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
591 SEC_STD_READ_CONTROL
| SEC_FILE_READ_ATTRIBUTE
);
592 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
594 torture_comment(tctx
, "try open for write => access_denied\n");
595 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
596 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
597 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
599 torture_comment(tctx
, "try open for read => access_denied\n");
600 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
601 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
602 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
604 torture_comment(tctx
, "try open for generic write => access_denied\n");
605 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_WRITE
;
606 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
607 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
609 torture_comment(tctx
, "try open for generic read => access_denied\n");
610 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_READ
;
611 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
612 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
614 torture_comment(tctx
, "set empty sd\n");
615 sd
->type
&= ~SEC_DESC_DACL_PRESENT
;
618 s
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
619 s
.set_secdesc
.in
.file
.fnum
= fnum
;
620 s
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
621 s
.set_secdesc
.in
.sd
= sd
;
622 status
= smb_raw_setfileinfo(cli
->tree
, &s
);
623 CHECK_STATUS(status
, NT_STATUS_OK
);
625 torture_comment(tctx
, "get the sd\n");
626 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
627 q
.query_secdesc
.in
.file
.fnum
= fnum
;
628 q
.query_secdesc
.in
.secinfo_flags
=
632 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
633 CHECK_STATUS(status
, NT_STATUS_OK
);
635 /* Testing the modified DACL */
636 if (!(q
.query_secdesc
.out
.sd
->type
& SEC_DESC_DACL_PRESENT
)) {
638 torture_result(tctx
, TORTURE_FAIL
, "DACL_PRESENT flag not set by the server!\n");
641 if (q
.query_secdesc
.out
.sd
->dacl
!= NULL
) {
643 torture_result(tctx
, TORTURE_FAIL
, "DACL has been created on the server!\n");
647 smbcli_close(cli
->tree
, fnum
);
648 smb_raw_exit(cli
->session
);
649 smbcli_deltree(cli
->tree
, BASEDIR
);
654 test the behaviour of the well known SID_CREATOR_OWNER sid, and some generic
656 Test copied to smb2/acls.c for SMB2.
658 static bool test_creator_sid(struct torture_context
*tctx
,
659 struct smbcli_state
*cli
)
663 const char *fname
= BASEDIR
"\\creator.txt";
666 union smb_fileinfo q
;
667 union smb_setfileinfo set
;
668 struct security_descriptor
*sd
, *sd_orig
, *sd2
;
669 const char *owner_sid
;
671 if (!torture_setup_dir(cli
, BASEDIR
))
674 torture_comment(tctx
, "TESTING SID_CREATOR_OWNER\n");
676 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
677 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
678 io
.ntcreatex
.in
.flags
= 0;
679 io
.ntcreatex
.in
.access_mask
= SEC_STD_READ_CONTROL
| SEC_STD_WRITE_DAC
| SEC_STD_WRITE_OWNER
;
680 io
.ntcreatex
.in
.create_options
= 0;
681 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
682 io
.ntcreatex
.in
.share_access
=
683 NTCREATEX_SHARE_ACCESS_READ
|
684 NTCREATEX_SHARE_ACCESS_WRITE
;
685 io
.ntcreatex
.in
.alloc_size
= 0;
686 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
687 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
688 io
.ntcreatex
.in
.security_flags
= 0;
689 io
.ntcreatex
.in
.fname
= fname
;
690 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
691 CHECK_STATUS(status
, NT_STATUS_OK
);
692 fnum
= io
.ntcreatex
.out
.file
.fnum
;
694 torture_comment(tctx
, "get the original sd\n");
695 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
696 q
.query_secdesc
.in
.file
.fnum
= fnum
;
697 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
698 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
699 CHECK_STATUS(status
, NT_STATUS_OK
);
700 sd_orig
= q
.query_secdesc
.out
.sd
;
702 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
704 torture_comment(tctx
, "set a sec desc allowing no write by CREATOR_OWNER\n");
705 sd
= security_descriptor_dacl_create(tctx
,
708 SEC_ACE_TYPE_ACCESS_ALLOWED
,
709 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
713 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
714 set
.set_secdesc
.in
.file
.fnum
= fnum
;
715 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
716 set
.set_secdesc
.in
.sd
= sd
;
718 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
719 CHECK_STATUS(status
, NT_STATUS_OK
);
721 torture_comment(tctx
, "try open for write\n");
722 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
723 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
724 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
726 torture_comment(tctx
, "try open for read\n");
727 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
728 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
729 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
731 torture_comment(tctx
, "try open for generic write\n");
732 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_WRITE
;
733 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
734 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
736 torture_comment(tctx
, "try open for generic read\n");
737 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_READ
;
738 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
739 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
741 torture_comment(tctx
, "set a sec desc allowing no write by owner\n");
742 sd
= security_descriptor_dacl_create(tctx
,
745 SEC_ACE_TYPE_ACCESS_ALLOWED
,
746 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
750 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
751 set
.set_secdesc
.in
.file
.fnum
= fnum
;
752 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
753 set
.set_secdesc
.in
.sd
= sd
;
754 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
755 CHECK_STATUS(status
, NT_STATUS_OK
);
757 torture_comment(tctx
, "check that sd has been mapped correctly\n");
758 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
759 CHECK_STATUS(status
, NT_STATUS_OK
);
760 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
762 torture_comment(tctx
, "try open for write\n");
763 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
764 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
765 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
767 torture_comment(tctx
, "try open for read\n");
768 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
769 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
770 CHECK_STATUS(status
, NT_STATUS_OK
);
771 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
773 SEC_FILE_READ_ATTRIBUTE
);
774 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
776 torture_comment(tctx
, "try open for generic write\n");
777 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_WRITE
;
778 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
779 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
781 torture_comment(tctx
, "try open for generic read\n");
782 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_READ
;
783 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
784 CHECK_STATUS(status
, NT_STATUS_OK
);
785 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
786 SEC_RIGHTS_FILE_READ
);
787 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
789 torture_comment(tctx
, "set a sec desc allowing generic read by owner\n");
790 sd
= security_descriptor_dacl_create(tctx
,
793 SEC_ACE_TYPE_ACCESS_ALLOWED
,
794 SEC_GENERIC_READ
| SEC_STD_ALL
,
798 set
.set_secdesc
.in
.sd
= sd
;
799 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
800 CHECK_STATUS(status
, NT_STATUS_OK
);
802 torture_comment(tctx
, "check that generic read has been mapped correctly\n");
803 sd2
= security_descriptor_dacl_create(tctx
,
806 SEC_ACE_TYPE_ACCESS_ALLOWED
,
807 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
811 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
812 CHECK_STATUS(status
, NT_STATUS_OK
);
813 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
815 torture_comment(tctx
, "try open for write\n");
816 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
817 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
818 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
820 torture_comment(tctx
, "try open for read\n");
821 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
822 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
823 CHECK_STATUS(status
, NT_STATUS_OK
);
824 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
826 SEC_FILE_READ_ATTRIBUTE
);
827 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
829 torture_comment(tctx
, "try open for generic write\n");
830 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_WRITE
;
831 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
832 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
834 torture_comment(tctx
, "try open for generic read\n");
835 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_READ
;
836 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
837 CHECK_STATUS(status
, NT_STATUS_OK
);
838 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
, SEC_RIGHTS_FILE_READ
);
839 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
842 torture_comment(tctx
, "put back original sd\n");
843 set
.set_secdesc
.in
.sd
= sd_orig
;
844 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
845 CHECK_STATUS(status
, NT_STATUS_OK
);
849 smbcli_close(cli
->tree
, fnum
);
850 smb_raw_exit(cli
->session
);
851 smbcli_deltree(cli
->tree
, BASEDIR
);
857 test the mapping of the SEC_GENERIC_xx bits to SEC_STD_xx and
859 Test copied to smb2/acls.c for SMB2.
861 static bool test_generic_bits(struct torture_context
*tctx
,
862 struct smbcli_state
*cli
)
866 const char *fname
= BASEDIR
"\\generic.txt";
869 union smb_fileinfo q
;
870 union smb_setfileinfo set
;
871 struct security_descriptor
*sd
, *sd_orig
, *sd2
;
872 const char *owner_sid
;
875 uint32_t specific_bits
;
876 } file_mappings
[] = {
878 { SEC_GENERIC_READ
, SEC_RIGHTS_FILE_READ
},
879 { SEC_GENERIC_WRITE
, SEC_RIGHTS_FILE_WRITE
},
880 { SEC_GENERIC_EXECUTE
, SEC_RIGHTS_FILE_EXECUTE
},
881 { SEC_GENERIC_ALL
, SEC_RIGHTS_FILE_ALL
},
882 { SEC_FILE_READ_DATA
, SEC_FILE_READ_DATA
},
883 { SEC_FILE_READ_ATTRIBUTE
, SEC_FILE_READ_ATTRIBUTE
}
887 uint32_t specific_bits
;
890 { SEC_GENERIC_READ
, SEC_RIGHTS_DIR_READ
},
891 { SEC_GENERIC_WRITE
, SEC_RIGHTS_DIR_WRITE
},
892 { SEC_GENERIC_EXECUTE
, SEC_RIGHTS_DIR_EXECUTE
},
893 { SEC_GENERIC_ALL
, SEC_RIGHTS_DIR_ALL
}
895 bool has_restore_privilege
;
896 bool has_take_ownership_privilege
;
898 if (!torture_setup_dir(cli
, BASEDIR
))
901 torture_comment(tctx
, "TESTING FILE GENERIC BITS\n");
903 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
904 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
905 io
.ntcreatex
.in
.flags
= 0;
906 io
.ntcreatex
.in
.access_mask
=
907 SEC_STD_READ_CONTROL
|
910 io
.ntcreatex
.in
.create_options
= 0;
911 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
912 io
.ntcreatex
.in
.share_access
=
913 NTCREATEX_SHARE_ACCESS_READ
|
914 NTCREATEX_SHARE_ACCESS_WRITE
;
915 io
.ntcreatex
.in
.alloc_size
= 0;
916 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
917 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
918 io
.ntcreatex
.in
.security_flags
= 0;
919 io
.ntcreatex
.in
.fname
= fname
;
920 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
921 CHECK_STATUS(status
, NT_STATUS_OK
);
922 fnum
= io
.ntcreatex
.out
.file
.fnum
;
924 torture_comment(tctx
, "get the original sd\n");
925 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
926 q
.query_secdesc
.in
.file
.fnum
= fnum
;
927 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
928 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
929 CHECK_STATUS(status
, NT_STATUS_OK
);
930 sd_orig
= q
.query_secdesc
.out
.sd
;
932 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
934 status
= torture_check_privilege(cli
,
936 sec_privilege_name(SEC_PRIV_RESTORE
));
937 has_restore_privilege
= NT_STATUS_IS_OK(status
);
938 if (!NT_STATUS_IS_OK(status
)) {
939 torture_warning(tctx
, "torture_check_privilege - %s\n",
942 torture_comment(tctx
, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege
?"Yes":"No");
944 status
= torture_check_privilege(cli
,
946 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP
));
947 has_take_ownership_privilege
= NT_STATUS_IS_OK(status
);
948 if (!NT_STATUS_IS_OK(status
)) {
949 torture_warning(tctx
, "torture_check_privilege - %s\n",
952 torture_comment(tctx
, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege
?"Yes":"No");
954 for (i
=0;i
<ARRAY_SIZE(file_mappings
);i
++) {
955 uint32_t expected_mask
=
957 SEC_STD_READ_CONTROL
|
958 SEC_FILE_READ_ATTRIBUTE
|
960 uint32_t expected_mask_anon
= SEC_FILE_READ_ATTRIBUTE
;
962 if (has_restore_privilege
) {
963 expected_mask_anon
|= SEC_STD_DELETE
;
966 torture_comment(tctx
, "Testing generic bits 0x%08x\n",
967 file_mappings
[i
].gen_bits
);
968 sd
= security_descriptor_dacl_create(tctx
,
971 SEC_ACE_TYPE_ACCESS_ALLOWED
,
972 file_mappings
[i
].gen_bits
,
976 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
977 set
.set_secdesc
.in
.file
.fnum
= fnum
;
978 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
979 set
.set_secdesc
.in
.sd
= sd
;
981 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
982 CHECK_STATUS(status
, NT_STATUS_OK
);
984 sd2
= security_descriptor_dacl_create(tctx
,
987 SEC_ACE_TYPE_ACCESS_ALLOWED
,
988 file_mappings
[i
].specific_bits
,
992 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
993 CHECK_STATUS(status
, NT_STATUS_OK
);
994 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
996 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
997 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
998 CHECK_STATUS(status
, NT_STATUS_OK
);
999 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
1000 expected_mask
| file_mappings
[i
].specific_bits
);
1001 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1003 if (!has_take_ownership_privilege
) {
1007 torture_comment(tctx
, "Testing generic bits 0x%08x (anonymous)\n",
1008 file_mappings
[i
].gen_bits
);
1009 sd
= security_descriptor_dacl_create(tctx
,
1010 0, SID_NT_ANONYMOUS
, NULL
,
1012 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1013 file_mappings
[i
].gen_bits
,
1017 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1018 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1019 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1020 set
.set_secdesc
.in
.sd
= sd
;
1022 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1023 CHECK_STATUS(status
, NT_STATUS_OK
);
1025 sd2
= security_descriptor_dacl_create(tctx
,
1026 0, SID_NT_ANONYMOUS
, NULL
,
1028 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1029 file_mappings
[i
].specific_bits
,
1033 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1034 CHECK_STATUS(status
, NT_STATUS_OK
);
1035 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1037 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1038 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1039 CHECK_STATUS(status
, NT_STATUS_OK
);
1040 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
1041 expected_mask_anon
| file_mappings
[i
].specific_bits
);
1042 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1045 torture_comment(tctx
, "put back original sd\n");
1046 set
.set_secdesc
.in
.sd
= sd_orig
;
1047 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1048 CHECK_STATUS(status
, NT_STATUS_OK
);
1050 smbcli_close(cli
->tree
, fnum
);
1051 smbcli_unlink(cli
->tree
, fname
);
1054 torture_comment(tctx
, "TESTING DIR GENERIC BITS\n");
1056 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1057 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1058 io
.ntcreatex
.in
.flags
= 0;
1059 io
.ntcreatex
.in
.access_mask
=
1060 SEC_STD_READ_CONTROL
|
1062 SEC_STD_WRITE_OWNER
;
1063 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1064 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1065 io
.ntcreatex
.in
.share_access
=
1066 NTCREATEX_SHARE_ACCESS_READ
|
1067 NTCREATEX_SHARE_ACCESS_WRITE
;
1068 io
.ntcreatex
.in
.alloc_size
= 0;
1069 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1070 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1071 io
.ntcreatex
.in
.security_flags
= 0;
1072 io
.ntcreatex
.in
.fname
= fname
;
1073 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1074 CHECK_STATUS(status
, NT_STATUS_OK
);
1075 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1077 torture_comment(tctx
, "get the original sd\n");
1078 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1079 q
.query_secdesc
.in
.file
.fnum
= fnum
;
1080 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1081 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1082 CHECK_STATUS(status
, NT_STATUS_OK
);
1083 sd_orig
= q
.query_secdesc
.out
.sd
;
1085 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1087 status
= torture_check_privilege(cli
,
1089 sec_privilege_name(SEC_PRIV_RESTORE
));
1090 has_restore_privilege
= NT_STATUS_IS_OK(status
);
1091 if (!NT_STATUS_IS_OK(status
)) {
1092 torture_warning(tctx
, "torture_check_privilege - %s\n",
1095 torture_comment(tctx
, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege
?"Yes":"No");
1097 status
= torture_check_privilege(cli
,
1099 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP
));
1100 has_take_ownership_privilege
= NT_STATUS_IS_OK(status
);
1101 if (!NT_STATUS_IS_OK(status
)) {
1102 torture_warning(tctx
, "torture_check_privilege - %s\n",
1105 torture_comment(tctx
, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege
?"Yes":"No");
1107 for (i
=0;i
<ARRAY_SIZE(dir_mappings
);i
++) {
1108 uint32_t expected_mask
=
1110 SEC_STD_READ_CONTROL
|
1111 SEC_FILE_READ_ATTRIBUTE
|
1113 uint32_t expected_mask_anon
= SEC_FILE_READ_ATTRIBUTE
;
1115 if (has_restore_privilege
) {
1116 expected_mask_anon
|= SEC_STD_DELETE
;
1119 torture_comment(tctx
, "Testing generic bits 0x%08x\n",
1120 file_mappings
[i
].gen_bits
);
1121 sd
= security_descriptor_dacl_create(tctx
,
1124 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1125 dir_mappings
[i
].gen_bits
,
1129 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1130 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1131 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1132 set
.set_secdesc
.in
.sd
= sd
;
1134 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1135 CHECK_STATUS(status
, NT_STATUS_OK
);
1137 sd2
= security_descriptor_dacl_create(tctx
,
1140 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1141 dir_mappings
[i
].specific_bits
,
1145 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1146 CHECK_STATUS(status
, NT_STATUS_OK
);
1147 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1149 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1150 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1151 CHECK_STATUS(status
, NT_STATUS_OK
);
1152 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
1153 expected_mask
| dir_mappings
[i
].specific_bits
);
1154 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1156 if (!has_take_ownership_privilege
) {
1160 torture_comment(tctx
, "Testing generic bits 0x%08x (anonymous)\n",
1161 file_mappings
[i
].gen_bits
);
1162 sd
= security_descriptor_dacl_create(tctx
,
1163 0, SID_NT_ANONYMOUS
, NULL
,
1165 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1166 file_mappings
[i
].gen_bits
,
1170 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1171 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1172 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1173 set
.set_secdesc
.in
.sd
= sd
;
1175 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1176 CHECK_STATUS(status
, NT_STATUS_OK
);
1178 sd2
= security_descriptor_dacl_create(tctx
,
1179 0, SID_NT_ANONYMOUS
, NULL
,
1181 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1182 file_mappings
[i
].specific_bits
,
1186 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1187 CHECK_STATUS(status
, NT_STATUS_OK
);
1188 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1190 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1191 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1192 CHECK_STATUS(status
, NT_STATUS_OK
);
1193 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
,
1194 expected_mask_anon
| dir_mappings
[i
].specific_bits
);
1195 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1198 torture_comment(tctx
, "put back original sd\n");
1199 set
.set_secdesc
.in
.sd
= sd_orig
;
1200 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1201 CHECK_STATUS(status
, NT_STATUS_OK
);
1203 smbcli_close(cli
->tree
, fnum
);
1204 smbcli_unlink(cli
->tree
, fname
);
1207 smbcli_close(cli
->tree
, fnum
);
1208 smb_raw_exit(cli
->session
);
1209 smbcli_deltree(cli
->tree
, BASEDIR
);
1215 see what access bits the owner of a file always gets
1216 Test copied to smb2/acls.c for SMB2.
1218 static bool test_owner_bits(struct torture_context
*tctx
,
1219 struct smbcli_state
*cli
)
1223 const char *fname
= BASEDIR
"\\test_owner_bits.txt";
1226 union smb_fileinfo q
;
1227 union smb_setfileinfo set
;
1228 struct security_descriptor
*sd
, *sd_orig
;
1229 const char *owner_sid
;
1230 bool has_restore_privilege
;
1231 bool has_take_ownership_privilege
;
1232 uint32_t expected_bits
;
1234 if (!torture_setup_dir(cli
, BASEDIR
))
1237 torture_comment(tctx
, "TESTING FILE OWNER BITS\n");
1239 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1240 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1241 io
.ntcreatex
.in
.flags
= 0;
1242 io
.ntcreatex
.in
.access_mask
=
1243 SEC_STD_READ_CONTROL
|
1245 SEC_STD_WRITE_OWNER
;
1246 io
.ntcreatex
.in
.create_options
= 0;
1247 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1248 io
.ntcreatex
.in
.share_access
=
1249 NTCREATEX_SHARE_ACCESS_READ
|
1250 NTCREATEX_SHARE_ACCESS_WRITE
;
1251 io
.ntcreatex
.in
.alloc_size
= 0;
1252 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1253 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1254 io
.ntcreatex
.in
.security_flags
= 0;
1255 io
.ntcreatex
.in
.fname
= fname
;
1256 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1257 CHECK_STATUS(status
, NT_STATUS_OK
);
1258 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1260 torture_comment(tctx
, "get the original sd\n");
1261 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1262 q
.query_secdesc
.in
.file
.fnum
= fnum
;
1263 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1264 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1265 CHECK_STATUS(status
, NT_STATUS_OK
);
1266 sd_orig
= q
.query_secdesc
.out
.sd
;
1268 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1270 status
= torture_check_privilege(cli
,
1272 sec_privilege_name(SEC_PRIV_RESTORE
));
1273 has_restore_privilege
= NT_STATUS_IS_OK(status
);
1274 if (!NT_STATUS_IS_OK(status
)) {
1275 torture_warning(tctx
, "torture_check_privilege - %s\n", nt_errstr(status
));
1277 torture_comment(tctx
, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege
?"Yes":"No");
1279 status
= torture_check_privilege(cli
,
1281 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP
));
1282 has_take_ownership_privilege
= NT_STATUS_IS_OK(status
);
1283 if (!NT_STATUS_IS_OK(status
)) {
1284 torture_warning(tctx
, "torture_check_privilege - %s\n", nt_errstr(status
));
1286 torture_comment(tctx
, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege
?"Yes":"No");
1288 sd
= security_descriptor_dacl_create(tctx
,
1291 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1292 SEC_FILE_WRITE_DATA
,
1296 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1297 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1298 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1299 set
.set_secdesc
.in
.sd
= sd
;
1301 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1302 CHECK_STATUS(status
, NT_STATUS_OK
);
1304 expected_bits
= SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
;
1306 for (i
=0;i
<16;i
++) {
1307 uint32_t bit
= (1<<i
);
1308 io
.ntcreatex
.in
.access_mask
= bit
;
1309 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1310 if (expected_bits
& bit
) {
1311 if (!NT_STATUS_IS_OK(status
)) {
1312 torture_warning(tctx
, "failed with access mask 0x%08x of expected 0x%08x\n",
1313 bit
, expected_bits
);
1315 CHECK_STATUS(status
, NT_STATUS_OK
);
1316 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.file
.fnum
, bit
| SEC_FILE_READ_ATTRIBUTE
);
1317 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1319 if (NT_STATUS_IS_OK(status
)) {
1320 torture_warning(tctx
, "open succeeded with access mask 0x%08x of "
1321 "expected 0x%08x - should fail\n",
1322 bit
, expected_bits
);
1324 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1328 torture_comment(tctx
, "put back original sd\n");
1329 set
.set_secdesc
.in
.sd
= sd_orig
;
1330 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1331 CHECK_STATUS(status
, NT_STATUS_OK
);
1334 smbcli_close(cli
->tree
, fnum
);
1335 smbcli_unlink(cli
->tree
, fname
);
1336 smb_raw_exit(cli
->session
);
1337 smbcli_deltree(cli
->tree
, BASEDIR
);
1344 test the inheritance of ACL flags onto new files and directories
1345 Test copied to smb2/acls.c for SMB2.
1347 static bool test_inheritance(struct torture_context
*tctx
,
1348 struct smbcli_state
*cli
)
1352 const char *dname
= BASEDIR
"\\inheritance";
1353 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1354 const char *fname2
= BASEDIR
"\\inheritance\\testdir";
1356 int fnum
=0, fnum2
, i
;
1357 union smb_fileinfo q
;
1358 union smb_setfileinfo set
;
1359 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
, *sd_def1
, *sd_def2
;
1360 const char *owner_sid
, *group_sid
;
1361 const struct dom_sid
*creator_owner
;
1363 uint32_t parent_flags
;
1364 uint32_t file_flags
;
1373 SEC_ACE_FLAG_OBJECT_INHERIT
,
1375 SEC_ACE_FLAG_OBJECT_INHERIT
|
1376 SEC_ACE_FLAG_INHERIT_ONLY
,
1379 SEC_ACE_FLAG_CONTAINER_INHERIT
,
1381 SEC_ACE_FLAG_CONTAINER_INHERIT
,
1384 SEC_ACE_FLAG_OBJECT_INHERIT
|
1385 SEC_ACE_FLAG_CONTAINER_INHERIT
,
1387 SEC_ACE_FLAG_OBJECT_INHERIT
|
1388 SEC_ACE_FLAG_CONTAINER_INHERIT
,
1391 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
1396 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
1397 SEC_ACE_FLAG_OBJECT_INHERIT
,
1402 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
1403 SEC_ACE_FLAG_CONTAINER_INHERIT
,
1408 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
1409 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1410 SEC_ACE_FLAG_OBJECT_INHERIT
,
1415 SEC_ACE_FLAG_INHERIT_ONLY
,
1420 SEC_ACE_FLAG_INHERIT_ONLY
|
1421 SEC_ACE_FLAG_OBJECT_INHERIT
,
1423 SEC_ACE_FLAG_OBJECT_INHERIT
|
1424 SEC_ACE_FLAG_INHERIT_ONLY
,
1427 SEC_ACE_FLAG_INHERIT_ONLY
|
1428 SEC_ACE_FLAG_CONTAINER_INHERIT
,
1430 SEC_ACE_FLAG_CONTAINER_INHERIT
,
1433 SEC_ACE_FLAG_INHERIT_ONLY
|
1434 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1435 SEC_ACE_FLAG_OBJECT_INHERIT
,
1437 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1438 SEC_ACE_FLAG_OBJECT_INHERIT
,
1441 SEC_ACE_FLAG_INHERIT_ONLY
|
1442 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
1447 SEC_ACE_FLAG_INHERIT_ONLY
|
1448 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
1449 SEC_ACE_FLAG_OBJECT_INHERIT
,
1454 SEC_ACE_FLAG_INHERIT_ONLY
|
1455 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
1456 SEC_ACE_FLAG_CONTAINER_INHERIT
,
1461 SEC_ACE_FLAG_INHERIT_ONLY
|
1462 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
1463 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1464 SEC_ACE_FLAG_OBJECT_INHERIT
,
1470 if (!torture_setup_dir(cli
, BASEDIR
))
1473 torture_comment(tctx
, "TESTING ACL INHERITANCE\n");
1475 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1476 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1477 io
.ntcreatex
.in
.flags
= 0;
1478 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1479 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1480 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1481 io
.ntcreatex
.in
.share_access
= 0;
1482 io
.ntcreatex
.in
.alloc_size
= 0;
1483 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1484 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1485 io
.ntcreatex
.in
.security_flags
= 0;
1486 io
.ntcreatex
.in
.fname
= dname
;
1488 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1489 CHECK_STATUS(status
, NT_STATUS_OK
);
1490 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1492 torture_comment(tctx
, "get the original sd\n");
1493 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1494 q
.query_secdesc
.in
.file
.fnum
= fnum
;
1495 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
| SECINFO_GROUP
;
1496 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1497 CHECK_STATUS(status
, NT_STATUS_OK
);
1498 sd_orig
= q
.query_secdesc
.out
.sd
;
1500 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1501 group_sid
= dom_sid_string(tctx
, sd_orig
->group_sid
);
1503 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1504 torture_comment(tctx
, "group_sid is %s\n", group_sid
);
1506 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1508 if (torture_setting_bool(tctx
, "samba4", false)) {
1509 /* the default ACL in Samba4 includes the group and
1510 other permissions */
1511 sd_def1
= security_descriptor_dacl_create(tctx
,
1514 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1515 SEC_RIGHTS_FILE_ALL
,
1518 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1519 SEC_RIGHTS_FILE_READ
| SEC_FILE_EXECUTE
,
1522 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1523 SEC_RIGHTS_FILE_READ
| SEC_FILE_EXECUTE
,
1526 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1527 SEC_RIGHTS_FILE_ALL
,
1532 * The Windows Default ACL for a new file, when there is no ACL to be
1533 * inherited: FullControl for the owner and SYSTEM.
1535 sd_def1
= security_descriptor_dacl_create(tctx
,
1538 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1539 SEC_RIGHTS_FILE_ALL
,
1542 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1543 SEC_RIGHTS_FILE_ALL
,
1549 * Use this in the case the system being tested does not add an ACE for
1552 sd_def2
= security_descriptor_dacl_create(tctx
,
1555 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1556 SEC_RIGHTS_FILE_ALL
,
1560 creator_owner
= dom_sid_parse_talloc(tctx
, SID_CREATOR_OWNER
);
1562 for (i
=0;i
<ARRAY_SIZE(test_flags
);i
++) {
1563 sd
= security_descriptor_dacl_create(tctx
,
1566 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1567 SEC_FILE_WRITE_DATA
,
1568 test_flags
[i
].parent_flags
,
1570 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1571 SEC_FILE_ALL
| SEC_STD_ALL
,
1574 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1575 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1576 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1577 set
.set_secdesc
.in
.sd
= sd
;
1578 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1579 CHECK_STATUS(status
, NT_STATUS_OK
);
1581 io
.ntcreatex
.in
.fname
= fname1
;
1582 io
.ntcreatex
.in
.create_options
= 0;
1583 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1584 CHECK_STATUS(status
, NT_STATUS_OK
);
1585 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1587 q
.query_secdesc
.in
.file
.fnum
= fnum2
;
1588 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1589 CHECK_STATUS(status
, NT_STATUS_OK
);
1591 smbcli_close(cli
->tree
, fnum2
);
1592 smbcli_unlink(cli
->tree
, fname1
);
1594 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
)) {
1595 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def1
) &&
1596 !security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def2
)) {
1597 torture_warning(tctx
, "Expected default sd "
1599 NDR_PRINT_DEBUG(security_descriptor
, sd_def1
);
1600 torture_warning(tctx
, "at %d - got:\n", i
);
1601 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1606 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1607 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1608 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1609 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1610 sd_orig
->owner_sid
)) {
1612 torture_warning(tctx
, "Bad sd in child file at %d\n", i
);
1613 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1617 if (q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!=
1618 test_flags
[i
].file_flags
) {
1619 torture_warning(tctx
, "incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1620 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
,
1621 test_flags
[i
].file_flags
,
1622 test_flags
[i
].parent_flags
,
1628 io
.ntcreatex
.in
.fname
= fname2
;
1629 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1630 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1631 CHECK_STATUS(status
, NT_STATUS_OK
);
1632 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1634 q
.query_secdesc
.in
.file
.fnum
= fnum2
;
1635 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1636 CHECK_STATUS(status
, NT_STATUS_OK
);
1638 smbcli_close(cli
->tree
, fnum2
);
1639 smbcli_rmdir(cli
->tree
, fname2
);
1641 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1642 (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
) ||
1643 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
))) {
1644 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def1
) &&
1645 !security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def2
)) {
1646 torture_warning(tctx
, "Expected default sd for dir at %d:\n", i
);
1647 NDR_PRINT_DEBUG(security_descriptor
, sd_def1
);
1648 torture_warning(tctx
, "got:\n");
1649 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1654 if ((test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1655 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
)) {
1656 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1657 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1658 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1659 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1660 sd_orig
->owner_sid
) ||
1661 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1662 torture_warning(tctx
, "(CI & NP) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1663 test_flags
[i
].dir_flags
,
1664 test_flags
[i
].parent_flags
, i
);
1665 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1666 torture_comment(tctx
, "FYI, here is the parent sd:\n");
1667 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1671 } else if (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) {
1672 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1673 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 2 ||
1674 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1675 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1676 sd_orig
->owner_sid
) ||
1677 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].access_mask
!= SEC_FILE_WRITE_DATA
||
1678 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[1].trustee
,
1680 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= 0 ||
1681 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].flags
!=
1682 (test_flags
[i
].dir_flags
| SEC_ACE_FLAG_INHERIT_ONLY
)) {
1683 torture_warning(tctx
, "(CI) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1684 test_flags
[i
].dir_flags
,
1685 test_flags
[i
].parent_flags
, i
);
1686 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1687 torture_comment(tctx
, "FYI, here is the parent sd:\n");
1688 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1693 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1694 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1695 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1696 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1698 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1699 torture_warning(tctx
, "(0) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1700 test_flags
[i
].dir_flags
,
1701 test_flags
[i
].parent_flags
, i
);
1702 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1703 torture_comment(tctx
, "FYI, here is the parent sd:\n");
1704 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1711 torture_comment(tctx
, "Testing access checks on inherited create with %s\n", fname1
);
1712 sd
= security_descriptor_dacl_create(tctx
,
1715 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1716 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1717 SEC_ACE_FLAG_OBJECT_INHERIT
,
1719 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1720 SEC_FILE_ALL
| SEC_STD_ALL
,
1723 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1724 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1725 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1726 set
.set_secdesc
.in
.sd
= sd
;
1727 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1728 CHECK_STATUS(status
, NT_STATUS_OK
);
1730 /* Check DACL we just set. */
1731 torture_comment(tctx
, "checking new sd\n");
1732 q
.query_secdesc
.in
.file
.fnum
= fnum
;
1733 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1734 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1735 CHECK_STATUS(status
, NT_STATUS_OK
);
1736 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1738 io
.ntcreatex
.in
.fname
= fname1
;
1739 io
.ntcreatex
.in
.create_options
= 0;
1740 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1741 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1742 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1743 CHECK_STATUS(status
, NT_STATUS_OK
);
1744 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1745 CHECK_ACCESS_FLAGS(fnum2
, SEC_RIGHTS_FILE_ALL
);
1747 q
.query_secdesc
.in
.file
.fnum
= fnum2
;
1748 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1749 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1750 CHECK_STATUS(status
, NT_STATUS_OK
);
1751 smbcli_close(cli
->tree
, fnum2
);
1753 sd2
= security_descriptor_dacl_create(tctx
,
1756 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1757 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1760 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1762 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1763 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1764 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1765 if (NT_STATUS_IS_OK(status
)) {
1766 torture_warning(tctx
, "failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1768 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1769 CHECK_ACCESS_FLAGS(fnum2
, SEC_RIGHTS_FILE_ALL
);
1770 smbcli_close(cli
->tree
, fnum2
);
1772 if (TARGET_IS_WIN7(tctx
)) {
1773 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1775 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1779 torture_comment(tctx
, "trying without execute\n");
1780 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1781 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
& ~SEC_FILE_EXECUTE
;
1782 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1783 if (TARGET_IS_WIN7(tctx
)) {
1784 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1786 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1789 torture_comment(tctx
, "and with full permissions again\n");
1790 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1791 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1792 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1793 if (TARGET_IS_WIN7(tctx
)) {
1794 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1796 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1799 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
1800 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1801 CHECK_STATUS(status
, NT_STATUS_OK
);
1802 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1803 CHECK_ACCESS_FLAGS(fnum2
, SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
);
1804 smbcli_close(cli
->tree
, fnum2
);
1806 torture_comment(tctx
, "put back original sd\n");
1807 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1808 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1809 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1810 set
.set_secdesc
.in
.sd
= sd_orig
;
1811 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1812 CHECK_STATUS(status
, NT_STATUS_OK
);
1814 smbcli_close(cli
->tree
, fnum
);
1816 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1817 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1818 if (TARGET_IS_WIN7(tctx
)) {
1819 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1821 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1824 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
1825 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1826 CHECK_STATUS(status
, NT_STATUS_OK
);
1827 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1828 CHECK_ACCESS_FLAGS(fnum2
, SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
);
1829 smbcli_close(cli
->tree
, fnum2
);
1832 if (sd_orig
!= NULL
) {
1833 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1834 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1835 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1836 set
.set_secdesc
.in
.sd
= sd_orig
;
1837 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1840 smbcli_close(cli
->tree
, fnum
);
1841 smbcli_unlink(cli
->tree
, fname1
);
1842 smbcli_rmdir(cli
->tree
, dname
);
1843 smb_raw_exit(cli
->session
);
1844 smbcli_deltree(cli
->tree
, BASEDIR
);
1848 static bool test_inheritance_flags(struct torture_context
*tctx
,
1849 struct smbcli_state
*cli
)
1853 const char *dname
= BASEDIR
"\\inheritance";
1854 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1856 int fnum
=0, fnum2
, i
, j
;
1857 union smb_fileinfo q
;
1858 union smb_setfileinfo set
;
1859 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
;
1860 const char *owner_sid
;
1862 uint32_t parent_set_sd_type
; /* 3 options */
1863 uint32_t parent_set_ace_inherit
; /* 1 option */
1864 uint32_t parent_get_sd_type
;
1865 uint32_t parent_get_ace_inherit
;
1866 uint32_t child_get_sd_type
;
1867 uint32_t child_get_ace_inherit
;
1868 } tflags
[16]; /* 2^4 */
1870 for (i
= 0; i
< 15; i
++) {
1871 torture_comment(tctx
, "i=%d:", i
);
1873 ZERO_STRUCT(tflags
[i
]);
1876 tflags
[i
].parent_set_sd_type
|=
1877 SEC_DESC_DACL_AUTO_INHERITED
;
1878 torture_comment(tctx
, "AUTO_INHERITED, ");
1881 tflags
[i
].parent_set_sd_type
|=
1882 SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1883 torture_comment(tctx
, "AUTO_INHERIT_REQ, ");
1886 tflags
[i
].parent_set_sd_type
|=
1887 SEC_DESC_DACL_PROTECTED
;
1888 tflags
[i
].parent_get_sd_type
|=
1889 SEC_DESC_DACL_PROTECTED
;
1890 torture_comment(tctx
, "PROTECTED, ");
1893 tflags
[i
].parent_set_ace_inherit
|=
1894 SEC_ACE_FLAG_INHERITED_ACE
;
1895 tflags
[i
].parent_get_ace_inherit
|=
1896 SEC_ACE_FLAG_INHERITED_ACE
;
1897 torture_comment(tctx
, "INHERITED, ");
1900 if ((tflags
[i
].parent_set_sd_type
&
1901 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) ==
1902 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) {
1903 tflags
[i
].parent_get_sd_type
|=
1904 SEC_DESC_DACL_AUTO_INHERITED
;
1905 tflags
[i
].child_get_sd_type
|=
1906 SEC_DESC_DACL_AUTO_INHERITED
;
1907 tflags
[i
].child_get_ace_inherit
|=
1908 SEC_ACE_FLAG_INHERITED_ACE
;
1909 torture_comment(tctx
, " ... parent is AUTO INHERITED");
1912 if (tflags
[i
].parent_set_ace_inherit
&
1913 SEC_ACE_FLAG_INHERITED_ACE
) {
1914 tflags
[i
].parent_get_ace_inherit
=
1915 SEC_ACE_FLAG_INHERITED_ACE
;
1916 torture_comment(tctx
, " ... parent ACE is INHERITED");
1919 torture_comment(tctx
, "\n");
1922 if (!torture_setup_dir(cli
, BASEDIR
))
1925 torture_comment(tctx
, "TESTING ACL INHERITANCE FLAGS\n");
1927 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1928 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1929 io
.ntcreatex
.in
.flags
= 0;
1930 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1931 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1932 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1933 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
;
1934 io
.ntcreatex
.in
.alloc_size
= 0;
1935 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1936 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1937 io
.ntcreatex
.in
.security_flags
= 0;
1938 io
.ntcreatex
.in
.fname
= dname
;
1940 torture_comment(tctx
, "creating initial directory %s\n", dname
);
1941 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1942 CHECK_STATUS(status
, NT_STATUS_OK
);
1943 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1945 torture_comment(tctx
, "getting original sd\n");
1946 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1947 q
.query_secdesc
.in
.file
.fnum
= fnum
;
1948 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1949 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1950 CHECK_STATUS(status
, NT_STATUS_OK
);
1951 sd_orig
= q
.query_secdesc
.out
.sd
;
1953 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1954 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1956 for (i
=0; i
< ARRAY_SIZE(tflags
); i
++) {
1957 torture_comment(tctx
, "setting a new sd on directory, pass #%d\n", i
);
1959 sd
= security_descriptor_dacl_create(tctx
,
1960 tflags
[i
].parent_set_sd_type
,
1963 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1964 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1965 SEC_ACE_FLAG_OBJECT_INHERIT
|
1966 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1967 tflags
[i
].parent_set_ace_inherit
,
1969 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1970 SEC_FILE_ALL
| SEC_STD_ALL
,
1973 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1974 set
.set_secdesc
.in
.file
.fnum
= fnum
;
1975 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1976 set
.set_secdesc
.in
.sd
= sd
;
1977 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1978 CHECK_STATUS(status
, NT_STATUS_OK
);
1981 * Check DACL we just set, except change the bits to what they
1984 torture_comment(tctx
, " checking new sd\n");
1986 /* REQ bit should always be false. */
1987 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1989 if ((tflags
[i
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1990 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1992 q
.query_secdesc
.in
.file
.fnum
= fnum
;
1993 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1994 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
1995 CHECK_STATUS(status
, NT_STATUS_OK
);
1996 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1999 torture_comment(tctx
, " creating file %s\n", fname1
);
2000 io
.ntcreatex
.in
.fname
= fname1
;
2001 io
.ntcreatex
.in
.create_options
= 0;
2002 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2003 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2004 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2005 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2006 CHECK_STATUS(status
, NT_STATUS_OK
);
2007 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2008 CHECK_ACCESS_FLAGS(fnum2
, SEC_RIGHTS_FILE_ALL
);
2010 q
.query_secdesc
.in
.file
.fnum
= fnum2
;
2011 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
2012 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
2013 CHECK_STATUS(status
, NT_STATUS_OK
);
2015 torture_comment(tctx
, " checking sd on file %s\n", fname1
);
2016 sd2
= security_descriptor_dacl_create(tctx
,
2017 tflags
[i
].child_get_sd_type
,
2020 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2021 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
2022 tflags
[i
].child_get_ace_inherit
,
2024 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
2027 * Set new sd on file ... prove that the bits have nothing to
2028 * do with the parents bits when manually setting an ACL. The
2029 * _AUTO_INHERITED bit comes directly from the ACL set.
2031 for (j
= 0; j
< ARRAY_SIZE(tflags
); j
++) {
2032 torture_comment(tctx
, " setting new file sd, pass #%d\n", j
);
2034 /* Change sd type. */
2035 sd2
->type
&= ~(SEC_DESC_DACL_AUTO_INHERITED
|
2036 SEC_DESC_DACL_AUTO_INHERIT_REQ
|
2037 SEC_DESC_DACL_PROTECTED
);
2038 sd2
->type
|= tflags
[j
].parent_set_sd_type
;
2040 sd2
->dacl
->aces
[0].flags
&=
2041 ~SEC_ACE_FLAG_INHERITED_ACE
;
2042 sd2
->dacl
->aces
[0].flags
|=
2043 tflags
[j
].parent_set_ace_inherit
;
2045 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2046 set
.set_secdesc
.in
.file
.fnum
= fnum2
;
2047 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2048 set
.set_secdesc
.in
.sd
= sd2
;
2049 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
2050 CHECK_STATUS(status
, NT_STATUS_OK
);
2052 /* Check DACL we just set. */
2053 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
2054 if ((tflags
[j
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
2055 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
2057 q
.query_secdesc
.in
.file
.fnum
= fnum2
;
2058 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
2059 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
2060 CHECK_STATUS(status
, NT_STATUS_OK
);
2062 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
2065 smbcli_close(cli
->tree
, fnum2
);
2066 smbcli_unlink(cli
->tree
, fname1
);
2070 smbcli_close(cli
->tree
, fnum
);
2071 smb_raw_exit(cli
->session
);
2072 smbcli_deltree(cli
->tree
, BASEDIR
);
2077 test dynamic acl inheritance
2078 Test copied to smb2/acls.c for SMB2.
2080 static bool test_inheritance_dynamic(struct torture_context
*tctx
,
2081 struct smbcli_state
*cli
)
2085 const char *dname
= BASEDIR
"\\inheritance2";
2086 const char *fname1
= BASEDIR
"\\inheritance2\\testfile";
2089 union smb_fileinfo q
;
2090 union smb_setfileinfo set
;
2091 struct security_descriptor
*sd
, *sd_orig
=NULL
;
2092 const char *owner_sid
;
2094 torture_comment(tctx
, "TESTING DYNAMIC ACL INHERITANCE\n");
2096 if (!torture_setup_dir(cli
, BASEDIR
))
2099 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2100 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2101 io
.ntcreatex
.in
.flags
= 0;
2102 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2103 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
2104 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
2105 io
.ntcreatex
.in
.share_access
= 0;
2106 io
.ntcreatex
.in
.alloc_size
= 0;
2107 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2108 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2109 io
.ntcreatex
.in
.security_flags
= 0;
2110 io
.ntcreatex
.in
.fname
= dname
;
2112 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2113 CHECK_STATUS(status
, NT_STATUS_OK
);
2114 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2116 torture_comment(tctx
, "get the original sd\n");
2117 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2118 q
.query_secdesc
.in
.file
.fnum
= fnum
;
2119 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
2120 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &q
);
2121 CHECK_STATUS(status
, NT_STATUS_OK
);
2122 sd_orig
= q
.query_secdesc
.out
.sd
;
2124 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
2126 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
2128 sd
= security_descriptor_dacl_create(tctx
,
2131 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2132 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
,
2133 SEC_ACE_FLAG_OBJECT_INHERIT
,
2135 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
2137 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2138 set
.set_secdesc
.in
.file
.fnum
= fnum
;
2139 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2140 set
.set_secdesc
.in
.sd
= sd
;
2141 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
2142 CHECK_STATUS(status
, NT_STATUS_OK
);
2144 torture_comment(tctx
, "create a file with an inherited acl\n");
2145 io
.ntcreatex
.in
.fname
= fname1
;
2146 io
.ntcreatex
.in
.create_options
= 0;
2147 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
;
2148 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2149 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2150 CHECK_STATUS(status
, NT_STATUS_OK
);
2151 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2152 smbcli_close(cli
->tree
, fnum2
);
2154 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
2155 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
2156 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
2157 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2158 CHECK_STATUS(status
, NT_STATUS_OK
);
2159 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2160 smbcli_close(cli
->tree
, fnum2
);
2162 torture_comment(tctx
, "try and access file with extra rights - should be denied\n");
2163 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
2164 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2165 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
2167 torture_comment(tctx
, "update parent sd\n");
2168 sd
= security_descriptor_dacl_create(tctx
,
2171 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2172 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
,
2173 SEC_ACE_FLAG_OBJECT_INHERIT
,
2175 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
2177 set
.set_secdesc
.in
.sd
= sd
;
2178 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
2179 CHECK_STATUS(status
, NT_STATUS_OK
);
2181 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
2182 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
2183 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2184 CHECK_STATUS(status
, NT_STATUS_OK
);
2185 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2186 smbcli_close(cli
->tree
, fnum2
);
2189 torture_comment(tctx
, "try and access now - should be OK if dynamic inheritance works\n");
2190 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
2191 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2192 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
2193 torture_comment(tctx
, "Server does not have dynamic inheritance\n");
2195 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
2196 torture_comment(tctx
, "Server does have dynamic inheritance\n");
2198 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
2200 smbcli_unlink(cli
->tree
, fname1
);
2203 torture_comment(tctx
, "put back original sd\n");
2204 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2205 set
.set_secdesc
.in
.file
.fnum
= fnum
;
2206 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2207 set
.set_secdesc
.in
.sd
= sd_orig
;
2208 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
2210 smbcli_close(cli
->tree
, fnum
);
2211 smbcli_rmdir(cli
->tree
, dname
);
2212 smb_raw_exit(cli
->session
);
2213 smbcli_deltree(cli
->tree
, BASEDIR
);
2218 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
2219 if (!(bits & desired_64)) {\
2220 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
2223 CHECK_STATUS(status, NT_STATUS_OK); \
2227 #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
2228 if (NT_STATUS_IS_OK(status)) { \
2229 if (!(granted & access)) {\
2231 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
2232 __location__, nt_errstr(status), access, granted, desired); \
2236 if (granted & access) {\
2238 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
2239 __location__, nt_errstr(status), access, granted, desired); \
2243 CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
2246 /* test what access mask is needed for getting and setting security_descriptors
2247 Test copied to smb2/acls.c for SMB2. */
2248 static bool test_sd_get_set(struct torture_context
*tctx
,
2249 struct smbcli_state
*cli
)
2254 union smb_fileinfo fi
;
2255 union smb_setfileinfo si
;
2256 struct security_descriptor
*sd
;
2257 struct security_descriptor
*sd_owner
= NULL
;
2258 struct security_descriptor
*sd_group
= NULL
;
2259 struct security_descriptor
*sd_dacl
= NULL
;
2260 struct security_descriptor
*sd_sacl
= NULL
;
2262 const char *fname
= BASEDIR
"\\sd_get_set.txt";
2263 uint64_t desired_64
;
2264 uint32_t desired
= 0, granted
;
2266 #define NO_BITS_HACK (((uint64_t)1)<<32)
2267 uint64_t open_bits
=
2269 SEC_FLAG_SYSTEM_SECURITY
|
2270 SEC_FLAG_MAXIMUM_ALLOWED
|
2274 uint64_t get_owner_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
2275 uint64_t set_owner_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
2276 uint64_t get_group_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
2277 uint64_t set_group_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
2278 uint64_t get_dacl_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
2279 uint64_t set_dacl_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_DAC
;
2280 uint64_t get_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
2281 uint64_t set_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
2283 if (!torture_setup_dir(cli
, BASEDIR
))
2286 torture_comment(tctx
, "TESTING ACCESS MASKS FOR SD GET/SET\n");
2288 /* first create a file with full access for everyone */
2289 sd
= security_descriptor_dacl_create(tctx
,
2290 0, SID_NT_ANONYMOUS
, SID_BUILTIN_USERS
,
2292 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2296 sd
->type
|= SEC_DESC_SACL_PRESENT
;
2298 io
.ntcreatex
.level
= RAW_OPEN_NTTRANS_CREATE
;
2299 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2300 io
.ntcreatex
.in
.flags
= 0;
2301 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_ALL
;
2302 io
.ntcreatex
.in
.create_options
= 0;
2303 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2304 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
2305 io
.ntcreatex
.in
.alloc_size
= 0;
2306 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
2307 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2308 io
.ntcreatex
.in
.security_flags
= 0;
2309 io
.ntcreatex
.in
.fname
= fname
;
2310 io
.ntcreatex
.in
.sec_desc
= sd
;
2311 io
.ntcreatex
.in
.ea_list
= NULL
;
2312 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2313 CHECK_STATUS(status
, NT_STATUS_OK
);
2314 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2316 status
= smbcli_close(cli
->tree
, fnum
);
2317 CHECK_STATUS(status
, NT_STATUS_OK
);
2320 * now try each access_mask bit and no bit at all in a loop
2321 * and see what's allowed
2322 * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
2324 for (i
=0; i
<= 32; i
++) {
2325 desired_64
= ((uint64_t)1) << i
;
2326 desired
= (uint32_t)desired_64
;
2328 /* first open the file with the desired access */
2329 io
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
2330 io
.ntcreatex
.in
.access_mask
= desired
;
2331 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
2332 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2333 CHECK_STATUS_FOR_BIT_ACTION(status
, open_bits
, goto next
);
2334 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2336 /* then check what access was granted */
2337 fi
.access_information
.level
= RAW_FILEINFO_ACCESS_INFORMATION
;
2338 fi
.access_information
.in
.file
.fnum
= fnum
;
2339 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &fi
);
2340 CHECK_STATUS(status
, NT_STATUS_OK
);
2341 granted
= fi
.access_information
.out
.access_flags
;
2343 /* test the owner */
2345 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2346 fi
.query_secdesc
.in
.file
.fnum
= fnum
;
2347 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
2348 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &fi
);
2349 CHECK_STATUS_FOR_BIT(status
, get_owner_bits
, SEC_STD_READ_CONTROL
);
2350 if (fi
.query_secdesc
.out
.sd
) {
2351 sd_owner
= fi
.query_secdesc
.out
.sd
;
2352 } else if (!sd_owner
) {
2355 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2356 si
.set_secdesc
.in
.file
.fnum
= fnum
;
2357 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
2358 si
.set_secdesc
.in
.sd
= sd_owner
;
2359 status
= smb_raw_setfileinfo(cli
->tree
, &si
);
2360 CHECK_STATUS_FOR_BIT(status
, set_owner_bits
, SEC_STD_WRITE_OWNER
);
2362 /* test the group */
2364 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2365 fi
.query_secdesc
.in
.file
.fnum
= fnum
;
2366 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
2367 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &fi
);
2368 CHECK_STATUS_FOR_BIT(status
, get_group_bits
, SEC_STD_READ_CONTROL
);
2369 if (fi
.query_secdesc
.out
.sd
) {
2370 sd_group
= fi
.query_secdesc
.out
.sd
;
2371 } else if (!sd_group
) {
2374 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2375 si
.set_secdesc
.in
.file
.fnum
= fnum
;
2376 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
2377 si
.set_secdesc
.in
.sd
= sd_group
;
2378 status
= smb_raw_setfileinfo(cli
->tree
, &si
);
2379 CHECK_STATUS_FOR_BIT(status
, set_group_bits
, SEC_STD_WRITE_OWNER
);
2383 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2384 fi
.query_secdesc
.in
.file
.fnum
= fnum
;
2385 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2386 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &fi
);
2387 CHECK_STATUS_FOR_BIT(status
, get_dacl_bits
, SEC_STD_READ_CONTROL
);
2388 if (fi
.query_secdesc
.out
.sd
) {
2389 sd_dacl
= fi
.query_secdesc
.out
.sd
;
2390 } else if (!sd_dacl
) {
2393 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2394 si
.set_secdesc
.in
.file
.fnum
= fnum
;
2395 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2396 si
.set_secdesc
.in
.sd
= sd_dacl
;
2397 status
= smb_raw_setfileinfo(cli
->tree
, &si
);
2398 CHECK_STATUS_FOR_BIT(status
, set_dacl_bits
, SEC_STD_WRITE_DAC
);
2402 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2403 fi
.query_secdesc
.in
.file
.fnum
= fnum
;
2404 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
2405 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &fi
);
2406 CHECK_STATUS_FOR_BIT(status
, get_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
2407 if (fi
.query_secdesc
.out
.sd
) {
2408 sd_sacl
= fi
.query_secdesc
.out
.sd
;
2409 } else if (!sd_sacl
) {
2412 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2413 si
.set_secdesc
.in
.file
.fnum
= fnum
;
2414 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
2415 si
.set_secdesc
.in
.sd
= sd_sacl
;
2416 status
= smb_raw_setfileinfo(cli
->tree
, &si
);
2417 CHECK_STATUS_FOR_BIT(status
, set_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
2419 /* close the handle */
2420 status
= smbcli_close(cli
->tree
, fnum
);
2421 CHECK_STATUS(status
, NT_STATUS_OK
);
2427 smbcli_close(cli
->tree
, fnum
);
2428 smbcli_unlink(cli
->tree
, fname
);
2429 smb_raw_exit(cli
->session
);
2430 smbcli_deltree(cli
->tree
, BASEDIR
);
2437 basic testing of security descriptor calls
2439 struct torture_suite
*torture_raw_acls(TALLOC_CTX
*mem_ctx
)
2441 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "ACLS");
2443 torture_suite_add_1smb_test(suite
, "SD", test_sd
);
2444 torture_suite_add_1smb_test(suite
, "CREATE_FILE", test_nttrans_create_file
);
2445 torture_suite_add_1smb_test(suite
, "CREATE_DIR", test_nttrans_create_dir
);
2446 torture_suite_add_1smb_test(suite
, "NULLDACL", test_nttrans_create_null_dacl
);
2447 torture_suite_add_1smb_test(suite
, "CREATOR", test_creator_sid
);
2448 torture_suite_add_1smb_test(suite
, "GENERIC", test_generic_bits
);
2449 torture_suite_add_1smb_test(suite
, "OWNER", test_owner_bits
);
2450 torture_suite_add_1smb_test(suite
, "INHERITANCE", test_inheritance
);
2452 /* torture_suite_add_1smb_test(suite, "INHERITFLAGS", test_inheritance_flags); */
2453 torture_suite_add_1smb_test(suite
, "DYNAMIC", test_inheritance_dynamic
);
2454 /* XXX This test does not work against XP or Vista.
2455 torture_suite_add_1smb_test(suite, "GETSET", test_sd_get_set);