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 "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "torture/torture.h"
26 #include "torture/util.h"
27 #include "torture/smb2/proto.h"
28 #include "libcli/security/security.h"
29 #include "librpc/gen_ndr/ndr_security.h"
31 #define CHECK_STATUS(status, correct) do { \
32 if (!NT_STATUS_EQUAL(status, correct)) { \
33 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
34 __location__, nt_errstr(status), nt_errstr(correct)); \
39 #define BASEDIR "smb2-testsd"
41 #define CHECK_ACCESS_IGNORE SEC_STD_SYNCHRONIZE
43 #define CHECK_ACCESS_FLAGS(_fh, flags) do { \
44 union smb_fileinfo _q; \
45 _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
46 _q.access_information.in.file.handle = (_fh); \
47 status = smb2_getinfo_file(tree, tctx, &_q); \
48 CHECK_STATUS(status, NT_STATUS_OK); \
49 /* Handle a Vista bug where SEC_STD_SYNCHRONIZE doesn't come back. */ \
50 if ((((flags) & CHECK_ACCESS_IGNORE) == CHECK_ACCESS_IGNORE) && \
51 ((_q.access_information.out.access_flags & CHECK_ACCESS_IGNORE) != CHECK_ACCESS_IGNORE)) { \
52 torture_comment(tctx, "SKIPPING (Vista bug): (%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
53 __location__, _q.access_information.out.access_flags, (flags)); \
55 if ((_q.access_information.out.access_flags & ~CHECK_ACCESS_IGNORE) != \
56 (((flags) & ~CHECK_ACCESS_IGNORE))) { \
57 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
58 __location__, _q.access_information.out.access_flags, (flags)); \
64 #define FAIL_UNLESS(__cond) \
66 if (__cond) {} else { \
67 torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n", \
68 __location__, #__cond); \
69 ret = false; goto done; \
73 #define CHECK_SECURITY_DESCRIPTOR(_sd1, _sd2) do { \
74 if (!security_descriptor_equal(_sd1, _sd2)) { \
75 torture_warning(tctx, "%s: security descriptors don't match!\n", __location__); \
76 torture_warning(tctx, "got:\n"); \
77 NDR_PRINT_DEBUG(security_descriptor, _sd1); \
78 torture_warning(tctx, "expected:\n"); \
79 NDR_PRINT_DEBUG(security_descriptor, _sd2); \
85 test the behaviour of the well known SID_CREATOR_OWNER sid, and some generic
87 Note: This test was copied from raw/acls.c.
89 static bool test_creator_sid(struct torture_context
*tctx
, struct smb2_tree
*tree
)
92 struct smb2_create io
;
93 const char *fname
= BASEDIR
"\\creator.txt";
95 struct smb2_handle handle
;
97 union smb_setfileinfo set
;
98 struct security_descriptor
*sd
, *sd_orig
, *sd2
;
99 const char *owner_sid
;
101 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
104 torture_comment(tctx
, "TESTING SID_CREATOR_OWNER\n");
107 io
.level
= RAW_OPEN_SMB2
;
108 io
.in
.create_flags
= 0;
109 io
.in
.desired_access
= SEC_STD_READ_CONTROL
| SEC_STD_WRITE_DAC
| SEC_STD_WRITE_OWNER
;
110 io
.in
.create_options
= 0;
111 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
112 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
|
113 NTCREATEX_SHARE_ACCESS_READ
|
114 NTCREATEX_SHARE_ACCESS_WRITE
;
115 io
.in
.alloc_size
= 0;
116 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
117 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
118 io
.in
.security_flags
= 0;
121 status
= smb2_create(tree
, tctx
, &io
);
122 CHECK_STATUS(status
, NT_STATUS_OK
);
123 handle
= io
.out
.file
.handle
;
125 torture_comment(tctx
, "get the original sd\n");
126 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
127 q
.query_secdesc
.in
.file
.handle
= handle
;
128 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
129 status
= smb2_getinfo_file(tree
, tctx
, &q
);
130 CHECK_STATUS(status
, NT_STATUS_OK
);
131 sd_orig
= q
.query_secdesc
.out
.sd
;
133 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
135 torture_comment(tctx
, "set a sec desc allowing no write by CREATOR_OWNER\n");
136 sd
= security_descriptor_dacl_create(tctx
,
139 SEC_ACE_TYPE_ACCESS_ALLOWED
,
140 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
144 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
145 set
.set_secdesc
.in
.file
.handle
= handle
;
146 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
147 set
.set_secdesc
.in
.sd
= sd
;
149 status
= smb2_setinfo_file(tree
, &set
);
150 CHECK_STATUS(status
, NT_STATUS_OK
);
152 torture_comment(tctx
, "try open for write\n");
153 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
154 status
= smb2_create(tree
, tctx
, &io
);
155 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
157 torture_comment(tctx
, "try open for read\n");
158 io
.in
.desired_access
= SEC_FILE_READ_DATA
;
159 status
= smb2_create(tree
, tctx
, &io
);
160 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
162 torture_comment(tctx
, "try open for generic write\n");
163 io
.in
.desired_access
= SEC_GENERIC_WRITE
;
164 status
= smb2_create(tree
, tctx
, &io
);
165 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
167 torture_comment(tctx
, "try open for generic read\n");
168 io
.in
.desired_access
= SEC_GENERIC_READ
;
169 status
= smb2_create(tree
, tctx
, &io
);
170 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
172 torture_comment(tctx
, "set a sec desc allowing no write by owner\n");
173 sd
= security_descriptor_dacl_create(tctx
,
176 SEC_ACE_TYPE_ACCESS_ALLOWED
,
177 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
181 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
182 set
.set_secdesc
.in
.file
.handle
= handle
;
183 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
184 set
.set_secdesc
.in
.sd
= sd
;
185 status
= smb2_setinfo_file(tree
, &set
);
186 CHECK_STATUS(status
, NT_STATUS_OK
);
188 torture_comment(tctx
, "check that sd has been mapped correctly\n");
189 status
= smb2_getinfo_file(tree
, tctx
, &q
);
190 CHECK_STATUS(status
, NT_STATUS_OK
);
191 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
193 torture_comment(tctx
, "try open for write\n");
194 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
195 status
= smb2_create(tree
, tctx
, &io
);
196 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
198 torture_comment(tctx
, "try open for read\n");
199 io
.in
.desired_access
= SEC_FILE_READ_DATA
;
200 status
= smb2_create(tree
, tctx
, &io
);
201 CHECK_STATUS(status
, NT_STATUS_OK
);
202 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
204 smb2_util_close(tree
, io
.out
.file
.handle
);
206 torture_comment(tctx
, "try open for generic write\n");
207 io
.in
.desired_access
= SEC_GENERIC_WRITE
;
208 status
= smb2_create(tree
, tctx
, &io
);
209 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
211 torture_comment(tctx
, "try open for generic read\n");
212 io
.in
.desired_access
= SEC_GENERIC_READ
;
213 status
= smb2_create(tree
, tctx
, &io
);
214 CHECK_STATUS(status
, NT_STATUS_OK
);
215 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
216 SEC_RIGHTS_FILE_READ
);
217 smb2_util_close(tree
, io
.out
.file
.handle
);
219 torture_comment(tctx
, "set a sec desc allowing generic read by owner\n");
220 sd
= security_descriptor_dacl_create(tctx
,
223 SEC_ACE_TYPE_ACCESS_ALLOWED
,
224 SEC_GENERIC_READ
| SEC_STD_ALL
,
228 set
.set_secdesc
.in
.sd
= sd
;
229 status
= smb2_setinfo_file(tree
, &set
);
230 CHECK_STATUS(status
, NT_STATUS_OK
);
232 torture_comment(tctx
, "check that generic read has been mapped correctly\n");
233 sd2
= security_descriptor_dacl_create(tctx
,
236 SEC_ACE_TYPE_ACCESS_ALLOWED
,
237 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
241 status
= smb2_getinfo_file(tree
, tctx
, &q
);
242 CHECK_STATUS(status
, NT_STATUS_OK
);
243 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
245 torture_comment(tctx
, "try open for write\n");
246 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
247 status
= smb2_create(tree
, tctx
, &io
);
248 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
250 torture_comment(tctx
, "try open for read\n");
251 io
.in
.desired_access
= SEC_FILE_READ_DATA
;
252 status
= smb2_create(tree
, tctx
, &io
);
253 CHECK_STATUS(status
, NT_STATUS_OK
);
254 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
256 smb2_util_close(tree
, io
.out
.file
.handle
);
258 torture_comment(tctx
, "try open for generic write\n");
259 io
.in
.desired_access
= SEC_GENERIC_WRITE
;
260 status
= smb2_create(tree
, tctx
, &io
);
261 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
263 torture_comment(tctx
, "try open for generic read\n");
264 io
.in
.desired_access
= SEC_GENERIC_READ
;
265 status
= smb2_create(tree
, tctx
, &io
);
266 CHECK_STATUS(status
, NT_STATUS_OK
);
267 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
, SEC_RIGHTS_FILE_READ
);
268 smb2_util_close(tree
, io
.out
.file
.handle
);
271 torture_comment(tctx
, "put back original sd\n");
272 set
.set_secdesc
.in
.sd
= sd_orig
;
273 status
= smb2_setinfo_file(tree
, &set
);
274 CHECK_STATUS(status
, NT_STATUS_OK
);
278 smb2_util_close(tree
, handle
);
279 smb2_deltree(tree
, BASEDIR
);
281 smb2_logoff(tree
->session
);
287 test the mapping of the SEC_GENERIC_xx bits to SEC_STD_xx and
289 Note: This test was copied from raw/acls.c.
291 static bool test_generic_bits(struct torture_context
*tctx
, struct smb2_tree
*tree
)
294 struct smb2_create io
;
295 const char *fname
= BASEDIR
"\\generic.txt";
297 struct smb2_handle handle
;
299 union smb_fileinfo q
;
300 union smb_setfileinfo set
;
301 struct security_descriptor
*sd
, *sd_orig
, *sd2
;
302 const char *owner_sid
;
305 uint32_t specific_bits
;
306 } file_mappings
[] = {
308 { SEC_GENERIC_READ
, SEC_RIGHTS_FILE_READ
},
309 { SEC_GENERIC_WRITE
, SEC_RIGHTS_FILE_WRITE
},
310 { SEC_GENERIC_EXECUTE
, SEC_RIGHTS_FILE_EXECUTE
},
311 { SEC_GENERIC_ALL
, SEC_RIGHTS_FILE_ALL
},
312 { SEC_FILE_READ_DATA
, SEC_FILE_READ_DATA
},
313 { SEC_FILE_READ_ATTRIBUTE
, SEC_FILE_READ_ATTRIBUTE
}
317 uint32_t specific_bits
;
320 { SEC_GENERIC_READ
, SEC_RIGHTS_DIR_READ
},
321 { SEC_GENERIC_WRITE
, SEC_RIGHTS_DIR_WRITE
},
322 { SEC_GENERIC_EXECUTE
, SEC_RIGHTS_DIR_EXECUTE
},
323 { SEC_GENERIC_ALL
, SEC_RIGHTS_DIR_ALL
}
325 bool has_restore_privilege
= false;
326 bool has_take_ownership_privilege
= false;
328 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
331 torture_comment(tctx
, "TESTING FILE GENERIC BITS\n");
334 io
.level
= RAW_OPEN_SMB2
;
335 io
.in
.create_flags
= 0;
336 io
.in
.desired_access
=
337 SEC_STD_READ_CONTROL
|
340 io
.in
.create_options
= 0;
341 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
343 NTCREATEX_SHARE_ACCESS_READ
|
344 NTCREATEX_SHARE_ACCESS_WRITE
;
345 io
.in
.alloc_size
= 0;
346 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
347 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
348 io
.in
.security_flags
= 0;
350 status
= smb2_create(tree
, tctx
, &io
);
351 CHECK_STATUS(status
, NT_STATUS_OK
);
352 handle
= io
.out
.file
.handle
;
354 torture_comment(tctx
, "get the original sd\n");
355 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
356 q
.query_secdesc
.in
.file
.handle
= handle
;
357 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
358 status
= smb2_getinfo_file(tree
, tctx
, &q
);
359 CHECK_STATUS(status
, NT_STATUS_OK
);
360 sd_orig
= q
.query_secdesc
.out
.sd
;
362 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
365 * XXX: The smblsa calls use SMB as their transport - need to get rid of
369 status = smblsa_sid_check_privilege(cli,
371 sec_privilege_name(SEC_PRIV_RESTORE));
372 has_restore_privilege = NT_STATUS_IS_OK(status);
373 if (!NT_STATUS_IS_OK(status)) {
374 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
376 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
378 status = smblsa_sid_check_privilege(cli,
380 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
381 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
382 if (!NT_STATUS_IS_OK(status)) {
383 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
385 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
388 for (i
=0;i
<ARRAY_SIZE(file_mappings
);i
++) {
389 uint32_t expected_mask
=
391 SEC_STD_READ_CONTROL
|
392 SEC_FILE_READ_ATTRIBUTE
|
394 uint32_t expected_mask_anon
= SEC_FILE_READ_ATTRIBUTE
;
396 if (has_restore_privilege
) {
397 expected_mask_anon
|= SEC_STD_DELETE
;
400 torture_comment(tctx
, "Testing generic bits 0x%08x\n",
401 file_mappings
[i
].gen_bits
);
402 sd
= security_descriptor_dacl_create(tctx
,
405 SEC_ACE_TYPE_ACCESS_ALLOWED
,
406 file_mappings
[i
].gen_bits
,
410 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
411 set
.set_secdesc
.in
.file
.handle
= handle
;
412 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
413 set
.set_secdesc
.in
.sd
= sd
;
415 status
= smb2_setinfo_file(tree
, &set
);
416 CHECK_STATUS(status
, NT_STATUS_OK
);
418 sd2
= security_descriptor_dacl_create(tctx
,
421 SEC_ACE_TYPE_ACCESS_ALLOWED
,
422 file_mappings
[i
].specific_bits
,
426 status
= smb2_getinfo_file(tree
, tctx
, &q
);
427 CHECK_STATUS(status
, NT_STATUS_OK
);
428 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
430 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
431 status
= smb2_create(tree
, tctx
, &io
);
432 CHECK_STATUS(status
, NT_STATUS_OK
);
433 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
434 expected_mask
| file_mappings
[i
].specific_bits
);
435 smb2_util_close(tree
, io
.out
.file
.handle
);
437 if (!has_take_ownership_privilege
) {
441 torture_comment(tctx
, "Testing generic bits 0x%08x (anonymous)\n",
442 file_mappings
[i
].gen_bits
);
443 sd
= security_descriptor_dacl_create(tctx
,
444 0, SID_NT_ANONYMOUS
, NULL
,
446 SEC_ACE_TYPE_ACCESS_ALLOWED
,
447 file_mappings
[i
].gen_bits
,
451 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
452 set
.set_secdesc
.in
.file
.handle
= handle
;
453 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
454 set
.set_secdesc
.in
.sd
= sd
;
456 status
= smb2_setinfo_file(tree
, &set
);
457 CHECK_STATUS(status
, NT_STATUS_OK
);
459 sd2
= security_descriptor_dacl_create(tctx
,
460 0, SID_NT_ANONYMOUS
, NULL
,
462 SEC_ACE_TYPE_ACCESS_ALLOWED
,
463 file_mappings
[i
].specific_bits
,
467 status
= smb2_getinfo_file(tree
, tctx
, &q
);
468 CHECK_STATUS(status
, NT_STATUS_OK
);
469 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
471 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
472 status
= smb2_create(tree
, tctx
, &io
);
473 CHECK_STATUS(status
, NT_STATUS_OK
);
474 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
475 expected_mask_anon
| file_mappings
[i
].specific_bits
);
476 smb2_util_close(tree
, io
.out
.file
.handle
);
479 torture_comment(tctx
, "put back original sd\n");
480 set
.set_secdesc
.in
.sd
= sd_orig
;
481 status
= smb2_setinfo_file(tree
, &set
);
482 CHECK_STATUS(status
, NT_STATUS_OK
);
484 smb2_util_close(tree
, handle
);
485 smb2_util_unlink(tree
, fname
);
488 torture_comment(tctx
, "TESTING DIR GENERIC BITS\n");
491 io
.level
= RAW_OPEN_SMB2
;
492 io
.in
.create_flags
= 0;
493 io
.in
.desired_access
=
494 SEC_STD_READ_CONTROL
|
497 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
498 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
500 NTCREATEX_SHARE_ACCESS_READ
|
501 NTCREATEX_SHARE_ACCESS_WRITE
;
502 io
.in
.alloc_size
= 0;
503 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
504 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
505 io
.in
.security_flags
= 0;
507 status
= smb2_create(tree
, tctx
, &io
);
508 CHECK_STATUS(status
, NT_STATUS_OK
);
509 handle
= io
.out
.file
.handle
;
511 torture_comment(tctx
, "get the original sd\n");
512 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
513 q
.query_secdesc
.in
.file
.handle
= handle
;
514 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
515 status
= smb2_getinfo_file(tree
, tctx
, &q
);
516 CHECK_STATUS(status
, NT_STATUS_OK
);
517 sd_orig
= q
.query_secdesc
.out
.sd
;
519 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
522 * XXX: The smblsa calls use SMB as their transport - need to get rid of
526 status = smblsa_sid_check_privilege(cli,
528 sec_privilege_name(SEC_PRIV_RESTORE));
529 has_restore_privilege = NT_STATUS_IS_OK(status);
530 if (!NT_STATUS_IS_OK(status)) {
531 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
533 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
535 status = smblsa_sid_check_privilege(cli,
537 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
538 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
539 if (!NT_STATUS_IS_OK(status)) {
540 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
542 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
545 for (i
=0;i
<ARRAY_SIZE(dir_mappings
);i
++) {
546 uint32_t expected_mask
=
548 SEC_STD_READ_CONTROL
|
549 SEC_FILE_READ_ATTRIBUTE
|
551 uint32_t expected_mask_anon
= SEC_FILE_READ_ATTRIBUTE
;
553 if (has_restore_privilege
) {
554 expected_mask_anon
|= SEC_STD_DELETE
;
557 torture_comment(tctx
, "Testing generic bits 0x%08x\n",
558 file_mappings
[i
].gen_bits
);
559 sd
= security_descriptor_dacl_create(tctx
,
562 SEC_ACE_TYPE_ACCESS_ALLOWED
,
563 dir_mappings
[i
].gen_bits
,
567 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
568 set
.set_secdesc
.in
.file
.handle
= handle
;
569 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
570 set
.set_secdesc
.in
.sd
= sd
;
572 status
= smb2_setinfo_file(tree
, &set
);
573 CHECK_STATUS(status
, NT_STATUS_OK
);
575 sd2
= security_descriptor_dacl_create(tctx
,
578 SEC_ACE_TYPE_ACCESS_ALLOWED
,
579 dir_mappings
[i
].specific_bits
,
583 status
= smb2_getinfo_file(tree
, tctx
, &q
);
584 CHECK_STATUS(status
, NT_STATUS_OK
);
585 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
587 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
588 status
= smb2_create(tree
, tctx
, &io
);
589 CHECK_STATUS(status
, NT_STATUS_OK
);
590 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
591 expected_mask
| dir_mappings
[i
].specific_bits
);
592 smb2_util_close(tree
, io
.out
.file
.handle
);
594 if (!has_take_ownership_privilege
) {
598 torture_comment(tctx
, "Testing generic bits 0x%08x (anonymous)\n",
599 file_mappings
[i
].gen_bits
);
600 sd
= security_descriptor_dacl_create(tctx
,
601 0, SID_NT_ANONYMOUS
, NULL
,
603 SEC_ACE_TYPE_ACCESS_ALLOWED
,
604 file_mappings
[i
].gen_bits
,
608 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
609 set
.set_secdesc
.in
.file
.handle
= handle
;
610 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
611 set
.set_secdesc
.in
.sd
= sd
;
613 status
= smb2_setinfo_file(tree
, &set
);
614 CHECK_STATUS(status
, NT_STATUS_OK
);
616 sd2
= security_descriptor_dacl_create(tctx
,
617 0, SID_NT_ANONYMOUS
, NULL
,
619 SEC_ACE_TYPE_ACCESS_ALLOWED
,
620 file_mappings
[i
].specific_bits
,
624 status
= smb2_getinfo_file(tree
, tctx
, &q
);
625 CHECK_STATUS(status
, NT_STATUS_OK
);
626 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
628 io
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
629 status
= smb2_create(tree
, tctx
, &io
);
630 CHECK_STATUS(status
, NT_STATUS_OK
);
631 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
,
632 expected_mask_anon
| dir_mappings
[i
].specific_bits
);
633 smb2_util_close(tree
, io
.out
.file
.handle
);
636 torture_comment(tctx
, "put back original sd\n");
637 set
.set_secdesc
.in
.sd
= sd_orig
;
638 status
= smb2_setinfo_file(tree
, &set
);
639 CHECK_STATUS(status
, NT_STATUS_OK
);
641 smb2_util_close(tree
, handle
);
642 smb2_util_unlink(tree
, fname
);
645 smb2_util_close(tree
, handle
);
646 smb2_deltree(tree
, BASEDIR
);
648 smb2_logoff(tree
->session
);
654 see what access bits the owner of a file always gets
655 Note: This test was copied from raw/acls.c.
657 static bool test_owner_bits(struct torture_context
*tctx
, struct smb2_tree
*tree
)
660 struct smb2_create io
;
661 const char *fname
= BASEDIR
"\\test_owner_bits.txt";
663 struct smb2_handle handle
;
665 union smb_fileinfo q
;
666 union smb_setfileinfo set
;
667 struct security_descriptor
*sd
, *sd_orig
;
668 const char *owner_sid
;
669 uint32_t expected_bits
;
671 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
674 torture_comment(tctx
, "TESTING FILE OWNER BITS\n");
677 io
.level
= RAW_OPEN_SMB2
;
678 io
.in
.create_flags
= 0;
679 io
.in
.desired_access
=
680 SEC_STD_READ_CONTROL
|
683 io
.in
.create_options
= 0;
684 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
686 NTCREATEX_SHARE_ACCESS_READ
|
687 NTCREATEX_SHARE_ACCESS_WRITE
;
688 io
.in
.alloc_size
= 0;
689 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
690 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
691 io
.in
.security_flags
= 0;
693 status
= smb2_create(tree
, tctx
, &io
);
694 CHECK_STATUS(status
, NT_STATUS_OK
);
695 handle
= io
.out
.file
.handle
;
697 torture_comment(tctx
, "get the original sd\n");
698 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
699 q
.query_secdesc
.in
.file
.handle
= handle
;
700 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
701 status
= smb2_getinfo_file(tree
, tctx
, &q
);
702 CHECK_STATUS(status
, NT_STATUS_OK
);
703 sd_orig
= q
.query_secdesc
.out
.sd
;
705 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
708 * XXX: The smblsa calls use SMB as their transport - need to get rid of
712 status = smblsa_sid_check_privilege(cli,
714 sec_privilege_name(SEC_PRIV_RESTORE));
715 has_restore_privilege = NT_STATUS_IS_OK(status);
716 if (!NT_STATUS_IS_OK(status)) {
717 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
719 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
721 status = smblsa_sid_check_privilege(cli,
723 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
724 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
725 if (!NT_STATUS_IS_OK(status)) {
726 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
728 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
731 sd
= security_descriptor_dacl_create(tctx
,
734 SEC_ACE_TYPE_ACCESS_ALLOWED
,
739 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
740 set
.set_secdesc
.in
.file
.handle
= handle
;
741 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
742 set
.set_secdesc
.in
.sd
= sd
;
744 status
= smb2_setinfo_file(tree
, &set
);
745 CHECK_STATUS(status
, NT_STATUS_OK
);
747 expected_bits
= SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
;
750 uint32_t bit
= (1<<i
);
751 io
.in
.desired_access
= bit
;
752 status
= smb2_create(tree
, tctx
, &io
);
753 if (expected_bits
& bit
) {
754 if (!NT_STATUS_IS_OK(status
)) {
755 torture_warning(tctx
, "failed with access mask 0x%08x of expected 0x%08x\n",
758 CHECK_STATUS(status
, NT_STATUS_OK
);
759 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
, bit
);
760 smb2_util_close(tree
, io
.out
.file
.handle
);
762 if (NT_STATUS_IS_OK(status
)) {
763 torture_warning(tctx
, "open succeeded with access mask 0x%08x of "
764 "expected 0x%08x - should fail\n",
767 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
771 torture_comment(tctx
, "put back original sd\n");
772 set
.set_secdesc
.in
.sd
= sd_orig
;
773 status
= smb2_setinfo_file(tree
, &set
);
774 CHECK_STATUS(status
, NT_STATUS_OK
);
777 smb2_util_close(tree
, handle
);
778 smb2_util_unlink(tree
, fname
);
779 smb2_deltree(tree
, BASEDIR
);
781 smb2_logoff(tree
->session
);
788 test the inheritance of ACL flags onto new files and directories
789 Note: This test was copied from raw/acls.c.
791 static bool test_inheritance(struct torture_context
*tctx
, struct smb2_tree
*tree
)
794 struct smb2_create io
;
795 const char *dname
= BASEDIR
"\\inheritance";
796 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
797 const char *fname2
= BASEDIR
"\\inheritance\\testdir";
799 struct smb2_handle handle
, handle2
;
801 union smb_fileinfo q
;
802 union smb_setfileinfo set
;
803 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
, *sd_def1
, *sd_def2
;
804 const char *owner_sid
;
805 const struct dom_sid
*creator_owner
;
807 uint32_t parent_flags
;
817 SEC_ACE_FLAG_OBJECT_INHERIT
,
819 SEC_ACE_FLAG_OBJECT_INHERIT
|
820 SEC_ACE_FLAG_INHERIT_ONLY
,
823 SEC_ACE_FLAG_CONTAINER_INHERIT
,
825 SEC_ACE_FLAG_CONTAINER_INHERIT
,
828 SEC_ACE_FLAG_OBJECT_INHERIT
|
829 SEC_ACE_FLAG_CONTAINER_INHERIT
,
831 SEC_ACE_FLAG_OBJECT_INHERIT
|
832 SEC_ACE_FLAG_CONTAINER_INHERIT
,
835 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
840 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
841 SEC_ACE_FLAG_OBJECT_INHERIT
,
846 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
847 SEC_ACE_FLAG_CONTAINER_INHERIT
,
852 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
853 SEC_ACE_FLAG_CONTAINER_INHERIT
|
854 SEC_ACE_FLAG_OBJECT_INHERIT
,
859 SEC_ACE_FLAG_INHERIT_ONLY
,
864 SEC_ACE_FLAG_INHERIT_ONLY
|
865 SEC_ACE_FLAG_OBJECT_INHERIT
,
867 SEC_ACE_FLAG_OBJECT_INHERIT
|
868 SEC_ACE_FLAG_INHERIT_ONLY
,
871 SEC_ACE_FLAG_INHERIT_ONLY
|
872 SEC_ACE_FLAG_CONTAINER_INHERIT
,
874 SEC_ACE_FLAG_CONTAINER_INHERIT
,
877 SEC_ACE_FLAG_INHERIT_ONLY
|
878 SEC_ACE_FLAG_CONTAINER_INHERIT
|
879 SEC_ACE_FLAG_OBJECT_INHERIT
,
881 SEC_ACE_FLAG_CONTAINER_INHERIT
|
882 SEC_ACE_FLAG_OBJECT_INHERIT
,
885 SEC_ACE_FLAG_INHERIT_ONLY
|
886 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
891 SEC_ACE_FLAG_INHERIT_ONLY
|
892 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
893 SEC_ACE_FLAG_OBJECT_INHERIT
,
898 SEC_ACE_FLAG_INHERIT_ONLY
|
899 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
900 SEC_ACE_FLAG_CONTAINER_INHERIT
,
905 SEC_ACE_FLAG_INHERIT_ONLY
|
906 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
907 SEC_ACE_FLAG_CONTAINER_INHERIT
|
908 SEC_ACE_FLAG_OBJECT_INHERIT
,
914 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
917 torture_comment(tctx
, "TESTING ACL INHERITANCE\n");
920 io
.level
= RAW_OPEN_SMB2
;
921 io
.in
.create_flags
= 0;
922 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
923 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
924 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
925 io
.in
.share_access
= 0;
926 io
.in
.alloc_size
= 0;
927 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
928 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
929 io
.in
.security_flags
= 0;
932 status
= smb2_create(tree
, tctx
, &io
);
933 CHECK_STATUS(status
, NT_STATUS_OK
);
934 handle
= io
.out
.file
.handle
;
936 torture_comment(tctx
, "get the original sd\n");
937 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
938 q
.query_secdesc
.in
.file
.handle
= handle
;
939 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
940 status
= smb2_getinfo_file(tree
, tctx
, &q
);
941 CHECK_STATUS(status
, NT_STATUS_OK
);
942 sd_orig
= q
.query_secdesc
.out
.sd
;
944 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
946 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
949 * The Windows Default ACL for a new file, when there is no ACL to be
950 * inherited: FullControl for the owner and SYSTEM.
952 sd_def1
= security_descriptor_dacl_create(tctx
,
955 SEC_ACE_TYPE_ACCESS_ALLOWED
,
959 SEC_ACE_TYPE_ACCESS_ALLOWED
,
965 * Use this in the case the system being tested does not add an ACE for
968 sd_def2
= security_descriptor_dacl_create(tctx
,
971 SEC_ACE_TYPE_ACCESS_ALLOWED
,
976 creator_owner
= dom_sid_parse_talloc(tctx
, SID_CREATOR_OWNER
);
978 for (i
=0;i
<ARRAY_SIZE(test_flags
);i
++) {
979 sd
= security_descriptor_dacl_create(tctx
,
982 SEC_ACE_TYPE_ACCESS_ALLOWED
,
984 test_flags
[i
].parent_flags
,
986 SEC_ACE_TYPE_ACCESS_ALLOWED
,
987 SEC_FILE_ALL
| SEC_STD_ALL
,
990 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
991 set
.set_secdesc
.in
.file
.handle
= handle
;
992 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
993 set
.set_secdesc
.in
.sd
= sd
;
994 status
= smb2_setinfo_file(tree
, &set
);
995 CHECK_STATUS(status
, NT_STATUS_OK
);
997 io
.in
.fname
= fname1
;
998 io
.in
.create_options
= 0;
999 status
= smb2_create(tree
, tctx
, &io
);
1000 CHECK_STATUS(status
, NT_STATUS_OK
);
1001 handle2
= io
.out
.file
.handle
;
1003 q
.query_secdesc
.in
.file
.handle
= handle2
;
1004 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1005 CHECK_STATUS(status
, NT_STATUS_OK
);
1007 smb2_util_close(tree
, handle2
);
1008 smb2_util_unlink(tree
, fname1
);
1010 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
)) {
1011 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def1
) &&
1012 !security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def2
)) {
1013 torture_warning(tctx
, "Expected default sd:\n");
1014 NDR_PRINT_DEBUG(security_descriptor
, sd_def1
);
1015 torture_warning(tctx
, "at %d - got:\n", i
);
1016 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1021 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1022 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1023 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1024 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1025 sd_orig
->owner_sid
)) {
1026 torture_warning(tctx
, "Bad sd in child file at %d\n", i
);
1027 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1032 if (q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!=
1033 test_flags
[i
].file_flags
) {
1034 torture_warning(tctx
, "incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1035 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
,
1036 test_flags
[i
].file_flags
,
1037 test_flags
[i
].parent_flags
,
1043 io
.in
.fname
= fname2
;
1044 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1045 status
= smb2_create(tree
, tctx
, &io
);
1046 CHECK_STATUS(status
, NT_STATUS_OK
);
1047 handle2
= io
.out
.file
.handle
;
1049 q
.query_secdesc
.in
.file
.handle
= handle2
;
1050 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1051 CHECK_STATUS(status
, NT_STATUS_OK
);
1053 smb2_util_close(tree
, handle2
);
1054 smb2_util_rmdir(tree
, fname2
);
1056 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1057 (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
) ||
1058 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
))) {
1059 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def1
) &&
1060 !security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def2
)) {
1061 torture_warning(tctx
, "Expected default sd for dir at %d:\n", i
);
1062 NDR_PRINT_DEBUG(security_descriptor
, sd_def1
);
1063 torture_warning(tctx
, "got:\n");
1064 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1069 if ((test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1070 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
)) {
1071 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1072 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1073 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1074 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1075 sd_orig
->owner_sid
) ||
1076 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1077 torture_warning(tctx
, "(CI & NP) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1078 test_flags
[i
].dir_flags
,
1079 test_flags
[i
].parent_flags
, i
);
1080 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1081 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1082 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1086 } else if (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) {
1087 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1088 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 2 ||
1089 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1090 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1091 sd_orig
->owner_sid
) ||
1092 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].access_mask
!= SEC_FILE_WRITE_DATA
||
1093 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[1].trustee
,
1095 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= 0 ||
1096 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].flags
!=
1097 (test_flags
[i
].dir_flags
| SEC_ACE_FLAG_INHERIT_ONLY
)) {
1098 torture_warning(tctx
, "(CI) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1099 test_flags
[i
].dir_flags
,
1100 test_flags
[i
].parent_flags
, i
);
1101 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1102 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1103 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1108 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1109 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1110 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1111 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1113 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1114 torture_warning(tctx
, "(0) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1115 test_flags
[i
].dir_flags
,
1116 test_flags
[i
].parent_flags
, i
);
1117 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1118 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1119 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1126 torture_comment(tctx
, "Testing access checks on inherited create with %s\n", fname1
);
1127 sd
= security_descriptor_dacl_create(tctx
,
1130 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1131 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1132 SEC_ACE_FLAG_OBJECT_INHERIT
,
1134 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1135 SEC_FILE_ALL
| SEC_STD_ALL
,
1138 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1139 set
.set_secdesc
.in
.file
.handle
= handle
;
1140 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1141 set
.set_secdesc
.in
.sd
= sd
;
1142 status
= smb2_setinfo_file(tree
, &set
);
1143 CHECK_STATUS(status
, NT_STATUS_OK
);
1145 /* Check DACL we just set. */
1146 torture_comment(tctx
, "checking new sd\n");
1147 q
.query_secdesc
.in
.file
.handle
= handle
;
1148 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1149 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1150 CHECK_STATUS(status
, NT_STATUS_OK
);
1151 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1153 io
.in
.fname
= fname1
;
1154 io
.in
.create_options
= 0;
1155 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1156 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1157 status
= smb2_create(tree
, tctx
, &io
);
1158 CHECK_STATUS(status
, NT_STATUS_OK
);
1159 handle2
= io
.out
.file
.handle
;
1160 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1162 q
.query_secdesc
.in
.file
.handle
= handle2
;
1163 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1164 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1165 CHECK_STATUS(status
, NT_STATUS_OK
);
1166 smb2_util_close(tree
, handle2
);
1168 sd2
= security_descriptor_dacl_create(tctx
,
1171 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1172 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1175 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1177 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1178 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1179 status
= smb2_create(tree
, tctx
, &io
);
1180 if (NT_STATUS_IS_OK(status
)) {
1181 torture_warning(tctx
, "failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1183 handle2
= io
.out
.file
.handle
;
1184 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1185 smb2_util_close(tree
, handle2
);
1187 if (torture_setting_bool(tctx
, "hide_on_access_denied",
1189 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1191 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1195 torture_comment(tctx
, "trying without execute\n");
1196 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1197 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
& ~SEC_FILE_EXECUTE
;
1198 status
= smb2_create(tree
, tctx
, &io
);
1199 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1200 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1202 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1205 torture_comment(tctx
, "and with full permissions again\n");
1206 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1207 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1208 status
= smb2_create(tree
, tctx
, &io
);
1209 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1210 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1212 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1215 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1216 status
= smb2_create(tree
, tctx
, &io
);
1217 CHECK_STATUS(status
, NT_STATUS_OK
);
1218 handle2
= io
.out
.file
.handle
;
1219 CHECK_ACCESS_FLAGS(handle2
, SEC_FILE_WRITE_DATA
);
1220 smb2_util_close(tree
, handle2
);
1222 torture_comment(tctx
, "put back original sd\n");
1223 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1224 set
.set_secdesc
.in
.file
.handle
= handle
;
1225 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1226 set
.set_secdesc
.in
.sd
= sd_orig
;
1227 status
= smb2_setinfo_file(tree
, &set
);
1228 CHECK_STATUS(status
, NT_STATUS_OK
);
1230 smb2_util_close(tree
, handle
);
1232 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1233 status
= smb2_create(tree
, tctx
, &io
);
1234 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1235 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1237 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1240 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1241 status
= smb2_create(tree
, tctx
, &io
);
1242 CHECK_STATUS(status
, NT_STATUS_OK
);
1243 handle2
= io
.out
.file
.handle
;
1244 CHECK_ACCESS_FLAGS(handle2
, SEC_FILE_WRITE_DATA
);
1245 smb2_util_close(tree
, handle2
);
1247 smb2_util_unlink(tree
, fname1
);
1248 smb2_util_rmdir(tree
, dname
);
1251 if (sd_orig
!= NULL
) {
1252 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1253 set
.set_secdesc
.in
.file
.handle
= handle
;
1254 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1255 set
.set_secdesc
.in
.sd
= sd_orig
;
1256 status
= smb2_setinfo_file(tree
, &set
);
1259 smb2_util_close(tree
, handle
);
1260 smb2_deltree(tree
, BASEDIR
);
1262 smb2_logoff(tree
->session
);
1266 static bool test_inheritance_flags(struct torture_context
*tctx
,
1267 struct smb2_tree
*tree
)
1270 struct smb2_create io
;
1271 const char *dname
= BASEDIR
"\\inheritance";
1272 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1274 struct smb2_handle handle
, handle2
;
1276 union smb_fileinfo q
;
1277 union smb_setfileinfo set
;
1278 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
;
1279 const char *owner_sid
;
1281 uint32_t parent_set_sd_type
; /* 3 options */
1282 uint32_t parent_set_ace_inherit
; /* 1 option */
1283 uint32_t parent_get_sd_type
;
1284 uint32_t parent_get_ace_inherit
;
1285 uint32_t child_get_sd_type
;
1286 uint32_t child_get_ace_inherit
;
1287 } tflags
[16] = {{0}}; /* 2^4 */
1289 for (i
= 0; i
< 15; i
++) {
1290 torture_comment(tctx
, "i=%d:", i
);
1293 tflags
[i
].parent_set_sd_type
|=
1294 SEC_DESC_DACL_AUTO_INHERITED
;
1295 torture_comment(tctx
, "AUTO_INHERITED, ");
1298 tflags
[i
].parent_set_sd_type
|=
1299 SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1300 torture_comment(tctx
, "AUTO_INHERIT_REQ, ");
1303 tflags
[i
].parent_set_sd_type
|=
1304 SEC_DESC_DACL_PROTECTED
;
1305 torture_comment(tctx
, "PROTECTED, ");
1306 tflags
[i
].parent_get_sd_type
|=
1307 SEC_DESC_DACL_PROTECTED
;
1310 tflags
[i
].parent_set_ace_inherit
|=
1311 SEC_ACE_FLAG_INHERITED_ACE
;
1312 torture_comment(tctx
, "INHERITED, ");
1313 tflags
[i
].parent_get_ace_inherit
|=
1314 SEC_ACE_FLAG_INHERITED_ACE
;
1317 if ((tflags
[i
].parent_set_sd_type
&
1318 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) ==
1319 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) {
1320 tflags
[i
].parent_get_sd_type
|=
1321 SEC_DESC_DACL_AUTO_INHERITED
;
1322 tflags
[i
].child_get_sd_type
|=
1323 SEC_DESC_DACL_AUTO_INHERITED
;
1324 tflags
[i
].child_get_ace_inherit
|=
1325 SEC_ACE_FLAG_INHERITED_ACE
;
1326 torture_comment(tctx
, " ... parent is AUTO INHERITED");
1329 if (tflags
[i
].parent_set_ace_inherit
&
1330 SEC_ACE_FLAG_INHERITED_ACE
) {
1331 tflags
[i
].parent_get_ace_inherit
=
1332 SEC_ACE_FLAG_INHERITED_ACE
;
1333 torture_comment(tctx
, " ... parent ACE is INHERITED");
1336 torture_comment(tctx
, "\n");
1339 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1342 torture_comment(tctx
, "TESTING ACL INHERITANCE FLAGS\n");
1345 io
.level
= RAW_OPEN_SMB2
;
1346 io
.in
.create_flags
= 0;
1347 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1348 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1349 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1350 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
;
1351 io
.in
.alloc_size
= 0;
1352 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1353 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1354 io
.in
.security_flags
= 0;
1355 io
.in
.fname
= dname
;
1357 torture_comment(tctx
, "creating initial directory %s\n", dname
);
1358 status
= smb2_create(tree
, tctx
, &io
);
1359 CHECK_STATUS(status
, NT_STATUS_OK
);
1360 handle
= io
.out
.file
.handle
;
1362 torture_comment(tctx
, "getting original sd\n");
1363 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1364 q
.query_secdesc
.in
.file
.handle
= handle
;
1365 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1366 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1367 CHECK_STATUS(status
, NT_STATUS_OK
);
1368 sd_orig
= q
.query_secdesc
.out
.sd
;
1370 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1371 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1373 for (i
=0; i
< ARRAY_SIZE(tflags
); i
++) {
1374 torture_comment(tctx
, "setting a new sd on directory, pass #%d\n", i
);
1376 sd
= security_descriptor_dacl_create(tctx
,
1377 tflags
[i
].parent_set_sd_type
,
1380 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1381 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1382 SEC_ACE_FLAG_OBJECT_INHERIT
|
1383 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1384 tflags
[i
].parent_set_ace_inherit
,
1386 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1387 SEC_FILE_ALL
| SEC_STD_ALL
,
1390 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1391 set
.set_secdesc
.in
.file
.handle
= handle
;
1392 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1393 set
.set_secdesc
.in
.sd
= sd
;
1394 status
= smb2_setinfo_file(tree
, &set
);
1395 CHECK_STATUS(status
, NT_STATUS_OK
);
1398 * Check DACL we just set, except change the bits to what they
1401 torture_comment(tctx
, " checking new sd\n");
1403 /* REQ bit should always be false. */
1404 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1406 if ((tflags
[i
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1407 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1409 q
.query_secdesc
.in
.file
.handle
= handle
;
1410 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1411 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1412 CHECK_STATUS(status
, NT_STATUS_OK
);
1413 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1416 torture_comment(tctx
, " creating file %s\n", fname1
);
1417 io
.in
.fname
= fname1
;
1418 io
.in
.create_options
= 0;
1419 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1420 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1421 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1422 status
= smb2_create(tree
, tctx
, &io
);
1423 CHECK_STATUS(status
, NT_STATUS_OK
);
1424 handle2
= io
.out
.file
.handle
;
1425 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1427 q
.query_secdesc
.in
.file
.handle
= handle2
;
1428 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1429 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1430 CHECK_STATUS(status
, NT_STATUS_OK
);
1432 torture_comment(tctx
, " checking sd on file %s\n", fname1
);
1433 sd2
= security_descriptor_dacl_create(tctx
,
1434 tflags
[i
].child_get_sd_type
,
1437 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1438 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1439 tflags
[i
].child_get_ace_inherit
,
1441 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1444 * Set new sd on file ... prove that the bits have nothing to
1445 * do with the parents bits when manually setting an ACL. The
1446 * _AUTO_INHERITED bit comes directly from the ACL set.
1448 for (j
= 0; j
< ARRAY_SIZE(tflags
); j
++) {
1449 torture_comment(tctx
, " setting new file sd, pass #%d\n", j
);
1451 /* Change sd type. */
1452 sd2
->type
&= ~(SEC_DESC_DACL_AUTO_INHERITED
|
1453 SEC_DESC_DACL_AUTO_INHERIT_REQ
|
1454 SEC_DESC_DACL_PROTECTED
);
1455 sd2
->type
|= tflags
[j
].parent_set_sd_type
;
1457 sd2
->dacl
->aces
[0].flags
&=
1458 ~SEC_ACE_FLAG_INHERITED_ACE
;
1459 sd2
->dacl
->aces
[0].flags
|=
1460 tflags
[j
].parent_set_ace_inherit
;
1462 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1463 set
.set_secdesc
.in
.file
.handle
= handle2
;
1464 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1465 set
.set_secdesc
.in
.sd
= sd2
;
1466 status
= smb2_setinfo_file(tree
, &set
);
1467 CHECK_STATUS(status
, NT_STATUS_OK
);
1469 /* Check DACL we just set. */
1470 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1471 if ((tflags
[j
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1472 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1474 q
.query_secdesc
.in
.file
.handle
= handle2
;
1475 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1476 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1477 CHECK_STATUS(status
, NT_STATUS_OK
);
1479 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1482 smb2_util_close(tree
, handle2
);
1483 smb2_util_unlink(tree
, fname1
);
1487 smb2_util_close(tree
, handle
);
1488 smb2_deltree(tree
, BASEDIR
);
1490 smb2_logoff(tree
->session
);
1495 test dynamic acl inheritance
1496 Note: This test was copied from raw/acls.c.
1498 static bool test_inheritance_dynamic(struct torture_context
*tctx
,
1499 struct smb2_tree
*tree
)
1502 struct smb2_create io
;
1503 const char *dname
= BASEDIR
"\\inheritance";
1504 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1506 struct smb2_handle handle
, handle2
;
1507 union smb_fileinfo q
;
1508 union smb_setfileinfo set
;
1509 struct security_descriptor
*sd
, *sd_orig
=NULL
;
1510 const char *owner_sid
;
1512 torture_comment(tctx
, "TESTING DYNAMIC ACL INHERITANCE\n");
1514 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1518 io
.level
= RAW_OPEN_SMB2
;
1519 io
.in
.create_flags
= 0;
1520 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1521 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1522 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1523 io
.in
.share_access
= 0;
1524 io
.in
.alloc_size
= 0;
1525 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1526 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1527 io
.in
.security_flags
= 0;
1528 io
.in
.fname
= dname
;
1530 status
= smb2_create(tree
, tctx
, &io
);
1531 CHECK_STATUS(status
, NT_STATUS_OK
);
1532 handle
= io
.out
.file
.handle
;
1534 torture_comment(tctx
, "get the original sd\n");
1535 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1536 q
.query_secdesc
.in
.file
.handle
= handle
;
1537 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1538 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1539 CHECK_STATUS(status
, NT_STATUS_OK
);
1540 sd_orig
= q
.query_secdesc
.out
.sd
;
1542 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1544 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1546 sd
= security_descriptor_dacl_create(tctx
,
1549 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1550 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
,
1551 SEC_ACE_FLAG_OBJECT_INHERIT
,
1553 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1555 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1556 set
.set_secdesc
.in
.file
.handle
= handle
;
1557 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1558 set
.set_secdesc
.in
.sd
= sd
;
1559 status
= smb2_setinfo_file(tree
, &set
);
1560 CHECK_STATUS(status
, NT_STATUS_OK
);
1562 torture_comment(tctx
, "create a file with an inherited acl\n");
1563 io
.in
.fname
= fname1
;
1564 io
.in
.create_options
= 0;
1565 io
.in
.desired_access
= SEC_FILE_READ_ATTRIBUTE
;
1566 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1567 status
= smb2_create(tree
, tctx
, &io
);
1568 CHECK_STATUS(status
, NT_STATUS_OK
);
1569 handle2
= io
.out
.file
.handle
;
1570 smb2_util_close(tree
, handle2
);
1572 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
1573 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1574 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1575 status
= smb2_create(tree
, tctx
, &io
);
1576 CHECK_STATUS(status
, NT_STATUS_OK
);
1577 handle2
= io
.out
.file
.handle
;
1578 smb2_util_close(tree
, handle2
);
1580 torture_comment(tctx
, "try and access file with extra rights - should be denied\n");
1581 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1582 status
= smb2_create(tree
, tctx
, &io
);
1583 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1585 torture_comment(tctx
, "update parent sd\n");
1586 sd
= security_descriptor_dacl_create(tctx
,
1589 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1590 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
,
1591 SEC_ACE_FLAG_OBJECT_INHERIT
,
1593 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1595 set
.set_secdesc
.in
.sd
= sd
;
1596 status
= smb2_setinfo_file(tree
, &set
);
1597 CHECK_STATUS(status
, NT_STATUS_OK
);
1599 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
1600 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1601 status
= smb2_create(tree
, tctx
, &io
);
1602 CHECK_STATUS(status
, NT_STATUS_OK
);
1603 handle2
= io
.out
.file
.handle
;
1604 smb2_util_close(tree
, handle2
);
1607 torture_comment(tctx
, "try and access now - should be OK if dynamic inheritance works\n");
1608 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1609 status
= smb2_create(tree
, tctx
, &io
);
1610 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1611 torture_comment(tctx
, "Server does not have dynamic inheritance\n");
1613 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1614 torture_comment(tctx
, "Server does have dynamic inheritance\n");
1616 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1618 smb2_util_unlink(tree
, fname1
);
1621 torture_comment(tctx
, "put back original sd\n");
1622 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1623 set
.set_secdesc
.in
.file
.handle
= handle
;
1624 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1625 set
.set_secdesc
.in
.sd
= sd_orig
;
1626 status
= smb2_setinfo_file(tree
, &set
);
1628 smb2_util_close(tree
, handle
);
1629 smb2_util_rmdir(tree
, dname
);
1630 smb2_deltree(tree
, BASEDIR
);
1632 smb2_logoff(tree
->session
);
1637 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
1638 if (!(bits & desired_64)) {\
1639 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
1642 CHECK_STATUS(status, NT_STATUS_OK); \
1646 #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
1647 if (NT_STATUS_IS_OK(status)) { \
1648 if (!(granted & access)) {\
1650 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
1651 __location__, nt_errstr(status), access, granted, desired); \
1655 if (granted & access) {\
1657 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
1658 __location__, nt_errstr(status), access, granted, desired); \
1662 CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
1665 /* test what access mask is needed for getting and setting security_descriptors */
1666 /* Note: This test was copied from raw/acls.c. */
1667 static bool test_sd_get_set(struct torture_context
*tctx
, struct smb2_tree
*tree
)
1671 struct smb2_create io
;
1672 union smb_fileinfo fi
;
1673 union smb_setfileinfo si
;
1674 struct security_descriptor
*sd
;
1675 struct security_descriptor
*sd_owner
= NULL
;
1676 struct security_descriptor
*sd_group
= NULL
;
1677 struct security_descriptor
*sd_dacl
= NULL
;
1678 struct security_descriptor
*sd_sacl
= NULL
;
1679 struct smb2_handle handle
;
1680 const char *fname
= BASEDIR
"\\sd_get_set.txt";
1681 uint64_t desired_64
;
1682 uint32_t desired
= 0, granted
;
1684 #define NO_BITS_HACK (((uint64_t)1)<<32)
1685 uint64_t open_bits
=
1687 SEC_FLAG_SYSTEM_SECURITY
|
1688 SEC_FLAG_MAXIMUM_ALLOWED
|
1692 uint64_t get_owner_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1693 uint64_t set_owner_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
1694 uint64_t get_group_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1695 uint64_t set_group_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
1696 uint64_t get_dacl_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1697 uint64_t set_dacl_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_DAC
;
1698 uint64_t get_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
1699 uint64_t set_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
1701 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1704 torture_comment(tctx
, "TESTING ACCESS MASKS FOR SD GET/SET\n");
1706 /* first create a file with full access for everyone */
1707 sd
= security_descriptor_dacl_create(tctx
,
1708 0, SID_NT_ANONYMOUS
, SID_BUILTIN_USERS
,
1710 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1714 sd
->type
|= SEC_DESC_SACL_PRESENT
;
1717 io
.level
= RAW_OPEN_SMB2
;
1718 io
.in
.create_flags
= 0;
1719 io
.in
.desired_access
= SEC_GENERIC_ALL
;
1720 io
.in
.create_options
= 0;
1721 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1722 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1723 io
.in
.alloc_size
= 0;
1724 io
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1725 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1726 io
.in
.security_flags
= 0;
1727 io
.in
.fname
= fname
;
1728 io
.in
.sec_desc
= sd
;
1729 status
= smb2_create(tree
, tctx
, &io
);
1730 CHECK_STATUS(status
, NT_STATUS_OK
);
1731 handle
= io
.out
.file
.handle
;
1733 status
= smb2_util_close(tree
, handle
);
1734 CHECK_STATUS(status
, NT_STATUS_OK
);
1737 * now try each access_mask bit and no bit at all in a loop
1738 * and see what's allowed
1739 * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
1741 for (i
=0; i
<= 32; i
++) {
1742 desired_64
= ((uint64_t)1) << i
;
1743 desired
= (uint32_t)desired_64
;
1745 /* first open the file with the desired access */
1746 io
.level
= RAW_OPEN_SMB2
;
1747 io
.in
.desired_access
= desired
;
1748 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1749 status
= smb2_create(tree
, tctx
, &io
);
1750 CHECK_STATUS_FOR_BIT_ACTION(status
, open_bits
, goto next
);
1751 handle
= io
.out
.file
.handle
;
1753 /* then check what access was granted */
1754 fi
.access_information
.level
= RAW_FILEINFO_ACCESS_INFORMATION
;
1755 fi
.access_information
.in
.file
.handle
= handle
;
1756 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1757 CHECK_STATUS(status
, NT_STATUS_OK
);
1758 granted
= fi
.access_information
.out
.access_flags
;
1760 /* test the owner */
1762 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1763 fi
.query_secdesc
.in
.file
.handle
= handle
;
1764 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
1765 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1766 CHECK_STATUS_FOR_BIT(status
, get_owner_bits
, SEC_STD_READ_CONTROL
);
1767 if (fi
.query_secdesc
.out
.sd
) {
1768 sd_owner
= fi
.query_secdesc
.out
.sd
;
1769 } else if (!sd_owner
) {
1772 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1773 si
.set_secdesc
.in
.file
.handle
= handle
;
1774 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
1775 si
.set_secdesc
.in
.sd
= sd_owner
;
1776 status
= smb2_setinfo_file(tree
, &si
);
1777 CHECK_STATUS_FOR_BIT(status
, set_owner_bits
, SEC_STD_WRITE_OWNER
);
1779 /* test the group */
1781 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1782 fi
.query_secdesc
.in
.file
.handle
= handle
;
1783 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
1784 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1785 CHECK_STATUS_FOR_BIT(status
, get_group_bits
, SEC_STD_READ_CONTROL
);
1786 if (fi
.query_secdesc
.out
.sd
) {
1787 sd_group
= fi
.query_secdesc
.out
.sd
;
1788 } else if (!sd_group
) {
1791 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1792 si
.set_secdesc
.in
.file
.handle
= handle
;
1793 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
1794 si
.set_secdesc
.in
.sd
= sd_group
;
1795 status
= smb2_setinfo_file(tree
, &si
);
1796 CHECK_STATUS_FOR_BIT(status
, set_group_bits
, SEC_STD_WRITE_OWNER
);
1800 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1801 fi
.query_secdesc
.in
.file
.handle
= handle
;
1802 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1803 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1804 CHECK_STATUS_FOR_BIT(status
, get_dacl_bits
, SEC_STD_READ_CONTROL
);
1805 if (fi
.query_secdesc
.out
.sd
) {
1806 sd_dacl
= fi
.query_secdesc
.out
.sd
;
1807 } else if (!sd_dacl
) {
1810 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1811 si
.set_secdesc
.in
.file
.handle
= handle
;
1812 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1813 si
.set_secdesc
.in
.sd
= sd_dacl
;
1814 status
= smb2_setinfo_file(tree
, &si
);
1815 CHECK_STATUS_FOR_BIT(status
, set_dacl_bits
, SEC_STD_WRITE_DAC
);
1819 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1820 fi
.query_secdesc
.in
.file
.handle
= handle
;
1821 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
1822 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1823 CHECK_STATUS_FOR_BIT(status
, get_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
1824 if (fi
.query_secdesc
.out
.sd
) {
1825 sd_sacl
= fi
.query_secdesc
.out
.sd
;
1826 } else if (!sd_sacl
) {
1829 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1830 si
.set_secdesc
.in
.file
.handle
= handle
;
1831 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
1832 si
.set_secdesc
.in
.sd
= sd_sacl
;
1833 status
= smb2_setinfo_file(tree
, &si
);
1834 CHECK_STATUS_FOR_BIT(status
, set_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
1836 /* close the handle */
1837 status
= smb2_util_close(tree
, handle
);
1838 CHECK_STATUS(status
, NT_STATUS_OK
);
1844 smb2_util_close(tree
, handle
);
1845 smb2_util_unlink(tree
, fname
);
1846 smb2_deltree(tree
, BASEDIR
);
1848 smb2_logoff(tree
->session
);
1854 basic testing of SMB2 ACLs
1856 struct torture_suite
*torture_smb2_acls_init(void)
1858 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "acls");
1860 torture_suite_add_1smb2_test(suite
, "CREATOR", test_creator_sid
);
1861 torture_suite_add_1smb2_test(suite
, "GENERIC", test_generic_bits
);
1862 torture_suite_add_1smb2_test(suite
, "OWNER", test_owner_bits
);
1863 torture_suite_add_1smb2_test(suite
, "INHERITANCE", test_inheritance
);
1864 torture_suite_add_1smb2_test(suite
, "INHERITFLAGS", test_inheritance_flags
);
1865 torture_suite_add_1smb2_test(suite
, "DYNAMIC", test_inheritance_dynamic
);
1866 /* XXX This test does not work against XP or Vista.
1867 torture_suite_add_1smb2_test(suite, "GETSET", test_sd_get_set);
1870 suite
->description
= talloc_strdup(suite
, "SMB2-ACLS tests");