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 bool has_restore_privilege
= false;
670 bool has_take_ownership_privilege
= false;
671 uint32_t expected_bits
;
673 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
676 torture_comment(tctx
, "TESTING FILE OWNER BITS\n");
679 io
.level
= RAW_OPEN_SMB2
;
680 io
.in
.create_flags
= 0;
681 io
.in
.desired_access
=
682 SEC_STD_READ_CONTROL
|
685 io
.in
.create_options
= 0;
686 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
688 NTCREATEX_SHARE_ACCESS_READ
|
689 NTCREATEX_SHARE_ACCESS_WRITE
;
690 io
.in
.alloc_size
= 0;
691 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
692 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
693 io
.in
.security_flags
= 0;
695 status
= smb2_create(tree
, tctx
, &io
);
696 CHECK_STATUS(status
, NT_STATUS_OK
);
697 handle
= io
.out
.file
.handle
;
699 torture_comment(tctx
, "get the original sd\n");
700 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
701 q
.query_secdesc
.in
.file
.handle
= handle
;
702 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
703 status
= smb2_getinfo_file(tree
, tctx
, &q
);
704 CHECK_STATUS(status
, NT_STATUS_OK
);
705 sd_orig
= q
.query_secdesc
.out
.sd
;
707 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
710 * XXX: The smblsa calls use SMB as their transport - need to get rid of
714 status = smblsa_sid_check_privilege(cli,
716 sec_privilege_name(SEC_PRIV_RESTORE));
717 has_restore_privilege = NT_STATUS_IS_OK(status);
718 if (!NT_STATUS_IS_OK(status)) {
719 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
721 torture_comment(tctx, "SEC_PRIV_RESTORE - %s\n", has_restore_privilege?"Yes":"No");
723 status = smblsa_sid_check_privilege(cli,
725 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP));
726 has_take_ownership_privilege = NT_STATUS_IS_OK(status);
727 if (!NT_STATUS_IS_OK(status)) {
728 torture_warning(tctx, "smblsa_sid_check_privilege - %s\n", nt_errstr(status));
730 torture_comment(tctx, "SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_take_ownership_privilege?"Yes":"No");
733 sd
= security_descriptor_dacl_create(tctx
,
736 SEC_ACE_TYPE_ACCESS_ALLOWED
,
741 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
742 set
.set_secdesc
.in
.file
.handle
= handle
;
743 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
744 set
.set_secdesc
.in
.sd
= sd
;
746 status
= smb2_setinfo_file(tree
, &set
);
747 CHECK_STATUS(status
, NT_STATUS_OK
);
749 expected_bits
= SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
;
752 uint32_t bit
= (1<<i
);
753 io
.in
.desired_access
= bit
;
754 status
= smb2_create(tree
, tctx
, &io
);
755 if (expected_bits
& bit
) {
756 if (!NT_STATUS_IS_OK(status
)) {
757 torture_warning(tctx
, "failed with access mask 0x%08x of expected 0x%08x\n",
760 CHECK_STATUS(status
, NT_STATUS_OK
);
761 CHECK_ACCESS_FLAGS(io
.out
.file
.handle
, bit
);
762 smb2_util_close(tree
, io
.out
.file
.handle
);
764 if (NT_STATUS_IS_OK(status
)) {
765 torture_warning(tctx
, "open succeeded with access mask 0x%08x of "
766 "expected 0x%08x - should fail\n",
769 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
773 torture_comment(tctx
, "put back original sd\n");
774 set
.set_secdesc
.in
.sd
= sd_orig
;
775 status
= smb2_setinfo_file(tree
, &set
);
776 CHECK_STATUS(status
, NT_STATUS_OK
);
779 smb2_util_close(tree
, handle
);
780 smb2_util_unlink(tree
, fname
);
781 smb2_deltree(tree
, BASEDIR
);
783 smb2_logoff(tree
->session
);
790 test the inheritance of ACL flags onto new files and directories
791 Note: This test was copied from raw/acls.c.
793 static bool test_inheritance(struct torture_context
*tctx
, struct smb2_tree
*tree
)
796 struct smb2_create io
;
797 const char *dname
= BASEDIR
"\\inheritance";
798 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
799 const char *fname2
= BASEDIR
"\\inheritance\\testdir";
801 struct smb2_handle handle
, handle2
;
803 union smb_fileinfo q
;
804 union smb_setfileinfo set
;
805 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
, *sd_def1
, *sd_def2
;
806 const char *owner_sid
;
807 const struct dom_sid
*creator_owner
;
809 uint32_t parent_flags
;
819 SEC_ACE_FLAG_OBJECT_INHERIT
,
821 SEC_ACE_FLAG_OBJECT_INHERIT
|
822 SEC_ACE_FLAG_INHERIT_ONLY
,
825 SEC_ACE_FLAG_CONTAINER_INHERIT
,
827 SEC_ACE_FLAG_CONTAINER_INHERIT
,
830 SEC_ACE_FLAG_OBJECT_INHERIT
|
831 SEC_ACE_FLAG_CONTAINER_INHERIT
,
833 SEC_ACE_FLAG_OBJECT_INHERIT
|
834 SEC_ACE_FLAG_CONTAINER_INHERIT
,
837 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
842 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
843 SEC_ACE_FLAG_OBJECT_INHERIT
,
848 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
849 SEC_ACE_FLAG_CONTAINER_INHERIT
,
854 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
855 SEC_ACE_FLAG_CONTAINER_INHERIT
|
856 SEC_ACE_FLAG_OBJECT_INHERIT
,
861 SEC_ACE_FLAG_INHERIT_ONLY
,
866 SEC_ACE_FLAG_INHERIT_ONLY
|
867 SEC_ACE_FLAG_OBJECT_INHERIT
,
869 SEC_ACE_FLAG_OBJECT_INHERIT
|
870 SEC_ACE_FLAG_INHERIT_ONLY
,
873 SEC_ACE_FLAG_INHERIT_ONLY
|
874 SEC_ACE_FLAG_CONTAINER_INHERIT
,
876 SEC_ACE_FLAG_CONTAINER_INHERIT
,
879 SEC_ACE_FLAG_INHERIT_ONLY
|
880 SEC_ACE_FLAG_CONTAINER_INHERIT
|
881 SEC_ACE_FLAG_OBJECT_INHERIT
,
883 SEC_ACE_FLAG_CONTAINER_INHERIT
|
884 SEC_ACE_FLAG_OBJECT_INHERIT
,
887 SEC_ACE_FLAG_INHERIT_ONLY
|
888 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
893 SEC_ACE_FLAG_INHERIT_ONLY
|
894 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
895 SEC_ACE_FLAG_OBJECT_INHERIT
,
900 SEC_ACE_FLAG_INHERIT_ONLY
|
901 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
902 SEC_ACE_FLAG_CONTAINER_INHERIT
,
907 SEC_ACE_FLAG_INHERIT_ONLY
|
908 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
909 SEC_ACE_FLAG_CONTAINER_INHERIT
|
910 SEC_ACE_FLAG_OBJECT_INHERIT
,
916 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
919 torture_comment(tctx
, "TESTING ACL INHERITANCE\n");
922 io
.level
= RAW_OPEN_SMB2
;
923 io
.in
.create_flags
= 0;
924 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
925 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
926 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
927 io
.in
.share_access
= 0;
928 io
.in
.alloc_size
= 0;
929 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
930 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
931 io
.in
.security_flags
= 0;
934 status
= smb2_create(tree
, tctx
, &io
);
935 CHECK_STATUS(status
, NT_STATUS_OK
);
936 handle
= io
.out
.file
.handle
;
938 torture_comment(tctx
, "get the original sd\n");
939 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
940 q
.query_secdesc
.in
.file
.handle
= handle
;
941 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
942 status
= smb2_getinfo_file(tree
, tctx
, &q
);
943 CHECK_STATUS(status
, NT_STATUS_OK
);
944 sd_orig
= q
.query_secdesc
.out
.sd
;
946 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
948 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
951 * The Windows Default ACL for a new file, when there is no ACL to be
952 * inherited: FullControl for the owner and SYSTEM.
954 sd_def1
= security_descriptor_dacl_create(tctx
,
957 SEC_ACE_TYPE_ACCESS_ALLOWED
,
961 SEC_ACE_TYPE_ACCESS_ALLOWED
,
967 * Use this in the case the system being tested does not add an ACE for
970 sd_def2
= security_descriptor_dacl_create(tctx
,
973 SEC_ACE_TYPE_ACCESS_ALLOWED
,
978 creator_owner
= dom_sid_parse_talloc(tctx
, SID_CREATOR_OWNER
);
980 for (i
=0;i
<ARRAY_SIZE(test_flags
);i
++) {
981 sd
= security_descriptor_dacl_create(tctx
,
984 SEC_ACE_TYPE_ACCESS_ALLOWED
,
986 test_flags
[i
].parent_flags
,
988 SEC_ACE_TYPE_ACCESS_ALLOWED
,
989 SEC_FILE_ALL
| SEC_STD_ALL
,
992 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
993 set
.set_secdesc
.in
.file
.handle
= handle
;
994 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
995 set
.set_secdesc
.in
.sd
= sd
;
996 status
= smb2_setinfo_file(tree
, &set
);
997 CHECK_STATUS(status
, NT_STATUS_OK
);
999 io
.in
.fname
= fname1
;
1000 io
.in
.create_options
= 0;
1001 status
= smb2_create(tree
, tctx
, &io
);
1002 CHECK_STATUS(status
, NT_STATUS_OK
);
1003 handle2
= io
.out
.file
.handle
;
1005 q
.query_secdesc
.in
.file
.handle
= handle2
;
1006 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1007 CHECK_STATUS(status
, NT_STATUS_OK
);
1009 smb2_util_close(tree
, handle2
);
1010 smb2_util_unlink(tree
, fname1
);
1012 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
)) {
1013 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def1
) &&
1014 !security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def2
)) {
1015 torture_warning(tctx
, "Expected default sd:\n");
1016 NDR_PRINT_DEBUG(security_descriptor
, sd_def1
);
1017 torture_warning(tctx
, "at %d - got:\n", i
);
1018 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1023 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1024 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1025 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1026 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1027 sd_orig
->owner_sid
)) {
1028 torture_warning(tctx
, "Bad sd in child file at %d\n", i
);
1029 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1034 if (q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!=
1035 test_flags
[i
].file_flags
) {
1036 torture_warning(tctx
, "incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1037 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
,
1038 test_flags
[i
].file_flags
,
1039 test_flags
[i
].parent_flags
,
1045 io
.in
.fname
= fname2
;
1046 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1047 status
= smb2_create(tree
, tctx
, &io
);
1048 CHECK_STATUS(status
, NT_STATUS_OK
);
1049 handle2
= io
.out
.file
.handle
;
1051 q
.query_secdesc
.in
.file
.handle
= handle2
;
1052 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1053 CHECK_STATUS(status
, NT_STATUS_OK
);
1055 smb2_util_close(tree
, handle2
);
1056 smb2_util_rmdir(tree
, fname2
);
1058 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1059 (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
) ||
1060 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
))) {
1061 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def1
) &&
1062 !security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def2
)) {
1063 torture_warning(tctx
, "Expected default sd for dir at %d:\n", i
);
1064 NDR_PRINT_DEBUG(security_descriptor
, sd_def1
);
1065 torture_warning(tctx
, "got:\n");
1066 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1071 if ((test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1072 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
)) {
1073 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1074 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1075 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1076 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1077 sd_orig
->owner_sid
) ||
1078 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1079 torture_warning(tctx
, "(CI & NP) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1080 test_flags
[i
].dir_flags
,
1081 test_flags
[i
].parent_flags
, i
);
1082 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1083 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1084 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1088 } else if (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) {
1089 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1090 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 2 ||
1091 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1092 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1093 sd_orig
->owner_sid
) ||
1094 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].access_mask
!= SEC_FILE_WRITE_DATA
||
1095 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[1].trustee
,
1097 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= 0 ||
1098 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].flags
!=
1099 (test_flags
[i
].dir_flags
| SEC_ACE_FLAG_INHERIT_ONLY
)) {
1100 torture_warning(tctx
, "(CI) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1101 test_flags
[i
].dir_flags
,
1102 test_flags
[i
].parent_flags
, i
);
1103 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1104 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1105 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1110 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1111 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1112 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1113 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1115 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1116 torture_warning(tctx
, "(0) Bad sd in child dir - expected 0x%x for parent 0x%x (i=%d)\n",
1117 test_flags
[i
].dir_flags
,
1118 test_flags
[i
].parent_flags
, i
);
1119 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1120 torture_warning(tctx
, "FYI, here is the parent sd:\n");
1121 NDR_PRINT_DEBUG(security_descriptor
, sd
);
1128 torture_comment(tctx
, "testing access checks on inherited create with %s\n", fname1
);
1129 sd
= security_descriptor_dacl_create(tctx
,
1132 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1133 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1134 SEC_ACE_FLAG_OBJECT_INHERIT
,
1136 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1137 SEC_FILE_ALL
| SEC_STD_ALL
,
1140 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1141 set
.set_secdesc
.in
.file
.handle
= handle
;
1142 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1143 set
.set_secdesc
.in
.sd
= sd
;
1144 status
= smb2_setinfo_file(tree
, &set
);
1145 CHECK_STATUS(status
, NT_STATUS_OK
);
1147 /* Check DACL we just set. */
1148 torture_comment(tctx
, "checking new sd\n");
1149 q
.query_secdesc
.in
.file
.handle
= handle
;
1150 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1151 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1152 CHECK_STATUS(status
, NT_STATUS_OK
);
1153 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1155 io
.in
.fname
= fname1
;
1156 io
.in
.create_options
= 0;
1157 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1158 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1159 status
= smb2_create(tree
, tctx
, &io
);
1160 CHECK_STATUS(status
, NT_STATUS_OK
);
1161 handle2
= io
.out
.file
.handle
;
1162 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1164 q
.query_secdesc
.in
.file
.handle
= handle2
;
1165 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1166 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1167 CHECK_STATUS(status
, NT_STATUS_OK
);
1168 smb2_util_close(tree
, handle2
);
1170 sd2
= security_descriptor_dacl_create(tctx
,
1173 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1174 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1177 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1179 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1180 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1181 status
= smb2_create(tree
, tctx
, &io
);
1182 if (NT_STATUS_IS_OK(status
)) {
1183 torture_warning(tctx
, "failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1185 handle2
= io
.out
.file
.handle
;
1186 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1187 smb2_util_close(tree
, handle2
);
1189 if (torture_setting_bool(tctx
, "hide_on_access_denied",
1191 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1193 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1197 torture_comment(tctx
, "trying without execute\n");
1198 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1199 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
& ~SEC_FILE_EXECUTE
;
1200 status
= smb2_create(tree
, tctx
, &io
);
1201 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1202 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1204 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1207 torture_comment(tctx
, "and with full permissions again\n");
1208 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1209 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1210 status
= smb2_create(tree
, tctx
, &io
);
1211 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1212 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1214 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1217 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1218 status
= smb2_create(tree
, tctx
, &io
);
1219 CHECK_STATUS(status
, NT_STATUS_OK
);
1220 handle2
= io
.out
.file
.handle
;
1221 CHECK_ACCESS_FLAGS(handle2
, SEC_FILE_WRITE_DATA
);
1222 smb2_util_close(tree
, handle2
);
1224 torture_comment(tctx
, "put back original sd\n");
1225 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1226 set
.set_secdesc
.in
.file
.handle
= handle
;
1227 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1228 set
.set_secdesc
.in
.sd
= sd_orig
;
1229 status
= smb2_setinfo_file(tree
, &set
);
1230 CHECK_STATUS(status
, NT_STATUS_OK
);
1232 smb2_util_close(tree
, handle
);
1234 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1235 status
= smb2_create(tree
, tctx
, &io
);
1236 if (torture_setting_bool(tctx
, "hide_on_access_denied", false)) {
1237 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1239 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1242 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1243 status
= smb2_create(tree
, tctx
, &io
);
1244 CHECK_STATUS(status
, NT_STATUS_OK
);
1245 handle2
= io
.out
.file
.handle
;
1246 CHECK_ACCESS_FLAGS(handle2
, SEC_FILE_WRITE_DATA
);
1247 smb2_util_close(tree
, handle2
);
1249 smb2_util_unlink(tree
, fname1
);
1250 smb2_util_rmdir(tree
, dname
);
1253 if (sd_orig
!= NULL
) {
1254 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1255 set
.set_secdesc
.in
.file
.handle
= handle
;
1256 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1257 set
.set_secdesc
.in
.sd
= sd_orig
;
1258 status
= smb2_setinfo_file(tree
, &set
);
1261 smb2_util_close(tree
, handle
);
1262 smb2_deltree(tree
, BASEDIR
);
1264 smb2_logoff(tree
->session
);
1268 static bool test_inheritance_flags(struct torture_context
*tctx
,
1269 struct smb2_tree
*tree
)
1272 struct smb2_create io
;
1273 const char *dname
= BASEDIR
"\\inheritance";
1274 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1276 struct smb2_handle handle
, handle2
;
1278 union smb_fileinfo q
;
1279 union smb_setfileinfo set
;
1280 struct security_descriptor
*sd
, *sd2
, *sd_orig
=NULL
;
1281 const char *owner_sid
;
1283 uint32_t parent_set_sd_type
; /* 3 options */
1284 uint32_t parent_set_ace_inherit
; /* 1 option */
1285 uint32_t parent_get_sd_type
;
1286 uint32_t parent_get_ace_inherit
;
1287 uint32_t child_get_sd_type
;
1288 uint32_t child_get_ace_inherit
;
1289 } tflags
[16] = {0}; /* 2^4 */
1291 for (i
= 0; i
< 15; i
++) {
1292 torture_comment(tctx
, "i=%d:", i
);
1295 tflags
[i
].parent_set_sd_type
|=
1296 SEC_DESC_DACL_AUTO_INHERITED
;
1297 torture_comment(tctx
, "AUTO_INHERITED, ");
1300 tflags
[i
].parent_set_sd_type
|=
1301 SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1302 torture_comment(tctx
, "AUTO_INHERIT_REQ, ");
1305 tflags
[i
].parent_set_sd_type
|=
1306 SEC_DESC_DACL_PROTECTED
;
1307 torture_comment(tctx
, "PROTECTED, ");
1308 tflags
[i
].parent_get_sd_type
|=
1309 SEC_DESC_DACL_PROTECTED
;
1312 tflags
[i
].parent_set_ace_inherit
|=
1313 SEC_ACE_FLAG_INHERITED_ACE
;
1314 torture_comment(tctx
, "INHERITED, ");
1315 tflags
[i
].parent_get_ace_inherit
|=
1316 SEC_ACE_FLAG_INHERITED_ACE
;
1319 if ((tflags
[i
].parent_set_sd_type
&
1320 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) ==
1321 (SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
)) {
1322 tflags
[i
].parent_get_sd_type
|=
1323 SEC_DESC_DACL_AUTO_INHERITED
;
1324 tflags
[i
].child_get_sd_type
|=
1325 SEC_DESC_DACL_AUTO_INHERITED
;
1326 tflags
[i
].child_get_ace_inherit
|=
1327 SEC_ACE_FLAG_INHERITED_ACE
;
1328 torture_comment(tctx
, " ... parent is AUTO INHERITED");
1331 if (tflags
[i
].parent_set_ace_inherit
&
1332 SEC_ACE_FLAG_INHERITED_ACE
) {
1333 tflags
[i
].parent_get_ace_inherit
=
1334 SEC_ACE_FLAG_INHERITED_ACE
;
1335 torture_comment(tctx
, " ... parent ACE is INHERITED");
1338 torture_comment(tctx
, "\n");
1341 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1344 torture_comment(tctx
, "TESTING ACL INHERITANCE FLAGS\n");
1347 io
.level
= RAW_OPEN_SMB2
;
1348 io
.in
.create_flags
= 0;
1349 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1350 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1351 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1352 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_MASK
;
1353 io
.in
.alloc_size
= 0;
1354 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1355 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1356 io
.in
.security_flags
= 0;
1357 io
.in
.fname
= dname
;
1359 torture_comment(tctx
, "creating initial directory %s\n", dname
);
1360 status
= smb2_create(tree
, tctx
, &io
);
1361 CHECK_STATUS(status
, NT_STATUS_OK
);
1362 handle
= io
.out
.file
.handle
;
1364 torture_comment(tctx
, "getting original sd\n");
1365 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1366 q
.query_secdesc
.in
.file
.handle
= handle
;
1367 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1368 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1369 CHECK_STATUS(status
, NT_STATUS_OK
);
1370 sd_orig
= q
.query_secdesc
.out
.sd
;
1372 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1373 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1375 for (i
=0; i
< ARRAY_SIZE(tflags
); i
++) {
1376 torture_comment(tctx
, "setting a new sd on directory, pass #%d\n", i
);
1378 sd
= security_descriptor_dacl_create(tctx
,
1379 tflags
[i
].parent_set_sd_type
,
1382 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1383 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1384 SEC_ACE_FLAG_OBJECT_INHERIT
|
1385 SEC_ACE_FLAG_CONTAINER_INHERIT
|
1386 tflags
[i
].parent_set_ace_inherit
,
1388 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1389 SEC_FILE_ALL
| SEC_STD_ALL
,
1392 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1393 set
.set_secdesc
.in
.file
.handle
= handle
;
1394 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1395 set
.set_secdesc
.in
.sd
= sd
;
1396 status
= smb2_setinfo_file(tree
, &set
);
1397 CHECK_STATUS(status
, NT_STATUS_OK
);
1400 * Check DACL we just set, except change the bits to what they
1403 torture_comment(tctx
, " checking new sd\n");
1405 /* REQ bit should always be false. */
1406 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1408 if ((tflags
[i
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1409 sd
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1411 q
.query_secdesc
.in
.file
.handle
= handle
;
1412 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1413 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1414 CHECK_STATUS(status
, NT_STATUS_OK
);
1415 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd
);
1418 torture_comment(tctx
, " creating file %s\n", fname1
);
1419 io
.in
.fname
= fname1
;
1420 io
.in
.create_options
= 0;
1421 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1422 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1423 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1424 status
= smb2_create(tree
, tctx
, &io
);
1425 CHECK_STATUS(status
, NT_STATUS_OK
);
1426 handle2
= io
.out
.file
.handle
;
1427 CHECK_ACCESS_FLAGS(handle2
, SEC_RIGHTS_FILE_ALL
);
1429 q
.query_secdesc
.in
.file
.handle
= handle2
;
1430 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1431 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1432 CHECK_STATUS(status
, NT_STATUS_OK
);
1434 torture_comment(tctx
, " checking sd on file %s\n", fname1
);
1435 sd2
= security_descriptor_dacl_create(tctx
,
1436 tflags
[i
].child_get_sd_type
,
1439 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1440 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1441 tflags
[i
].child_get_ace_inherit
,
1443 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1446 * Set new sd on file ... prove that the bits have nothing to
1447 * do with the parents bits when manually setting an ACL. The
1448 * _AUTO_INHERITED bit comes directly from the ACL set.
1450 for (j
= 0; j
< ARRAY_SIZE(tflags
); j
++) {
1451 torture_comment(tctx
, " setting new file sd, pass #%d\n", j
);
1453 /* Change sd type. */
1454 sd2
->type
&= ~(SEC_DESC_DACL_AUTO_INHERITED
|
1455 SEC_DESC_DACL_AUTO_INHERIT_REQ
|
1456 SEC_DESC_DACL_PROTECTED
);
1457 sd2
->type
|= tflags
[j
].parent_set_sd_type
;
1459 sd2
->dacl
->aces
[0].flags
&=
1460 ~SEC_ACE_FLAG_INHERITED_ACE
;
1461 sd2
->dacl
->aces
[0].flags
|=
1462 tflags
[j
].parent_set_ace_inherit
;
1464 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1465 set
.set_secdesc
.in
.file
.handle
= handle2
;
1466 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1467 set
.set_secdesc
.in
.sd
= sd2
;
1468 status
= smb2_setinfo_file(tree
, &set
);
1469 CHECK_STATUS(status
, NT_STATUS_OK
);
1471 /* Check DACL we just set. */
1472 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1473 if ((tflags
[j
].parent_get_sd_type
& SEC_DESC_DACL_AUTO_INHERITED
) == 0)
1474 sd2
->type
&= ~SEC_DESC_DACL_AUTO_INHERITED
;
1476 q
.query_secdesc
.in
.file
.handle
= handle2
;
1477 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1478 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1479 CHECK_STATUS(status
, NT_STATUS_OK
);
1481 CHECK_SECURITY_DESCRIPTOR(q
.query_secdesc
.out
.sd
, sd2
);
1484 smb2_util_close(tree
, handle2
);
1485 smb2_util_unlink(tree
, fname1
);
1489 smb2_util_close(tree
, handle
);
1490 smb2_deltree(tree
, BASEDIR
);
1492 smb2_logoff(tree
->session
);
1497 test dynamic acl inheritance
1498 Note: This test was copied from raw/acls.c.
1500 static bool test_inheritance_dynamic(struct torture_context
*tctx
,
1501 struct smb2_tree
*tree
)
1504 struct smb2_create io
;
1505 const char *dname
= BASEDIR
"\\inheritance";
1506 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1508 struct smb2_handle handle
, handle2
;
1509 union smb_fileinfo q
;
1510 union smb_setfileinfo set
;
1511 struct security_descriptor
*sd
, *sd_orig
=NULL
;
1512 const char *owner_sid
;
1514 torture_comment(tctx
, "TESTING DYNAMIC ACL INHERITANCE\n");
1516 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1520 io
.level
= RAW_OPEN_SMB2
;
1521 io
.in
.create_flags
= 0;
1522 io
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1523 io
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1524 io
.in
.file_attributes
= FILE_ATTRIBUTE_DIRECTORY
;
1525 io
.in
.share_access
= 0;
1526 io
.in
.alloc_size
= 0;
1527 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1528 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1529 io
.in
.security_flags
= 0;
1530 io
.in
.fname
= dname
;
1532 status
= smb2_create(tree
, tctx
, &io
);
1533 CHECK_STATUS(status
, NT_STATUS_OK
);
1534 handle
= io
.out
.file
.handle
;
1536 torture_comment(tctx
, "get the original sd\n");
1537 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1538 q
.query_secdesc
.in
.file
.handle
= handle
;
1539 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1540 status
= smb2_getinfo_file(tree
, tctx
, &q
);
1541 CHECK_STATUS(status
, NT_STATUS_OK
);
1542 sd_orig
= q
.query_secdesc
.out
.sd
;
1544 owner_sid
= dom_sid_string(tctx
, sd_orig
->owner_sid
);
1546 torture_comment(tctx
, "owner_sid is %s\n", owner_sid
);
1548 sd
= security_descriptor_dacl_create(tctx
,
1551 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1552 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
,
1553 SEC_ACE_FLAG_OBJECT_INHERIT
,
1555 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1557 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1558 set
.set_secdesc
.in
.file
.handle
= handle
;
1559 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1560 set
.set_secdesc
.in
.sd
= sd
;
1561 status
= smb2_setinfo_file(tree
, &set
);
1562 CHECK_STATUS(status
, NT_STATUS_OK
);
1564 torture_comment(tctx
, "create a file with an inherited acl\n");
1565 io
.in
.fname
= fname1
;
1566 io
.in
.create_options
= 0;
1567 io
.in
.desired_access
= SEC_FILE_READ_ATTRIBUTE
;
1568 io
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1569 status
= smb2_create(tree
, tctx
, &io
);
1570 CHECK_STATUS(status
, NT_STATUS_OK
);
1571 handle2
= io
.out
.file
.handle
;
1572 smb2_util_close(tree
, handle2
);
1574 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
1575 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1576 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1577 status
= smb2_create(tree
, tctx
, &io
);
1578 CHECK_STATUS(status
, NT_STATUS_OK
);
1579 handle2
= io
.out
.file
.handle
;
1580 smb2_util_close(tree
, handle2
);
1582 torture_comment(tctx
, "try and access file with extra rights - should be denied\n");
1583 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1584 status
= smb2_create(tree
, tctx
, &io
);
1585 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1587 torture_comment(tctx
, "update parent sd\n");
1588 sd
= security_descriptor_dacl_create(tctx
,
1591 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1592 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
,
1593 SEC_ACE_FLAG_OBJECT_INHERIT
,
1595 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1597 set
.set_secdesc
.in
.sd
= sd
;
1598 status
= smb2_setinfo_file(tree
, &set
);
1599 CHECK_STATUS(status
, NT_STATUS_OK
);
1601 torture_comment(tctx
, "try and access file with base rights - should be OK\n");
1602 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
;
1603 status
= smb2_create(tree
, tctx
, &io
);
1604 CHECK_STATUS(status
, NT_STATUS_OK
);
1605 handle2
= io
.out
.file
.handle
;
1606 smb2_util_close(tree
, handle2
);
1609 torture_comment(tctx
, "try and access now - should be OK if dynamic inheritance works\n");
1610 io
.in
.desired_access
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1611 status
= smb2_create(tree
, tctx
, &io
);
1612 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1613 torture_comment(tctx
, "Server does not have dynamic inheritance\n");
1615 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1616 torture_comment(tctx
, "Server does have dynamic inheritance\n");
1618 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1620 smb2_util_unlink(tree
, fname1
);
1623 torture_comment(tctx
, "put back original sd\n");
1624 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1625 set
.set_secdesc
.in
.file
.handle
= handle
;
1626 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1627 set
.set_secdesc
.in
.sd
= sd_orig
;
1628 status
= smb2_setinfo_file(tree
, &set
);
1630 smb2_util_close(tree
, handle
);
1631 smb2_util_rmdir(tree
, dname
);
1632 smb2_deltree(tree
, BASEDIR
);
1634 smb2_logoff(tree
->session
);
1639 #define CHECK_STATUS_FOR_BIT_ACTION(status, bits, action) do { \
1640 if (!(bits & desired_64)) {\
1641 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); \
1644 CHECK_STATUS(status, NT_STATUS_OK); \
1648 #define CHECK_STATUS_FOR_BIT(status, bits, access) do { \
1649 if (NT_STATUS_IS_OK(status)) { \
1650 if (!(granted & access)) {\
1652 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are not granted! granted[0x%08X] desired[0x%08X]\n", \
1653 __location__, nt_errstr(status), access, granted, desired); \
1657 if (granted & access) {\
1659 torture_result(tctx, TORTURE_FAIL, "(%s) %s but flags 0x%08X are granted! granted[0x%08X] desired[0x%08X]\n", \
1660 __location__, nt_errstr(status), access, granted, desired); \
1664 CHECK_STATUS_FOR_BIT_ACTION(status, bits, do {} while (0)); \
1667 /* test what access mask is needed for getting and setting security_descriptors */
1668 /* Note: This test was copied from raw/acls.c. */
1669 static bool test_sd_get_set(struct torture_context
*tctx
, struct smb2_tree
*tree
)
1673 struct smb2_create io
;
1674 union smb_fileinfo fi
;
1675 union smb_setfileinfo si
;
1676 struct security_descriptor
*sd
;
1677 struct security_descriptor
*sd_owner
= NULL
;
1678 struct security_descriptor
*sd_group
= NULL
;
1679 struct security_descriptor
*sd_dacl
= NULL
;
1680 struct security_descriptor
*sd_sacl
= NULL
;
1681 struct smb2_handle handle
;
1682 const char *fname
= BASEDIR
"\\sd_get_set.txt";
1683 uint64_t desired_64
;
1684 uint32_t desired
= 0, granted
;
1686 #define NO_BITS_HACK (((uint64_t)1)<<32)
1687 uint64_t open_bits
=
1689 SEC_FLAG_SYSTEM_SECURITY
|
1690 SEC_FLAG_MAXIMUM_ALLOWED
|
1694 uint64_t get_owner_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1695 uint64_t set_owner_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
1696 uint64_t get_group_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1697 uint64_t set_group_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_OWNER
;
1698 uint64_t get_dacl_bits
= SEC_MASK_GENERIC
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_READ_CONTROL
;
1699 uint64_t set_dacl_bits
= SEC_GENERIC_ALL
| SEC_FLAG_MAXIMUM_ALLOWED
| SEC_STD_WRITE_DAC
;
1700 uint64_t get_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
1701 uint64_t set_sacl_bits
= SEC_FLAG_SYSTEM_SECURITY
;
1703 if (!smb2_util_setup_dir(tctx
, tree
, BASEDIR
))
1706 torture_comment(tctx
, "TESTING ACCESS MASKS FOR SD GET/SET\n");
1708 /* first create a file with full access for everyone */
1709 sd
= security_descriptor_dacl_create(tctx
,
1710 0, SID_NT_ANONYMOUS
, SID_BUILTIN_USERS
,
1712 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1716 sd
->type
|= SEC_DESC_SACL_PRESENT
;
1719 io
.level
= RAW_OPEN_SMB2
;
1720 io
.in
.create_flags
= 0;
1721 io
.in
.desired_access
= SEC_GENERIC_ALL
;
1722 io
.in
.create_options
= 0;
1723 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1724 io
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1725 io
.in
.alloc_size
= 0;
1726 io
.in
.create_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1727 io
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1728 io
.in
.security_flags
= 0;
1729 io
.in
.fname
= fname
;
1730 io
.in
.sec_desc
= sd
;
1731 status
= smb2_create(tree
, tctx
, &io
);
1732 CHECK_STATUS(status
, NT_STATUS_OK
);
1733 handle
= io
.out
.file
.handle
;
1735 status
= smb2_util_close(tree
, handle
);
1736 CHECK_STATUS(status
, NT_STATUS_OK
);
1739 * now try each access_mask bit and no bit at all in a loop
1740 * and see what's allowed
1741 * NOTE: if i == 32 it means access_mask = 0 (see NO_BITS_HACK above)
1743 for (i
=0; i
<= 32; i
++) {
1744 desired_64
= ((uint64_t)1) << i
;
1745 desired
= (uint32_t)desired_64
;
1747 /* first open the file with the desired access */
1748 io
.level
= RAW_OPEN_SMB2
;
1749 io
.in
.desired_access
= desired
;
1750 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1751 status
= smb2_create(tree
, tctx
, &io
);
1752 CHECK_STATUS_FOR_BIT_ACTION(status
, open_bits
, goto next
);
1753 handle
= io
.out
.file
.handle
;
1755 /* then check what access was granted */
1756 fi
.access_information
.level
= RAW_FILEINFO_ACCESS_INFORMATION
;
1757 fi
.access_information
.in
.file
.handle
= handle
;
1758 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1759 CHECK_STATUS(status
, NT_STATUS_OK
);
1760 granted
= fi
.access_information
.out
.access_flags
;
1762 /* test the owner */
1764 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1765 fi
.query_secdesc
.in
.file
.handle
= handle
;
1766 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
1767 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1768 CHECK_STATUS_FOR_BIT(status
, get_owner_bits
, SEC_STD_READ_CONTROL
);
1769 if (fi
.query_secdesc
.out
.sd
) {
1770 sd_owner
= fi
.query_secdesc
.out
.sd
;
1771 } else if (!sd_owner
) {
1774 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1775 si
.set_secdesc
.in
.file
.handle
= handle
;
1776 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
1777 si
.set_secdesc
.in
.sd
= sd_owner
;
1778 status
= smb2_setinfo_file(tree
, &si
);
1779 CHECK_STATUS_FOR_BIT(status
, set_owner_bits
, SEC_STD_WRITE_OWNER
);
1781 /* test the group */
1783 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1784 fi
.query_secdesc
.in
.file
.handle
= handle
;
1785 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
1786 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1787 CHECK_STATUS_FOR_BIT(status
, get_group_bits
, SEC_STD_READ_CONTROL
);
1788 if (fi
.query_secdesc
.out
.sd
) {
1789 sd_group
= fi
.query_secdesc
.out
.sd
;
1790 } else if (!sd_group
) {
1793 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1794 si
.set_secdesc
.in
.file
.handle
= handle
;
1795 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_GROUP
;
1796 si
.set_secdesc
.in
.sd
= sd_group
;
1797 status
= smb2_setinfo_file(tree
, &si
);
1798 CHECK_STATUS_FOR_BIT(status
, set_group_bits
, SEC_STD_WRITE_OWNER
);
1802 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1803 fi
.query_secdesc
.in
.file
.handle
= handle
;
1804 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1805 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1806 CHECK_STATUS_FOR_BIT(status
, get_dacl_bits
, SEC_STD_READ_CONTROL
);
1807 if (fi
.query_secdesc
.out
.sd
) {
1808 sd_dacl
= fi
.query_secdesc
.out
.sd
;
1809 } else if (!sd_dacl
) {
1812 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1813 si
.set_secdesc
.in
.file
.handle
= handle
;
1814 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1815 si
.set_secdesc
.in
.sd
= sd_dacl
;
1816 status
= smb2_setinfo_file(tree
, &si
);
1817 CHECK_STATUS_FOR_BIT(status
, set_dacl_bits
, SEC_STD_WRITE_DAC
);
1821 fi
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1822 fi
.query_secdesc
.in
.file
.handle
= handle
;
1823 fi
.query_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
1824 status
= smb2_getinfo_file(tree
, tctx
, &fi
);
1825 CHECK_STATUS_FOR_BIT(status
, get_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
1826 if (fi
.query_secdesc
.out
.sd
) {
1827 sd_sacl
= fi
.query_secdesc
.out
.sd
;
1828 } else if (!sd_sacl
) {
1831 si
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1832 si
.set_secdesc
.in
.file
.handle
= handle
;
1833 si
.set_secdesc
.in
.secinfo_flags
= SECINFO_SACL
;
1834 si
.set_secdesc
.in
.sd
= sd_sacl
;
1835 status
= smb2_setinfo_file(tree
, &si
);
1836 CHECK_STATUS_FOR_BIT(status
, set_sacl_bits
, SEC_FLAG_SYSTEM_SECURITY
);
1838 /* close the handle */
1839 status
= smb2_util_close(tree
, handle
);
1840 CHECK_STATUS(status
, NT_STATUS_OK
);
1846 smb2_util_close(tree
, handle
);
1847 smb2_util_unlink(tree
, fname
);
1848 smb2_deltree(tree
, BASEDIR
);
1850 smb2_logoff(tree
->session
);
1856 basic testing of SMB2 ACLs
1858 struct torture_suite
*torture_smb2_acls_init(void)
1860 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "ACLS");
1862 torture_suite_add_1smb2_test(suite
, "CREATOR", test_creator_sid
);
1863 torture_suite_add_1smb2_test(suite
, "GENERIC", test_generic_bits
);
1864 torture_suite_add_1smb2_test(suite
, "OWNER", test_owner_bits
);
1865 torture_suite_add_1smb2_test(suite
, "INHERITANCE", test_inheritance
);
1866 torture_suite_add_1smb2_test(suite
, "INHERITFLAGS", test_inheritance_flags
);
1867 torture_suite_add_1smb2_test(suite
, "DYNAMIC", test_inheritance_dynamic
);
1868 /* XXX This test does not work against XP or Vista.
1869 torture_suite_add_1smb2_test(suite, "GETSET", test_sd_get_set);
1872 suite
->description
= talloc_strdup(suite
, "SMB2-ACLS tests");