2 Unix SMB/CIFS implementation.
4 test security descriptor operations for SMB2
6 Copyright (C) Zack Kirsch 2009
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 "lib/cmdline/popt_common.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "libcli/smb/smbXcli_base.h"
27 #include "torture/torture.h"
28 #include "libcli/resolve/resolve.h"
29 #include "torture/util.h"
30 #include "torture/smb2/proto.h"
31 #include "libcli/security/security.h"
32 #include "librpc/gen_ndr/ndr_security.h"
33 #include "lib/param/param.h"
35 #define CHECK_STATUS(status, correct) do { \
36 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)); \
43 #define BASEDIR "smb2-testsd"
45 #define CHECK_ACCESS_IGNORE SEC_STD_SYNCHRONIZE
47 #define CHECK_ACCESS_FLAGS(_fh, flags) do { \
48 union smb_fileinfo _q; \
49 _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
50 _q.access_information.in.file.handle = (_fh); \
51 status = smb2_getinfo_file(tree, tctx, &_q); \
52 CHECK_STATUS(status, NT_STATUS_OK); \
53 /* Handle a Vista bug where SEC_STD_SYNCHRONIZE doesn't come back. */ \
54 if ((((flags) & CHECK_ACCESS_IGNORE) == CHECK_ACCESS_IGNORE) && \
55 ((_q.access_information.out.access_flags & CHECK_ACCESS_IGNORE) != CHECK_ACCESS_IGNORE)) { \
56 torture_comment(tctx, "SKIPPING (Vista bug): (%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
57 __location__, _q.access_information.out.access_flags, (flags)); \
59 if ((_q.access_information.out.access_flags & ~CHECK_ACCESS_IGNORE) != \
60 (((flags) & ~CHECK_ACCESS_IGNORE))) { \
61 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
62 __location__, _q.access_information.out.access_flags, (flags)); \
68 #define FAIL_UNLESS(__cond) \
70 if (__cond) {} else { \
71 torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \
72 __location__, #__cond); \
73 ret = false; goto done; \
77 #define CHECK_SECURITY_DESCRIPTOR(_sd1, _sd2) do { \
78 if (!security_descriptor_equal(_sd1, _sd2)) { \
79 torture_warning(tctx, "security descriptors don't match!\n"); \
80 torture_warning(tctx, "got:\n"); \
81 NDR_PRINT_DEBUG(security_descriptor, _sd1); \
82 torture_warning(tctx, "expected:\n"); \
83 NDR_PRINT_DEBUG(security_descriptor, _sd2); \
84 torture_result(tctx, TORTURE_FAIL, \
85 "%s: security descriptors don't match!\n", \
92 test the behaviour of the well known SID_CREATOR_OWNER sid, and some generic
94 Note: This test was copied from raw/acls.c.
96 static bool test_creator_sid(struct torture_context
*tctx
, struct smb2_tree
*tree
)
99 struct smb2_create io
;
100 const char *fname
= BASEDIR
"\\creator.txt";
102 struct smb2_handle handle
= {{0}};
103 union smb_fileinfo q
;
104 union smb_setfileinfo set
;
105 struct security_descriptor
*sd
, *sd_orig
, *sd2
;
106 const char *owner_sid
;
108 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
111 torture_comment(tctx
, "TESTING SID_CREATOR_OWNER\n");
114 io
.level
= RAW_OPEN_SMB2
;
115 io
.in
.create_flags
= 0;
116 io
.in
.desired_access
= SEC_STD_READ_CONTROL
| SEC_STD_WRITE_DAC
| SEC_STD_WRITE_OWNER
;
117 io
.in
.create_options
= 0;
118 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
119 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
|
120 NTCREATEX_SHARE_ACCESS_READ
|
121 NTCREATEX_SHARE_ACCESS_WRITE
;
122 io
.in
.alloc_size
= 0;
123 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
124 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
125 io
.in
.security_flags
= 0;
128 status
= smb2_create(tree
, tctx
, &io
);
129 CHECK_STATUS(status
, NT_STATUS_OK
);
130 handle
= io
.out
.file
.handle
;
132 torture_comment(tctx
, "get the original sd\n");
133 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
134 q
.query_secdesc
.in
.file
.handle
= handle
;
135 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
136 status
= smb2_getinfo_file(tree
, tctx
, &q
);
137 CHECK_STATUS(status
, NT_STATUS_OK
);
138 sd_orig
= q
.query_secdesc
.out
.sd
;
140 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
142 torture_comment(tctx
, "set a sec desc allowing no write by CREATOR_OWNER\n");
143 sd
= security_descriptor_dacl_create(tctx
,
146 SEC_ACE_TYPE_ACCESS_ALLOWED
,
147 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
151 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
152 set
.set_secdesc
.in
.file
.handle
= handle
;
153 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
154 set
.set_secdesc
.in
.sd
= sd
;
156 status
= smb2_setinfo_file(tree
, &set
);
157 CHECK_STATUS(status
, NT_STATUS_OK
);
159 torture_comment(tctx
, "try open for write\n");
160 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
161 status
= smb2_create(tree
, tctx
, &io
);
162 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
164 torture_comment(tctx
, "try open for read\n");
165 io
.in
.desired_access
= SEC_FILE_READ_DATA
;
166 status
= smb2_create(tree
, tctx
, &io
);
167 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
169 torture_comment(tctx
, "try open for generic write\n");
170 io
.in
.desired_access
= SEC_GENERIC_WRITE
;
171 status
= smb2_create(tree
, tctx
, &io
);
172 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
174 torture_comment(tctx
, "try open for generic read\n");
175 io
.in
.desired_access
= SEC_GENERIC_READ
;
176 status
= smb2_create(tree
, tctx
, &io
);
177 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
179 torture_comment(tctx
, "set a sec desc allowing no write by owner\n");
180 sd
= security_descriptor_dacl_create(tctx
,
183 SEC_ACE_TYPE_ACCESS_ALLOWED
,
184 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
188 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
189 set
.set_secdesc
.in
.file
.handle
= handle
;
190 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
191 set
.set_secdesc
.in
.sd
= sd
;
192 status
= smb2_setinfo_file(tree
, &set
);
193 CHECK_STATUS(status
, NT_STATUS_OK
);
195 torture_comment(tctx
, "check that sd has been mapped correctly\n");
196 status
= smb2_getinfo_file(tree
, tctx
, &q
);
197 CHECK_STATUS(status
, NT_STATUS_OK
);
198 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
200 torture_comment(tctx
, "try open for write\n");
201 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
202 status
= smb2_create(tree
, tctx
, &io
);
203 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
205 torture_comment(tctx
, "try open for read\n");
206 io
.in
.desired_access
= SEC_FILE_READ_DATA
;
207 status
= smb2_create(tree
, tctx
, &io
);
208 CHECK_STATUS(status
, NT_STATUS_OK
);
209 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
211 smb2_util_close(tree
, io
.out
.file
.handle
);
213 torture_comment(tctx
, "try open for generic write\n");
214 io
.in
.desired_access
= SEC_GENERIC_WRITE
;
215 status
= smb2_create(tree
, tctx
, &io
);
216 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
218 torture_comment(tctx
, "try open for generic read\n");
219 io
.in
.desired_access
= SEC_GENERIC_READ
;
220 status
= smb2_create(tree
, tctx
, &io
);
221 CHECK_STATUS(status
, NT_STATUS_OK
);
222 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
223 SEC_RIGHTS_FILE_READ
);
224 smb2_util_close(tree
, io
.out
.file
.handle
);
226 torture_comment(tctx
, "set a sec desc allowing generic read by owner\n");
227 sd
= security_descriptor_dacl_create(tctx
,
230 SEC_ACE_TYPE_ACCESS_ALLOWED
,
231 SEC_GENERIC_READ
| SEC_STD_ALL
,
235 set
.set_secdesc
.in
.sd
= sd
;
236 status
= smb2_setinfo_file(tree
, &set
);
237 CHECK_STATUS(status
, NT_STATUS_OK
);
239 torture_comment(tctx
, "check that generic read has been mapped correctly\n");
240 sd2
= security_descriptor_dacl_create(tctx
,
243 SEC_ACE_TYPE_ACCESS_ALLOWED
,
244 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
248 status
= smb2_getinfo_file(tree
, tctx
, &q
);
249 CHECK_STATUS(status
, NT_STATUS_OK
);
250 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
252 torture_comment(tctx
, "try open for write\n");
253 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
254 status
= smb2_create(tree
, tctx
, &io
);
255 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
257 torture_comment(tctx
, "try open for read\n");
258 io
.in
.desired_access
= SEC_FILE_READ_DATA
;
259 status
= smb2_create(tree
, tctx
, &io
);
260 CHECK_STATUS(status
, NT_STATUS_OK
);
261 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
263 smb2_util_close(tree
, io
.out
.file
.handle
);
265 torture_comment(tctx
, "try open for generic write\n");
266 io
.in
.desired_access
= SEC_GENERIC_WRITE
;
267 status
= smb2_create(tree
, tctx
, &io
);
268 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
270 torture_comment(tctx
, "try open for generic read\n");
271 io
.in
.desired_access
= SEC_GENERIC_READ
;
272 status
= smb2_create(tree
, tctx
, &io
);
273 CHECK_STATUS(status
, NT_STATUS_OK
);
274 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
, SEC_RIGHTS_FILE_READ
);
275 smb2_util_close(tree
, io
.out
.file
.handle
);
278 torture_comment(tctx
, "put back original sd\n");
279 set
.set_secdesc
.in
.sd
= sd_orig
;
280 status
= smb2_setinfo_file(tree
, &set
);
281 CHECK_STATUS(status
, NT_STATUS_OK
);
285 smb2_util_close(tree
, handle
);
286 smb2_deltree(tree
, BASEDIR
);
288 smb2_logoff(tree
->session
);
294 test the mapping of the SEC_GENERIC_xx bits to SEC_STD_xx and
296 Note: This test was copied from raw/acls.c.
298 static bool test_generic_bits(struct torture_context
*tctx
, struct smb2_tree
*tree
)
301 struct smb2_create io
;
302 const char *fname
= BASEDIR
"\\generic.txt";
304 struct smb2_handle handle
= {{0}};
306 union smb_fileinfo q
;
307 union smb_setfileinfo set
;
308 struct security_descriptor
*sd
, *sd_orig
, *sd2
;
309 const char *owner_sid
;
312 uint32_t specific_bits
;
313 } file_mappings
[] = {
315 { SEC_GENERIC_READ
, SEC_RIGHTS_FILE_READ
},
316 { SEC_GENERIC_WRITE
, SEC_RIGHTS_FILE_WRITE
},
317 { SEC_GENERIC_EXECUTE
, SEC_RIGHTS_FILE_EXECUTE
},
318 { SEC_GENERIC_ALL
, SEC_RIGHTS_FILE_ALL
},
319 { SEC_FILE_READ_DATA
, SEC_FILE_READ_DATA
},
320 { SEC_FILE_READ_ATTRIBUTE
, SEC_FILE_READ_ATTRIBUTE
}
324 uint32_t specific_bits
;
327 { SEC_GENERIC_READ
, SEC_RIGHTS_DIR_READ
},
328 { SEC_GENERIC_WRITE
, SEC_RIGHTS_DIR_WRITE
},
329 { SEC_GENERIC_EXECUTE
, SEC_RIGHTS_DIR_EXECUTE
},
330 { SEC_GENERIC_ALL
, SEC_RIGHTS_DIR_ALL
}
332 bool has_restore_privilege
= false;
333 bool has_take_ownership_privilege
= false;
335 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
338 torture_comment(tctx
, "TESTING FILE GENERIC BITS\n");
341 io
.level
= RAW_OPEN_SMB2
;
342 io
.in
.create_flags
= 0;
343 io
.in
.desired_access
=
344 SEC_STD_READ_CONTROL
|
347 io
.in
.create_options
= 0;
348 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
350 NTCREATEX_SHARE_ACCESS_READ
|
351 NTCREATEX_SHARE_ACCESS_WRITE
;
352 io
.in
.alloc_size
= 0;
353 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
354 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
355 io
.in
.security_flags
= 0;
357 status
= smb2_create(tree
, tctx
, &io
);
358 CHECK_STATUS(status
, NT_STATUS_OK
);
359 handle
= io
.out
.file
.handle
;
361 torture_comment(tctx
, "get the original sd\n");
362 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
363 q
.query_secdesc
.in
.file
.handle
= handle
;
364 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
365 status
= smb2_getinfo_file(tree
, tctx
, &q
);
366 CHECK_STATUS(status
, NT_STATUS_OK
);
367 sd_orig
= q
.query_secdesc
.out
.sd
;
369 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
372 * XXX: The smblsa calls use SMB as their transport - need to get rid of
376 status = smblsa_sid_check_privilege(cli,
378 sec_privilege_name(SEC_PRIV_RESTORE));
379 has_restore_privilege = NT_STATUS_IS_OK(status);
380 if (!NT_STATUS_IS_OK(status)) {
381 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
383 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
385 status = smblsa_sid_check_privilege(cli,
387 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
388 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
389 if (!NT_STATUS_IS_OK(status)) {
390 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
392 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
395 for (i
=0;i
<ARRAY_SIZE(file_mappings
);i
++) {
396 uint32_t expected_mask
=
398 SEC_STD_READ_CONTROL
|
399 SEC_FILE_READ_ATTRIBUTE
|
401 uint32_t expected_mask_anon
= SEC_FILE_READ_ATTRIBUTE
;
403 if (has_restore_privilege
) {
404 expected_mask_anon
|= SEC_STD_DELETE
;
407 torture_comment(tctx
, "Testing generic bits 0x%08x\n",
408 file_mappings
[i
].gen_bits
);
409 sd
= security_descriptor_dacl_create(tctx
,
412 SEC_ACE_TYPE_ACCESS_ALLOWED
,
413 file_mappings
[i
].gen_bits
,
417 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
418 set
.set_secdesc
.in
.file
.handle
= handle
;
419 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
420 set
.set_secdesc
.in
.sd
= sd
;
422 status
= smb2_setinfo_file(tree
, &set
);
423 CHECK_STATUS(status
, NT_STATUS_OK
);
425 sd2
= security_descriptor_dacl_create(tctx
,
428 SEC_ACE_TYPE_ACCESS_ALLOWED
,
429 file_mappings
[i
].specific_bits
,
433 status
= smb2_getinfo_file(tree
, tctx
, &q
);
434 CHECK_STATUS(status
, NT_STATUS_OK
);
435 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
437 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
438 status
= smb2_create(tree
, tctx
, &io
);
439 CHECK_STATUS(status
, NT_STATUS_OK
);
440 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
441 expected_mask
| file_mappings
[i
].specific_bits
);
442 smb2_util_close(tree
, io
.out
.file
.handle
);
444 if (!has_take_ownership_privilege
) {
448 torture_comment(tctx
, "Testing generic bits 0x%08x (anonymous)\n",
449 file_mappings
[i
].gen_bits
);
450 sd
= security_descriptor_dacl_create(tctx
,
451 0, SID_NT_ANONYMOUS
, NULL
,
453 SEC_ACE_TYPE_ACCESS_ALLOWED
,
454 file_mappings
[i
].gen_bits
,
458 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
459 set
.set_secdesc
.in
.file
.handle
= handle
;
460 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
461 set
.set_secdesc
.in
.sd
= sd
;
463 status
= smb2_setinfo_file(tree
, &set
);
464 CHECK_STATUS(status
, NT_STATUS_OK
);
466 sd2
= security_descriptor_dacl_create(tctx
,
467 0, SID_NT_ANONYMOUS
, NULL
,
469 SEC_ACE_TYPE_ACCESS_ALLOWED
,
470 file_mappings
[i
].specific_bits
,
474 status
= smb2_getinfo_file(tree
, tctx
, &q
);
475 CHECK_STATUS(status
, NT_STATUS_OK
);
476 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
478 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
479 status
= smb2_create(tree
, tctx
, &io
);
480 CHECK_STATUS(status
, NT_STATUS_OK
);
481 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
482 expected_mask_anon
| file_mappings
[i
].specific_bits
);
483 smb2_util_close(tree
, io
.out
.file
.handle
);
486 torture_comment(tctx
, "put back original sd\n");
487 set
.set_secdesc
.in
.sd
= sd_orig
;
488 status
= smb2_setinfo_file(tree
, &set
);
489 CHECK_STATUS(status
, NT_STATUS_OK
);
491 smb2_util_close(tree
, handle
);
492 smb2_util_unlink(tree
, fname
);
495 torture_comment(tctx
, "TESTING DIR GENERIC BITS\n");
498 io
.level
= RAW_OPEN_SMB2
;
499 io
.in
.create_flags
= 0;
500 io
.in
.desired_access
=
501 SEC_STD_READ_CONTROL
|
504 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
505 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
507 NTCREATEX_SHARE_ACCESS_READ
|
508 NTCREATEX_SHARE_ACCESS_WRITE
;
509 io
.in
.alloc_size
= 0;
510 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
511 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
512 io
.in
.security_flags
= 0;
514 status
= smb2_create(tree
, tctx
, &io
);
515 CHECK_STATUS(status
, NT_STATUS_OK
);
516 handle
= io
.out
.file
.handle
;
518 torture_comment(tctx
, "get the original sd\n");
519 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
520 q
.query_secdesc
.in
.file
.handle
= handle
;
521 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
522 status
= smb2_getinfo_file(tree
, tctx
, &q
);
523 CHECK_STATUS(status
, NT_STATUS_OK
);
524 sd_orig
= q
.query_secdesc
.out
.sd
;
526 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
529 * XXX: The smblsa calls use SMB as their transport - need to get rid of
533 status = smblsa_sid_check_privilege(cli,
535 sec_privilege_name(SEC_PRIV_RESTORE));
536 has_restore_privilege = NT_STATUS_IS_OK(status);
537 if (!NT_STATUS_IS_OK(status)) {
538 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
540 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
542 status = smblsa_sid_check_privilege(cli,
544 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
545 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
546 if (!NT_STATUS_IS_OK(status)) {
547 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
549 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
552 for (i
=0;i
<ARRAY_SIZE(dir_mappings
);i
++) {
553 uint32_t expected_mask
=
555 SEC_STD_READ_CONTROL
|
556 SEC_FILE_READ_ATTRIBUTE
|
558 uint32_t expected_mask_anon
= SEC_FILE_READ_ATTRIBUTE
;
560 if (has_restore_privilege
) {
561 expected_mask_anon
|= SEC_STD_DELETE
;
564 torture_comment(tctx
, "Testing generic bits 0x%08x\n",
565 file_mappings
[i
].gen_bits
);
566 sd
= security_descriptor_dacl_create(tctx
,
569 SEC_ACE_TYPE_ACCESS_ALLOWED
,
570 dir_mappings
[i
].gen_bits
,
574 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
575 set
.set_secdesc
.in
.file
.handle
= handle
;
576 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
577 set
.set_secdesc
.in
.sd
= sd
;
579 status
= smb2_setinfo_file(tree
, &set
);
580 CHECK_STATUS(status
, NT_STATUS_OK
);
582 sd2
= security_descriptor_dacl_create(tctx
,
585 SEC_ACE_TYPE_ACCESS_ALLOWED
,
586 dir_mappings
[i
].specific_bits
,
590 status
= smb2_getinfo_file(tree
, tctx
, &q
);
591 CHECK_STATUS(status
, NT_STATUS_OK
);
592 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
594 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
595 status
= smb2_create(tree
, tctx
, &io
);
596 CHECK_STATUS(status
, NT_STATUS_OK
);
597 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
598 expected_mask
| dir_mappings
[i
].specific_bits
);
599 smb2_util_close(tree
, io
.out
.file
.handle
);
601 if (!has_take_ownership_privilege
) {
605 torture_comment(tctx
, "Testing generic bits 0x%08x (anonymous)\n",
606 file_mappings
[i
].gen_bits
);
607 sd
= security_descriptor_dacl_create(tctx
,
608 0, SID_NT_ANONYMOUS
, NULL
,
610 SEC_ACE_TYPE_ACCESS_ALLOWED
,
611 file_mappings
[i
].gen_bits
,
615 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
616 set
.set_secdesc
.in
.file
.handle
= handle
;
617 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
618 set
.set_secdesc
.in
.sd
= sd
;
620 status
= smb2_setinfo_file(tree
, &set
);
621 CHECK_STATUS(status
, NT_STATUS_OK
);
623 sd2
= security_descriptor_dacl_create(tctx
,
624 0, SID_NT_ANONYMOUS
, NULL
,
626 SEC_ACE_TYPE_ACCESS_ALLOWED
,
627 file_mappings
[i
].specific_bits
,
631 status
= smb2_getinfo_file(tree
, tctx
, &q
);
632 CHECK_STATUS(status
, NT_STATUS_OK
);
633 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
635 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
636 status
= smb2_create(tree
, tctx
, &io
);
637 CHECK_STATUS(status
, NT_STATUS_OK
);
638 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
639 expected_mask_anon
| dir_mappings
[i
].specific_bits
);
640 smb2_util_close(tree
, io
.out
.file
.handle
);
643 torture_comment(tctx
, "put back original sd\n");
644 set
.set_secdesc
.in
.sd
= sd_orig
;
645 status
= smb2_setinfo_file(tree
, &set
);
646 CHECK_STATUS(status
, NT_STATUS_OK
);
648 smb2_util_close(tree
, handle
);
649 smb2_util_unlink(tree
, fname
);
652 smb2_util_close(tree
, handle
);
653 smb2_deltree(tree
, BASEDIR
);
655 smb2_logoff(tree
->session
);
661 see what access bits the owner of a file always gets
662 Note: This test was copied from raw/acls.c.
664 static bool test_owner_bits(struct torture_context
*tctx
, struct smb2_tree
*tree
)
667 struct smb2_create io
;
668 const char *fname
= BASEDIR
"\\test_owner_bits.txt";
670 struct smb2_handle handle
= {{0}};
672 union smb_fileinfo q
;
673 union smb_setfileinfo set
;
674 struct security_descriptor
*sd
, *sd_orig
;
675 const char *owner_sid
;
676 uint32_t expected_bits
;
678 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
681 torture_comment(tctx
, "TESTING FILE OWNER BITS\n");
684 io
.level
= RAW_OPEN_SMB2
;
685 io
.in
.create_flags
= 0;
686 io
.in
.desired_access
=
687 SEC_STD_READ_CONTROL
|
690 io
.in
.create_options
= 0;
691 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
693 NTCREATEX_SHARE_ACCESS_READ
|
694 NTCREATEX_SHARE_ACCESS_WRITE
;
695 io
.in
.alloc_size
= 0;
696 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
697 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
698 io
.in
.security_flags
= 0;
700 status
= smb2_create(tree
, tctx
, &io
);
701 CHECK_STATUS(status
, NT_STATUS_OK
);
702 handle
= io
.out
.file
.handle
;
704 torture_comment(tctx
, "get the original sd\n");
705 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
706 q
.query_secdesc
.in
.file
.handle
= handle
;
707 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
708 status
= smb2_getinfo_file(tree
, tctx
, &q
);
709 CHECK_STATUS(status
, NT_STATUS_OK
);
710 sd_orig
= q
.query_secdesc
.out
.sd
;
712 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
715 * XXX: The smblsa calls use SMB as their transport - need to get rid of
719 status = smblsa_sid_check_privilege(cli,
721 sec_privilege_name(SEC_PRIV_RESTORE));
722 has_restore_privilege = NT_STATUS_IS_OK(status);
723 if (!NT_STATUS_IS_OK(status)) {
724 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
726 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
728 status = smblsa_sid_check_privilege(cli,
730 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
731 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
732 if (!NT_STATUS_IS_OK(status)) {
733 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
735 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
738 sd
= security_descriptor_dacl_create(tctx
,
741 SEC_ACE_TYPE_ACCESS_ALLOWED
,
746 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
747 set
.set_secdesc
.in
.file
.handle
= handle
;
748 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
749 set
.set_secdesc
.in
.sd
= sd
;
751 status
= smb2_setinfo_file(tree
, &set
);
752 CHECK_STATUS(status
, NT_STATUS_OK
);
754 expected_bits
= SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
;
757 uint32_t bit
= (1<<i
);
758 io
.in
.desired_access
= bit
;
759 status
= smb2_create(tree
, tctx
, &io
);
760 if (expected_bits
& bit
) {
761 if (!NT_STATUS_IS_OK(status
)) {
762 torture_warning(tctx
, "failed with access mask 0x%08x of expected 0x%08x\n",
765 CHECK_STATUS(status
, NT_STATUS_OK
);
766 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
, bit
);
767 smb2_util_close(tree
, io
.out
.file
.handle
);
769 if (NT_STATUS_IS_OK(status
)) {
770 torture_warning(tctx
, "open succeeded with access mask 0x%08x of "
771 "expected 0x%08x - should fail\n",
774 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
778 torture_comment(tctx
, "put back original sd\n");
779 set
.set_secdesc
.in
.sd
= sd_orig
;
780 status
= smb2_setinfo_file(tree
, &set
);
781 CHECK_STATUS(status
, NT_STATUS_OK
);
784 smb2_util_close(tree
, handle
);
785 smb2_util_unlink(tree
, fname
);
786 smb2_deltree(tree
, BASEDIR
);
788 smb2_logoff(tree
->session
);
795 test the inheritance of ACL flags onto new files and directories
796 Note: This test was copied from raw/acls.c.
798 static bool test_inheritance(struct torture_context
*tctx
, struct smb2_tree
*tree
)
801 struct smb2_create io
;
802 const char *dname
= BASEDIR
"\\inheritance";
803 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
804 const char *fname2
= BASEDIR
"\\inheritance\\testdir";
806 struct smb2_handle handle
= {{0}};
807 struct smb2_handle handle2
= {{0}};
809 union smb_fileinfo q
;
810 union smb_setfileinfo set
;
811 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
, *sd_def1
, *sd_def2
;
812 const char *owner_sid
;
813 const struct dom_sid
*creator_owner
;
815 uint32_t parent_flags
;
825 SEC_ACE_FLAG_OBJECT_INHERIT
,
827 SEC_ACE_FLAG_OBJECT_INHERIT
|
828 SEC_ACE_FLAG_INHERIT_ONLY
,
831 SEC_ACE_FLAG_CONTAINER_INHERIT
,
833 SEC_ACE_FLAG_CONTAINER_INHERIT
,
836 SEC_ACE_FLAG_OBJECT_INHERIT
|
837 SEC_ACE_FLAG_CONTAINER_INHERIT
,
839 SEC_ACE_FLAG_OBJECT_INHERIT
|
840 SEC_ACE_FLAG_CONTAINER_INHERIT
,
843 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
848 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
849 SEC_ACE_FLAG_OBJECT_INHERIT
,
854 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
855 SEC_ACE_FLAG_CONTAINER_INHERIT
,
860 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
861 SEC_ACE_FLAG_CONTAINER_INHERIT
|
862 SEC_ACE_FLAG_OBJECT_INHERIT
,
867 SEC_ACE_FLAG_INHERIT_ONLY
,
872 SEC_ACE_FLAG_INHERIT_ONLY
|
873 SEC_ACE_FLAG_OBJECT_INHERIT
,
875 SEC_ACE_FLAG_OBJECT_INHERIT
|
876 SEC_ACE_FLAG_INHERIT_ONLY
,
879 SEC_ACE_FLAG_INHERIT_ONLY
|
880 SEC_ACE_FLAG_CONTAINER_INHERIT
,
882 SEC_ACE_FLAG_CONTAINER_INHERIT
,
885 SEC_ACE_FLAG_INHERIT_ONLY
|
886 SEC_ACE_FLAG_CONTAINER_INHERIT
|
887 SEC_ACE_FLAG_OBJECT_INHERIT
,
889 SEC_ACE_FLAG_CONTAINER_INHERIT
|
890 SEC_ACE_FLAG_OBJECT_INHERIT
,
893 SEC_ACE_FLAG_INHERIT_ONLY
|
894 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
899 SEC_ACE_FLAG_INHERIT_ONLY
|
900 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
901 SEC_ACE_FLAG_OBJECT_INHERIT
,
906 SEC_ACE_FLAG_INHERIT_ONLY
|
907 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
908 SEC_ACE_FLAG_CONTAINER_INHERIT
,
913 SEC_ACE_FLAG_INHERIT_ONLY
|
914 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
915 SEC_ACE_FLAG_CONTAINER_INHERIT
|
916 SEC_ACE_FLAG_OBJECT_INHERIT
,
922 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
925 torture_comment(tctx
, "TESTING ACL INHERITANCE\n");
928 io
.level
= RAW_OPEN_SMB2
;
929 io
.in
.create_flags
= 0;
930 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
931 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
932 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
933 io
.in
.share_access
= 0;
934 io
.in
.alloc_size
= 0;
935 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
936 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
937 io
.in
.security_flags
= 0;
940 status
= smb2_create(tree
, tctx
, &io
);
941 CHECK_STATUS(status
, NT_STATUS_OK
);
942 handle
= io
.out
.file
.handle
;
944 torture_comment(tctx
, "get the original sd\n");
945 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
946 q
.query_secdesc
.in
.file
.handle
= handle
;
947 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
948 status
= smb2_getinfo_file(tree
, tctx
, &q
);
949 CHECK_STATUS(status
, NT_STATUS_OK
);
950 sd_orig
= q
.query_secdesc
.out
.sd
;
952 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
954 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
957 * The Windows Default ACL for a new file, when there is no ACL to be
958 * inherited: FullControl for the owner and SYSTEM.
960 sd_def1
= security_descriptor_dacl_create(tctx
,
963 SEC_ACE_TYPE_ACCESS_ALLOWED
,
967 SEC_ACE_TYPE_ACCESS_ALLOWED
,
973 * Use this in the case the system being tested does not add an ACE for
976 sd_def2
= security_descriptor_dacl_create(tctx
,
979 SEC_ACE_TYPE_ACCESS_ALLOWED
,
984 creator_owner
= dom_sid_parse_talloc(tctx
, SID_CREATOR_OWNER
);
986 for (i
=0;i
<ARRAY_SIZE(test_flags
);i
++) {
987 sd
= security_descriptor_dacl_create(tctx
,
990 SEC_ACE_TYPE_ACCESS_ALLOWED
,
992 test_flags
[i
].parent_flags
,
994 SEC_ACE_TYPE_ACCESS_ALLOWED
,
995 SEC_FILE_ALL
| SEC_STD_ALL
,
998 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
999 set
.set_secdesc
.in
.file
.handle
= handle
;
1000 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1001 set
.set_secdesc
.in
.sd
= sd
;
1002 status
= smb2_setinfo_file(tree
, &set
);
1003 CHECK_STATUS(status
, NT_STATUS_OK
);
1005 io
.in
.fname
= fname1
;
1006 io
.in
.create_options
= 0;
1007 status
= smb2_create(tree
, tctx
, &io
);
1008 CHECK_STATUS(status
, NT_STATUS_OK
);
1009 handle2
= io
.out
.file
.handle
;
1011 q
.query_secdesc
.in
.file
.handle
= handle2
;
1012 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1013 CHECK_STATUS(status
, NT_STATUS_OK
);
1015 smb2_util_close(tree
, handle2
);
1016 smb2_util_unlink(tree
, fname1
);
1018 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
)) {
1019 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def1
) &&
1020 !security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def2
)) {
1021 torture_warning(tctx
, "Expected default sd:\n");
1022 NDR_PRINT_DEBUG(security_descriptor
, sd_def1
);
1023 torture_warning(tctx
, "at %d - got:\n", i
);
1024 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1029 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1030 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1031 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1032 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1033 sd_orig
->owner_sid
)) {
1034 torture_warning(tctx
, "Bad sd in child file at %d\n", i
);
1035 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1040 if (q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!=
1041 test_flags
[i
].file_flags
) {
1042 torture_warning(tctx
, "incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1043 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
,
1044 test_flags
[i
].file_flags
,
1045 test_flags
[i
].parent_flags
,
1051 io
.in
.fname
= fname2
;
1052 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1053 status
= smb2_create(tree
, tctx
, &io
);
1054 CHECK_STATUS(status
, NT_STATUS_OK
);
1055 handle2
= io
.out
.file
.handle
;
1057 q
.query_secdesc
.in
.file
.handle
= handle2
;
1058 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1059 CHECK_STATUS(status
, NT_STATUS_OK
);
1061 smb2_util_close(tree
, handle2
);
1062 smb2_util_rmdir(tree
, fname2
);
1064 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1065 (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
) ||
1066 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
))) {
1067 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def1
) &&
1068 !security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def2
)) {
1069 torture_warning(tctx
, "Expected default sd for dir at %d:\n", i
);
1070 NDR_PRINT_DEBUG(security_descriptor
, sd_def1
);
1071 torture_warning(tctx
, "got:\n");
1072 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1077 if ((test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1078 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
)) {
1079 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1080 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1081 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1082 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1083 sd_orig
->owner_sid
) ||
1084 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1085 torture_warning(tctx
, "(CI & NP) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1086 test_flags
[i
].dir_flags
,
1087 test_flags
[i
].parent_flags
, i
);
1088 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1089 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1090 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1094 } else if (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) {
1095 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1096 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 2 ||
1097 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1098 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1099 sd_orig
->owner_sid
) ||
1100 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].access_mask
!= SEC_FILE_WRITE_DATA
||
1101 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[1].trustee
,
1103 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= 0 ||
1104 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].flags
!=
1105 (test_flags
[i
].dir_flags
| SEC_ACE_FLAG_INHERIT_ONLY
)) {
1106 torture_warning(tctx
, "(CI) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1107 test_flags
[i
].dir_flags
,
1108 test_flags
[i
].parent_flags
, i
);
1109 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1110 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1111 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1116 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1117 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1118 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1119 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1121 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1122 torture_warning(tctx
, "(0) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1123 test_flags
[i
].dir_flags
,
1124 test_flags
[i
].parent_flags
, i
);
1125 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1126 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1127 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1134 torture_comment(tctx
, "Testing access checks on inherited create with %s\n", fname1
);
1135 sd
= security_descriptor_dacl_create(tctx
,
1138 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1139 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1140 SEC_ACE_FLAG_OBJECT_INHERIT
,
1142 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1143 SEC_FILE_ALL
| SEC_STD_ALL
,
1146 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1147 set
.set_secdesc
.in
.file
.handle
= handle
;
1148 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1149 set
.set_secdesc
.in
.sd
= sd
;
1150 status
= smb2_setinfo_file(tree
, &set
);
1151 CHECK_STATUS(status
, NT_STATUS_OK
);
1153 /* Check DACL we just set. */
1154 torture_comment(tctx
, "checking new sd\n");
1155 q
.query_secdesc
.in
.file
.handle
= handle
;
1156 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1157 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1158 CHECK_STATUS(status
, NT_STATUS_OK
);
1159 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1161 io
.in
.fname
= fname1
;
1162 io
.in
.create_options
= 0;
1163 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1164 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1165 status
= smb2_create(tree
, tctx
, &io
);
1166 CHECK_STATUS(status
, NT_STATUS_OK
);
1167 handle2
= io
.out
.file
.handle
;
1168 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1170 q
.query_secdesc
.in
.file
.handle
= handle2
;
1171 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1172 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1173 CHECK_STATUS(status
, NT_STATUS_OK
);
1174 smb2_util_close(tree
, handle2
);
1176 sd2
= security_descriptor_dacl_create(tctx
,
1179 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1180 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1183 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1185 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1186 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1187 status
= smb2_create(tree
, tctx
, &io
);
1188 if (NT_STATUS_IS_OK(status
)) {
1189 torture_warning(tctx
, "failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1191 handle2
= io
.out
.file
.handle
;
1192 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1193 smb2_util_close(tree
, handle2
);
1195 if (torture_setting_bool(tctx
, "hide_on_access_denied",
1197 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1199 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1203 torture_comment(tctx
, "trying without execute\n");
1204 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1205 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
& ~SEC_FILE_EXECUTE
;
1206 status
= smb2_create(tree
, tctx
, &io
);
1207 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1208 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1210 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1213 torture_comment(tctx
, "and with full permissions again\n");
1214 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1215 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1216 status
= smb2_create(tree
, tctx
, &io
);
1217 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1218 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1220 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1223 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1224 status
= smb2_create(tree
, tctx
, &io
);
1225 CHECK_STATUS(status
, NT_STATUS_OK
);
1226 handle2
= io
.out
.file
.handle
;
1227 CHECK_ACCESS_FLAGS(handle2
, SEC_FILE_WRITE_DATA
);
1228 smb2_util_close(tree
, handle2
);
1230 torture_comment(tctx
, "put back original sd\n");
1231 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1232 set
.set_secdesc
.in
.file
.handle
= handle
;
1233 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1234 set
.set_secdesc
.in
.sd
= sd_orig
;
1235 status
= smb2_setinfo_file(tree
, &set
);
1236 CHECK_STATUS(status
, NT_STATUS_OK
);
1238 smb2_util_close(tree
, handle
);
1240 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1241 status
= smb2_create(tree
, tctx
, &io
);
1242 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1243 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1245 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1248 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1249 status
= smb2_create(tree
, tctx
, &io
);
1250 CHECK_STATUS(status
, NT_STATUS_OK
);
1251 handle2
= io
.out
.file
.handle
;
1252 CHECK_ACCESS_FLAGS(handle2
, SEC_FILE_WRITE_DATA
);
1253 smb2_util_close(tree
, handle2
);
1255 smb2_util_unlink(tree
, fname1
);
1256 smb2_util_rmdir(tree
, dname
);
1259 if (sd_orig
!= NULL
) {
1260 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1261 set
.set_secdesc
.in
.file
.handle
= handle
;
1262 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1263 set
.set_secdesc
.in
.sd
= sd_orig
;
1264 status
= smb2_setinfo_file(tree
, &set
);
1267 smb2_util_close(tree
, handle
);
1268 smb2_deltree(tree
, BASEDIR
);
1270 smb2_logoff(tree
->session
);
1274 static bool test_inheritance_flags(struct torture_context
*tctx
,
1275 struct smb2_tree
*tree
)
1278 struct smb2_create io
;
1279 const char *dname
= BASEDIR
"\\inheritance";
1280 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1282 struct smb2_handle handle
= {{0}};
1283 struct smb2_handle handle2
= {{0}};
1285 union smb_fileinfo q
;
1286 union smb_setfileinfo set
;
1287 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
;
1288 const char *owner_sid
;
1290 uint32_t parent_set_sd_type
; /* 3 options */
1291 uint32_t parent_set_ace_inherit
; /* 1 option */
1292 uint32_t parent_get_sd_type
;
1293 uint32_t parent_get_ace_inherit
;
1294 uint32_t child_get_sd_type
;
1295 uint32_t child_get_ace_inherit
;
1296 } tflags
[16] = {{0}}; /* 2^4 */
1298 for (i
= 0; i
< 15; i
++) {
1299 torture_comment(tctx
, "i=%d:", i
);
1302 tflags
[i
].parent_set_sd_type
|=
1303 SEC_DESC_DACL_AUTO_INHERITED
;
1304 torture_comment(tctx
, "AUTO_INHERITED, ");
1307 tflags
[i
].parent_set_sd_type
|=
1308 SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1309 torture_comment(tctx
, "AUTO_INHERIT_REQ, ");
1312 tflags
[i
].parent_set_sd_type
|=
1313 SEC_DESC_DACL_PROTECTED
;
1314 torture_comment(tctx
, "PROTECTED, ");
1315 tflags
[i
].parent_get_sd_type
|=
1316 SEC_DESC_DACL_PROTECTED
;
1319 tflags
[i
].parent_set_ace_inherit
|=
1320 SEC_ACE_FLAG_INHERITED_ACE
;
1321 torture_comment(tctx
, "INHERITED, ");
1322 tflags
[i
].parent_get_ace_inherit
|=
1323 SEC_ACE_FLAG_INHERITED_ACE
;
1326 if ((tflags
[i
].parent_set_sd_type
&
1327 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) ==
1328 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) {
1329 tflags
[i
].parent_get_sd_type
|=
1330 SEC_DESC_DACL_AUTO_INHERITED
;
1331 tflags
[i
].child_get_sd_type
|=
1332 SEC_DESC_DACL_AUTO_INHERITED
;
1333 tflags
[i
].child_get_ace_inherit
|=
1334 SEC_ACE_FLAG_INHERITED_ACE
;
1335 torture_comment(tctx
, " ... parent is AUTO INHERITED");
1338 if (tflags
[i
].parent_set_ace_inherit
&
1339 SEC_ACE_FLAG_INHERITED_ACE
) {
1340 tflags
[i
].parent_get_ace_inherit
=
1341 SEC_ACE_FLAG_INHERITED_ACE
;
1342 torture_comment(tctx
, " ... parent ACE is INHERITED");
1345 torture_comment(tctx
, "\n");
1348 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1351 torture_comment(tctx
, "TESTING ACL INHERITANCE FLAGS\n");
1354 io
.level
= RAW_OPEN_SMB2
;
1355 io
.in
.create_flags
= 0;
1356 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1357 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1358 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1359 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
;
1360 io
.in
.alloc_size
= 0;
1361 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1362 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1363 io
.in
.security_flags
= 0;
1364 io
.in
.fname
= dname
;
1366 torture_comment(tctx
, "creating initial directory %s\n", dname
);
1367 status
= smb2_create(tree
, tctx
, &io
);
1368 CHECK_STATUS(status
, NT_STATUS_OK
);
1369 handle
= io
.out
.file
.handle
;
1371 torture_comment(tctx
, "getting original sd\n");
1372 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1373 q
.query_secdesc
.in
.file
.handle
= handle
;
1374 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1375 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1376 CHECK_STATUS(status
, NT_STATUS_OK
);
1377 sd_orig
= q
.query_secdesc
.out
.sd
;
1379 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1380 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1382 for (i
=0; i
< ARRAY_SIZE(tflags
); i
++) {
1383 torture_comment(tctx
, "setting a new sd on directory, pass #%d\n", i
);
1385 sd
= security_descriptor_dacl_create(tctx
,
1386 tflags
[i
].parent_set_sd_type
,
1389 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1390 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1391 SEC_ACE_FLAG_OBJECT_INHERIT
|
1392 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1393 tflags
[i
].parent_set_ace_inherit
,
1395 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1396 SEC_FILE_ALL
| SEC_STD_ALL
,
1399 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1400 set
.set_secdesc
.in
.file
.handle
= handle
;
1401 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1402 set
.set_secdesc
.in
.sd
= sd
;
1403 status
= smb2_setinfo_file(tree
, &set
);
1404 CHECK_STATUS(status
, NT_STATUS_OK
);
1407 * Check DACL we just set, except change the bits to what they
1410 torture_comment(tctx
, " checking new sd\n");
1412 /* REQ bit should always be false. */
1413 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1415 if ((tflags
[i
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1416 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1418 q
.query_secdesc
.in
.file
.handle
= handle
;
1419 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1420 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1421 CHECK_STATUS(status
, NT_STATUS_OK
);
1422 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1425 torture_comment(tctx
, " creating file %s\n", fname1
);
1426 io
.in
.fname
= fname1
;
1427 io
.in
.create_options
= 0;
1428 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1429 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1430 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1431 status
= smb2_create(tree
, tctx
, &io
);
1432 CHECK_STATUS(status
, NT_STATUS_OK
);
1433 handle2
= io
.out
.file
.handle
;
1434 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1436 q
.query_secdesc
.in
.file
.handle
= handle2
;
1437 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1438 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1439 CHECK_STATUS(status
, NT_STATUS_OK
);
1441 torture_comment(tctx
, " checking sd on file %s\n", fname1
);
1442 sd2
= security_descriptor_dacl_create(tctx
,
1443 tflags
[i
].child_get_sd_type
,
1446 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1447 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1448 tflags
[i
].child_get_ace_inherit
,
1450 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1453 * Set new sd on file ... prove that the bits have nothing to
1454 * do with the parents bits when manually setting an ACL. The
1455 * _AUTO_INHERITED bit comes directly from the ACL set.
1457 for (j
= 0; j
< ARRAY_SIZE(tflags
); j
++) {
1458 torture_comment(tctx
, " setting new file sd, pass #%d\n", j
);
1460 /* Change sd type. */
1461 sd2
->type
&= ~(SEC_DESC_DACL_AUTO_INHERITED
|
1462 SEC_DESC_DACL_AUTO_INHERIT_REQ
|
1463 SEC_DESC_DACL_PROTECTED
);
1464 sd2
->type
|= tflags
[j
].parent_set_sd_type
;
1466 sd2
->dacl
->aces
[0].flags
&=
1467 ~SEC_ACE_FLAG_INHERITED_ACE
;
1468 sd2
->dacl
->aces
[0].flags
|=
1469 tflags
[j
].parent_set_ace_inherit
;
1471 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1472 set
.set_secdesc
.in
.file
.handle
= handle2
;
1473 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1474 set
.set_secdesc
.in
.sd
= sd2
;
1475 status
= smb2_setinfo_file(tree
, &set
);
1476 CHECK_STATUS(status
, NT_STATUS_OK
);
1478 /* Check DACL we just set. */
1479 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1480 if ((tflags
[j
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1481 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1483 q
.query_secdesc
.in
.file
.handle
= handle2
;
1484 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1485 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1486 CHECK_STATUS(status
, NT_STATUS_OK
);
1488 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1491 smb2_util_close(tree
, handle2
);
1492 smb2_util_unlink(tree
, fname1
);
1496 smb2_util_close(tree
, handle
);
1497 smb2_deltree(tree
, BASEDIR
);
1499 smb2_logoff(tree
->session
);
1504 test dynamic acl inheritance
1505 Note: This test was copied from raw/acls.c.
1507 static bool test_inheritance_dynamic(struct torture_context
*tctx
,
1508 struct smb2_tree
*tree
)
1511 struct smb2_create io
;
1512 const char *dname
= BASEDIR
"\\inheritance";
1513 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1515 struct smb2_handle handle
= {{0}};
1516 struct smb2_handle handle2
= {{0}};
1517 union smb_fileinfo q
;
1518 union smb_setfileinfo set
;
1519 struct security_descriptor
*sd
, *sd_orig
=NULL
;
1520 const char *owner_sid
;
1522 torture_comment(tctx
, "TESTING DYNAMIC ACL INHERITANCE\n");
1524 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1528 io
.level
= RAW_OPEN_SMB2
;
1529 io
.in
.create_flags
= 0;
1530 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1531 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1532 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1533 io
.in
.share_access
= 0;
1534 io
.in
.alloc_size
= 0;
1535 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1536 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1537 io
.in
.security_flags
= 0;
1538 io
.in
.fname
= dname
;
1540 status
= smb2_create(tree
, tctx
, &io
);
1541 CHECK_STATUS(status
, NT_STATUS_OK
);
1542 handle
= io
.out
.file
.handle
;
1544 torture_comment(tctx
, "get the original sd\n");
1545 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1546 q
.query_secdesc
.in
.file
.handle
= handle
;
1547 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1548 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1549 CHECK_STATUS(status
, NT_STATUS_OK
);
1550 sd_orig
= q
.query_secdesc
.out
.sd
;
1552 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1554 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1556 sd
= security_descriptor_dacl_create(tctx
,
1559 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1560 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
,
1561 SEC_ACE_FLAG_OBJECT_INHERIT
,
1563 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1565 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1566 set
.set_secdesc
.in
.file
.handle
= handle
;
1567 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1568 set
.set_secdesc
.in
.sd
= sd
;
1569 status
= smb2_setinfo_file(tree
, &set
);
1570 CHECK_STATUS(status
, NT_STATUS_OK
);
1572 torture_comment(tctx
, "create a file with an inherited acl\n");
1573 io
.in
.fname
= fname1
;
1574 io
.in
.create_options
= 0;
1575 io
.in
.desired_access
= SEC_FILE_READ_ATTRIBUTE
;
1576 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1577 status
= smb2_create(tree
, tctx
, &io
);
1578 CHECK_STATUS(status
, NT_STATUS_OK
);
1579 handle2
= io
.out
.file
.handle
;
1580 smb2_util_close(tree
, handle2
);
1582 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
1583 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1584 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1585 status
= smb2_create(tree
, tctx
, &io
);
1586 CHECK_STATUS(status
, NT_STATUS_OK
);
1587 handle2
= io
.out
.file
.handle
;
1588 smb2_util_close(tree
, handle2
);
1590 torture_comment(tctx
, "try and access file with extra rights - should be denied\n");
1591 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1592 status
= smb2_create(tree
, tctx
, &io
);
1593 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1595 torture_comment(tctx
, "update parent sd\n");
1596 sd
= security_descriptor_dacl_create(tctx
,
1599 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1600 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
,
1601 SEC_ACE_FLAG_OBJECT_INHERIT
,
1603 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1605 set
.set_secdesc
.in
.sd
= sd
;
1606 status
= smb2_setinfo_file(tree
, &set
);
1607 CHECK_STATUS(status
, NT_STATUS_OK
);
1609 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
1610 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1611 status
= smb2_create(tree
, tctx
, &io
);
1612 CHECK_STATUS(status
, NT_STATUS_OK
);
1613 handle2
= io
.out
.file
.handle
;
1614 smb2_util_close(tree
, handle2
);
1617 torture_comment(tctx
, "try and access now - should be OK if dynamic inheritance works\n");
1618 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1619 status
= smb2_create(tree
, tctx
, &io
);
1620 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1621 torture_comment(tctx
, "Server does not have dynamic inheritance\n");
1623 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1624 torture_comment(tctx
, "Server does have dynamic inheritance\n");
1626 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1628 smb2_util_unlink(tree
, fname1
);
1631 torture_comment(tctx
, "put back original sd\n");
1632 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1633 set
.set_secdesc
.in
.file
.handle
= handle
;
1634 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1635 set
.set_secdesc
.in
.sd
= sd_orig
;
1636 status
= smb2_setinfo_file(tree
, &set
);
1638 smb2_util_close(tree
, handle
);
1639 smb2_util_rmdir(tree
, dname
);
1640 smb2_deltree(tree
, BASEDIR
);
1642 smb2_logoff(tree
->session
);
1647 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
1648 if (!(bits & desired_64)) {\
1649 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
1652 CHECK_STATUS(status, NT_STATUS_OK); \
1656 #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
1657 if (NT_STATUS_IS_OK(status)) { \
1658 if (!(granted & access)) {\
1660 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
1661 __location__, nt_errstr(status), access, granted, desired); \
1665 if (granted & access) {\
1667 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
1668 __location__, nt_errstr(status), access, granted, desired); \
1672 CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
1676 /* test what access mask is needed for getting and setting security_descriptors */
1677 /* Note: This test was copied from raw/acls.c. */
1678 static bool test_sd_get_set(struct torture_context
*tctx
, struct smb2_tree
*tree
)
1682 struct smb2_create io
;
1683 union smb_fileinfo fi
;
1684 union smb_setfileinfo si
;
1685 struct security_descriptor
*sd
;
1686 struct security_descriptor
*sd_owner
= NULL
;
1687 struct security_descriptor
*sd_group
= NULL
;
1688 struct security_descriptor
*sd_dacl
= NULL
;
1689 struct security_descriptor
*sd_sacl
= NULL
;
1690 struct smb2_handle handle
;
1691 const char *fname
= BASEDIR
"\\sd_get_set.txt";
1692 uint64_t desired_64
;
1693 uint32_t desired
= 0, granted
;
1695 #define NO_BITS_HACK (((uint64_t)1)<<32)
1696 uint64_t open_bits
=
1698 SEC_FLAG_SYSTEM_SECURITY
|
1699 SEC_FLAG_MAXIMUM_ALLOWED
|
1703 uint64_t get_owner_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1704 uint64_t set_owner_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
1705 uint64_t get_group_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1706 uint64_t set_group_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
1707 uint64_t get_dacl_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1708 uint64_t set_dacl_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_DAC
;
1709 uint64_t get_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
1710 uint64_t set_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
1712 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1715 torture_comment(tctx
, "TESTING ACCESS MASKS FOR SD GET/SET\n");
1717 /* first create a file with full access for everyone */
1718 sd
= security_descriptor_dacl_create(tctx
,
1719 0, SID_NT_ANONYMOUS
, SID_BUILTIN_USERS
,
1721 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1725 sd
->type
|= SEC_DESC_SACL_PRESENT
;
1728 io
.level
= RAW_OPEN_SMB2
;
1729 io
.in
.create_flags
= 0;
1730 io
.in
.desired_access
= SEC_GENERIC_ALL
;
1731 io
.in
.create_options
= 0;
1732 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1733 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1734 io
.in
.alloc_size
= 0;
1735 io
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1736 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1737 io
.in
.security_flags
= 0;
1738 io
.in
.fname
= fname
;
1739 io
.in
.sec_desc
= sd
;
1740 status
= smb2_create(tree
, tctx
, &io
);
1741 CHECK_STATUS(status
, NT_STATUS_OK
);
1742 handle
= io
.out
.file
.handle
;
1744 status
= smb2_util_close(tree
, handle
);
1745 CHECK_STATUS(status
, NT_STATUS_OK
);
1748 * now try each access_mask bit and no bit at all in a loop
1749 * and see what's allowed
1750 * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
1752 for (i
=0; i
<= 32; i
++) {
1753 desired_64
= ((uint64_t)1) << i
;
1754 desired
= (uint32_t)desired_64
;
1756 /* first open the file with the desired access */
1757 io
.level
= RAW_OPEN_SMB2
;
1758 io
.in
.desired_access
= desired
;
1759 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1760 status
= smb2_create(tree
, tctx
, &io
);
1761 CHECK_STATUS_FOR_BIT_ACTION(status
, open_bits
, goto next
);
1762 handle
= io
.out
.file
.handle
;
1764 /* then check what access was granted */
1765 fi
.access_information
.level
= RAW_FILEINFO_ACCESS_INFORMATION
;
1766 fi
.access_information
.in
.file
.handle
= handle
;
1767 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1768 CHECK_STATUS(status
, NT_STATUS_OK
);
1769 granted
= fi
.access_information
.out
.access_flags
;
1771 /* test the owner */
1773 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1774 fi
.query_secdesc
.in
.file
.handle
= handle
;
1775 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
1776 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1777 CHECK_STATUS_FOR_BIT(status
, get_owner_bits
, SEC_STD_READ_CONTROL
);
1778 if (fi
.query_secdesc
.out
.sd
) {
1779 sd_owner
= fi
.query_secdesc
.out
.sd
;
1780 } else if (!sd_owner
) {
1783 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1784 si
.set_secdesc
.in
.file
.handle
= handle
;
1785 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
1786 si
.set_secdesc
.in
.sd
= sd_owner
;
1787 status
= smb2_setinfo_file(tree
, &si
);
1788 CHECK_STATUS_FOR_BIT(status
, set_owner_bits
, SEC_STD_WRITE_OWNER
);
1790 /* test the group */
1792 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1793 fi
.query_secdesc
.in
.file
.handle
= handle
;
1794 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
1795 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1796 CHECK_STATUS_FOR_BIT(status
, get_group_bits
, SEC_STD_READ_CONTROL
);
1797 if (fi
.query_secdesc
.out
.sd
) {
1798 sd_group
= fi
.query_secdesc
.out
.sd
;
1799 } else if (!sd_group
) {
1802 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1803 si
.set_secdesc
.in
.file
.handle
= handle
;
1804 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
1805 si
.set_secdesc
.in
.sd
= sd_group
;
1806 status
= smb2_setinfo_file(tree
, &si
);
1807 CHECK_STATUS_FOR_BIT(status
, set_group_bits
, SEC_STD_WRITE_OWNER
);
1811 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1812 fi
.query_secdesc
.in
.file
.handle
= handle
;
1813 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1814 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1815 CHECK_STATUS_FOR_BIT(status
, get_dacl_bits
, SEC_STD_READ_CONTROL
);
1816 if (fi
.query_secdesc
.out
.sd
) {
1817 sd_dacl
= fi
.query_secdesc
.out
.sd
;
1818 } else if (!sd_dacl
) {
1821 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1822 si
.set_secdesc
.in
.file
.handle
= handle
;
1823 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1824 si
.set_secdesc
.in
.sd
= sd_dacl
;
1825 status
= smb2_setinfo_file(tree
, &si
);
1826 CHECK_STATUS_FOR_BIT(status
, set_dacl_bits
, SEC_STD_WRITE_DAC
);
1830 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1831 fi
.query_secdesc
.in
.file
.handle
= handle
;
1832 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
1833 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1834 CHECK_STATUS_FOR_BIT(status
, get_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
1835 if (fi
.query_secdesc
.out
.sd
) {
1836 sd_sacl
= fi
.query_secdesc
.out
.sd
;
1837 } else if (!sd_sacl
) {
1840 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1841 si
.set_secdesc
.in
.file
.handle
= handle
;
1842 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
1843 si
.set_secdesc
.in
.sd
= sd_sacl
;
1844 status
= smb2_setinfo_file(tree
, &si
);
1845 CHECK_STATUS_FOR_BIT(status
, set_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
1847 /* close the handle */
1848 status
= smb2_util_close(tree
, handle
);
1849 CHECK_STATUS(status
, NT_STATUS_OK
);
1855 smb2_util_close(tree
, handle
);
1856 smb2_util_unlink(tree
, fname
);
1857 smb2_deltree(tree
, BASEDIR
);
1859 smb2_logoff(tree
->session
);
1866 * SMB2 connect with explicit share
1868 static bool torture_smb2_con_share(struct torture_context
*tctx
,
1870 struct smb2_tree
**tree
)
1872 struct smbcli_options options
;
1874 const char *host
= torture_setting_string(tctx
, "host", NULL
);
1875 struct cli_credentials
*credentials
= cmdline_credentials
;
1877 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
1879 status
= smb2_connect_ext(tctx
,
1881 lpcfg_smb_ports(tctx
->lp_ctx
),
1883 lpcfg_resolve_context(tctx
->lp_ctx
),
1889 lpcfg_socket_options(tctx
->lp_ctx
),
1890 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
1892 if (!NT_STATUS_IS_OK(status
)) {
1893 torture_comment(tctx
, "Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
1894 host
, share
, nt_errstr(status
));
1900 static bool test_access_based(struct torture_context
*tctx
,
1901 struct smb2_tree
*tree
)
1903 struct smb2_tree
*tree1
= NULL
;
1905 struct smb2_create io
;
1906 const char *fname
= BASEDIR
"\\testfile";
1908 struct smb2_handle fhandle
, dhandle
;
1909 union smb_fileinfo q
;
1910 union smb_setfileinfo set
;
1911 struct security_descriptor
*sd
, *sd_orig
=NULL
;
1912 const char *owner_sid
;
1915 * Can't test without SEC_STD_READ_CONTROL as we
1916 * own the file and implicitly have SEC_STD_READ_CONTROL.
1918 uint32_t access_masks
[] = {
1919 /* Full READ access. */
1920 SEC_STD_READ_CONTROL
|FILE_READ_DATA
|
1921 FILE_READ_ATTRIBUTES
|FILE_READ_EA
,
1923 /* Missing FILE_READ_EA. */
1924 SEC_STD_READ_CONTROL
|FILE_READ_DATA
|
1925 FILE_READ_ATTRIBUTES
,
1927 /* Missing FILE_READ_ATTRIBUTES. */
1928 SEC_STD_READ_CONTROL
|FILE_READ_DATA
|
1931 /* Missing FILE_READ_DATA. */
1932 SEC_STD_READ_CONTROL
|
1933 FILE_READ_ATTRIBUTES
|FILE_READ_EA
,
1938 union smb_search_data
*d
;
1940 ZERO_STRUCT(fhandle
);
1941 ZERO_STRUCT(dhandle
);
1943 if (!torture_smb2_con_share(tctx
, "hideunread", &tree1
)) {
1944 torture_result(tctx
, TORTURE_FAIL
, "(%s) Unable to connect "
1945 "to share 'hideunread'\n",
1951 flags
= smb2cli_tcon_flags(tree1
->smbXcli
);
1953 smb2_util_unlink(tree1
, fname
);
1954 smb2_deltree(tree1
, BASEDIR
);
1956 torture_comment(tctx
, "TESTING ACCESS BASED ENUMERATION\n");
1958 if ((flags
& SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM
)==0) {
1959 torture_result(tctx
, TORTURE_FAIL
, "(%s) No access enumeration "
1960 "on share 'hideunread'\n",
1966 if (!smb2_util_setup_dir(tctx
, tree1
, BASEDIR
)) {
1967 torture_result(tctx
, TORTURE_FAIL
, "(%s) Unable to setup %s\n",
1968 __location__
, BASEDIR
);
1973 /* Get a handle to the BASEDIR directory. */
1974 status
= torture_smb2_testdir(tree1
, BASEDIR
, &dhandle
);
1975 CHECK_STATUS(status
, NT_STATUS_OK
);
1976 smb2_util_close(tree1
, dhandle
);
1977 ZERO_STRUCT(dhandle
);
1980 io
.level
= RAW_OPEN_SMB2
;
1981 io
.in
.create_flags
= 0;
1982 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1983 io
.in
.create_options
= 0;
1984 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1985 io
.in
.share_access
= 0;
1986 io
.in
.alloc_size
= 0;
1987 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1988 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1989 io
.in
.security_flags
= 0;
1990 io
.in
.fname
= fname
;
1992 status
= smb2_create(tree1
, tctx
, &io
);
1993 CHECK_STATUS(status
, NT_STATUS_OK
);
1994 fhandle
= io
.out
.file
.handle
;
1996 torture_comment(tctx
, "get the original sd\n");
1997 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1998 q
.query_secdesc
.in
.file
.handle
= fhandle
;
1999 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
2000 status
= smb2_getinfo_file(tree1
, tctx
, &q
);
2001 CHECK_STATUS(status
, NT_STATUS_OK
);
2002 sd_orig
= q
.query_secdesc
.out
.sd
;
2004 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
2006 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
2008 /* Setup for the search. */
2011 f
.in
.continue_flags
= SMB2_CONTINUE_FLAG_REOPEN
;
2012 f
.in
.max_response_size
= 0x1000;
2013 f
.in
.level
= SMB2_FIND_DIRECTORY_INFO
;
2015 for (i
= 0; i
< ARRAY_SIZE(access_masks
); i
++) {
2017 sd
= security_descriptor_dacl_create(tctx
,
2020 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2021 access_masks
[i
]|SEC_STD_SYNCHRONIZE
,
2025 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2026 set
.set_secdesc
.in
.file
.handle
= fhandle
;
2027 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2028 set
.set_secdesc
.in
.sd
= sd
;
2029 status
= smb2_setinfo_file(tree1
, &set
);
2030 CHECK_STATUS(status
, NT_STATUS_OK
);
2032 /* Now see if we can see the file in a directory listing. */
2034 /* Re-open dhandle. */
2035 status
= torture_smb2_testdir(tree1
, BASEDIR
, &dhandle
);
2036 CHECK_STATUS(status
, NT_STATUS_OK
);
2037 f
.in
.file
.handle
= dhandle
;
2041 status
= smb2_find_level(tree1
, tree1
, &f
, &count
, &d
);
2044 CHECK_STATUS(status
, NT_STATUS_OK
);
2046 smb2_util_close(tree1
, dhandle
);
2047 ZERO_STRUCT(dhandle
);
2050 /* We should see the first sd. */
2052 torture_result(tctx
, TORTURE_FAIL
,
2053 "(%s) Normal SD - Unable "
2061 /* But no others. */
2063 torture_result(tctx
, TORTURE_FAIL
,
2064 "(%s) SD 0x%x - can "
2078 smb2_util_close(tree1
, fhandle
);
2079 smb2_util_close(tree1
, dhandle
);
2080 smb2_util_unlink(tree1
, fname
);
2081 smb2_deltree(tree1
, BASEDIR
);
2083 smb2_logoff(tree1
->session
);
2086 smb2_logoff(tree
->session
);
2091 basic testing of SMB2 ACLs
2093 struct torture_suite
*torture_smb2_acls_init(void)
2095 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "acls");
2097 torture_suite_add_1smb2_test(suite
, "CREATOR", test_creator_sid
);
2098 torture_suite_add_1smb2_test(suite
, "GENERIC", test_generic_bits
);
2099 torture_suite_add_1smb2_test(suite
, "OWNER", test_owner_bits
);
2100 torture_suite_add_1smb2_test(suite
, "INHERITANCE", test_inheritance
);
2101 torture_suite_add_1smb2_test(suite
, "INHERITFLAGS", test_inheritance_flags
);
2102 torture_suite_add_1smb2_test(suite
, "DYNAMIC", test_inheritance_dynamic
);
2104 /* XXX This test does not work against XP or Vista. */
2105 torture_suite_add_1smb2_test(suite
, "GETSET", test_sd_get_set
);
2107 torture_suite_add_1smb2_test(suite
, "ACCESSBASED", test_access_based
);
2109 suite
->description
= talloc_strdup(suite
, "SMB2-ACLS tests");