2 * Unix SMB/Netbios implementation.
3 * SEC_DESC handling functions
4 * Copyright (C) Andrew Tridgell 1992-1998,
5 * Copyright (C) Jeremy R. Allison 1995-2003.
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7 * Copyright (C) Paul Ashton 1997-1998.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "libcli/security/security.h"
27 /* Map generic permissions to file object specific permissions */
29 const struct generic_mapping file_generic_mapping
= {
36 /*******************************************************************
37 Given a security_descriptor return the sec_info.
38 ********************************************************************/
40 uint32_t get_sec_info(const struct security_descriptor
*sd
)
42 uint32_t sec_info
= 0;
46 if (sd
->owner_sid
!= NULL
) {
47 sec_info
|= SECINFO_OWNER
;
49 if (sd
->group_sid
!= NULL
) {
50 sec_info
|= SECINFO_GROUP
;
52 if (sd
->sacl
!= NULL
) {
53 sec_info
|= SECINFO_SACL
;
55 if (sd
->dacl
!= NULL
) {
56 sec_info
|= SECINFO_DACL
;
59 if (sd
->type
& SEC_DESC_SACL_PROTECTED
) {
60 sec_info
|= SECINFO_PROTECTED_SACL
;
61 } else if (sd
->type
& SEC_DESC_SACL_AUTO_INHERITED
) {
62 sec_info
|= SECINFO_UNPROTECTED_SACL
;
64 if (sd
->type
& SEC_DESC_DACL_PROTECTED
) {
65 sec_info
|= SECINFO_PROTECTED_DACL
;
66 } else if (sd
->type
& SEC_DESC_DACL_AUTO_INHERITED
) {
67 sec_info
|= SECINFO_UNPROTECTED_DACL
;
74 /*******************************************************************
75 Merge part of security descriptor old_sec in to the empty sections of
76 security descriptor new_sec.
77 ********************************************************************/
79 struct sec_desc_buf
*sec_desc_merge_buf(TALLOC_CTX
*ctx
, struct sec_desc_buf
*new_sdb
, struct sec_desc_buf
*old_sdb
)
81 struct dom_sid
*owner_sid
, *group_sid
;
82 struct sec_desc_buf
*return_sdb
;
83 struct security_acl
*dacl
, *sacl
;
84 struct security_descriptor
*psd
= NULL
;
85 uint16_t secdesc_type
;
88 /* Copy over owner and group sids. There seems to be no flag for
89 this so just check the pointer values. */
91 owner_sid
= new_sdb
->sd
->owner_sid
? new_sdb
->sd
->owner_sid
:
92 old_sdb
->sd
->owner_sid
;
94 group_sid
= new_sdb
->sd
->group_sid
? new_sdb
->sd
->group_sid
:
95 old_sdb
->sd
->group_sid
;
97 secdesc_type
= new_sdb
->sd
->type
;
99 /* Ignore changes to the system ACL. This has the effect of making
100 changes through the security tab audit button not sticking.
101 Perhaps in future Samba could implement these settings somehow. */
104 secdesc_type
&= ~SEC_DESC_SACL_PRESENT
;
106 /* Copy across discretionary ACL */
108 if (secdesc_type
& SEC_DESC_DACL_PRESENT
) {
109 dacl
= new_sdb
->sd
->dacl
;
111 dacl
= old_sdb
->sd
->dacl
;
114 /* Create new security descriptor from bits */
116 psd
= make_sec_desc(ctx
, new_sdb
->sd
->revision
, secdesc_type
,
117 owner_sid
, group_sid
, sacl
, dacl
, &secdesc_size
);
119 return_sdb
= make_sec_desc_buf(ctx
, secdesc_size
, psd
);
124 struct security_descriptor
*sec_desc_merge(TALLOC_CTX
*ctx
, struct security_descriptor
*new_sdb
, struct security_descriptor
*old_sdb
)
126 struct dom_sid
*owner_sid
, *group_sid
;
127 struct security_acl
*dacl
, *sacl
;
128 struct security_descriptor
*psd
= NULL
;
129 uint16_t secdesc_type
;
132 /* Copy over owner and group sids. There seems to be no flag for
133 this so just check the pointer values. */
135 owner_sid
= new_sdb
->owner_sid
? new_sdb
->owner_sid
:
138 group_sid
= new_sdb
->group_sid
? new_sdb
->group_sid
:
141 secdesc_type
= new_sdb
->type
;
143 /* Ignore changes to the system ACL. This has the effect of making
144 changes through the security tab audit button not sticking.
145 Perhaps in future Samba could implement these settings somehow. */
148 secdesc_type
&= ~SEC_DESC_SACL_PRESENT
;
150 /* Copy across discretionary ACL */
152 if (secdesc_type
& SEC_DESC_DACL_PRESENT
) {
153 dacl
= new_sdb
->dacl
;
155 dacl
= old_sdb
->dacl
;
158 /* Create new security descriptor from bits */
159 psd
= make_sec_desc(ctx
, new_sdb
->revision
, secdesc_type
,
160 owner_sid
, group_sid
, sacl
, dacl
, &secdesc_size
);
165 /*******************************************************************
166 Creates a struct security_descriptor structure
167 ********************************************************************/
168 struct security_descriptor
*make_sec_desc(TALLOC_CTX
*ctx
,
169 enum security_descriptor_revision revision
,
171 const struct dom_sid
*owner_sid
, const struct dom_sid
*grp_sid
,
172 struct security_acl
*sacl
, struct security_acl
*dacl
, size_t *sd_size
)
174 struct security_descriptor
*dst
;
176 if (sd_size
!= NULL
) {
180 dst
= security_descriptor_initialise(ctx
);
185 dst
->revision
= revision
;
189 dst
->sacl
= security_acl_dup(dst
, sacl
);
190 if (dst
->sacl
== NULL
) {
193 dst
->type
|= SEC_DESC_SACL_PRESENT
;
197 dst
->dacl
= security_acl_dup(dst
, dacl
);
198 if (dst
->dacl
== NULL
) {
201 dst
->type
|= SEC_DESC_DACL_PRESENT
;
204 if (owner_sid
!= NULL
) {
205 dst
->owner_sid
= dom_sid_dup(dst
, owner_sid
);
206 if (dst
->owner_sid
== NULL
) {
211 if (grp_sid
!= NULL
) {
212 dst
->group_sid
= dom_sid_dup(dst
, grp_sid
);
213 if (dst
->group_sid
== NULL
) {
218 if (sd_size
!= NULL
) {
219 *sd_size
= ndr_size_security_descriptor(dst
, 0);
229 /*******************************************************************
230 Convert a secdesc into a byte stream
231 ********************************************************************/
232 NTSTATUS
marshall_sec_desc(TALLOC_CTX
*mem_ctx
,
233 const struct security_descriptor
*secdesc
,
234 uint8_t **data
, size_t *len
)
237 enum ndr_err_code ndr_err
;
239 ndr_err
= ndr_push_struct_blob(
240 &blob
, mem_ctx
, secdesc
,
241 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
243 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
244 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
245 ndr_errstr(ndr_err
)));
246 return ndr_map_error2ntstatus(ndr_err
);
254 /*******************************************************************
255 Convert a secdesc_buf into a byte stream
256 ********************************************************************/
258 NTSTATUS
marshall_sec_desc_buf(TALLOC_CTX
*mem_ctx
,
259 const struct sec_desc_buf
*secdesc_buf
,
260 uint8_t **data
, size_t *len
)
263 enum ndr_err_code ndr_err
;
265 ndr_err
= ndr_push_struct_blob(
266 &blob
, mem_ctx
, secdesc_buf
,
267 (ndr_push_flags_fn_t
)ndr_push_sec_desc_buf
);
269 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
270 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
271 ndr_errstr(ndr_err
)));
272 return ndr_map_error2ntstatus(ndr_err
);
280 /*******************************************************************
281 Parse a byte stream into a secdesc
282 ********************************************************************/
283 NTSTATUS
unmarshall_sec_desc(TALLOC_CTX
*mem_ctx
, uint8_t *data
, size_t len
,
284 struct security_descriptor
**psecdesc
)
287 enum ndr_err_code ndr_err
;
288 struct security_descriptor
*result
;
290 if ((data
== NULL
) || (len
== 0)) {
291 return NT_STATUS_INVALID_PARAMETER
;
294 result
= talloc_zero(mem_ctx
, struct security_descriptor
);
295 if (result
== NULL
) {
296 return NT_STATUS_NO_MEMORY
;
299 blob
= data_blob_const(data
, len
);
301 ndr_err
= ndr_pull_struct_blob(&blob
, result
, result
,
302 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
304 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
305 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
306 ndr_errstr(ndr_err
)));
308 return ndr_map_error2ntstatus(ndr_err
);
315 /*******************************************************************
316 Parse a byte stream into a sec_desc_buf
317 ********************************************************************/
319 NTSTATUS
unmarshall_sec_desc_buf(TALLOC_CTX
*mem_ctx
, uint8_t *data
, size_t len
,
320 struct sec_desc_buf
**psecdesc_buf
)
323 enum ndr_err_code ndr_err
;
324 struct sec_desc_buf
*result
;
326 if ((data
== NULL
) || (len
== 0)) {
327 return NT_STATUS_INVALID_PARAMETER
;
330 result
= talloc_zero(mem_ctx
, struct sec_desc_buf
);
331 if (result
== NULL
) {
332 return NT_STATUS_NO_MEMORY
;
335 blob
= data_blob_const(data
, len
);
337 ndr_err
= ndr_pull_struct_blob(&blob
, result
, result
,
338 (ndr_pull_flags_fn_t
)ndr_pull_sec_desc_buf
);
340 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
341 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
342 ndr_errstr(ndr_err
)));
344 return ndr_map_error2ntstatus(ndr_err
);
347 *psecdesc_buf
= result
;
351 /*******************************************************************
352 Creates a struct security_descriptor structure with typical defaults.
353 ********************************************************************/
355 struct security_descriptor
*make_standard_sec_desc(TALLOC_CTX
*ctx
, const struct dom_sid
*owner_sid
, const struct dom_sid
*grp_sid
,
356 struct security_acl
*dacl
, size_t *sd_size
)
358 return make_sec_desc(ctx
, SECURITY_DESCRIPTOR_REVISION_1
,
359 SEC_DESC_SELF_RELATIVE
, owner_sid
, grp_sid
, NULL
,
363 /*******************************************************************
364 Creates a struct sec_desc_buf structure.
365 ********************************************************************/
367 struct sec_desc_buf
*make_sec_desc_buf(TALLOC_CTX
*ctx
, size_t len
, struct security_descriptor
*sec_desc
)
369 struct sec_desc_buf
*dst
;
371 if((dst
= talloc_zero(ctx
, struct sec_desc_buf
)) == NULL
)
374 /* max buffer size (allocated size) */
375 dst
->sd_size
= (uint32_t)len
;
377 if (sec_desc
!= NULL
) {
378 dst
->sd
= security_descriptor_copy(ctx
, sec_desc
);
379 if (dst
->sd
== NULL
) {
387 /*******************************************************************
388 Duplicates a struct sec_desc_buf structure.
389 ********************************************************************/
391 struct sec_desc_buf
*dup_sec_desc_buf(TALLOC_CTX
*ctx
, struct sec_desc_buf
*src
)
396 return make_sec_desc_buf( ctx
, src
->sd_size
, src
->sd
);
399 /*******************************************************************
400 Modify a SID's permissions in a struct security_descriptor.
401 ********************************************************************/
403 NTSTATUS
sec_desc_mod_sid(struct security_descriptor
*sd
, struct dom_sid
*sid
, uint32_t mask
)
408 return NT_STATUS_INVALID_PARAMETER
;
410 status
= sec_ace_mod_sid(sd
->dacl
->aces
, sd
->dacl
->num_aces
, sid
, mask
);
412 if (!NT_STATUS_IS_OK(status
))
419 * Determine if an struct security_ace is inheritable
422 static bool is_inheritable_ace(const struct security_ace
*ace
,
426 return ((ace
->flags
& SEC_ACE_FLAG_OBJECT_INHERIT
) != 0);
429 if (ace
->flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
) {
433 if ((ace
->flags
& SEC_ACE_FLAG_OBJECT_INHERIT
) &&
434 !(ace
->flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
)) {
442 * Does a security descriptor have any inheritable components for
443 * the newly created type ?
446 bool sd_has_inheritable_components(const struct security_descriptor
*parent_ctr
, bool container
)
449 const struct security_acl
*the_acl
= parent_ctr
->dacl
;
451 if (the_acl
== NULL
) {
455 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
456 const struct security_ace
*ace
= &the_acl
->aces
[i
];
458 if (is_inheritable_ace(ace
, container
)) {
465 /* Create a child security descriptor using another security descriptor as
466 the parent container. This child object can either be a container or
467 non-container object. */
469 NTSTATUS
se_create_child_secdesc(TALLOC_CTX
*ctx
,
470 struct security_descriptor
**ppsd
,
472 const struct security_descriptor
*parent_ctr
,
473 const struct dom_sid
*owner_sid
,
474 const struct dom_sid
*group_sid
,
477 struct security_acl
*new_dacl
= NULL
, *the_acl
= NULL
;
478 struct security_ace
*new_ace_list
= NULL
;
479 unsigned int new_ace_list_ndx
= 0, i
;
480 bool set_inherited_flags
= (parent_ctr
->type
& SEC_DESC_DACL_AUTO_INHERITED
);
487 /* Currently we only process the dacl when creating the child. The
488 sacl should also be processed but this is left out as sacls are
489 not implemented in Samba at the moment.*/
491 the_acl
= parent_ctr
->dacl
;
493 if (the_acl
->num_aces
) {
494 if (2*the_acl
->num_aces
< the_acl
->num_aces
) {
495 return NT_STATUS_NO_MEMORY
;
498 if (!(new_ace_list
= talloc_array(ctx
, struct security_ace
,
499 2*the_acl
->num_aces
))) {
500 return NT_STATUS_NO_MEMORY
;
506 frame
= talloc_stackframe();
508 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
509 const struct security_ace
*ace
= &the_acl
->aces
[i
];
510 struct security_ace
*new_ace
= &new_ace_list
[new_ace_list_ndx
];
511 const struct dom_sid
*ptrustee
= &ace
->trustee
;
512 const struct dom_sid
*creator
= NULL
;
513 uint8_t new_flags
= ace
->flags
;
515 if (!is_inheritable_ace(ace
, container
)) {
519 /* see the RAW-ACLS inheritance test for details on these rules */
524 * We need to remove SEC_ACE_FLAG_INHERITED_ACE here
525 * if present because it should only be set if the
526 * parent has the AUTO_INHERITED bit set in the
527 * type/control field. If we don't it will slip through
528 * and create DACLs with incorrectly ordered ACEs
529 * when there are CREATOR_OWNER or CREATOR_GROUP
532 new_flags
&= ~(SEC_ACE_FLAG_INHERIT_ONLY
533 | SEC_ACE_FLAG_INHERITED_ACE
);
535 if (!(new_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
)) {
536 new_flags
|= SEC_ACE_FLAG_INHERIT_ONLY
;
538 if (new_flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
) {
543 /* The CREATOR sids are special when inherited */
544 if (dom_sid_equal(ptrustee
, &global_sid_Creator_Owner
)) {
545 creator
= &global_sid_Creator_Owner
;
546 ptrustee
= owner_sid
;
547 } else if (dom_sid_equal(ptrustee
, &global_sid_Creator_Group
)) {
548 creator
= &global_sid_Creator_Group
;
549 ptrustee
= group_sid
;
552 if (creator
&& container
&&
553 (new_flags
& SEC_ACE_FLAG_CONTAINER_INHERIT
)) {
555 /* First add the regular ACE entry. */
556 init_sec_ace(new_ace
, ptrustee
, ace
->type
,
558 set_inherited_flags
? SEC_ACE_FLAG_INHERITED_ACE
: 0);
560 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
561 " inherited as %s:%d/0x%02x/0x%08x\n",
562 dom_sid_string(frame
, &ace
->trustee
),
563 ace
->type
, ace
->flags
, ace
->access_mask
,
564 dom_sid_string(frame
, &new_ace
->trustee
),
565 new_ace
->type
, new_ace
->flags
,
566 new_ace
->access_mask
));
570 /* Now add the extra creator ACE. */
571 new_ace
= &new_ace_list
[new_ace_list_ndx
];
574 new_flags
|= SEC_ACE_FLAG_INHERIT_ONLY
;
576 } else if (container
&&
577 !(ace
->flags
& SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
)) {
578 ptrustee
= &ace
->trustee
;
581 init_sec_ace(new_ace
, ptrustee
, ace
->type
,
582 ace
->access_mask
, new_flags
|
583 (set_inherited_flags
? SEC_ACE_FLAG_INHERITED_ACE
: 0));
585 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
586 " inherited as %s:%d/0x%02x/0x%08x\n",
587 dom_sid_string(frame
, &ace
->trustee
),
588 ace
->type
, ace
->flags
, ace
->access_mask
,
589 dom_sid_string(frame
, &ace
->trustee
),
590 new_ace
->type
, new_ace
->flags
,
591 new_ace
->access_mask
));
601 for (i
=1; i
< new_ace_list_ndx
;) {
602 struct security_ace
*ai
= &new_ace_list
[i
];
603 unsigned int remaining
, j
;
604 bool remove_ace
= false;
606 for (j
=0; j
< i
; j
++) {
607 struct security_ace
*aj
= &new_ace_list
[j
];
609 if (!security_ace_equal(ai
, aj
)) {
623 remaining
= new_ace_list_ndx
- i
;
624 if (remaining
== 0) {
625 ZERO_STRUCT(new_ace_list
[i
]);
628 memmove(&new_ace_list
[i
], &new_ace_list
[i
+1],
629 sizeof(new_ace_list
[i
]) * remaining
);
632 /* Create child security descriptor to return */
633 if (new_ace_list_ndx
) {
634 new_dacl
= make_sec_acl(ctx
,
640 return NT_STATUS_NO_MEMORY
;
644 *ppsd
= make_sec_desc(ctx
,
645 SECURITY_DESCRIPTOR_REVISION_1
,
646 SEC_DESC_SELF_RELATIVE
|SEC_DESC_DACL_PRESENT
|
647 (set_inherited_flags
? SEC_DESC_DACL_AUTO_INHERITED
: 0),
654 return NT_STATUS_NO_MEMORY
;
659 NTSTATUS
se_create_child_secdesc_buf(TALLOC_CTX
*ctx
,
660 struct sec_desc_buf
**ppsdb
,
661 const struct security_descriptor
*parent_ctr
,
666 struct security_descriptor
*sd
= NULL
;
669 status
= se_create_child_secdesc(ctx
,
673 parent_ctr
->owner_sid
,
674 parent_ctr
->group_sid
,
676 if (!NT_STATUS_IS_OK(status
)) {
680 *ppsdb
= make_sec_desc_buf(ctx
, size
, sd
);
682 return NT_STATUS_NO_MEMORY
;