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/cmdline.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 * This is basically a copy of test_inheritance_flags() with an additional twist
1505 * to change the owner of the testfile, verifying that the security descriptor
1506 * flags are not altered.
1508 static bool test_sd_flags_vs_chown(struct torture_context
*tctx
,
1509 struct smb2_tree
*tree
)
1512 struct smb2_create io
;
1513 const char *dname
= BASEDIR
"\\inheritance";
1514 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1516 struct smb2_handle handle
= {{0}};
1517 struct smb2_handle handle2
= {{0}};
1519 union smb_fileinfo q
;
1520 union smb_setfileinfo set
;
1521 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
;
1522 struct security_descriptor
*owner_sd
= NULL
;
1523 const char *owner_sid_string
= NULL
;
1524 struct dom_sid
*owner_sid
= NULL
;
1525 struct dom_sid world_sid
= global_sid_World
;
1527 uint32_t parent_set_sd_type
; /* 3 options */
1528 uint32_t parent_set_ace_inherit
; /* 1 option */
1529 uint32_t parent_get_sd_type
;
1530 uint32_t parent_get_ace_inherit
;
1531 uint32_t child_get_sd_type
;
1532 uint32_t child_get_ace_inherit
;
1533 } tflags
[16] = {{0}}; /* 2^4 */
1535 owner_sd
= security_descriptor_dacl_create(tctx
,
1540 torture_assert_not_null_goto(tctx
, owner_sd
, ret
, done
,
1541 "security_descriptor_dacl_create failed\n");
1543 for (i
= 0; i
< 15; i
++) {
1544 torture_comment(tctx
, "i=%d:", i
);
1547 tflags
[i
].parent_set_sd_type
|=
1548 SEC_DESC_DACL_AUTO_INHERITED
;
1549 torture_comment(tctx
, "AUTO_INHERITED, ");
1552 tflags
[i
].parent_set_sd_type
|=
1553 SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1554 torture_comment(tctx
, "AUTO_INHERIT_REQ, ");
1557 tflags
[i
].parent_set_sd_type
|=
1558 SEC_DESC_DACL_PROTECTED
;
1559 torture_comment(tctx
, "PROTECTED, ");
1560 tflags
[i
].parent_get_sd_type
|=
1561 SEC_DESC_DACL_PROTECTED
;
1564 tflags
[i
].parent_set_ace_inherit
|=
1565 SEC_ACE_FLAG_INHERITED_ACE
;
1566 torture_comment(tctx
, "INHERITED, ");
1567 tflags
[i
].parent_get_ace_inherit
|=
1568 SEC_ACE_FLAG_INHERITED_ACE
;
1571 if ((tflags
[i
].parent_set_sd_type
&
1572 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) ==
1573 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) {
1574 tflags
[i
].parent_get_sd_type
|=
1575 SEC_DESC_DACL_AUTO_INHERITED
;
1576 tflags
[i
].child_get_sd_type
|=
1577 SEC_DESC_DACL_AUTO_INHERITED
;
1578 tflags
[i
].child_get_ace_inherit
|=
1579 SEC_ACE_FLAG_INHERITED_ACE
;
1580 torture_comment(tctx
, " ... parent is AUTO INHERITED");
1583 if (tflags
[i
].parent_set_ace_inherit
&
1584 SEC_ACE_FLAG_INHERITED_ACE
) {
1585 tflags
[i
].parent_get_ace_inherit
=
1586 SEC_ACE_FLAG_INHERITED_ACE
;
1587 torture_comment(tctx
, " ... parent ACE is INHERITED");
1590 torture_comment(tctx
, "\n");
1593 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1596 torture_comment(tctx
, "TESTING ACL INHERITANCE FLAGS\n");
1599 io
.level
= RAW_OPEN_SMB2
;
1600 io
.in
.create_flags
= 0;
1601 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1602 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1603 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1604 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
;
1605 io
.in
.alloc_size
= 0;
1606 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1607 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1608 io
.in
.security_flags
= 0;
1609 io
.in
.fname
= dname
;
1611 torture_comment(tctx
, "creating initial directory %s\n", dname
);
1612 status
= smb2_create(tree
, tctx
, &io
);
1613 CHECK_STATUS(status
, NT_STATUS_OK
);
1614 handle
= io
.out
.file
.handle
;
1616 torture_comment(tctx
, "getting original sd\n");
1617 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1618 q
.query_secdesc
.in
.file
.handle
= handle
;
1619 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1620 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1621 CHECK_STATUS(status
, NT_STATUS_OK
);
1622 sd_orig
= q
.query_secdesc
.out
.sd
;
1624 owner_sid
= sd_orig
->owner_sid
;
1625 owner_sid_string
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1626 torture_comment(tctx
, "owner_sid is %s\n", owner_sid_string
);
1628 for (i
=0; i
< ARRAY_SIZE(tflags
); i
++) {
1629 torture_comment(tctx
, "setting a new sd on directory, pass #%d\n", i
);
1631 sd
= security_descriptor_dacl_create(tctx
,
1632 tflags
[i
].parent_set_sd_type
,
1635 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1636 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1637 SEC_ACE_FLAG_OBJECT_INHERIT
|
1638 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1639 tflags
[i
].parent_set_ace_inherit
,
1641 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1642 SEC_FILE_ALL
| SEC_STD_ALL
,
1645 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1646 set
.set_secdesc
.in
.file
.handle
= handle
;
1647 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1648 set
.set_secdesc
.in
.sd
= sd
;
1649 status
= smb2_setinfo_file(tree
, &set
);
1650 CHECK_STATUS(status
, NT_STATUS_OK
);
1653 * Check DACL we just set, except change the bits to what they
1656 torture_comment(tctx
, " checking new sd\n");
1658 /* REQ bit should always be false. */
1659 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1661 if ((tflags
[i
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1662 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1664 q
.query_secdesc
.in
.file
.handle
= handle
;
1665 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1666 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1667 CHECK_STATUS(status
, NT_STATUS_OK
);
1668 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1671 torture_comment(tctx
, " creating file %s\n", fname1
);
1672 io
.in
.fname
= fname1
;
1673 io
.in
.create_options
= 0;
1674 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1675 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1676 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1677 status
= smb2_create(tree
, tctx
, &io
);
1678 CHECK_STATUS(status
, NT_STATUS_OK
);
1679 handle2
= io
.out
.file
.handle
;
1680 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1682 q
.query_secdesc
.in
.file
.handle
= handle2
;
1683 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1684 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1685 CHECK_STATUS(status
, NT_STATUS_OK
);
1687 torture_comment(tctx
, " checking sd on file %s\n", fname1
);
1688 sd2
= security_descriptor_dacl_create(tctx
,
1689 tflags
[i
].child_get_sd_type
,
1690 owner_sid_string
, NULL
,
1692 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1693 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1694 tflags
[i
].child_get_ace_inherit
,
1696 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1699 * Set new sd on file ... prove that the bits have nothing to
1700 * do with the parents bits when manually setting an ACL. The
1701 * _AUTO_INHERITED bit comes directly from the ACL set.
1703 for (j
= 0; j
< ARRAY_SIZE(tflags
); j
++) {
1704 torture_comment(tctx
, " setting new file sd, pass #%d\n", j
);
1706 /* Change sd type. */
1707 sd2
->type
&= ~(SEC_DESC_DACL_AUTO_INHERITED
|
1708 SEC_DESC_DACL_AUTO_INHERIT_REQ
|
1709 SEC_DESC_DACL_PROTECTED
);
1710 sd2
->type
|= tflags
[j
].parent_set_sd_type
;
1712 sd2
->dacl
->aces
[0].flags
&=
1713 ~SEC_ACE_FLAG_INHERITED_ACE
;
1714 sd2
->dacl
->aces
[0].flags
|=
1715 tflags
[j
].parent_set_ace_inherit
;
1717 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1718 set
.set_secdesc
.in
.file
.handle
= handle2
;
1719 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1720 set
.set_secdesc
.in
.sd
= sd2
;
1721 status
= smb2_setinfo_file(tree
, &set
);
1722 CHECK_STATUS(status
, NT_STATUS_OK
);
1724 /* Check DACL we just set. */
1725 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1726 if ((tflags
[j
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1727 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1729 q
.query_secdesc
.in
.file
.handle
= handle2
;
1730 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1731 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1732 CHECK_STATUS(status
, NT_STATUS_OK
);
1734 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1737 * Check that changing ownder doesn't affect SD flags.
1739 * Do this by first changing ownder to world and then
1740 * back to the original ownder. Afterwards compare SD,
1741 * should be the same.
1743 owner_sd
->owner_sid
= &world_sid
;
1744 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1745 set
.set_secdesc
.in
.file
.handle
= handle2
;
1746 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
1747 set
.set_secdesc
.in
.sd
= owner_sd
;
1748 status
= smb2_setinfo_file(tree
, &set
);
1749 CHECK_STATUS(status
, NT_STATUS_OK
);
1751 owner_sd
->owner_sid
= owner_sid
;
1752 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1753 set
.set_secdesc
.in
.file
.handle
= handle2
;
1754 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
1755 set
.set_secdesc
.in
.sd
= owner_sd
;
1756 status
= smb2_setinfo_file(tree
, &set
);
1757 CHECK_STATUS(status
, NT_STATUS_OK
);
1759 q
.query_secdesc
.in
.file
.handle
= handle2
;
1760 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1761 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1762 CHECK_STATUS(status
, NT_STATUS_OK
);
1764 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1765 torture_assert_goto(tctx
, ret
, ret
, done
, "CHECK_SECURITY_DESCRIPTOR failed\n");
1768 smb2_util_close(tree
, handle2
);
1769 smb2_util_unlink(tree
, fname1
);
1773 smb2_util_close(tree
, handle
);
1774 smb2_deltree(tree
, BASEDIR
);
1776 smb2_logoff(tree
->session
);
1781 test dynamic acl inheritance
1782 Note: This test was copied from raw/acls.c.
1784 static bool test_inheritance_dynamic(struct torture_context
*tctx
,
1785 struct smb2_tree
*tree
)
1788 struct smb2_create io
;
1789 const char *dname
= BASEDIR
"\\inheritance";
1790 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1792 struct smb2_handle handle
= {{0}};
1793 struct smb2_handle handle2
= {{0}};
1794 union smb_fileinfo q
;
1795 union smb_setfileinfo set
;
1796 struct security_descriptor
*sd
, *sd_orig
=NULL
;
1797 const char *owner_sid
;
1799 torture_comment(tctx
, "TESTING DYNAMIC ACL INHERITANCE\n");
1801 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1805 io
.level
= RAW_OPEN_SMB2
;
1806 io
.in
.create_flags
= 0;
1807 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1808 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1809 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1810 io
.in
.share_access
= 0;
1811 io
.in
.alloc_size
= 0;
1812 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1813 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1814 io
.in
.security_flags
= 0;
1815 io
.in
.fname
= dname
;
1817 status
= smb2_create(tree
, tctx
, &io
);
1818 CHECK_STATUS(status
, NT_STATUS_OK
);
1819 handle
= io
.out
.file
.handle
;
1821 torture_comment(tctx
, "get the original sd\n");
1822 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1823 q
.query_secdesc
.in
.file
.handle
= handle
;
1824 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1825 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1826 CHECK_STATUS(status
, NT_STATUS_OK
);
1827 sd_orig
= q
.query_secdesc
.out
.sd
;
1829 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1831 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1833 sd
= security_descriptor_dacl_create(tctx
,
1836 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1837 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
,
1838 SEC_ACE_FLAG_OBJECT_INHERIT
,
1840 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1842 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1843 set
.set_secdesc
.in
.file
.handle
= handle
;
1844 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1845 set
.set_secdesc
.in
.sd
= sd
;
1846 status
= smb2_setinfo_file(tree
, &set
);
1847 CHECK_STATUS(status
, NT_STATUS_OK
);
1849 torture_comment(tctx
, "create a file with an inherited acl\n");
1850 io
.in
.fname
= fname1
;
1851 io
.in
.create_options
= 0;
1852 io
.in
.desired_access
= SEC_FILE_READ_ATTRIBUTE
;
1853 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1854 status
= smb2_create(tree
, tctx
, &io
);
1855 CHECK_STATUS(status
, NT_STATUS_OK
);
1856 handle2
= io
.out
.file
.handle
;
1857 smb2_util_close(tree
, handle2
);
1859 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
1860 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1861 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1862 status
= smb2_create(tree
, tctx
, &io
);
1863 CHECK_STATUS(status
, NT_STATUS_OK
);
1864 handle2
= io
.out
.file
.handle
;
1865 smb2_util_close(tree
, handle2
);
1867 torture_comment(tctx
, "try and access file with extra rights - should be denied\n");
1868 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1869 status
= smb2_create(tree
, tctx
, &io
);
1870 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1872 torture_comment(tctx
, "update parent sd\n");
1873 sd
= security_descriptor_dacl_create(tctx
,
1876 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1877 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
,
1878 SEC_ACE_FLAG_OBJECT_INHERIT
,
1880 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1882 set
.set_secdesc
.in
.sd
= sd
;
1883 status
= smb2_setinfo_file(tree
, &set
);
1884 CHECK_STATUS(status
, NT_STATUS_OK
);
1886 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
1887 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1888 status
= smb2_create(tree
, tctx
, &io
);
1889 CHECK_STATUS(status
, NT_STATUS_OK
);
1890 handle2
= io
.out
.file
.handle
;
1891 smb2_util_close(tree
, handle2
);
1894 torture_comment(tctx
, "try and access now - should be OK if dynamic inheritance works\n");
1895 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1896 status
= smb2_create(tree
, tctx
, &io
);
1897 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1898 torture_comment(tctx
, "Server does not have dynamic inheritance\n");
1900 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1901 torture_comment(tctx
, "Server does have dynamic inheritance\n");
1903 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1905 smb2_util_unlink(tree
, fname1
);
1908 torture_comment(tctx
, "put back original sd\n");
1909 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1910 set
.set_secdesc
.in
.file
.handle
= handle
;
1911 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1912 set
.set_secdesc
.in
.sd
= sd_orig
;
1913 status
= smb2_setinfo_file(tree
, &set
);
1915 smb2_util_close(tree
, handle
);
1916 smb2_util_rmdir(tree
, dname
);
1917 smb2_deltree(tree
, BASEDIR
);
1919 smb2_logoff(tree
->session
);
1924 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
1925 if (!(bits & desired_64)) {\
1926 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
1929 CHECK_STATUS(status, NT_STATUS_OK); \
1933 #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
1934 if (NT_STATUS_IS_OK(status)) { \
1935 if (!(granted & access)) {\
1937 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
1938 __location__, nt_errstr(status), access, granted, desired); \
1942 if (granted & access) {\
1944 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
1945 __location__, nt_errstr(status), access, granted, desired); \
1949 CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
1953 /* test what access mask is needed for getting and setting security_descriptors */
1954 /* Note: This test was copied from raw/acls.c. */
1955 static bool test_sd_get_set(struct torture_context
*tctx
, struct smb2_tree
*tree
)
1959 struct smb2_create io
;
1960 union smb_fileinfo fi
;
1961 union smb_setfileinfo si
;
1962 struct security_descriptor
*sd
;
1963 struct security_descriptor
*sd_owner
= NULL
;
1964 struct security_descriptor
*sd_group
= NULL
;
1965 struct security_descriptor
*sd_dacl
= NULL
;
1966 struct security_descriptor
*sd_sacl
= NULL
;
1967 struct smb2_handle handle
;
1968 const char *fname
= BASEDIR
"\\sd_get_set.txt";
1969 uint64_t desired_64
;
1970 uint32_t desired
= 0, granted
;
1972 #define NO_BITS_HACK (((uint64_t)1)<<32)
1973 uint64_t open_bits
=
1975 SEC_FLAG_SYSTEM_SECURITY
|
1976 SEC_FLAG_MAXIMUM_ALLOWED
|
1980 uint64_t get_owner_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1981 uint64_t set_owner_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
1982 uint64_t get_group_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1983 uint64_t set_group_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
1984 uint64_t get_dacl_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1985 uint64_t set_dacl_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_DAC
;
1986 uint64_t get_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
1987 uint64_t set_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
1989 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1992 torture_comment(tctx
, "TESTING ACCESS MASKS FOR SD GET/SET\n");
1994 /* first create a file with full access for everyone */
1995 sd
= security_descriptor_dacl_create(tctx
,
1996 0, SID_NT_ANONYMOUS
, SID_BUILTIN_USERS
,
1998 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2002 sd
->type
|= SEC_DESC_SACL_PRESENT
;
2005 io
.level
= RAW_OPEN_SMB2
;
2006 io
.in
.create_flags
= 0;
2007 io
.in
.desired_access
= SEC_GENERIC_ALL
;
2008 io
.in
.create_options
= 0;
2009 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
2010 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
2011 io
.in
.alloc_size
= 0;
2012 io
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
2013 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2014 io
.in
.security_flags
= 0;
2015 io
.in
.fname
= fname
;
2016 io
.in
.sec_desc
= sd
;
2017 status
= smb2_create(tree
, tctx
, &io
);
2018 CHECK_STATUS(status
, NT_STATUS_OK
);
2019 handle
= io
.out
.file
.handle
;
2021 status
= smb2_util_close(tree
, handle
);
2022 CHECK_STATUS(status
, NT_STATUS_OK
);
2025 * now try each access_mask bit and no bit at all in a loop
2026 * and see what's allowed
2027 * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
2029 for (i
=0; i
<= 32; i
++) {
2030 desired_64
= ((uint64_t)1) << i
;
2031 desired
= (uint32_t)desired_64
;
2033 /* first open the file with the desired access */
2034 io
.level
= RAW_OPEN_SMB2
;
2035 io
.in
.desired_access
= desired
;
2036 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
2037 status
= smb2_create(tree
, tctx
, &io
);
2038 CHECK_STATUS_FOR_BIT_ACTION(status
, open_bits
, goto next
);
2039 handle
= io
.out
.file
.handle
;
2041 /* then check what access was granted */
2042 fi
.access_information
.level
= RAW_FILEINFO_ACCESS_INFORMATION
;
2043 fi
.access_information
.in
.file
.handle
= handle
;
2044 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
2045 CHECK_STATUS(status
, NT_STATUS_OK
);
2046 granted
= fi
.access_information
.out
.access_flags
;
2048 /* test the owner */
2050 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2051 fi
.query_secdesc
.in
.file
.handle
= handle
;
2052 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
2053 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
2054 CHECK_STATUS_FOR_BIT(status
, get_owner_bits
, SEC_STD_READ_CONTROL
);
2055 if (fi
.query_secdesc
.out
.sd
) {
2056 sd_owner
= fi
.query_secdesc
.out
.sd
;
2057 } else if (!sd_owner
) {
2060 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2061 si
.set_secdesc
.in
.file
.handle
= handle
;
2062 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
2063 si
.set_secdesc
.in
.sd
= sd_owner
;
2064 status
= smb2_setinfo_file(tree
, &si
);
2065 CHECK_STATUS_FOR_BIT(status
, set_owner_bits
, SEC_STD_WRITE_OWNER
);
2067 /* test the group */
2069 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2070 fi
.query_secdesc
.in
.file
.handle
= handle
;
2071 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
2072 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
2073 CHECK_STATUS_FOR_BIT(status
, get_group_bits
, SEC_STD_READ_CONTROL
);
2074 if (fi
.query_secdesc
.out
.sd
) {
2075 sd_group
= fi
.query_secdesc
.out
.sd
;
2076 } else if (!sd_group
) {
2079 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2080 si
.set_secdesc
.in
.file
.handle
= handle
;
2081 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
2082 si
.set_secdesc
.in
.sd
= sd_group
;
2083 status
= smb2_setinfo_file(tree
, &si
);
2084 CHECK_STATUS_FOR_BIT(status
, set_group_bits
, SEC_STD_WRITE_OWNER
);
2088 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2089 fi
.query_secdesc
.in
.file
.handle
= handle
;
2090 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2091 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
2092 CHECK_STATUS_FOR_BIT(status
, get_dacl_bits
, SEC_STD_READ_CONTROL
);
2093 if (fi
.query_secdesc
.out
.sd
) {
2094 sd_dacl
= fi
.query_secdesc
.out
.sd
;
2095 } else if (!sd_dacl
) {
2098 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2099 si
.set_secdesc
.in
.file
.handle
= handle
;
2100 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2101 si
.set_secdesc
.in
.sd
= sd_dacl
;
2102 status
= smb2_setinfo_file(tree
, &si
);
2103 CHECK_STATUS_FOR_BIT(status
, set_dacl_bits
, SEC_STD_WRITE_DAC
);
2107 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2108 fi
.query_secdesc
.in
.file
.handle
= handle
;
2109 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
2110 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
2111 CHECK_STATUS_FOR_BIT(status
, get_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
2112 if (fi
.query_secdesc
.out
.sd
) {
2113 sd_sacl
= fi
.query_secdesc
.out
.sd
;
2114 } else if (!sd_sacl
) {
2117 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2118 si
.set_secdesc
.in
.file
.handle
= handle
;
2119 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
2120 si
.set_secdesc
.in
.sd
= sd_sacl
;
2121 status
= smb2_setinfo_file(tree
, &si
);
2122 CHECK_STATUS_FOR_BIT(status
, set_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
2124 /* close the handle */
2125 status
= smb2_util_close(tree
, handle
);
2126 CHECK_STATUS(status
, NT_STATUS_OK
);
2132 smb2_util_close(tree
, handle
);
2133 smb2_util_unlink(tree
, fname
);
2134 smb2_deltree(tree
, BASEDIR
);
2136 smb2_logoff(tree
->session
);
2143 * SMB2 connect with explicit share
2145 static bool torture_smb2_con_share(struct torture_context
*tctx
,
2147 struct smb2_tree
**tree
)
2149 struct smbcli_options options
;
2151 const char *host
= torture_setting_string(tctx
, "host", NULL
);
2153 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
2155 status
= smb2_connect_ext(tctx
,
2157 lpcfg_smb_ports(tctx
->lp_ctx
),
2159 lpcfg_resolve_context(tctx
->lp_ctx
),
2160 samba_cmdline_get_creds(),
2165 lpcfg_socket_options(tctx
->lp_ctx
),
2166 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)
2168 if (!NT_STATUS_IS_OK(status
)) {
2169 torture_comment(tctx
, "Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
2170 host
, share
, nt_errstr(status
));
2176 static bool test_access_based(struct torture_context
*tctx
,
2177 struct smb2_tree
*tree
)
2179 struct smb2_tree
*tree1
= NULL
;
2181 struct smb2_create io
;
2182 const char *fname
= BASEDIR
"\\testfile";
2184 struct smb2_handle fhandle
, dhandle
;
2185 union smb_fileinfo q
;
2186 union smb_setfileinfo set
;
2187 struct security_descriptor
*sd
, *sd_orig
=NULL
;
2188 const char *owner_sid
;
2191 * Can't test without SEC_STD_READ_CONTROL as we
2192 * own the file and implicitly have SEC_STD_READ_CONTROL.
2194 uint32_t access_masks
[] = {
2195 /* Full READ access. */
2196 SEC_STD_READ_CONTROL
|FILE_READ_DATA
|
2197 FILE_READ_ATTRIBUTES
|FILE_READ_EA
,
2199 /* Missing FILE_READ_EA. */
2200 SEC_STD_READ_CONTROL
|FILE_READ_DATA
|
2201 FILE_READ_ATTRIBUTES
,
2203 /* Missing FILE_READ_ATTRIBUTES. */
2204 SEC_STD_READ_CONTROL
|FILE_READ_DATA
|
2207 /* Missing FILE_READ_DATA. */
2208 SEC_STD_READ_CONTROL
|
2209 FILE_READ_ATTRIBUTES
|FILE_READ_EA
,
2214 union smb_search_data
*d
;
2216 ZERO_STRUCT(fhandle
);
2217 ZERO_STRUCT(dhandle
);
2219 if (!torture_smb2_con_share(tctx
, "hideunread", &tree1
)) {
2220 torture_result(tctx
, TORTURE_FAIL
, "(%s) Unable to connect "
2221 "to share 'hideunread'\n",
2227 flags
= smb2cli_tcon_flags(tree1
->smbXcli
);
2229 smb2_util_unlink(tree1
, fname
);
2230 smb2_deltree(tree1
, BASEDIR
);
2232 torture_comment(tctx
, "TESTING ACCESS BASED ENUMERATION\n");
2234 if ((flags
& SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM
)==0) {
2235 torture_result(tctx
, TORTURE_FAIL
, "(%s) No access enumeration "
2236 "on share 'hideunread'\n",
2242 if (!smb2_util_setup_dir(tctx
, tree1
, BASEDIR
)) {
2243 torture_result(tctx
, TORTURE_FAIL
, "(%s) Unable to setup %s\n",
2244 __location__
, BASEDIR
);
2249 /* Get a handle to the BASEDIR directory. */
2250 status
= torture_smb2_testdir(tree1
, BASEDIR
, &dhandle
);
2251 CHECK_STATUS(status
, NT_STATUS_OK
);
2252 smb2_util_close(tree1
, dhandle
);
2253 ZERO_STRUCT(dhandle
);
2256 io
.level
= RAW_OPEN_SMB2
;
2257 io
.in
.create_flags
= 0;
2258 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
2259 io
.in
.create_options
= 0;
2260 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
2261 io
.in
.share_access
= 0;
2262 io
.in
.alloc_size
= 0;
2263 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
2264 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2265 io
.in
.security_flags
= 0;
2266 io
.in
.fname
= fname
;
2268 status
= smb2_create(tree1
, tctx
, &io
);
2269 CHECK_STATUS(status
, NT_STATUS_OK
);
2270 fhandle
= io
.out
.file
.handle
;
2272 torture_comment(tctx
, "get the original sd\n");
2273 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
2274 q
.query_secdesc
.in
.file
.handle
= fhandle
;
2275 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
2276 status
= smb2_getinfo_file(tree1
, tctx
, &q
);
2277 CHECK_STATUS(status
, NT_STATUS_OK
);
2278 sd_orig
= q
.query_secdesc
.out
.sd
;
2280 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
2282 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
2284 /* Setup for the search. */
2287 f
.in
.continue_flags
= SMB2_CONTINUE_FLAG_REOPEN
;
2288 f
.in
.max_response_size
= 0x1000;
2289 f
.in
.level
= SMB2_FIND_DIRECTORY_INFO
;
2291 for (i
= 0; i
< ARRAY_SIZE(access_masks
); i
++) {
2293 sd
= security_descriptor_dacl_create(tctx
,
2296 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2297 access_masks
[i
]|SEC_STD_SYNCHRONIZE
,
2301 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
2302 set
.set_secdesc
.in
.file
.handle
= fhandle
;
2303 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
2304 set
.set_secdesc
.in
.sd
= sd
;
2305 status
= smb2_setinfo_file(tree1
, &set
);
2306 CHECK_STATUS(status
, NT_STATUS_OK
);
2308 /* Now see if we can see the file in a directory listing. */
2310 /* Re-open dhandle. */
2311 status
= torture_smb2_testdir(tree1
, BASEDIR
, &dhandle
);
2312 CHECK_STATUS(status
, NT_STATUS_OK
);
2313 f
.in
.file
.handle
= dhandle
;
2317 status
= smb2_find_level(tree1
, tree1
, &f
, &count
, &d
);
2320 CHECK_STATUS(status
, NT_STATUS_OK
);
2322 smb2_util_close(tree1
, dhandle
);
2323 ZERO_STRUCT(dhandle
);
2326 /* We should see the first sd. */
2328 torture_result(tctx
, TORTURE_FAIL
,
2329 "(%s) Normal SD - Unable "
2337 /* But no others. */
2339 torture_result(tctx
, TORTURE_FAIL
,
2340 "(%s) SD 0x%x - can "
2354 smb2_util_close(tree1
, fhandle
);
2355 smb2_util_close(tree1
, dhandle
);
2356 smb2_util_unlink(tree1
, fname
);
2357 smb2_deltree(tree1
, BASEDIR
);
2359 smb2_logoff(tree1
->session
);
2362 smb2_logoff(tree
->session
);
2367 * test Owner Rights, S-1-3-4
2369 static bool test_owner_rights(struct torture_context
*tctx
,
2370 struct smb2_tree
*tree
)
2372 const char *fname
= BASEDIR
"\\owner_right.txt";
2373 struct smb2_create cr
;
2374 struct smb2_handle handle
= {{0}};
2375 union smb_fileinfo gi
;
2376 union smb_setfileinfo si
;
2377 struct security_descriptor
*sd_orig
= NULL
;
2378 struct security_descriptor
*sd
= NULL
;
2379 const char *owner_sid
= NULL
;
2380 NTSTATUS mxac_status
;
2384 smb2_deltree(tree
, BASEDIR
);
2386 ret
= smb2_util_setup_dir(tctx
, tree
, BASEDIR
);
2387 torture_assert_goto(tctx
, ret
, ret
, done
,
2388 "smb2_util_setup_dir failed\n");
2390 torture_comment(tctx
, "TESTING OWNER RIGHTS\n");
2392 cr
= (struct smb2_create
) {
2393 .in
.desired_access
= SEC_STD_READ_CONTROL
|
2394 SEC_STD_WRITE_DAC
|SEC_STD_WRITE_OWNER
,
2395 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2396 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2397 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2398 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2402 status
= smb2_create(tree
, tctx
, &cr
);
2403 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2404 "smb2_create failed\n");
2405 handle
= cr
.out
.file
.handle
;
2407 torture_comment(tctx
, "get the original sd\n");
2409 gi
= (union smb_fileinfo
) {
2410 .query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
,
2411 .query_secdesc
.in
.file
.handle
= handle
,
2412 .query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
|SECINFO_OWNER
,
2415 status
= smb2_getinfo_file(tree
, tctx
, &gi
);
2416 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2417 "smb2_getinfo_file failed\n");
2419 sd_orig
= gi
.query_secdesc
.out
.sd
;
2420 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
2423 * Add a 2 element ACL
2424 * SEC_RIGHTS_FILE_READ for the owner,
2425 * SEC_FILE_WRITE_DATA for SID_OWNER_RIGHTS.
2427 * Proves that the owner and SID_OWNER_RIGHTS
2428 * ACE entries are additive.
2430 sd
= security_descriptor_dacl_create(tctx
, 0, NULL
, NULL
,
2432 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2433 SEC_RIGHTS_FILE_READ
,
2436 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2437 SEC_FILE_WRITE_DATA
,
2440 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
2441 "SD create failed\n");
2443 si
= (union smb_setfileinfo
) {
2444 .set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
,
2445 .set_secdesc
.in
.file
.handle
= handle
,
2446 .set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
2447 .set_secdesc
.in
.sd
= sd
,
2450 status
= smb2_setinfo_file(tree
, &si
);
2451 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2452 "smb2_setinfo_file failed\n");
2454 status
= smb2_util_close(tree
, handle
);
2455 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2456 "smb2_util_close failed\n");
2457 ZERO_STRUCT(handle
);
2459 cr
= (struct smb2_create
) {
2460 .in
.desired_access
= SEC_STD_READ_CONTROL
,
2461 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2462 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2463 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2464 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2465 .in
.query_maximal_access
= true,
2469 status
= smb2_create(tree
, tctx
, &cr
);
2470 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2471 "smb2_setinfo_file failed\n");
2472 handle
= cr
.out
.file
.handle
;
2474 mxac_status
= NT_STATUS(cr
.out
.maximal_access_status
);
2475 torture_assert_ntstatus_ok_goto(tctx
, mxac_status
, ret
, done
,
2476 "smb2_setinfo_file failed\n");
2479 * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2480 * do. Mask it out so the test passes against Samba and Windows.
2482 torture_assert_int_equal_goto(tctx
,
2483 cr
.out
.maximal_access
& ~SEC_STD_DELETE
,
2484 SEC_RIGHTS_FILE_READ
|
2485 SEC_FILE_WRITE_DATA
,
2487 "Wrong maximum access\n");
2489 status
= smb2_util_close(tree
, handle
);
2490 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2491 "smb2_util_close failed\n");
2492 ZERO_STRUCT(handle
);
2495 if (!smb2_util_handle_empty(handle
)) {
2496 smb2_util_close(tree
, handle
);
2498 smb2_deltree(tree
, BASEDIR
);
2503 * test Owner Rights with a leading DENY ACE, S-1-3-4
2505 static bool test_owner_rights_deny(struct torture_context
*tctx
,
2506 struct smb2_tree
*tree
)
2508 const char *fname
= BASEDIR
"\\owner_right_deny.txt";
2509 struct smb2_create cr
;
2510 struct smb2_handle handle
= {{0}};
2511 union smb_fileinfo gi
;
2512 union smb_setfileinfo si
;
2513 struct security_descriptor
*sd_orig
= NULL
;
2514 struct security_descriptor
*sd
= NULL
;
2515 const char *owner_sid
= NULL
;
2516 NTSTATUS mxac_status
;
2520 smb2_deltree(tree
, BASEDIR
);
2522 ret
= smb2_util_setup_dir(tctx
, tree
, BASEDIR
);
2523 torture_assert_goto(tctx
, ret
, ret
, done
,
2524 "smb2_util_setup_dir failed\n");
2526 torture_comment(tctx
, "TESTING OWNER RIGHTS DENY\n");
2528 cr
= (struct smb2_create
) {
2529 .in
.desired_access
= SEC_STD_READ_CONTROL
|
2530 SEC_STD_WRITE_DAC
|SEC_STD_WRITE_OWNER
,
2531 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2532 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2533 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2534 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2538 status
= smb2_create(tree
, tctx
, &cr
);
2539 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2540 "smb2_create failed\n");
2541 handle
= cr
.out
.file
.handle
;
2543 torture_comment(tctx
, "get the original sd\n");
2545 gi
= (union smb_fileinfo
) {
2546 .query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
,
2547 .query_secdesc
.in
.file
.handle
= handle
,
2548 .query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
|SECINFO_OWNER
,
2551 status
= smb2_getinfo_file(tree
, tctx
, &gi
);
2552 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2553 "smb2_getinfo_file failed\n");
2555 sd_orig
= gi
.query_secdesc
.out
.sd
;
2556 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
2559 * Add a 2 element ACL
2560 * DENY SEC_FILE_DATA_READ for SID_OWNER_RIGHTS
2561 * SEC_FILE_READ_DATA for the owner.
2563 * Proves that the owner and SID_OWNER_RIGHTS
2564 * ACE entries are additive.
2566 sd
= security_descriptor_dacl_create(tctx
, 0, NULL
, NULL
,
2568 SEC_ACE_TYPE_ACCESS_DENIED
,
2572 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2573 SEC_RIGHTS_FILE_READ
,
2576 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
2577 "SD create failed\n");
2579 si
= (union smb_setfileinfo
) {
2580 .set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
,
2581 .set_secdesc
.in
.file
.handle
= handle
,
2582 .set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
2583 .set_secdesc
.in
.sd
= sd
,
2586 status
= smb2_setinfo_file(tree
, &si
);
2587 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2588 "smb2_setinfo_file failed\n");
2590 status
= smb2_util_close(tree
, handle
);
2591 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2592 "smb2_util_close failed\n");
2593 ZERO_STRUCT(handle
);
2595 cr
= (struct smb2_create
) {
2596 .in
.desired_access
= SEC_STD_READ_CONTROL
,
2597 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2598 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2599 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2600 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2601 .in
.query_maximal_access
= true,
2605 status
= smb2_create(tree
, tctx
, &cr
);
2606 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2607 "smb2_setinfo_file failed\n");
2608 handle
= cr
.out
.file
.handle
;
2610 mxac_status
= NT_STATUS(cr
.out
.maximal_access_status
);
2611 torture_assert_ntstatus_ok_goto(tctx
, mxac_status
, ret
, done
,
2612 "smb2_setinfo_file failed\n");
2615 * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2616 * do. Mask it out so the test passes against Samba and Windows.
2618 torture_assert_int_equal_goto(tctx
,
2619 cr
.out
.maximal_access
& ~SEC_STD_DELETE
,
2620 SEC_RIGHTS_FILE_READ
& ~SEC_FILE_READ_DATA
,
2622 "Wrong maximum access\n");
2624 status
= smb2_util_close(tree
, handle
);
2625 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2626 "smb2_util_close failed\n");
2627 ZERO_STRUCT(handle
);
2630 if (!smb2_util_handle_empty(handle
)) {
2631 smb2_util_close(tree
, handle
);
2633 smb2_deltree(tree
, BASEDIR
);
2638 * test Owner Rights with a trailing DENY ACE, S-1-3-4
2640 static bool test_owner_rights_deny1(struct torture_context
*tctx
,
2641 struct smb2_tree
*tree
)
2643 const char *fname
= BASEDIR
"\\owner_right_deny1.txt";
2644 struct smb2_create cr
;
2645 struct smb2_handle handle
= {{0}};
2646 union smb_fileinfo gi
;
2647 union smb_setfileinfo si
;
2648 struct security_descriptor
*sd_orig
= NULL
;
2649 struct security_descriptor
*sd
= NULL
;
2650 const char *owner_sid
= NULL
;
2651 NTSTATUS mxac_status
;
2655 smb2_deltree(tree
, BASEDIR
);
2657 ret
= smb2_util_setup_dir(tctx
, tree
, BASEDIR
);
2658 torture_assert_goto(tctx
, ret
, ret
, done
,
2659 "smb2_util_setup_dir failed\n");
2661 torture_comment(tctx
, "TESTING OWNER RIGHTS DENY1\n");
2663 cr
= (struct smb2_create
) {
2664 .in
.desired_access
= SEC_STD_READ_CONTROL
|
2665 SEC_STD_WRITE_DAC
|SEC_STD_WRITE_OWNER
,
2666 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2667 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2668 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2669 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2673 status
= smb2_create(tree
, tctx
, &cr
);
2674 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2675 "smb2_create failed\n");
2676 handle
= cr
.out
.file
.handle
;
2678 torture_comment(tctx
, "get the original sd\n");
2680 gi
= (union smb_fileinfo
) {
2681 .query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
,
2682 .query_secdesc
.in
.file
.handle
= handle
,
2683 .query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
|SECINFO_OWNER
,
2686 status
= smb2_getinfo_file(tree
, tctx
, &gi
);
2687 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2688 "smb2_getinfo_file failed\n");
2690 sd_orig
= gi
.query_secdesc
.out
.sd
;
2691 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
2694 * Add a 3 element ACL
2696 * SEC_RIGHTS_FILE_READ allow for owner.
2697 * SEC_FILE_WRITE_DATA allow for SID-OWNER-RIGHTS.
2698 * SEC_FILE_WRITE_DATA|SEC_FILE_READ_DATA) deny for SID-OWNER-RIGHTS.
2700 * Shows on Windows that trailing DENY entries don't
2701 * override granted permissions in max access calculations.
2703 sd
= security_descriptor_dacl_create(tctx
, 0, NULL
, NULL
,
2705 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2706 SEC_RIGHTS_FILE_READ
,
2709 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2710 SEC_FILE_WRITE_DATA
,
2713 SEC_ACE_TYPE_ACCESS_DENIED
,
2714 (SEC_FILE_WRITE_DATA
|
2715 SEC_FILE_READ_DATA
),
2718 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
2719 "SD create failed\n");
2721 si
= (union smb_setfileinfo
) {
2722 .set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
,
2723 .set_secdesc
.in
.file
.handle
= handle
,
2724 .set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
2725 .set_secdesc
.in
.sd
= sd
,
2728 status
= smb2_setinfo_file(tree
, &si
);
2729 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2730 "smb2_setinfo_file failed\n");
2732 status
= smb2_util_close(tree
, handle
);
2733 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2734 "smb2_util_close failed\n");
2735 ZERO_STRUCT(handle
);
2737 cr
= (struct smb2_create
) {
2738 .in
.desired_access
= SEC_STD_READ_CONTROL
,
2739 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2740 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2741 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2742 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2743 .in
.query_maximal_access
= true,
2747 status
= smb2_create(tree
, tctx
, &cr
);
2748 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2749 "smb2_setinfo_file failed\n");
2750 handle
= cr
.out
.file
.handle
;
2752 mxac_status
= NT_STATUS(cr
.out
.maximal_access_status
);
2753 torture_assert_ntstatus_ok_goto(tctx
, mxac_status
, ret
, done
,
2754 "smb2_setinfo_file failed\n");
2757 * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2758 * do. Mask it out so the test passes against Samba and Windows.
2760 torture_assert_int_equal_goto(tctx
,
2761 cr
.out
.maximal_access
& ~SEC_STD_DELETE
,
2762 SEC_RIGHTS_FILE_READ
| SEC_FILE_WRITE_DATA
,
2764 "Wrong maximum access\n");
2766 status
= smb2_util_close(tree
, handle
);
2767 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2768 "smb2_util_close failed\n");
2769 ZERO_STRUCT(handle
);
2772 if (!smb2_util_handle_empty(handle
)) {
2773 smb2_util_close(tree
, handle
);
2775 smb2_deltree(tree
, BASEDIR
);
2780 * test that shows that a DENY ACE doesn't remove rights granted
2781 * by a previous ALLOW ACE.
2783 static bool test_deny1(struct torture_context
*tctx
,
2784 struct smb2_tree
*tree
)
2786 const char *fname
= BASEDIR
"\\test_deny1.txt";
2787 struct smb2_create cr
;
2788 struct smb2_handle handle
= {{0}};
2789 union smb_fileinfo gi
;
2790 union smb_setfileinfo si
;
2791 struct security_descriptor
*sd_orig
= NULL
;
2792 struct security_descriptor
*sd
= NULL
;
2793 const char *owner_sid
= NULL
;
2794 NTSTATUS mxac_status
;
2798 smb2_deltree(tree
, BASEDIR
);
2800 ret
= smb2_util_setup_dir(tctx
, tree
, BASEDIR
);
2801 torture_assert_goto(tctx
, ret
, ret
, done
,
2802 "smb2_util_setup_dir failed\n");
2804 cr
= (struct smb2_create
) {
2805 .in
.desired_access
= SEC_STD_READ_CONTROL
|
2806 SEC_STD_WRITE_DAC
|SEC_STD_WRITE_OWNER
,
2807 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2808 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2809 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2810 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2814 status
= smb2_create(tree
, tctx
, &cr
);
2815 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2816 "smb2_create failed\n");
2817 handle
= cr
.out
.file
.handle
;
2819 torture_comment(tctx
, "get the original sd\n");
2821 gi
= (union smb_fileinfo
) {
2822 .query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
,
2823 .query_secdesc
.in
.file
.handle
= handle
,
2824 .query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
|SECINFO_OWNER
,
2827 status
= smb2_getinfo_file(tree
, tctx
, &gi
);
2828 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2829 "smb2_getinfo_file failed\n");
2831 sd_orig
= gi
.query_secdesc
.out
.sd
;
2832 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
2835 * Add a 2 element ACL
2837 * SEC_RIGHTS_FILE_READ|SEC_FILE_WRITE_DATA allow for owner.
2838 * SEC_FILE_WRITE_DATA deny for owner
2840 * Shows on Windows that trailing DENY entries don't
2841 * override granted permissions.
2843 sd
= security_descriptor_dacl_create(tctx
, 0, NULL
, NULL
,
2845 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2846 SEC_RIGHTS_FILE_READ
|SEC_FILE_WRITE_DATA
,
2849 SEC_ACE_TYPE_ACCESS_DENIED
,
2850 SEC_FILE_WRITE_DATA
,
2853 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
2854 "SD create failed\n");
2856 si
= (union smb_setfileinfo
) {
2857 .set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
,
2858 .set_secdesc
.in
.file
.handle
= handle
,
2859 .set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
2860 .set_secdesc
.in
.sd
= sd
,
2863 status
= smb2_setinfo_file(tree
, &si
);
2864 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2865 "smb2_setinfo_file failed\n");
2867 status
= smb2_util_close(tree
, handle
);
2868 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2869 "smb2_util_close failed\n");
2870 ZERO_STRUCT(handle
);
2872 cr
= (struct smb2_create
) {
2873 .in
.desired_access
= SEC_STD_READ_CONTROL
| SEC_FILE_WRITE_DATA
,
2874 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2875 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2876 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2877 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2878 .in
.query_maximal_access
= true,
2882 status
= smb2_create(tree
, tctx
, &cr
);
2883 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2884 "smb2_create failed\n");
2885 handle
= cr
.out
.file
.handle
;
2887 mxac_status
= NT_STATUS(cr
.out
.maximal_access_status
);
2888 torture_assert_ntstatus_ok_goto(tctx
, mxac_status
, ret
, done
,
2889 "Wrong maximum access status\n");
2892 * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
2893 * do. Mask it out so the test passes against Samba and Windows.
2894 * SEC_STD_WRITE_DAC comes from being the owner.
2896 torture_assert_int_equal_goto(tctx
,
2897 cr
.out
.maximal_access
& ~SEC_STD_DELETE
,
2898 SEC_RIGHTS_FILE_READ
|
2899 SEC_FILE_WRITE_DATA
|
2902 "Wrong maximum access\n");
2904 status
= smb2_util_close(tree
, handle
);
2905 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2906 "smb2_util_close failed\n");
2907 ZERO_STRUCT(handle
);
2910 if (!smb2_util_handle_empty(handle
)) {
2911 smb2_util_close(tree
, handle
);
2913 smb2_deltree(tree
, BASEDIR
);
2918 * test SEC_FLAG_MAXIMUM_ALLOWED with not-granted access
2920 * When access_mask contains SEC_FLAG_MAXIMUM_ALLOWED, the server must still
2921 * proces other bits from access_mask. Eg if access_mask contains a right that
2922 * the requester doesn't have, the function must validate that against the
2923 * effective permissions.
2925 static bool test_mxac_not_granted(struct torture_context
*tctx
,
2926 struct smb2_tree
*tree
)
2928 const char *fname
= BASEDIR
"\\test_mxac_not_granted.txt";
2929 struct smb2_create cr
;
2930 struct smb2_handle handle
= {{0}};
2931 union smb_fileinfo gi
;
2932 union smb_setfileinfo si
;
2933 struct security_descriptor
*sd_orig
= NULL
;
2934 struct security_descriptor
*sd
= NULL
;
2935 const char *owner_sid
= NULL
;
2939 smb2_deltree(tree
, BASEDIR
);
2941 ret
= smb2_util_setup_dir(tctx
, tree
, BASEDIR
);
2942 torture_assert_goto(tctx
, ret
, ret
, done
,
2943 "smb2_util_setup_dir failed\n");
2945 torture_comment(tctx
, "TESTING OWNER RIGHTS DENY\n");
2947 cr
= (struct smb2_create
) {
2948 .in
.desired_access
= SEC_STD_READ_CONTROL
|
2949 SEC_STD_WRITE_DAC
|SEC_STD_WRITE_OWNER
,
2950 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
2951 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
2952 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
2953 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
2957 status
= smb2_create(tree
, tctx
, &cr
);
2958 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2959 "smb2_create failed\n");
2960 handle
= cr
.out
.file
.handle
;
2962 torture_comment(tctx
, "get the original sd\n");
2964 gi
= (union smb_fileinfo
) {
2965 .query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
,
2966 .query_secdesc
.in
.file
.handle
= handle
,
2967 .query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
|SECINFO_OWNER
,
2970 status
= smb2_getinfo_file(tree
, tctx
, &gi
);
2971 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2972 "smb2_getinfo_file failed\n");
2974 sd_orig
= gi
.query_secdesc
.out
.sd
;
2975 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
2977 sd
= security_descriptor_dacl_create(tctx
, 0, NULL
, NULL
,
2979 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2983 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
2984 "SD create failed\n");
2986 si
= (union smb_setfileinfo
) {
2987 .set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
,
2988 .set_secdesc
.in
.file
.handle
= handle
,
2989 .set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
2990 .set_secdesc
.in
.sd
= sd
,
2993 status
= smb2_setinfo_file(tree
, &si
);
2994 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2995 "smb2_setinfo_file failed\n");
2997 status
= smb2_util_close(tree
, handle
);
2998 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
2999 "smb2_util_close failed\n");
3000 ZERO_STRUCT(handle
);
3002 cr
= (struct smb2_create
) {
3003 .in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
|
3004 SEC_FILE_WRITE_DATA
,
3005 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
3006 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
3007 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
3008 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
3012 status
= smb2_create(tree
, tctx
, &cr
);
3013 torture_assert_ntstatus_equal_goto(tctx
, status
,
3014 NT_STATUS_ACCESS_DENIED
,
3016 "Wrong smb2_create result\n");
3019 if (!smb2_util_handle_empty(handle
)) {
3020 smb2_util_close(tree
, handle
);
3022 smb2_deltree(tree
, BASEDIR
);
3027 basic testing of SMB2 ACLs
3029 struct torture_suite
*torture_smb2_acls_init(TALLOC_CTX
*ctx
)
3031 struct torture_suite
*suite
= torture_suite_create(ctx
, "acls");
3033 torture_suite_add_1smb2_test(suite
, "CREATOR", test_creator_sid
);
3034 torture_suite_add_1smb2_test(suite
, "GENERIC", test_generic_bits
);
3035 torture_suite_add_1smb2_test(suite
, "OWNER", test_owner_bits
);
3036 torture_suite_add_1smb2_test(suite
, "INHERITANCE", test_inheritance
);
3037 torture_suite_add_1smb2_test(suite
, "INHERITFLAGS", test_inheritance_flags
);
3038 torture_suite_add_1smb2_test(suite
, "SDFLAGSVSCHOWN", test_sd_flags_vs_chown
);
3039 torture_suite_add_1smb2_test(suite
, "DYNAMIC", test_inheritance_dynamic
);
3041 /* XXX This test does not work against XP or Vista. */
3042 torture_suite_add_1smb2_test(suite
, "GETSET", test_sd_get_set
);
3044 torture_suite_add_1smb2_test(suite
, "ACCESSBASED", test_access_based
);
3045 torture_suite_add_1smb2_test(suite
, "OWNER-RIGHTS", test_owner_rights
);
3046 torture_suite_add_1smb2_test(suite
, "OWNER-RIGHTS-DENY",
3047 test_owner_rights_deny
);
3048 torture_suite_add_1smb2_test(suite
, "OWNER-RIGHTS-DENY1",
3049 test_owner_rights_deny1
);
3050 torture_suite_add_1smb2_test(suite
, "DENY1",
3052 torture_suite_add_1smb2_test(suite
, "MXAC-NOT-GRANTED",
3053 test_mxac_not_granted
);
3055 suite
->description
= talloc_strdup(suite
, "SMB2-ACLS tests");
3060 static bool test_acls_non_canonical_flags(struct torture_context
*tctx
,
3061 struct smb2_tree
*tree
)
3063 const char *fname
= BASEDIR
"\\test_acls_non_canonical_flags.txt";
3064 struct smb2_create cr
;
3065 struct smb2_handle testdirh
= {{0}};
3066 struct smb2_handle handle
= {{0}};
3067 union smb_fileinfo gi
;
3068 union smb_setfileinfo si
;
3069 struct security_descriptor
*sd_orig
= NULL
;
3070 struct security_descriptor
*sd
= NULL
;
3074 smb2_deltree(tree
, BASEDIR
);
3076 status
= torture_smb2_testdir(tree
, BASEDIR
, &testdirh
);
3077 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3078 "torture_smb2_testdir failed\n");
3080 sd
= security_descriptor_dacl_create(tctx
,
3081 SEC_DESC_DACL_AUTO_INHERITED
3082 | SEC_DESC_DACL_AUTO_INHERIT_REQ
,
3086 SEC_ACE_TYPE_ACCESS_ALLOWED
,
3088 SEC_ACE_FLAG_OBJECT_INHERIT
3089 | SEC_ACE_FLAG_CONTAINER_INHERIT
,
3091 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
3092 "SD create failed\n");
3094 si
= (union smb_setfileinfo
) {
3095 .set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
,
3096 .set_secdesc
.in
.file
.handle
= testdirh
,
3097 .set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
3098 .set_secdesc
.in
.sd
= sd
,
3101 status
= smb2_setinfo_file(tree
, &si
);
3102 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3103 "smb2_setinfo_file failed\n");
3105 gi
= (union smb_fileinfo
) {
3106 .query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
,
3107 .query_secdesc
.in
.file
.handle
= testdirh
,
3108 .query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
3111 status
= smb2_getinfo_file(tree
, tctx
, &gi
);
3112 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3113 "smb2_getinfo_file failed\n");
3115 cr
= (struct smb2_create
) {
3116 .in
.desired_access
= SEC_STD_READ_CONTROL
|
3118 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
3119 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
3120 .in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
,
3121 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
3125 status
= smb2_create(tree
, tctx
, &cr
);
3126 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3127 "smb2_create failed\n");
3128 handle
= cr
.out
.file
.handle
;
3130 torture_comment(tctx
, "get the original sd\n");
3132 gi
= (union smb_fileinfo
) {
3133 .query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
,
3134 .query_secdesc
.in
.file
.handle
= handle
,
3135 .query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
3138 status
= smb2_getinfo_file(tree
, tctx
, &gi
);
3139 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3140 "smb2_getinfo_file failed\n");
3142 sd_orig
= gi
.query_secdesc
.out
.sd
;
3144 torture_assert_goto(tctx
, sd_orig
->type
& SEC_DESC_DACL_AUTO_INHERITED
,
3145 ret
, done
, "Missing SEC_DESC_DACL_AUTO_INHERITED\n");
3148 * SD with SEC_DESC_DACL_AUTO_INHERITED but without
3149 * SEC_DESC_DACL_AUTO_INHERITED_REQ, so the resulting SD should not have
3150 * SEC_DESC_DACL_AUTO_INHERITED on a Windows box.
3152 * But as we're testing against a share with
3154 * "acl flag inherited canonicalization = no"
3156 * the resulting SD should have acl flag inherited canonicalization set.
3158 sd
= security_descriptor_dacl_create(tctx
,
3159 SEC_DESC_DACL_AUTO_INHERITED
,
3163 SEC_ACE_TYPE_ACCESS_ALLOWED
,
3167 torture_assert_not_null_goto(tctx
, sd
, ret
, done
,
3168 "SD create failed\n");
3170 si
= (union smb_setfileinfo
) {
3171 .set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
,
3172 .set_secdesc
.in
.file
.handle
= handle
,
3173 .set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
3174 .set_secdesc
.in
.sd
= sd
,
3177 status
= smb2_setinfo_file(tree
, &si
);
3178 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3179 "smb2_setinfo_file failed\n");
3181 status
= smb2_util_close(tree
, handle
);
3182 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3183 "smb2_util_close failed\n");
3184 ZERO_STRUCT(handle
);
3186 cr
= (struct smb2_create
) {
3187 .in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
,
3188 .in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
,
3189 .in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
,
3190 .in
.create_disposition
= NTCREATEX_DISP_OPEN
,
3191 .in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
,
3195 status
= smb2_create(tree
, tctx
, &cr
);
3196 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3197 "smb2_create failed\n");
3198 handle
= cr
.out
.file
.handle
;
3200 gi
= (union smb_fileinfo
) {
3201 .query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
,
3202 .query_secdesc
.in
.file
.handle
= handle
,
3203 .query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
,
3206 status
= smb2_getinfo_file(tree
, tctx
, &gi
);
3207 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
3208 "smb2_getinfo_file failed\n");
3210 sd_orig
= gi
.query_secdesc
.out
.sd
;
3211 torture_assert_goto(tctx
, sd_orig
->type
& SEC_DESC_DACL_AUTO_INHERITED
,
3212 ret
, done
, "Missing SEC_DESC_DACL_AUTO_INHERITED\n");
3215 if (!smb2_util_handle_empty(handle
)) {
3216 smb2_util_close(tree
, testdirh
);
3218 if (!smb2_util_handle_empty(handle
)) {
3219 smb2_util_close(tree
, handle
);
3221 smb2_deltree(tree
, BASEDIR
);
3225 struct torture_suite
*torture_smb2_acls_non_canonical_init(TALLOC_CTX
*ctx
)
3227 struct torture_suite
*suite
= torture_suite_create(ctx
, "acls_non_canonical");
3229 torture_suite_add_1smb2_test(suite
, "flags", test_acls_non_canonical_flags
);