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"
26 #define ALL_SECURITY_INFORMATION (SECINFO_OWNER|SECINFO_GROUP|\
27 SECINFO_DACL|SECINFO_SACL|\
28 SECINFO_UNPROTECTED_SACL|\
29 SECINFO_UNPROTECTED_DACL|\
30 SECINFO_PROTECTED_SACL|\
31 SECINFO_PROTECTED_DACL)
33 /* Map generic permissions to file object specific permissions */
35 const struct generic_mapping file_generic_mapping = {
42 /*******************************************************************
43 Given a security_descriptor return the sec_info.
44 ********************************************************************/
46 uint32_t get_sec_info(const struct security_descriptor *sd)
48 uint32_t sec_info = ALL_SECURITY_INFORMATION;
52 if (sd->owner_sid == NULL) {
53 sec_info &= ~SECINFO_OWNER;
55 if (sd->group_sid == NULL) {
56 sec_info &= ~SECINFO_GROUP;
58 if (sd->sacl == NULL) {
59 sec_info &= ~SECINFO_SACL;
61 if (sd->dacl == NULL) {
62 sec_info &= ~SECINFO_DACL;
69 /*******************************************************************
70 Merge part of security descriptor old_sec in to the empty sections of
71 security descriptor new_sec.
72 ********************************************************************/
74 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
76 struct dom_sid *owner_sid, *group_sid;
77 struct sec_desc_buf *return_sdb;
78 struct security_acl *dacl, *sacl;
79 struct security_descriptor *psd = NULL;
83 /* Copy over owner and group sids. There seems to be no flag for
84 this so just check the pointer values. */
86 owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
87 old_sdb->sd->owner_sid;
89 group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
90 old_sdb->sd->group_sid;
92 secdesc_type = new_sdb->sd->type;
94 /* Ignore changes to the system ACL. This has the effect of making
95 changes through the security tab audit button not sticking.
96 Perhaps in future Samba could implement these settings somehow. */
99 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
101 /* Copy across discretionary ACL */
103 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
104 dacl = new_sdb->sd->dacl;
106 dacl = old_sdb->sd->dacl;
109 /* Create new security descriptor from bits */
111 psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
112 owner_sid, group_sid, sacl, dacl, &secdesc_size);
114 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
119 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
121 struct dom_sid *owner_sid, *group_sid;
122 struct security_acl *dacl, *sacl;
123 struct security_descriptor *psd = NULL;
127 /* Copy over owner and group sids. There seems to be no flag for
128 this so just check the pointer values. */
130 owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
133 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
136 secdesc_type = new_sdb->type;
138 /* Ignore changes to the system ACL. This has the effect of making
139 changes through the security tab audit button not sticking.
140 Perhaps in future Samba could implement these settings somehow. */
143 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
145 /* Copy across discretionary ACL */
147 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
148 dacl = new_sdb->dacl;
150 dacl = old_sdb->dacl;
153 /* Create new security descriptor from bits */
154 psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
155 owner_sid, group_sid, sacl, dacl, &secdesc_size);
160 /*******************************************************************
161 Creates a struct security_descriptor structure
162 ********************************************************************/
164 #define SEC_DESC_HEADER_SIZE (2 * sizeof(uint16) + 4 * sizeof(uint32))
166 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
167 enum security_descriptor_revision revision,
169 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
170 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
172 struct security_descriptor *dst;
177 if(( dst = TALLOC_ZERO_P(ctx, struct security_descriptor)) == NULL)
180 dst->revision = revision;
184 dst->type |= SEC_DESC_SACL_PRESENT;
186 dst->type |= SEC_DESC_DACL_PRESENT;
188 dst->owner_sid = NULL;
189 dst->group_sid = NULL;
193 if(owner_sid && ((dst->owner_sid = sid_dup_talloc(dst,owner_sid)) == NULL))
196 if(grp_sid && ((dst->group_sid = sid_dup_talloc(dst,grp_sid)) == NULL))
199 if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
202 if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
205 offset = SEC_DESC_HEADER_SIZE;
208 * Work out the linearization sizes.
211 if (dst->sacl != NULL) {
212 offset += dst->sacl->size;
214 if (dst->dacl != NULL) {
215 offset += dst->dacl->size;
218 if (dst->owner_sid != NULL) {
219 offset += ndr_size_dom_sid(dst->owner_sid, 0);
222 if (dst->group_sid != NULL) {
223 offset += ndr_size_dom_sid(dst->group_sid, 0);
226 *sd_size = (size_t)offset;
235 /*******************************************************************
236 Duplicate a struct security_descriptor structure.
237 ********************************************************************/
239 struct security_descriptor *dup_sec_desc(TALLOC_CTX *ctx, const struct security_descriptor *src)
246 return make_sec_desc( ctx, src->revision, src->type,
247 src->owner_sid, src->group_sid, src->sacl,
251 /*******************************************************************
252 Convert a secdesc into a byte stream
253 ********************************************************************/
254 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
255 struct security_descriptor *secdesc,
256 uint8 **data, size_t *len)
259 enum ndr_err_code ndr_err;
261 ndr_err = ndr_push_struct_blob(
262 &blob, mem_ctx, secdesc,
263 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
265 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
266 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
267 ndr_errstr(ndr_err)));
268 return ndr_map_error2ntstatus(ndr_err);;
276 /*******************************************************************
277 Convert a secdesc_buf into a byte stream
278 ********************************************************************/
280 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
281 struct sec_desc_buf *secdesc_buf,
282 uint8_t **data, size_t *len)
285 enum ndr_err_code ndr_err;
287 ndr_err = ndr_push_struct_blob(
288 &blob, mem_ctx, secdesc_buf,
289 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
291 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
292 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
293 ndr_errstr(ndr_err)));
294 return ndr_map_error2ntstatus(ndr_err);;
302 /*******************************************************************
303 Parse a byte stream into a secdesc
304 ********************************************************************/
305 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
306 struct security_descriptor **psecdesc)
309 enum ndr_err_code ndr_err;
310 struct security_descriptor *result;
312 if ((data == NULL) || (len == 0)) {
313 return NT_STATUS_INVALID_PARAMETER;
316 result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor);
317 if (result == NULL) {
318 return NT_STATUS_NO_MEMORY;
321 blob = data_blob_const(data, len);
323 ndr_err = ndr_pull_struct_blob(&blob, result, result,
324 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
326 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
327 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
328 ndr_errstr(ndr_err)));
330 return ndr_map_error2ntstatus(ndr_err);;
337 /*******************************************************************
338 Parse a byte stream into a sec_desc_buf
339 ********************************************************************/
341 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
342 struct sec_desc_buf **psecdesc_buf)
345 enum ndr_err_code ndr_err;
346 struct sec_desc_buf *result;
348 if ((data == NULL) || (len == 0)) {
349 return NT_STATUS_INVALID_PARAMETER;
352 result = TALLOC_ZERO_P(mem_ctx, struct sec_desc_buf);
353 if (result == NULL) {
354 return NT_STATUS_NO_MEMORY;
357 blob = data_blob_const(data, len);
359 ndr_err = ndr_pull_struct_blob(&blob, result, result,
360 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
362 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
363 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
364 ndr_errstr(ndr_err)));
366 return ndr_map_error2ntstatus(ndr_err);;
369 *psecdesc_buf = result;
373 /*******************************************************************
374 Creates a struct security_descriptor structure with typical defaults.
375 ********************************************************************/
377 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
378 struct security_acl *dacl, size_t *sd_size)
380 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
381 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
385 /*******************************************************************
386 Creates a struct sec_desc_buf structure.
387 ********************************************************************/
389 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
391 struct sec_desc_buf *dst;
393 if((dst = TALLOC_ZERO_P(ctx, struct sec_desc_buf)) == NULL)
396 /* max buffer size (allocated size) */
397 dst->sd_size = (uint32)len;
399 if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
406 /*******************************************************************
407 Duplicates a struct sec_desc_buf structure.
408 ********************************************************************/
410 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
415 return make_sec_desc_buf( ctx, src->sd_size, src->sd);
418 /*******************************************************************
419 Add a new SID with its permissions to struct security_descriptor.
420 ********************************************************************/
422 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, uint32 mask, size_t *sd_size)
424 struct security_descriptor *sd = 0;
425 struct security_acl *dacl = 0;
426 struct security_ace *ace = 0;
429 if (!ctx || !psd || !sid || !sd_size)
430 return NT_STATUS_INVALID_PARAMETER;
434 status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
436 if (!NT_STATUS_IS_OK(status))
439 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
440 return NT_STATUS_UNSUCCESSFUL;
442 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
443 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
444 return NT_STATUS_UNSUCCESSFUL;
451 /*******************************************************************
452 Modify a SID's permissions in a struct security_descriptor.
453 ********************************************************************/
455 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32 mask)
460 return NT_STATUS_INVALID_PARAMETER;
462 status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
464 if (!NT_STATUS_IS_OK(status))
470 /*******************************************************************
471 Delete a SID from a struct security_descriptor.
472 ********************************************************************/
474 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, size_t *sd_size)
476 struct security_descriptor *sd = 0;
477 struct security_acl *dacl = 0;
478 struct security_ace *ace = 0;
481 if (!ctx || !psd[0] || !sid || !sd_size)
482 return NT_STATUS_INVALID_PARAMETER;
486 status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
488 if (!NT_STATUS_IS_OK(status))
491 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
492 return NT_STATUS_UNSUCCESSFUL;
494 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
495 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
496 return NT_STATUS_UNSUCCESSFUL;
504 * Determine if an struct security_ace is inheritable
507 static bool is_inheritable_ace(const struct security_ace *ace,
511 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
514 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
518 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
519 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
527 * Does a security descriptor have any inheritable components for
528 * the newly created type ?
531 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
534 const struct security_acl *the_acl = parent_ctr->dacl;
536 for (i = 0; i < the_acl->num_aces; i++) {
537 const struct security_ace *ace = &the_acl->aces[i];
539 if (is_inheritable_ace(ace, container)) {
546 /* Create a child security descriptor using another security descriptor as
547 the parent container. This child object can either be a container or
548 non-container object. */
550 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
551 struct security_descriptor **ppsd,
553 const struct security_descriptor *parent_ctr,
554 const struct dom_sid *owner_sid,
555 const struct dom_sid *group_sid,
558 struct security_acl *new_dacl = NULL, *the_acl = NULL;
559 struct security_ace *new_ace_list = NULL;
560 unsigned int new_ace_list_ndx = 0, i;
565 /* Currently we only process the dacl when creating the child. The
566 sacl should also be processed but this is left out as sacls are
567 not implemented in Samba at the moment.*/
569 the_acl = parent_ctr->dacl;
571 if (the_acl->num_aces) {
572 if (2*the_acl->num_aces < the_acl->num_aces) {
573 return NT_STATUS_NO_MEMORY;
576 if (!(new_ace_list = TALLOC_ARRAY(ctx, struct security_ace,
577 2*the_acl->num_aces))) {
578 return NT_STATUS_NO_MEMORY;
584 for (i = 0; i < the_acl->num_aces; i++) {
585 const struct security_ace *ace = &the_acl->aces[i];
586 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
587 const struct dom_sid *ptrustee = &ace->trustee;
588 const struct dom_sid *creator = NULL;
589 uint8 new_flags = ace->flags;
591 if (!is_inheritable_ace(ace, container)) {
595 /* see the RAW-ACLS inheritance test for details on these rules */
599 new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
601 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
602 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
604 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
609 /* The CREATOR sids are special when inherited */
610 if (sid_equal(ptrustee, &global_sid_Creator_Owner)) {
611 creator = &global_sid_Creator_Owner;
612 ptrustee = owner_sid;
613 } else if (sid_equal(ptrustee, &global_sid_Creator_Group)) {
614 creator = &global_sid_Creator_Group;
615 ptrustee = group_sid;
618 if (creator && container &&
619 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
621 /* First add the regular ACE entry. */
622 init_sec_ace(new_ace, ptrustee, ace->type,
623 ace->access_mask, 0);
625 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
626 " inherited as %s:%d/0x%02x/0x%08x\n",
627 sid_string_dbg(&ace->trustee),
628 ace->type, ace->flags, ace->access_mask,
629 sid_string_dbg(&new_ace->trustee),
630 new_ace->type, new_ace->flags,
631 new_ace->access_mask));
635 /* Now add the extra creator ACE. */
636 new_ace = &new_ace_list[new_ace_list_ndx];
639 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
640 } else if (container &&
641 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
642 ptrustee = &ace->trustee;
645 init_sec_ace(new_ace, ptrustee, ace->type,
646 ace->access_mask, new_flags);
648 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
649 " inherited as %s:%d/0x%02x/0x%08x\n",
650 sid_string_dbg(&ace->trustee),
651 ace->type, ace->flags, ace->access_mask,
652 sid_string_dbg(&ace->trustee),
653 new_ace->type, new_ace->flags,
654 new_ace->access_mask));
659 /* Create child security descriptor to return */
660 if (new_ace_list_ndx) {
661 new_dacl = make_sec_acl(ctx,
667 return NT_STATUS_NO_MEMORY;
671 *ppsd = make_sec_desc(ctx,
672 SECURITY_DESCRIPTOR_REVISION_1,
673 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
680 return NT_STATUS_NO_MEMORY;
685 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
686 struct sec_desc_buf **ppsdb,
687 const struct security_descriptor *parent_ctr,
692 struct security_descriptor *sd = NULL;
695 status = se_create_child_secdesc(ctx,
699 parent_ctr->owner_sid,
700 parent_ctr->group_sid,
702 if (!NT_STATUS_IS_OK(status)) {
706 *ppsdb = make_sec_desc_buf(ctx, size, sd);
708 return NT_STATUS_NO_MEMORY;