s3:lib/gencache: place gencache.tdb into /var/cache/samba
[Samba.git] / libcli / security / secdesc.c
blob8570334f36c2a5f06508cc0a797231b06085d3a3
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 #define ALL_SECURITY_INFORMATION (SECINFO_OWNER|SECINFO_GROUP|\
28 SECINFO_DACL|SECINFO_SACL|\
29 SECINFO_UNPROTECTED_SACL|\
30 SECINFO_UNPROTECTED_DACL|\
31 SECINFO_PROTECTED_SACL|\
32 SECINFO_PROTECTED_DACL)
34 /* Map generic permissions to file object specific permissions */
36 const struct generic_mapping file_generic_mapping = {
37 FILE_GENERIC_READ,
38 FILE_GENERIC_WRITE,
39 FILE_GENERIC_EXECUTE,
40 FILE_GENERIC_ALL
43 /*******************************************************************
44 Given a security_descriptor return the sec_info.
45 ********************************************************************/
47 uint32_t get_sec_info(const struct security_descriptor *sd)
49 uint32_t sec_info = ALL_SECURITY_INFORMATION;
51 SMB_ASSERT(sd);
53 if (sd->owner_sid == NULL) {
54 sec_info &= ~SECINFO_OWNER;
56 if (sd->group_sid == NULL) {
57 sec_info &= ~SECINFO_GROUP;
59 if (sd->sacl == NULL) {
60 sec_info &= ~SECINFO_SACL;
62 if (sd->dacl == NULL) {
63 sec_info &= ~SECINFO_DACL;
66 return sec_info;
70 /*******************************************************************
71 Merge part of security descriptor old_sec in to the empty sections of
72 security descriptor new_sec.
73 ********************************************************************/
75 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
77 struct dom_sid *owner_sid, *group_sid;
78 struct sec_desc_buf *return_sdb;
79 struct security_acl *dacl, *sacl;
80 struct security_descriptor *psd = NULL;
81 uint16_t secdesc_type;
82 size_t secdesc_size;
84 /* Copy over owner and group sids. There seems to be no flag for
85 this so just check the pointer values. */
87 owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
88 old_sdb->sd->owner_sid;
90 group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
91 old_sdb->sd->group_sid;
93 secdesc_type = new_sdb->sd->type;
95 /* Ignore changes to the system ACL. This has the effect of making
96 changes through the security tab audit button not sticking.
97 Perhaps in future Samba could implement these settings somehow. */
99 sacl = NULL;
100 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
102 /* Copy across discretionary ACL */
104 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
105 dacl = new_sdb->sd->dacl;
106 } else {
107 dacl = old_sdb->sd->dacl;
110 /* Create new security descriptor from bits */
112 psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
113 owner_sid, group_sid, sacl, dacl, &secdesc_size);
115 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
117 return(return_sdb);
120 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
122 struct dom_sid *owner_sid, *group_sid;
123 struct security_acl *dacl, *sacl;
124 struct security_descriptor *psd = NULL;
125 uint16_t secdesc_type;
126 size_t secdesc_size;
128 /* Copy over owner and group sids. There seems to be no flag for
129 this so just check the pointer values. */
131 owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
132 old_sdb->owner_sid;
134 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
135 old_sdb->group_sid;
137 secdesc_type = new_sdb->type;
139 /* Ignore changes to the system ACL. This has the effect of making
140 changes through the security tab audit button not sticking.
141 Perhaps in future Samba could implement these settings somehow. */
143 sacl = NULL;
144 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
146 /* Copy across discretionary ACL */
148 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
149 dacl = new_sdb->dacl;
150 } else {
151 dacl = old_sdb->dacl;
154 /* Create new security descriptor from bits */
155 psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
156 owner_sid, group_sid, sacl, dacl, &secdesc_size);
158 return psd;
161 /*******************************************************************
162 Creates a struct security_descriptor structure
163 ********************************************************************/
165 #define SEC_DESC_HEADER_SIZE (2 * sizeof(uint16_t) + 4 * sizeof(uint32_t))
167 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
168 enum security_descriptor_revision revision,
169 uint16_t type,
170 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
171 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
173 struct security_descriptor *dst;
174 uint32_t offset = 0;
176 if (sd_size != NULL) {
177 *sd_size = 0;
180 if(( dst = talloc_zero(ctx, struct security_descriptor)) == NULL)
181 return NULL;
183 dst->revision = revision;
184 dst->type = type;
186 if (sacl)
187 dst->type |= SEC_DESC_SACL_PRESENT;
188 if (dacl)
189 dst->type |= SEC_DESC_DACL_PRESENT;
191 dst->owner_sid = NULL;
192 dst->group_sid = NULL;
193 dst->sacl = NULL;
194 dst->dacl = NULL;
196 if(owner_sid && ((dst->owner_sid = dom_sid_dup(dst,owner_sid)) == NULL))
197 goto error_exit;
199 if(grp_sid && ((dst->group_sid = dom_sid_dup(dst,grp_sid)) == NULL))
200 goto error_exit;
202 if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
203 goto error_exit;
205 if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
206 goto error_exit;
208 if (sd_size == NULL) {
209 return dst;
212 offset = SEC_DESC_HEADER_SIZE;
215 * Work out the linearization sizes.
218 if (dst->sacl != NULL) {
219 offset += dst->sacl->size;
221 if (dst->dacl != NULL) {
222 offset += dst->dacl->size;
225 if (dst->owner_sid != NULL) {
226 offset += ndr_size_dom_sid(dst->owner_sid, 0);
229 if (dst->group_sid != NULL) {
230 offset += ndr_size_dom_sid(dst->group_sid, 0);
233 *sd_size = (size_t)offset;
234 return dst;
236 error_exit:
238 if (sd_size != NULL) {
239 *sd_size = 0;
241 return NULL;
244 /*******************************************************************
245 Duplicate a struct security_descriptor structure.
246 ********************************************************************/
248 struct security_descriptor *dup_sec_desc(TALLOC_CTX *ctx, const struct security_descriptor *src)
250 size_t dummy;
252 if(src == NULL)
253 return NULL;
255 return make_sec_desc( ctx, src->revision, src->type,
256 src->owner_sid, src->group_sid, src->sacl,
257 src->dacl, &dummy);
260 /*******************************************************************
261 Convert a secdesc into a byte stream
262 ********************************************************************/
263 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
264 const struct security_descriptor *secdesc,
265 uint8_t **data, size_t *len)
267 DATA_BLOB blob;
268 enum ndr_err_code ndr_err;
270 ndr_err = ndr_push_struct_blob(
271 &blob, mem_ctx, secdesc,
272 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
274 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
275 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
276 ndr_errstr(ndr_err)));
277 return ndr_map_error2ntstatus(ndr_err);
280 *data = blob.data;
281 *len = blob.length;
282 return NT_STATUS_OK;
285 /*******************************************************************
286 Convert a secdesc_buf into a byte stream
287 ********************************************************************/
289 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
290 const struct sec_desc_buf *secdesc_buf,
291 uint8_t **data, size_t *len)
293 DATA_BLOB blob;
294 enum ndr_err_code ndr_err;
296 ndr_err = ndr_push_struct_blob(
297 &blob, mem_ctx, secdesc_buf,
298 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
300 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
301 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
302 ndr_errstr(ndr_err)));
303 return ndr_map_error2ntstatus(ndr_err);
306 *data = blob.data;
307 *len = blob.length;
308 return NT_STATUS_OK;
311 /*******************************************************************
312 Parse a byte stream into a secdesc
313 ********************************************************************/
314 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
315 struct security_descriptor **psecdesc)
317 DATA_BLOB blob;
318 enum ndr_err_code ndr_err;
319 struct security_descriptor *result;
321 if ((data == NULL) || (len == 0)) {
322 return NT_STATUS_INVALID_PARAMETER;
325 result = talloc_zero(mem_ctx, struct security_descriptor);
326 if (result == NULL) {
327 return NT_STATUS_NO_MEMORY;
330 blob = data_blob_const(data, len);
332 ndr_err = ndr_pull_struct_blob(&blob, result, result,
333 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
335 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
336 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
337 ndr_errstr(ndr_err)));
338 TALLOC_FREE(result);
339 return ndr_map_error2ntstatus(ndr_err);
342 *psecdesc = result;
343 return NT_STATUS_OK;
346 /*******************************************************************
347 Parse a byte stream into a sec_desc_buf
348 ********************************************************************/
350 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
351 struct sec_desc_buf **psecdesc_buf)
353 DATA_BLOB blob;
354 enum ndr_err_code ndr_err;
355 struct sec_desc_buf *result;
357 if ((data == NULL) || (len == 0)) {
358 return NT_STATUS_INVALID_PARAMETER;
361 result = talloc_zero(mem_ctx, struct sec_desc_buf);
362 if (result == NULL) {
363 return NT_STATUS_NO_MEMORY;
366 blob = data_blob_const(data, len);
368 ndr_err = ndr_pull_struct_blob(&blob, result, result,
369 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
371 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
372 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
373 ndr_errstr(ndr_err)));
374 TALLOC_FREE(result);
375 return ndr_map_error2ntstatus(ndr_err);
378 *psecdesc_buf = result;
379 return NT_STATUS_OK;
382 /*******************************************************************
383 Creates a struct security_descriptor structure with typical defaults.
384 ********************************************************************/
386 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
387 struct security_acl *dacl, size_t *sd_size)
389 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
390 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
391 dacl, sd_size);
394 /*******************************************************************
395 Creates a struct sec_desc_buf structure.
396 ********************************************************************/
398 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
400 struct sec_desc_buf *dst;
402 if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL)
403 return NULL;
405 /* max buffer size (allocated size) */
406 dst->sd_size = (uint32_t)len;
408 if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
409 return NULL;
412 return dst;
415 /*******************************************************************
416 Duplicates a struct sec_desc_buf structure.
417 ********************************************************************/
419 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
421 if(src == NULL)
422 return NULL;
424 return make_sec_desc_buf( ctx, src->sd_size, src->sd);
427 /*******************************************************************
428 Add a new SID with its permissions to struct security_descriptor.
429 ********************************************************************/
431 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, const struct dom_sid *sid, uint32_t mask, size_t *sd_size)
433 struct security_descriptor *sd = 0;
434 struct security_acl *dacl = 0;
435 struct security_ace *ace = 0;
436 NTSTATUS status;
438 if (!ctx || !psd || !sid || !sd_size)
439 return NT_STATUS_INVALID_PARAMETER;
441 *sd_size = 0;
443 status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
445 if (!NT_STATUS_IS_OK(status))
446 return status;
448 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
449 return NT_STATUS_UNSUCCESSFUL;
451 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
452 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
453 return NT_STATUS_UNSUCCESSFUL;
455 *psd = sd;
456 sd = 0;
457 return NT_STATUS_OK;
460 /*******************************************************************
461 Modify a SID's permissions in a struct security_descriptor.
462 ********************************************************************/
464 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32_t mask)
466 NTSTATUS status;
468 if (!sd || !sid)
469 return NT_STATUS_INVALID_PARAMETER;
471 status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
473 if (!NT_STATUS_IS_OK(status))
474 return status;
476 return NT_STATUS_OK;
479 /*******************************************************************
480 Delete a SID from a struct security_descriptor.
481 ********************************************************************/
483 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, size_t *sd_size)
485 struct security_descriptor *sd = 0;
486 struct security_acl *dacl = 0;
487 struct security_ace *ace = 0;
488 NTSTATUS status;
490 if (!ctx || !psd[0] || !sid || !sd_size)
491 return NT_STATUS_INVALID_PARAMETER;
493 *sd_size = 0;
495 status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
497 if (!NT_STATUS_IS_OK(status))
498 return status;
500 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
501 return NT_STATUS_UNSUCCESSFUL;
503 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
504 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
505 return NT_STATUS_UNSUCCESSFUL;
507 *psd = sd;
508 sd = 0;
509 return NT_STATUS_OK;
513 * Determine if an struct security_ace is inheritable
516 static bool is_inheritable_ace(const struct security_ace *ace,
517 bool container)
519 if (!container) {
520 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
523 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
524 return true;
527 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
528 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
529 return true;
532 return false;
536 * Does a security descriptor have any inheritable components for
537 * the newly created type ?
540 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
542 unsigned int i;
543 const struct security_acl *the_acl = parent_ctr->dacl;
545 if (the_acl == NULL) {
546 return false;
549 for (i = 0; i < the_acl->num_aces; i++) {
550 const struct security_ace *ace = &the_acl->aces[i];
552 if (is_inheritable_ace(ace, container)) {
553 return true;
556 return false;
559 /* Create a child security descriptor using another security descriptor as
560 the parent container. This child object can either be a container or
561 non-container object. */
563 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
564 struct security_descriptor **ppsd,
565 size_t *psize,
566 const struct security_descriptor *parent_ctr,
567 const struct dom_sid *owner_sid,
568 const struct dom_sid *group_sid,
569 bool container)
571 struct security_acl *new_dacl = NULL, *the_acl = NULL;
572 struct security_ace *new_ace_list = NULL;
573 unsigned int new_ace_list_ndx = 0, i;
574 bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED);
576 TALLOC_CTX *frame;
578 *ppsd = NULL;
579 *psize = 0;
581 /* Currently we only process the dacl when creating the child. The
582 sacl should also be processed but this is left out as sacls are
583 not implemented in Samba at the moment.*/
585 the_acl = parent_ctr->dacl;
587 if (the_acl->num_aces) {
588 if (2*the_acl->num_aces < the_acl->num_aces) {
589 return NT_STATUS_NO_MEMORY;
592 if (!(new_ace_list = talloc_array(ctx, struct security_ace,
593 2*the_acl->num_aces))) {
594 return NT_STATUS_NO_MEMORY;
596 } else {
597 new_ace_list = NULL;
600 frame = talloc_stackframe();
602 for (i = 0; i < the_acl->num_aces; i++) {
603 const struct security_ace *ace = &the_acl->aces[i];
604 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
605 const struct dom_sid *ptrustee = &ace->trustee;
606 const struct dom_sid *creator = NULL;
607 uint8_t new_flags = ace->flags;
609 if (!is_inheritable_ace(ace, container)) {
610 continue;
613 /* see the RAW-ACLS inheritance test for details on these rules */
614 if (!container) {
615 new_flags = 0;
616 } else {
618 * We need to remove SEC_ACE_FLAG_INHERITED_ACE here
619 * if present because it should only be set if the
620 * parent has the AUTO_INHERITED bit set in the
621 * type/control field. If we don't it will slip through
622 * and create DACLs with incorrectly ordered ACEs
623 * when there are CREATOR_OWNER or CREATOR_GROUP
624 * ACEs.
626 new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY
627 | SEC_ACE_FLAG_INHERITED_ACE);
629 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
630 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
632 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
633 new_flags = 0;
637 /* The CREATOR sids are special when inherited */
638 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
639 creator = &global_sid_Creator_Owner;
640 ptrustee = owner_sid;
641 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
642 creator = &global_sid_Creator_Group;
643 ptrustee = group_sid;
646 if (creator && container &&
647 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
649 /* First add the regular ACE entry. */
650 init_sec_ace(new_ace, ptrustee, ace->type,
651 ace->access_mask,
652 set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
654 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
655 " inherited as %s:%d/0x%02x/0x%08x\n",
656 dom_sid_string(frame, &ace->trustee),
657 ace->type, ace->flags, ace->access_mask,
658 dom_sid_string(frame, &new_ace->trustee),
659 new_ace->type, new_ace->flags,
660 new_ace->access_mask));
662 new_ace_list_ndx++;
664 /* Now add the extra creator ACE. */
665 new_ace = &new_ace_list[new_ace_list_ndx];
667 ptrustee = creator;
668 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
670 } else if (container &&
671 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
672 ptrustee = &ace->trustee;
675 init_sec_ace(new_ace, ptrustee, ace->type,
676 ace->access_mask, new_flags |
677 (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
679 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
680 " inherited as %s:%d/0x%02x/0x%08x\n",
681 dom_sid_string(frame, &ace->trustee),
682 ace->type, ace->flags, ace->access_mask,
683 dom_sid_string(frame, &ace->trustee),
684 new_ace->type, new_ace->flags,
685 new_ace->access_mask));
687 new_ace_list_ndx++;
690 talloc_free(frame);
693 * remove duplicates
695 for (i=1; i < new_ace_list_ndx;) {
696 struct security_ace *ai = &new_ace_list[i];
697 unsigned int remaining, j;
698 bool remove = false;
700 for (j=0; j < i; j++) {
701 struct security_ace *aj = &new_ace_list[j];
703 if (!sec_ace_equal(ai, aj)) {
704 continue;
707 remove = true;
708 break;
711 if (!remove) {
712 i++;
713 continue;
716 new_ace_list_ndx--;
717 remaining = new_ace_list_ndx - i;
718 if (remaining == 0) {
719 ZERO_STRUCT(new_ace_list[i]);
720 continue;
722 memmove(&new_ace_list[i], &new_ace_list[i+1],
723 sizeof(new_ace_list[i]) * remaining);
726 /* Create child security descriptor to return */
727 if (new_ace_list_ndx) {
728 new_dacl = make_sec_acl(ctx,
729 NT4_ACL_REVISION,
730 new_ace_list_ndx,
731 new_ace_list);
733 if (!new_dacl) {
734 return NT_STATUS_NO_MEMORY;
738 *ppsd = make_sec_desc(ctx,
739 SECURITY_DESCRIPTOR_REVISION_1,
740 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
741 (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
742 owner_sid,
743 group_sid,
744 NULL,
745 new_dacl,
746 psize);
747 if (!*ppsd) {
748 return NT_STATUS_NO_MEMORY;
750 return NT_STATUS_OK;
753 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
754 struct sec_desc_buf **ppsdb,
755 const struct security_descriptor *parent_ctr,
756 bool container)
758 NTSTATUS status;
759 size_t size = 0;
760 struct security_descriptor *sd = NULL;
762 *ppsdb = NULL;
763 status = se_create_child_secdesc(ctx,
764 &sd,
765 &size,
766 parent_ctr,
767 parent_ctr->owner_sid,
768 parent_ctr->group_sid,
769 container);
770 if (!NT_STATUS_IS_OK(status)) {
771 return status;
774 *ppsdb = make_sec_desc_buf(ctx, size, sd);
775 if (!*ppsdb) {
776 return NT_STATUS_NO_MEMORY;
778 return NT_STATUS_OK;