2 Unix SMB/CIFS implementation.
4 test security descriptor operations
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "libcli/raw/libcliraw.h"
25 #include "librpc/gen_ndr/ndr_security.h"
27 #define BASEDIR "\\testsd"
29 #define CHECK_STATUS(status, correct) do { \
30 if (!NT_STATUS_EQUAL(status, correct)) { \
31 printf("(%s) Incorrect status %s - should be %s\n", \
32 __location__, nt_errstr(status), nt_errstr(correct)); \
38 static BOOL
test_sd(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
42 const char *fname
= BASEDIR
"\\sd.txt";
46 union smb_setfileinfo set
;
47 struct security_ace ace
;
48 struct security_descriptor
*sd
;
49 struct dom_sid
*test_sid
;
51 printf("TESTING SETFILEINFO EA_SET\n");
53 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
54 io
.ntcreatex
.in
.root_fid
= 0;
55 io
.ntcreatex
.in
.flags
= 0;
56 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
57 io
.ntcreatex
.in
.create_options
= 0;
58 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
59 io
.ntcreatex
.in
.share_access
=
60 NTCREATEX_SHARE_ACCESS_READ
|
61 NTCREATEX_SHARE_ACCESS_WRITE
;
62 io
.ntcreatex
.in
.alloc_size
= 0;
63 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
64 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
65 io
.ntcreatex
.in
.security_flags
= 0;
66 io
.ntcreatex
.in
.fname
= fname
;
67 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
68 CHECK_STATUS(status
, NT_STATUS_OK
);
69 fnum
= io
.ntcreatex
.out
.fnum
;
71 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
72 q
.query_secdesc
.in
.fnum
= fnum
;
73 q
.query_secdesc
.in
.secinfo_flags
=
77 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
78 CHECK_STATUS(status
, NT_STATUS_OK
);
79 sd
= q
.query_secdesc
.out
.sd
;
81 printf("add a new ACE to the DACL\n");
83 test_sid
= dom_sid_parse_talloc(mem_ctx
, "S-1-5-32-1234-5432");
85 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
87 ace
.access_mask
= SEC_STD_ALL
;
88 ace
.trustee
= *test_sid
;
90 status
= security_descriptor_dacl_add(sd
, &ace
);
91 CHECK_STATUS(status
, NT_STATUS_OK
);
93 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
94 set
.set_secdesc
.file
.fnum
= fnum
;
95 set
.set_secdesc
.in
.secinfo_flags
= q
.query_secdesc
.in
.secinfo_flags
;
96 set
.set_secdesc
.in
.sd
= sd
;
98 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
99 CHECK_STATUS(status
, NT_STATUS_OK
);
101 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
102 CHECK_STATUS(status
, NT_STATUS_OK
);
104 if (!security_acl_equal(q
.query_secdesc
.out
.sd
->dacl
, sd
->dacl
)) {
105 printf("%s: security descriptors don't match!\n", __location__
);
107 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
108 printf("expected:\n");
109 NDR_PRINT_DEBUG(security_descriptor
, sd
);
113 printf("remove it again\n");
115 status
= security_descriptor_dacl_del(sd
, test_sid
);
116 CHECK_STATUS(status
, NT_STATUS_OK
);
118 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
119 CHECK_STATUS(status
, NT_STATUS_OK
);
121 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
122 CHECK_STATUS(status
, NT_STATUS_OK
);
124 if (!security_acl_equal(q
.query_secdesc
.out
.sd
->dacl
, sd
->dacl
)) {
125 printf("%s: security descriptors don't match!\n", __location__
);
127 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
128 printf("expected:\n");
129 NDR_PRINT_DEBUG(security_descriptor
, sd
);
134 smbcli_close(cli
->tree
, fnum
);
140 test using NTTRANS CREATE to create a file with an initial ACL set
142 static BOOL
test_nttrans_create(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
146 const char *fname
= BASEDIR
"\\acl2.txt";
149 union smb_fileinfo q
;
150 struct security_ace ace
;
151 struct security_descriptor
*sd
;
152 struct dom_sid
*test_sid
;
154 printf("TESTING NTTRANS CREATE WITH SEC_DESC\n");
156 io
.generic
.level
= RAW_OPEN_NTTRANS_CREATE
;
157 io
.ntcreatex
.in
.root_fid
= 0;
158 io
.ntcreatex
.in
.flags
= 0;
159 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
160 io
.ntcreatex
.in
.create_options
= 0;
161 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
162 io
.ntcreatex
.in
.share_access
=
163 NTCREATEX_SHARE_ACCESS_READ
|
164 NTCREATEX_SHARE_ACCESS_WRITE
;
165 io
.ntcreatex
.in
.alloc_size
= 0;
166 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
167 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
168 io
.ntcreatex
.in
.security_flags
= 0;
169 io
.ntcreatex
.in
.fname
= fname
;
170 io
.ntcreatex
.in
.sec_desc
= NULL
;
171 io
.ntcreatex
.in
.ea_list
= NULL
;
173 printf("creating normal file\n");
175 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
176 CHECK_STATUS(status
, NT_STATUS_OK
);
177 fnum
= io
.ntcreatex
.out
.fnum
;
179 printf("querying ACL\n");
181 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
182 q
.query_secdesc
.in
.fnum
= fnum
;
183 q
.query_secdesc
.in
.secinfo_flags
=
187 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
188 CHECK_STATUS(status
, NT_STATUS_OK
);
189 sd
= q
.query_secdesc
.out
.sd
;
191 smbcli_close(cli
->tree
, fnum
);
192 smbcli_unlink(cli
->tree
, fname
);
194 printf("adding a new ACE\n");
195 test_sid
= dom_sid_parse_talloc(mem_ctx
, "S-1-5-32-1234-54321");
197 ace
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
199 ace
.access_mask
= SEC_STD_ALL
;
200 ace
.trustee
= *test_sid
;
202 status
= security_descriptor_dacl_add(sd
, &ace
);
203 CHECK_STATUS(status
, NT_STATUS_OK
);
205 printf("creating a file with an initial ACL\n");
207 io
.ntcreatex
.in
.sec_desc
= sd
;
208 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
209 CHECK_STATUS(status
, NT_STATUS_OK
);
210 fnum
= io
.ntcreatex
.out
.fnum
;
212 q
.query_secdesc
.in
.fnum
= fnum
;
213 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
214 CHECK_STATUS(status
, NT_STATUS_OK
);
216 if (!security_acl_equal(q
.query_secdesc
.out
.sd
->dacl
, sd
->dacl
)) {
217 printf("%s: security descriptors don't match!\n", __location__
);
219 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
220 printf("expected:\n");
221 NDR_PRINT_DEBUG(security_descriptor
, sd
);
226 smbcli_close(cli
->tree
, fnum
);
230 #define CHECK_ACCESS_FLAGS(_fnum, flags) do { \
231 union smb_fileinfo _q; \
232 _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
233 _q.access_information.in.fnum = (_fnum); \
234 status = smb_raw_fileinfo(cli->tree, mem_ctx, &_q); \
235 CHECK_STATUS(status, NT_STATUS_OK); \
236 if (_q.access_information.out.access_flags != (flags)) { \
237 printf("(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
238 __location__, _q.access_information.out.access_flags, (flags)); \
246 test the behaviour of the well known SID_CREATOR_OWNER sid, and some generic
249 static BOOL
test_creator_sid(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
253 const char *fname
= BASEDIR
"\\creator.txt";
256 union smb_fileinfo q
;
257 union smb_setfileinfo set
;
258 struct security_descriptor
*sd
, *sd_orig
, *sd2
;
259 const char *owner_sid
;
261 printf("TESTING SID_CREATOR_OWNER\n");
263 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
264 io
.ntcreatex
.in
.root_fid
= 0;
265 io
.ntcreatex
.in
.flags
= 0;
266 io
.ntcreatex
.in
.access_mask
= SEC_STD_READ_CONTROL
| SEC_STD_WRITE_DAC
| SEC_STD_WRITE_OWNER
;
267 io
.ntcreatex
.in
.create_options
= 0;
268 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
269 io
.ntcreatex
.in
.share_access
=
270 NTCREATEX_SHARE_ACCESS_READ
|
271 NTCREATEX_SHARE_ACCESS_WRITE
;
272 io
.ntcreatex
.in
.alloc_size
= 0;
273 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
274 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
275 io
.ntcreatex
.in
.security_flags
= 0;
276 io
.ntcreatex
.in
.fname
= fname
;
277 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
278 CHECK_STATUS(status
, NT_STATUS_OK
);
279 fnum
= io
.ntcreatex
.out
.fnum
;
281 printf("get the original sd\n");
282 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
283 q
.query_secdesc
.in
.fnum
= fnum
;
284 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
285 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
286 CHECK_STATUS(status
, NT_STATUS_OK
);
287 sd_orig
= q
.query_secdesc
.out
.sd
;
289 owner_sid
= dom_sid_string(mem_ctx
, sd_orig
->owner_sid
);
291 printf("set a sec desc allowing no write by CREATOR_OWNER\n");
292 sd
= security_descriptor_create(mem_ctx
,
295 SEC_ACE_TYPE_ACCESS_ALLOWED
,
296 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
300 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
301 set
.set_secdesc
.file
.fnum
= fnum
;
302 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
303 set
.set_secdesc
.in
.sd
= sd
;
305 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
306 CHECK_STATUS(status
, NT_STATUS_OK
);
308 printf("try open for write\n");
309 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
310 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
311 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
313 printf("try open for read\n");
314 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
315 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
316 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
318 printf("try open for generic write\n");
319 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_WRITE
;
320 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
321 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
323 printf("try open for generic read\n");
324 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_READ
;
325 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
326 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
328 printf("set a sec desc allowing no write by owner\n");
329 sd
= security_descriptor_create(mem_ctx
,
332 SEC_ACE_TYPE_ACCESS_ALLOWED
,
333 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
337 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
338 set
.set_secdesc
.file
.fnum
= fnum
;
339 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
340 set
.set_secdesc
.in
.sd
= sd
;
341 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
342 CHECK_STATUS(status
, NT_STATUS_OK
);
344 printf("check that sd has been mapped correctly\n");
345 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
346 CHECK_STATUS(status
, NT_STATUS_OK
);
347 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd
)) {
348 printf("%s: security descriptors don't match!\n", __location__
);
350 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
351 printf("expected:\n");
352 NDR_PRINT_DEBUG(security_descriptor
, sd
);
356 printf("try open for write\n");
357 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
358 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
359 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
361 printf("try open for read\n");
362 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
363 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
364 CHECK_STATUS(status
, NT_STATUS_OK
);
365 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.fnum
,
367 SEC_FILE_READ_ATTRIBUTE
);
368 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.fnum
);
370 printf("try open for generic write\n");
371 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_WRITE
;
372 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
373 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
375 printf("try open for generic read\n");
376 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_READ
;
377 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
378 CHECK_STATUS(status
, NT_STATUS_OK
);
379 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.fnum
,
380 SEC_RIGHTS_FILE_READ
);
381 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.fnum
);
383 printf("set a sec desc allowing generic read by owner\n");
384 sd
= security_descriptor_create(mem_ctx
,
387 SEC_ACE_TYPE_ACCESS_ALLOWED
,
388 SEC_GENERIC_READ
| SEC_STD_ALL
,
392 set
.set_secdesc
.in
.sd
= sd
;
393 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
394 CHECK_STATUS(status
, NT_STATUS_OK
);
396 printf("check that generic read has been mapped correctly\n");
397 sd2
= security_descriptor_create(mem_ctx
,
400 SEC_ACE_TYPE_ACCESS_ALLOWED
,
401 SEC_RIGHTS_FILE_READ
| SEC_STD_ALL
,
405 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
406 CHECK_STATUS(status
, NT_STATUS_OK
);
407 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd2
)) {
408 printf("%s: security descriptors don't match!\n", __location__
);
410 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
411 printf("expected:\n");
412 NDR_PRINT_DEBUG(security_descriptor
, sd2
);
417 printf("try open for write\n");
418 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
419 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
420 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
422 printf("try open for read\n");
423 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
424 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
425 CHECK_STATUS(status
, NT_STATUS_OK
);
426 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.fnum
,
428 SEC_FILE_READ_ATTRIBUTE
);
429 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.fnum
);
431 printf("try open for generic write\n");
432 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_WRITE
;
433 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
434 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
436 printf("try open for generic read\n");
437 io
.ntcreatex
.in
.access_mask
= SEC_GENERIC_READ
;
438 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
439 CHECK_STATUS(status
, NT_STATUS_OK
);
440 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.fnum
, SEC_RIGHTS_FILE_READ
);
441 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.fnum
);
444 printf("put back original sd\n");
445 set
.set_secdesc
.in
.sd
= sd_orig
;
446 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
447 CHECK_STATUS(status
, NT_STATUS_OK
);
451 smbcli_close(cli
->tree
, fnum
);
457 test the mapping of the SEC_GENERIC_xx bits to SEC_STD_xx and
460 static BOOL
test_generic_bits(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
464 const char *fname
= BASEDIR
"\\generic.txt";
467 union smb_fileinfo q
;
468 union smb_setfileinfo set
;
469 struct security_descriptor
*sd
, *sd_orig
, *sd2
;
470 const char *owner_sid
;
473 uint32_t specific_bits
;
474 } file_mappings
[] = {
476 { SEC_GENERIC_READ
, SEC_RIGHTS_FILE_READ
},
477 { SEC_GENERIC_WRITE
, SEC_RIGHTS_FILE_WRITE
},
478 { SEC_GENERIC_EXECUTE
, SEC_RIGHTS_FILE_EXECUTE
},
479 { SEC_GENERIC_ALL
, SEC_RIGHTS_FILE_ALL
},
480 { SEC_FILE_READ_DATA
, SEC_FILE_READ_DATA
},
481 { SEC_FILE_READ_ATTRIBUTE
, SEC_FILE_READ_ATTRIBUTE
}
485 uint32_t specific_bits
;
488 { SEC_GENERIC_READ
, SEC_RIGHTS_DIR_READ
},
489 { SEC_GENERIC_WRITE
, SEC_RIGHTS_DIR_WRITE
},
490 { SEC_GENERIC_EXECUTE
, SEC_RIGHTS_DIR_EXECUTE
},
491 { SEC_GENERIC_ALL
, SEC_RIGHTS_DIR_ALL
}
493 BOOL has_restore_privilege
;
494 BOOL has_take_ownership_privilege
;
496 printf("TESTING FILE GENERIC BITS\n");
498 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
499 io
.ntcreatex
.in
.root_fid
= 0;
500 io
.ntcreatex
.in
.flags
= 0;
501 io
.ntcreatex
.in
.access_mask
=
502 SEC_STD_READ_CONTROL
|
505 io
.ntcreatex
.in
.create_options
= 0;
506 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
507 io
.ntcreatex
.in
.share_access
=
508 NTCREATEX_SHARE_ACCESS_READ
|
509 NTCREATEX_SHARE_ACCESS_WRITE
;
510 io
.ntcreatex
.in
.alloc_size
= 0;
511 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
512 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
513 io
.ntcreatex
.in
.security_flags
= 0;
514 io
.ntcreatex
.in
.fname
= fname
;
515 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
516 CHECK_STATUS(status
, NT_STATUS_OK
);
517 fnum
= io
.ntcreatex
.out
.fnum
;
519 printf("get the original sd\n");
520 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
521 q
.query_secdesc
.in
.fnum
= fnum
;
522 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
523 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
524 CHECK_STATUS(status
, NT_STATUS_OK
);
525 sd_orig
= q
.query_secdesc
.out
.sd
;
527 owner_sid
= dom_sid_string(mem_ctx
, sd_orig
->owner_sid
);
529 status
= smblsa_sid_check_privilege(cli
,
531 sec_privilege_name(SEC_PRIV_RESTORE
));
532 has_restore_privilege
= NT_STATUS_IS_OK(status
);
533 if (!NT_STATUS_IS_OK(status
)) {
534 printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status
));
536 printf("SEC_PRIV_RESTORE - %s\n", has_restore_privilege
?"Yes":"No");
538 status
= smblsa_sid_check_privilege(cli
,
540 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP
));
541 has_take_ownership_privilege
= NT_STATUS_IS_OK(status
);
542 if (!NT_STATUS_IS_OK(status
)) {
543 printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status
));
545 printf("SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_restore_privilege
?"Yes":"No");
547 for (i
=0;i
<ARRAY_SIZE(file_mappings
);i
++) {
548 uint32_t expected_mask
=
550 SEC_STD_READ_CONTROL
|
551 SEC_FILE_READ_ATTRIBUTE
|
553 uint32_t expected_mask_anon
= SEC_FILE_READ_ATTRIBUTE
;
555 if (has_restore_privilege
) {
556 expected_mask_anon
|= SEC_STD_DELETE
;
559 printf("testing generic bits 0x%08x\n",
560 file_mappings
[i
].gen_bits
);
561 sd
= security_descriptor_create(mem_ctx
,
564 SEC_ACE_TYPE_ACCESS_ALLOWED
,
565 file_mappings
[i
].gen_bits
,
569 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
570 set
.set_secdesc
.file
.fnum
= fnum
;
571 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
572 set
.set_secdesc
.in
.sd
= sd
;
574 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
575 CHECK_STATUS(status
, NT_STATUS_OK
);
577 sd2
= security_descriptor_create(mem_ctx
,
580 SEC_ACE_TYPE_ACCESS_ALLOWED
,
581 file_mappings
[i
].specific_bits
,
585 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
586 CHECK_STATUS(status
, NT_STATUS_OK
);
587 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd2
)) {
588 printf("%s: security descriptors don't match!\n", __location__
);
590 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
591 printf("expected:\n");
592 NDR_PRINT_DEBUG(security_descriptor
, sd2
);
596 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
597 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
598 CHECK_STATUS(status
, NT_STATUS_OK
);
599 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.fnum
,
600 expected_mask
| file_mappings
[i
].specific_bits
);
601 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.fnum
);
603 if (!has_take_ownership_privilege
) {
607 printf("testing generic bits 0x%08x (anonymous)\n",
608 file_mappings
[i
].gen_bits
);
609 sd
= security_descriptor_create(mem_ctx
,
610 SID_NT_ANONYMOUS
, NULL
,
612 SEC_ACE_TYPE_ACCESS_ALLOWED
,
613 file_mappings
[i
].gen_bits
,
617 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
618 set
.set_secdesc
.file
.fnum
= fnum
;
619 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
620 set
.set_secdesc
.in
.sd
= sd
;
622 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
623 CHECK_STATUS(status
, NT_STATUS_OK
);
625 sd2
= security_descriptor_create(mem_ctx
,
626 SID_NT_ANONYMOUS
, NULL
,
628 SEC_ACE_TYPE_ACCESS_ALLOWED
,
629 file_mappings
[i
].specific_bits
,
633 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
634 CHECK_STATUS(status
, NT_STATUS_OK
);
635 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd2
)) {
636 printf("%s: security descriptors don't match!\n", __location__
);
638 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
639 printf("expected:\n");
640 NDR_PRINT_DEBUG(security_descriptor
, sd2
);
644 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
645 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
646 CHECK_STATUS(status
, NT_STATUS_OK
);
647 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.fnum
,
648 expected_mask_anon
| file_mappings
[i
].specific_bits
);
649 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.fnum
);
652 printf("put back original sd\n");
653 set
.set_secdesc
.in
.sd
= sd_orig
;
654 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
655 CHECK_STATUS(status
, NT_STATUS_OK
);
657 smbcli_close(cli
->tree
, fnum
);
658 smbcli_unlink(cli
->tree
, fname
);
661 printf("TESTING DIR GENERIC BITS\n");
663 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
664 io
.ntcreatex
.in
.root_fid
= 0;
665 io
.ntcreatex
.in
.flags
= 0;
666 io
.ntcreatex
.in
.access_mask
= SEC_STD_READ_CONTROL
| SEC_STD_WRITE_DAC
;
667 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
668 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
669 io
.ntcreatex
.in
.share_access
=
670 NTCREATEX_SHARE_ACCESS_READ
|
671 NTCREATEX_SHARE_ACCESS_WRITE
;
672 io
.ntcreatex
.in
.alloc_size
= 0;
673 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
674 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
675 io
.ntcreatex
.in
.security_flags
= 0;
676 io
.ntcreatex
.in
.fname
= fname
;
677 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
678 CHECK_STATUS(status
, NT_STATUS_OK
);
679 fnum
= io
.ntcreatex
.out
.fnum
;
681 printf("get the original sd\n");
682 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
683 q
.query_secdesc
.in
.fnum
= fnum
;
684 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
685 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
686 CHECK_STATUS(status
, NT_STATUS_OK
);
687 sd_orig
= q
.query_secdesc
.out
.sd
;
689 owner_sid
= dom_sid_string(mem_ctx
, sd_orig
->owner_sid
);
692 for (i
=0;i
<ARRAY_SIZE(dir_mappings
);i
++) {
693 uint32_t expected_mask
=
695 SEC_STD_READ_CONTROL
|
696 SEC_FILE_READ_ATTRIBUTE
|
699 printf("testing generic bits 0x%08x\n",
700 file_mappings
[i
].gen_bits
);
701 sd
= security_descriptor_create(mem_ctx
,
704 SEC_ACE_TYPE_ACCESS_ALLOWED
,
705 dir_mappings
[i
].gen_bits
,
709 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
710 set
.set_secdesc
.file
.fnum
= fnum
;
711 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
712 set
.set_secdesc
.in
.sd
= sd
;
714 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
715 CHECK_STATUS(status
, NT_STATUS_OK
);
717 sd2
= security_descriptor_create(mem_ctx
,
720 SEC_ACE_TYPE_ACCESS_ALLOWED
,
721 dir_mappings
[i
].specific_bits
,
725 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
726 CHECK_STATUS(status
, NT_STATUS_OK
);
727 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd2
)) {
728 printf("%s: security descriptors don't match!\n", __location__
);
730 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
731 printf("expected:\n");
732 NDR_PRINT_DEBUG(security_descriptor
, sd2
);
736 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
737 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
738 CHECK_STATUS(status
, NT_STATUS_OK
);
739 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.fnum
,
740 expected_mask
| dir_mappings
[i
].specific_bits
);
741 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.fnum
);
744 printf("put back original sd\n");
745 set
.set_secdesc
.in
.sd
= sd_orig
;
746 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
747 CHECK_STATUS(status
, NT_STATUS_OK
);
749 smbcli_close(cli
->tree
, fnum
);
750 smbcli_unlink(cli
->tree
, fname
);
753 smbcli_close(cli
->tree
, fnum
);
759 see what access bits the owner of a file always gets
761 static BOOL
test_owner_bits(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
765 const char *fname
= BASEDIR
"\\generic.txt";
768 union smb_fileinfo q
;
769 union smb_setfileinfo set
;
770 struct security_descriptor
*sd
, *sd_orig
;
771 const char *owner_sid
;
772 BOOL has_restore_privilege
;
773 BOOL has_take_ownership_privilege
;
774 uint32_t expected_bits
;
776 printf("TESTING FILE OWNER BITS\n");
778 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
779 io
.ntcreatex
.in
.root_fid
= 0;
780 io
.ntcreatex
.in
.flags
= 0;
781 io
.ntcreatex
.in
.access_mask
=
782 SEC_STD_READ_CONTROL
|
785 io
.ntcreatex
.in
.create_options
= 0;
786 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
787 io
.ntcreatex
.in
.share_access
=
788 NTCREATEX_SHARE_ACCESS_READ
|
789 NTCREATEX_SHARE_ACCESS_WRITE
;
790 io
.ntcreatex
.in
.alloc_size
= 0;
791 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
792 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
793 io
.ntcreatex
.in
.security_flags
= 0;
794 io
.ntcreatex
.in
.fname
= fname
;
795 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
796 CHECK_STATUS(status
, NT_STATUS_OK
);
797 fnum
= io
.ntcreatex
.out
.fnum
;
799 printf("get the original sd\n");
800 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
801 q
.query_secdesc
.in
.fnum
= fnum
;
802 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
803 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
804 CHECK_STATUS(status
, NT_STATUS_OK
);
805 sd_orig
= q
.query_secdesc
.out
.sd
;
807 owner_sid
= dom_sid_string(mem_ctx
, sd_orig
->owner_sid
);
809 status
= smblsa_sid_check_privilege(cli
,
811 sec_privilege_name(SEC_PRIV_RESTORE
));
812 has_restore_privilege
= NT_STATUS_IS_OK(status
);
813 if (!NT_STATUS_IS_OK(status
)) {
814 printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status
));
816 printf("SEC_PRIV_RESTORE - %s\n", has_restore_privilege
?"Yes":"No");
818 status
= smblsa_sid_check_privilege(cli
,
820 sec_privilege_name(SEC_PRIV_TAKE_OWNERSHIP
));
821 has_take_ownership_privilege
= NT_STATUS_IS_OK(status
);
822 if (!NT_STATUS_IS_OK(status
)) {
823 printf("smblsa_sid_check_privilege - %s\n", nt_errstr(status
));
825 printf("SEC_PRIV_TAKE_OWNERSHIP - %s\n", has_restore_privilege
?"Yes":"No");
827 sd
= security_descriptor_create(mem_ctx
,
830 SEC_ACE_TYPE_ACCESS_ALLOWED
,
835 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
836 set
.set_secdesc
.file
.fnum
= fnum
;
837 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
838 set
.set_secdesc
.in
.sd
= sd
;
840 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
841 CHECK_STATUS(status
, NT_STATUS_OK
);
843 expected_bits
= SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
;
847 io
.ntcreatex
.in
.access_mask
= bit
;
848 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
849 if (expected_bits
& bit
) {
850 if (!NT_STATUS_IS_OK(status
)) {
851 printf("failed with access mask 0x%08x of expected 0x%08x\n",
854 CHECK_STATUS(status
, NT_STATUS_OK
);
855 CHECK_ACCESS_FLAGS(io
.ntcreatex
.out
.fnum
, bit
| SEC_FILE_READ_ATTRIBUTE
);
856 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.fnum
);
858 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
862 printf("put back original sd\n");
863 set
.set_secdesc
.in
.sd
= sd_orig
;
864 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
865 CHECK_STATUS(status
, NT_STATUS_OK
);
868 smbcli_close(cli
->tree
, fnum
);
869 smbcli_unlink(cli
->tree
, fname
);
876 test the inheritance of ACL flags onto new files and directories
878 static BOOL
test_inheritance(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
882 const char *dname
= BASEDIR
"\\inheritance";
883 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
884 const char *fname2
= BASEDIR
"\\inheritance\\testdir";
887 union smb_fileinfo q
;
888 union smb_setfileinfo set
;
889 struct security_descriptor
*sd
, *sd_orig
, *sd_def
;
890 const char *owner_sid
;
891 const struct dom_sid
*creator_owner
;
893 uint32_t parent_flags
;
903 SEC_ACE_FLAG_OBJECT_INHERIT
,
905 SEC_ACE_FLAG_OBJECT_INHERIT
|
906 SEC_ACE_FLAG_INHERIT_ONLY
,
909 SEC_ACE_FLAG_CONTAINER_INHERIT
,
911 SEC_ACE_FLAG_CONTAINER_INHERIT
,
914 SEC_ACE_FLAG_OBJECT_INHERIT
|
915 SEC_ACE_FLAG_CONTAINER_INHERIT
,
917 SEC_ACE_FLAG_OBJECT_INHERIT
|
918 SEC_ACE_FLAG_CONTAINER_INHERIT
,
921 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
926 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
927 SEC_ACE_FLAG_OBJECT_INHERIT
,
932 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
933 SEC_ACE_FLAG_CONTAINER_INHERIT
,
938 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
939 SEC_ACE_FLAG_CONTAINER_INHERIT
|
940 SEC_ACE_FLAG_OBJECT_INHERIT
,
945 SEC_ACE_FLAG_INHERIT_ONLY
,
950 SEC_ACE_FLAG_INHERIT_ONLY
|
951 SEC_ACE_FLAG_OBJECT_INHERIT
,
953 SEC_ACE_FLAG_OBJECT_INHERIT
|
954 SEC_ACE_FLAG_INHERIT_ONLY
,
957 SEC_ACE_FLAG_INHERIT_ONLY
|
958 SEC_ACE_FLAG_CONTAINER_INHERIT
,
960 SEC_ACE_FLAG_CONTAINER_INHERIT
,
963 SEC_ACE_FLAG_INHERIT_ONLY
|
964 SEC_ACE_FLAG_CONTAINER_INHERIT
|
965 SEC_ACE_FLAG_OBJECT_INHERIT
,
967 SEC_ACE_FLAG_CONTAINER_INHERIT
|
968 SEC_ACE_FLAG_OBJECT_INHERIT
,
971 SEC_ACE_FLAG_INHERIT_ONLY
|
972 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
,
977 SEC_ACE_FLAG_INHERIT_ONLY
|
978 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
979 SEC_ACE_FLAG_OBJECT_INHERIT
,
984 SEC_ACE_FLAG_INHERIT_ONLY
|
985 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
986 SEC_ACE_FLAG_CONTAINER_INHERIT
,
991 SEC_ACE_FLAG_INHERIT_ONLY
|
992 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
993 SEC_ACE_FLAG_CONTAINER_INHERIT
|
994 SEC_ACE_FLAG_OBJECT_INHERIT
,
1000 smbcli_rmdir(cli
->tree
, dname
);
1002 printf("TESTING ACL INHERITANCE\n");
1004 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1005 io
.ntcreatex
.in
.root_fid
= 0;
1006 io
.ntcreatex
.in
.flags
= 0;
1007 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1008 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1009 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1010 io
.ntcreatex
.in
.share_access
= 0;
1011 io
.ntcreatex
.in
.alloc_size
= 0;
1012 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1013 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1014 io
.ntcreatex
.in
.security_flags
= 0;
1015 io
.ntcreatex
.in
.fname
= dname
;
1017 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1018 CHECK_STATUS(status
, NT_STATUS_OK
);
1019 fnum
= io
.ntcreatex
.out
.fnum
;
1021 printf("get the original sd\n");
1022 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1023 q
.query_secdesc
.in
.fnum
= fnum
;
1024 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1025 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
1026 CHECK_STATUS(status
, NT_STATUS_OK
);
1027 sd_orig
= q
.query_secdesc
.out
.sd
;
1029 owner_sid
= dom_sid_string(mem_ctx
, sd_orig
->owner_sid
);
1031 printf("owner_sid is %s\n", owner_sid
);
1033 sd_def
= security_descriptor_create(mem_ctx
,
1036 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1037 SEC_RIGHTS_FILE_ALL
,
1040 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1041 SEC_RIGHTS_FILE_ALL
,
1045 creator_owner
= dom_sid_parse_talloc(mem_ctx
, SID_CREATOR_OWNER
);
1047 for (i
=0;i
<ARRAY_SIZE(test_flags
);i
++) {
1048 sd
= security_descriptor_create(mem_ctx
,
1051 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1052 SEC_FILE_WRITE_DATA
,
1053 test_flags
[i
].parent_flags
,
1055 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1056 SEC_FILE_ALL
| SEC_STD_ALL
,
1059 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1060 set
.set_secdesc
.file
.fnum
= fnum
;
1061 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1062 set
.set_secdesc
.in
.sd
= sd
;
1063 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1064 CHECK_STATUS(status
, NT_STATUS_OK
);
1066 io
.ntcreatex
.in
.fname
= fname1
;
1067 io
.ntcreatex
.in
.create_options
= 0;
1068 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1069 CHECK_STATUS(status
, NT_STATUS_OK
);
1070 fnum2
= io
.ntcreatex
.out
.fnum
;
1072 q
.query_secdesc
.in
.fnum
= fnum2
;
1073 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
1074 CHECK_STATUS(status
, NT_STATUS_OK
);
1076 smbcli_close(cli
->tree
, fnum2
);
1077 smbcli_unlink(cli
->tree
, fname1
);
1079 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
)) {
1080 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def
)) {
1081 printf("Expected default sd at %d - got:\n", i
);
1082 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1087 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1088 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
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 printf("Bad sd in child file at %d\n", i
);
1093 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1098 if (q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!=
1099 test_flags
[i
].file_flags
) {
1100 printf("incorrect file_flags 0x%x - expected 0x%x for parent 0x%x with (i=%d)\n",
1101 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
,
1102 test_flags
[i
].file_flags
,
1103 test_flags
[i
].parent_flags
,
1109 io
.ntcreatex
.in
.fname
= fname2
;
1110 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1111 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1112 CHECK_STATUS(status
, NT_STATUS_OK
);
1113 fnum2
= io
.ntcreatex
.out
.fnum
;
1115 q
.query_secdesc
.in
.fnum
= fnum2
;
1116 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
1117 CHECK_STATUS(status
, NT_STATUS_OK
);
1119 smbcli_close(cli
->tree
, fnum2
);
1120 smbcli_rmdir(cli
->tree
, fname2
);
1122 if (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1123 (!(test_flags
[i
].parent_flags
& SEC_ACE_FLAG_OBJECT_INHERIT
) ||
1124 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
))) {
1125 if (!security_descriptor_equal(q
.query_secdesc
.out
.sd
, sd_def
)) {
1126 printf("Expected default sd for dir at %d - got:\n", i
);
1127 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1132 if ((test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) &&
1133 (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
)) {
1134 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1135 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1136 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1137 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1138 sd_orig
->owner_sid
) ||
1139 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1140 printf("Bad sd in child dir at %d (parent 0x%x)\n",
1141 i
, test_flags
[i
].parent_flags
);
1142 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1146 } else if (test_flags
[i
].parent_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) {
1147 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1148 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 2 ||
1149 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1150 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1151 sd_orig
->owner_sid
) ||
1152 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].access_mask
!= SEC_FILE_WRITE_DATA
||
1153 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[1].trustee
,
1155 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= 0 ||
1156 q
.query_secdesc
.out
.sd
->dacl
->aces
[1].flags
!=
1157 (test_flags
[i
].dir_flags
| SEC_ACE_FLAG_INHERIT_ONLY
)) {
1158 printf("Bad sd in child dir at %d (parent 0x%x)\n",
1159 i
, test_flags
[i
].parent_flags
);
1160 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1165 if (q
.query_secdesc
.out
.sd
->dacl
== NULL
||
1166 q
.query_secdesc
.out
.sd
->dacl
->num_aces
!= 1 ||
1167 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].access_mask
!= SEC_FILE_WRITE_DATA
||
1168 !dom_sid_equal(&q
.query_secdesc
.out
.sd
->dacl
->aces
[0].trustee
,
1170 q
.query_secdesc
.out
.sd
->dacl
->aces
[0].flags
!= test_flags
[i
].dir_flags
) {
1171 printf("Bad sd in child dir at %d (parent 0x%x)\n",
1172 i
, test_flags
[i
].parent_flags
);
1173 NDR_PRINT_DEBUG(security_descriptor
, q
.query_secdesc
.out
.sd
);
1180 printf("testing access checks on inherited create with %s\n", fname1
);
1181 sd
= security_descriptor_create(mem_ctx
,
1184 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1185 SEC_FILE_WRITE_DATA
| SEC_STD_WRITE_DAC
,
1186 SEC_ACE_FLAG_OBJECT_INHERIT
,
1188 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1189 SEC_FILE_ALL
| SEC_STD_ALL
,
1192 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1193 set
.set_secdesc
.file
.fnum
= fnum
;
1194 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1195 set
.set_secdesc
.in
.sd
= sd
;
1196 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1197 CHECK_STATUS(status
, NT_STATUS_OK
);
1199 io
.ntcreatex
.in
.fname
= fname1
;
1200 io
.ntcreatex
.in
.create_options
= 0;
1201 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1202 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1203 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1204 CHECK_STATUS(status
, NT_STATUS_OK
);
1205 fnum2
= io
.ntcreatex
.out
.fnum
;
1206 CHECK_ACCESS_FLAGS(fnum2
, SEC_RIGHTS_FILE_ALL
);
1208 q
.query_secdesc
.in
.fnum
= fnum2
;
1209 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1210 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
1211 CHECK_STATUS(status
, NT_STATUS_OK
);
1212 smbcli_close(cli
->tree
, fnum2
);
1214 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1215 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1216 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1217 if (NT_STATUS_IS_OK(status
)) {
1218 printf("failed: w2k3 ACL bug (allowed open when ACL should deny)\n");
1220 fnum2
= io
.ntcreatex
.out
.fnum
;
1221 smbcli_close(cli
->tree
, fnum2
);
1223 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1226 printf("trying without execute\n");
1227 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1228 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
& ~SEC_FILE_EXECUTE
;
1229 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1230 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1232 printf("and with full permissions again\n");
1233 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1234 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1235 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1236 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1238 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
1239 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1240 CHECK_STATUS(status
, NT_STATUS_OK
);
1241 fnum2
= io
.ntcreatex
.out
.fnum
;
1242 CHECK_ACCESS_FLAGS(fnum2
, SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
);
1243 smbcli_close(cli
->tree
, fnum2
);
1245 printf("put back original sd\n");
1246 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1247 set
.set_secdesc
.file
.fnum
= fnum
;
1248 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1249 set
.set_secdesc
.in
.sd
= sd_orig
;
1250 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1251 CHECK_STATUS(status
, NT_STATUS_OK
);
1253 smbcli_close(cli
->tree
, fnum
);
1255 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1256 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1257 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1259 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
1260 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1261 CHECK_STATUS(status
, NT_STATUS_OK
);
1262 fnum2
= io
.ntcreatex
.out
.fnum
;
1263 CHECK_ACCESS_FLAGS(fnum2
, SEC_FILE_WRITE_DATA
| SEC_FILE_READ_ATTRIBUTE
);
1264 smbcli_close(cli
->tree
, fnum2
);
1266 smbcli_unlink(cli
->tree
, fname1
);
1267 smbcli_rmdir(cli
->tree
, dname
);
1270 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1271 set
.set_secdesc
.file
.fnum
= fnum
;
1272 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1273 set
.set_secdesc
.in
.sd
= sd_orig
;
1274 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1276 smbcli_close(cli
->tree
, fnum
);
1282 test dynamic acl inheritance
1284 static BOOL
test_inheritance_dynamic(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
1288 const char *dname
= BASEDIR
"\\inheritance";
1289 const char *fname1
= BASEDIR
"\\inheritance\\testfile";
1292 union smb_fileinfo q
;
1293 union smb_setfileinfo set
;
1294 struct security_descriptor
*sd
, *sd_orig
;
1295 const char *owner_sid
;
1297 printf("TESTING DYNAMIC ACL INHERITANCE\n");
1299 if (!torture_setup_dir(cli
, BASEDIR
)) {
1303 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1304 io
.ntcreatex
.in
.root_fid
= 0;
1305 io
.ntcreatex
.in
.flags
= 0;
1306 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1307 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1308 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1309 io
.ntcreatex
.in
.share_access
= 0;
1310 io
.ntcreatex
.in
.alloc_size
= 0;
1311 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1312 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1313 io
.ntcreatex
.in
.security_flags
= 0;
1314 io
.ntcreatex
.in
.fname
= dname
;
1316 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1317 CHECK_STATUS(status
, NT_STATUS_OK
);
1318 fnum
= io
.ntcreatex
.out
.fnum
;
1320 printf("get the original sd\n");
1321 q
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
1322 q
.query_secdesc
.in
.fnum
= fnum
;
1323 q
.query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
| SECINFO_OWNER
;
1324 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &q
);
1325 CHECK_STATUS(status
, NT_STATUS_OK
);
1326 sd_orig
= q
.query_secdesc
.out
.sd
;
1328 owner_sid
= dom_sid_string(mem_ctx
, sd_orig
->owner_sid
);
1330 printf("owner_sid is %s\n", owner_sid
);
1332 sd
= security_descriptor_create(mem_ctx
,
1335 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1336 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
,
1337 SEC_ACE_FLAG_OBJECT_INHERIT
,
1339 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1341 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1342 set
.set_secdesc
.file
.fnum
= fnum
;
1343 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1344 set
.set_secdesc
.in
.sd
= sd
;
1345 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1346 CHECK_STATUS(status
, NT_STATUS_OK
);
1348 printf("create a file with an inherited acl\n");
1349 io
.ntcreatex
.in
.fname
= fname1
;
1350 io
.ntcreatex
.in
.create_options
= 0;
1351 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
;
1352 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1353 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1354 CHECK_STATUS(status
, NT_STATUS_OK
);
1355 fnum2
= io
.ntcreatex
.out
.fnum
;
1356 smbcli_close(cli
->tree
, fnum2
);
1358 printf("try and access file with base rights - should be OK\n");
1359 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
1360 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1361 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1362 CHECK_STATUS(status
, NT_STATUS_OK
);
1363 fnum2
= io
.ntcreatex
.out
.fnum
;
1364 smbcli_close(cli
->tree
, fnum2
);
1366 printf("try and access file with extra rights - should be denied\n");
1367 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1368 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1369 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1371 printf("update parent sd\n");
1372 sd
= security_descriptor_create(mem_ctx
,
1375 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1376 SEC_FILE_WRITE_DATA
| SEC_STD_DELETE
| SEC_FILE_READ_ATTRIBUTE
| SEC_FILE_EXECUTE
,
1377 SEC_ACE_FLAG_OBJECT_INHERIT
,
1379 sd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
| SEC_DESC_DACL_AUTO_INHERIT_REQ
;
1381 set
.set_secdesc
.in
.sd
= sd
;
1382 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1383 CHECK_STATUS(status
, NT_STATUS_OK
);
1385 printf("try and access file with base rights - should be OK\n");
1386 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
1387 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1388 CHECK_STATUS(status
, NT_STATUS_OK
);
1389 fnum2
= io
.ntcreatex
.out
.fnum
;
1390 smbcli_close(cli
->tree
, fnum2
);
1393 printf("try and access now - should be OK if dynamic inheritance works\n");
1394 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
| SEC_FILE_EXECUTE
;
1395 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1396 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1397 printf("Server does not have dynamic inheritance\n");
1399 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1400 printf("Server does have dynamic inheritance\n");
1402 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
1404 smbcli_unlink(cli
->tree
, fname1
);
1407 printf("put back original sd\n");
1408 set
.set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
1409 set
.set_secdesc
.file
.fnum
= fnum
;
1410 set
.set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
1411 set
.set_secdesc
.in
.sd
= sd_orig
;
1412 status
= smb_raw_setfileinfo(cli
->tree
, &set
);
1414 smbcli_close(cli
->tree
, fnum
);
1415 smbcli_rmdir(cli
->tree
, dname
);
1422 basic testing of security descriptor calls
1424 BOOL
torture_raw_acls(void)
1426 struct smbcli_state
*cli
;
1428 TALLOC_CTX
*mem_ctx
;
1430 if (!torture_open_connection(&cli
)) {
1434 mem_ctx
= talloc_init("torture_raw_acls");
1436 if (!torture_setup_dir(cli
, BASEDIR
)) {
1440 ret
&= test_sd(cli
, mem_ctx
);
1441 ret
&= test_nttrans_create(cli
, mem_ctx
);
1442 ret
&= test_creator_sid(cli
, mem_ctx
);
1443 ret
&= test_generic_bits(cli
, mem_ctx
);
1444 ret
&= test_owner_bits(cli
, mem_ctx
);
1445 ret
&= test_inheritance(cli
, mem_ctx
);
1446 ret
&= test_inheritance_dynamic(cli
, mem_ctx
);
1448 smb_raw_exit(cli
->session
);
1449 smbcli_deltree(cli
->tree
, BASEDIR
);
1451 torture_close_connection(cli
);
1452 talloc_destroy(mem_ctx
);