auth/gensec: make sure gensec_start_mech_by_authtype() resets SIGN/SEAL before starting
[Samba.git] / libcli / security / secdesc.c
blob62207a008453f3388da8db83aeccd8d23c2f0793
1 /*
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/>.
23 #include "includes.h"
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 = {
30 FILE_GENERIC_READ,
31 FILE_GENERIC_WRITE,
32 FILE_GENERIC_EXECUTE,
33 FILE_GENERIC_ALL
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;
44 SMB_ASSERT(sd);
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;
70 return sec_info;
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;
86 size_t secdesc_size;
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. */
103 sacl = NULL;
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;
110 } else {
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);
121 return(return_sdb);
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;
130 size_t secdesc_size;
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 :
136 old_sdb->owner_sid;
138 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
139 old_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. */
147 sacl = NULL;
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;
154 } else {
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);
162 return psd;
165 /*******************************************************************
166 Creates a struct security_descriptor structure
167 ********************************************************************/
169 #define SEC_DESC_HEADER_SIZE (2 * sizeof(uint16_t) + 4 * sizeof(uint32_t))
171 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
172 enum security_descriptor_revision revision,
173 uint16_t type,
174 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
175 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
177 struct security_descriptor *dst;
178 uint32_t offset = 0;
180 if (sd_size != NULL) {
181 *sd_size = 0;
184 if(( dst = talloc_zero(ctx, struct security_descriptor)) == NULL)
185 return NULL;
187 dst->revision = revision;
188 dst->type = type;
190 if (sacl)
191 dst->type |= SEC_DESC_SACL_PRESENT;
192 if (dacl)
193 dst->type |= SEC_DESC_DACL_PRESENT;
195 dst->owner_sid = NULL;
196 dst->group_sid = NULL;
197 dst->sacl = NULL;
198 dst->dacl = NULL;
200 if(owner_sid && ((dst->owner_sid = dom_sid_dup(dst,owner_sid)) == NULL))
201 goto error_exit;
203 if(grp_sid && ((dst->group_sid = dom_sid_dup(dst,grp_sid)) == NULL))
204 goto error_exit;
206 if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
207 goto error_exit;
209 if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
210 goto error_exit;
212 if (sd_size == NULL) {
213 return dst;
216 offset = SEC_DESC_HEADER_SIZE;
219 * Work out the linearization sizes.
222 if (dst->sacl != NULL) {
223 offset += dst->sacl->size;
225 if (dst->dacl != NULL) {
226 offset += dst->dacl->size;
229 if (dst->owner_sid != NULL) {
230 offset += ndr_size_dom_sid(dst->owner_sid, 0);
233 if (dst->group_sid != NULL) {
234 offset += ndr_size_dom_sid(dst->group_sid, 0);
237 *sd_size = (size_t)offset;
238 return dst;
240 error_exit:
242 if (sd_size != NULL) {
243 *sd_size = 0;
245 return NULL;
248 /*******************************************************************
249 Duplicate a struct security_descriptor structure.
250 ********************************************************************/
252 struct security_descriptor *dup_sec_desc(TALLOC_CTX *ctx, const struct security_descriptor *src)
254 size_t dummy;
256 if(src == NULL)
257 return NULL;
259 return make_sec_desc( ctx, src->revision, src->type,
260 src->owner_sid, src->group_sid, src->sacl,
261 src->dacl, &dummy);
264 /*******************************************************************
265 Convert a secdesc into a byte stream
266 ********************************************************************/
267 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
268 const struct security_descriptor *secdesc,
269 uint8_t **data, size_t *len)
271 DATA_BLOB blob;
272 enum ndr_err_code ndr_err;
274 ndr_err = ndr_push_struct_blob(
275 &blob, mem_ctx, secdesc,
276 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
278 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
279 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
280 ndr_errstr(ndr_err)));
281 return ndr_map_error2ntstatus(ndr_err);
284 *data = blob.data;
285 *len = blob.length;
286 return NT_STATUS_OK;
289 /*******************************************************************
290 Convert a secdesc_buf into a byte stream
291 ********************************************************************/
293 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
294 const struct sec_desc_buf *secdesc_buf,
295 uint8_t **data, size_t *len)
297 DATA_BLOB blob;
298 enum ndr_err_code ndr_err;
300 ndr_err = ndr_push_struct_blob(
301 &blob, mem_ctx, secdesc_buf,
302 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
304 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
305 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
306 ndr_errstr(ndr_err)));
307 return ndr_map_error2ntstatus(ndr_err);
310 *data = blob.data;
311 *len = blob.length;
312 return NT_STATUS_OK;
315 /*******************************************************************
316 Parse a byte stream into a secdesc
317 ********************************************************************/
318 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
319 struct security_descriptor **psecdesc)
321 DATA_BLOB blob;
322 enum ndr_err_code ndr_err;
323 struct security_descriptor *result;
325 if ((data == NULL) || (len == 0)) {
326 return NT_STATUS_INVALID_PARAMETER;
329 result = talloc_zero(mem_ctx, struct security_descriptor);
330 if (result == NULL) {
331 return NT_STATUS_NO_MEMORY;
334 blob = data_blob_const(data, len);
336 ndr_err = ndr_pull_struct_blob(&blob, result, result,
337 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
339 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
340 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
341 ndr_errstr(ndr_err)));
342 TALLOC_FREE(result);
343 return ndr_map_error2ntstatus(ndr_err);
346 *psecdesc = result;
347 return NT_STATUS_OK;
350 /*******************************************************************
351 Parse a byte stream into a sec_desc_buf
352 ********************************************************************/
354 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
355 struct sec_desc_buf **psecdesc_buf)
357 DATA_BLOB blob;
358 enum ndr_err_code ndr_err;
359 struct sec_desc_buf *result;
361 if ((data == NULL) || (len == 0)) {
362 return NT_STATUS_INVALID_PARAMETER;
365 result = talloc_zero(mem_ctx, struct sec_desc_buf);
366 if (result == NULL) {
367 return NT_STATUS_NO_MEMORY;
370 blob = data_blob_const(data, len);
372 ndr_err = ndr_pull_struct_blob(&blob, result, result,
373 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
375 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
376 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
377 ndr_errstr(ndr_err)));
378 TALLOC_FREE(result);
379 return ndr_map_error2ntstatus(ndr_err);
382 *psecdesc_buf = result;
383 return NT_STATUS_OK;
386 /*******************************************************************
387 Creates a struct security_descriptor structure with typical defaults.
388 ********************************************************************/
390 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
391 struct security_acl *dacl, size_t *sd_size)
393 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
394 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
395 dacl, sd_size);
398 /*******************************************************************
399 Creates a struct sec_desc_buf structure.
400 ********************************************************************/
402 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
404 struct sec_desc_buf *dst;
406 if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL)
407 return NULL;
409 /* max buffer size (allocated size) */
410 dst->sd_size = (uint32_t)len;
412 if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
413 return NULL;
416 return dst;
419 /*******************************************************************
420 Duplicates a struct sec_desc_buf structure.
421 ********************************************************************/
423 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
425 if(src == NULL)
426 return NULL;
428 return make_sec_desc_buf( ctx, src->sd_size, src->sd);
431 /*******************************************************************
432 Add a new SID with its permissions to struct security_descriptor.
433 ********************************************************************/
435 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, const struct dom_sid *sid, uint32_t mask, size_t *sd_size)
437 struct security_descriptor *sd = 0;
438 struct security_acl *dacl = 0;
439 struct security_ace *ace = 0;
440 NTSTATUS status;
442 if (!ctx || !psd || !sid || !sd_size)
443 return NT_STATUS_INVALID_PARAMETER;
445 *sd_size = 0;
447 status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
449 if (!NT_STATUS_IS_OK(status))
450 return status;
452 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
453 return NT_STATUS_UNSUCCESSFUL;
455 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
456 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
457 return NT_STATUS_UNSUCCESSFUL;
459 *psd = sd;
460 sd = 0;
461 return NT_STATUS_OK;
464 /*******************************************************************
465 Modify a SID's permissions in a struct security_descriptor.
466 ********************************************************************/
468 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32_t mask)
470 NTSTATUS status;
472 if (!sd || !sid)
473 return NT_STATUS_INVALID_PARAMETER;
475 status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
477 if (!NT_STATUS_IS_OK(status))
478 return status;
480 return NT_STATUS_OK;
483 /*******************************************************************
484 Delete a SID from a struct security_descriptor.
485 ********************************************************************/
487 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, size_t *sd_size)
489 struct security_descriptor *sd = 0;
490 struct security_acl *dacl = 0;
491 struct security_ace *ace = 0;
492 NTSTATUS status;
494 if (!ctx || !psd[0] || !sid || !sd_size)
495 return NT_STATUS_INVALID_PARAMETER;
497 *sd_size = 0;
499 status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
501 if (!NT_STATUS_IS_OK(status))
502 return status;
504 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
505 return NT_STATUS_UNSUCCESSFUL;
507 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
508 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
509 return NT_STATUS_UNSUCCESSFUL;
511 *psd = sd;
512 sd = 0;
513 return NT_STATUS_OK;
517 * Determine if an struct security_ace is inheritable
520 static bool is_inheritable_ace(const struct security_ace *ace,
521 bool container)
523 if (!container) {
524 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
527 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
528 return true;
531 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
532 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
533 return true;
536 return false;
540 * Does a security descriptor have any inheritable components for
541 * the newly created type ?
544 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
546 unsigned int i;
547 const struct security_acl *the_acl = parent_ctr->dacl;
549 if (the_acl == NULL) {
550 return false;
553 for (i = 0; i < the_acl->num_aces; i++) {
554 const struct security_ace *ace = &the_acl->aces[i];
556 if (is_inheritable_ace(ace, container)) {
557 return true;
560 return false;
563 /* Create a child security descriptor using another security descriptor as
564 the parent container. This child object can either be a container or
565 non-container object. */
567 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
568 struct security_descriptor **ppsd,
569 size_t *psize,
570 const struct security_descriptor *parent_ctr,
571 const struct dom_sid *owner_sid,
572 const struct dom_sid *group_sid,
573 bool container)
575 struct security_acl *new_dacl = NULL, *the_acl = NULL;
576 struct security_ace *new_ace_list = NULL;
577 unsigned int new_ace_list_ndx = 0, i;
578 bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED);
580 TALLOC_CTX *frame;
582 *ppsd = NULL;
583 *psize = 0;
585 /* Currently we only process the dacl when creating the child. The
586 sacl should also be processed but this is left out as sacls are
587 not implemented in Samba at the moment.*/
589 the_acl = parent_ctr->dacl;
591 if (the_acl->num_aces) {
592 if (2*the_acl->num_aces < the_acl->num_aces) {
593 return NT_STATUS_NO_MEMORY;
596 if (!(new_ace_list = talloc_array(ctx, struct security_ace,
597 2*the_acl->num_aces))) {
598 return NT_STATUS_NO_MEMORY;
600 } else {
601 new_ace_list = NULL;
604 frame = talloc_stackframe();
606 for (i = 0; i < the_acl->num_aces; i++) {
607 const struct security_ace *ace = &the_acl->aces[i];
608 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
609 const struct dom_sid *ptrustee = &ace->trustee;
610 const struct dom_sid *creator = NULL;
611 uint8_t new_flags = ace->flags;
613 if (!is_inheritable_ace(ace, container)) {
614 continue;
617 /* see the RAW-ACLS inheritance test for details on these rules */
618 if (!container) {
619 new_flags = 0;
620 } else {
622 * We need to remove SEC_ACE_FLAG_INHERITED_ACE here
623 * if present because it should only be set if the
624 * parent has the AUTO_INHERITED bit set in the
625 * type/control field. If we don't it will slip through
626 * and create DACLs with incorrectly ordered ACEs
627 * when there are CREATOR_OWNER or CREATOR_GROUP
628 * ACEs.
630 new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY
631 | SEC_ACE_FLAG_INHERITED_ACE);
633 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
634 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
636 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
637 new_flags = 0;
641 /* The CREATOR sids are special when inherited */
642 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
643 creator = &global_sid_Creator_Owner;
644 ptrustee = owner_sid;
645 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
646 creator = &global_sid_Creator_Group;
647 ptrustee = group_sid;
650 if (creator && container &&
651 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
653 /* First add the regular ACE entry. */
654 init_sec_ace(new_ace, ptrustee, ace->type,
655 ace->access_mask,
656 set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
658 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
659 " inherited as %s:%d/0x%02x/0x%08x\n",
660 dom_sid_string(frame, &ace->trustee),
661 ace->type, ace->flags, ace->access_mask,
662 dom_sid_string(frame, &new_ace->trustee),
663 new_ace->type, new_ace->flags,
664 new_ace->access_mask));
666 new_ace_list_ndx++;
668 /* Now add the extra creator ACE. */
669 new_ace = &new_ace_list[new_ace_list_ndx];
671 ptrustee = creator;
672 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
674 } else if (container &&
675 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
676 ptrustee = &ace->trustee;
679 init_sec_ace(new_ace, ptrustee, ace->type,
680 ace->access_mask, new_flags |
681 (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
683 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
684 " inherited as %s:%d/0x%02x/0x%08x\n",
685 dom_sid_string(frame, &ace->trustee),
686 ace->type, ace->flags, ace->access_mask,
687 dom_sid_string(frame, &ace->trustee),
688 new_ace->type, new_ace->flags,
689 new_ace->access_mask));
691 new_ace_list_ndx++;
694 talloc_free(frame);
697 * remove duplicates
699 for (i=1; i < new_ace_list_ndx;) {
700 struct security_ace *ai = &new_ace_list[i];
701 unsigned int remaining, j;
702 bool remove = false;
704 for (j=0; j < i; j++) {
705 struct security_ace *aj = &new_ace_list[j];
707 if (!sec_ace_equal(ai, aj)) {
708 continue;
711 remove = true;
712 break;
715 if (!remove) {
716 i++;
717 continue;
720 new_ace_list_ndx--;
721 remaining = new_ace_list_ndx - i;
722 if (remaining == 0) {
723 ZERO_STRUCT(new_ace_list[i]);
724 continue;
726 memmove(&new_ace_list[i], &new_ace_list[i+1],
727 sizeof(new_ace_list[i]) * remaining);
730 /* Create child security descriptor to return */
731 if (new_ace_list_ndx) {
732 new_dacl = make_sec_acl(ctx,
733 NT4_ACL_REVISION,
734 new_ace_list_ndx,
735 new_ace_list);
737 if (!new_dacl) {
738 return NT_STATUS_NO_MEMORY;
742 *ppsd = make_sec_desc(ctx,
743 SECURITY_DESCRIPTOR_REVISION_1,
744 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
745 (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
746 owner_sid,
747 group_sid,
748 NULL,
749 new_dacl,
750 psize);
751 if (!*ppsd) {
752 return NT_STATUS_NO_MEMORY;
754 return NT_STATUS_OK;
757 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
758 struct sec_desc_buf **ppsdb,
759 const struct security_descriptor *parent_ctr,
760 bool container)
762 NTSTATUS status;
763 size_t size = 0;
764 struct security_descriptor *sd = NULL;
766 *ppsdb = NULL;
767 status = se_create_child_secdesc(ctx,
768 &sd,
769 &size,
770 parent_ctr,
771 parent_ctr->owner_sid,
772 parent_ctr->group_sid,
773 container);
774 if (!NT_STATUS_IS_OK(status)) {
775 return status;
778 *ppsdb = make_sec_desc_buf(ctx, size, sd);
779 if (!*ppsdb) {
780 return NT_STATUS_NO_MEMORY;
782 return NT_STATUS_OK;