Fix a typo
[sfrench/samba-autobuild/.git] / libcli / security / secdesc.c
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.
8  *
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.
13  *
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.
18  *
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/>.
21  */
22
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "libcli/security/security.h"
26
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)
33
34 /* Map generic permissions to file object specific permissions */
35
36 const struct generic_mapping file_generic_mapping = {
37         FILE_GENERIC_READ,
38         FILE_GENERIC_WRITE,
39         FILE_GENERIC_EXECUTE,
40         FILE_GENERIC_ALL
41 };
42
43 /*******************************************************************
44  Given a security_descriptor return the sec_info.
45 ********************************************************************/
46
47 uint32_t get_sec_info(const struct security_descriptor *sd)
48 {
49         uint32_t sec_info = ALL_SECURITY_INFORMATION;
50
51         SMB_ASSERT(sd);
52
53         if (sd->owner_sid == NULL) {
54                 sec_info &= ~SECINFO_OWNER;
55         }
56         if (sd->group_sid == NULL) {
57                 sec_info &= ~SECINFO_GROUP;
58         }
59         if (sd->sacl == NULL) {
60                 sec_info &= ~SECINFO_SACL;
61         }
62         if (sd->dacl == NULL) {
63                 sec_info &= ~SECINFO_DACL;
64         }
65
66         return sec_info;
67 }
68
69
70 /*******************************************************************
71  Merge part of security descriptor old_sec in to the empty sections of
72  security descriptor new_sec.
73 ********************************************************************/
74
75 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
76 {
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;
83
84         /* Copy over owner and group sids.  There seems to be no flag for
85            this so just check the pointer values. */
86
87         owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
88                 old_sdb->sd->owner_sid;
89
90         group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
91                 old_sdb->sd->group_sid;
92
93         secdesc_type = new_sdb->sd->type;
94
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. */
98
99         sacl = NULL;
100         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
101
102         /* Copy across discretionary ACL */
103
104         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
105                 dacl = new_sdb->sd->dacl;
106         } else {
107                 dacl = old_sdb->sd->dacl;
108         }
109
110         /* Create new security descriptor from bits */
111
112         psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
113                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
114
115         return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
116
117         return(return_sdb);
118 }
119
120 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
121 {
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;
127
128         /* Copy over owner and group sids.  There seems to be no flag for
129            this so just check the pointer values. */
130
131         owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
132                 old_sdb->owner_sid;
133
134         group_sid = new_sdb->group_sid ? new_sdb->group_sid :
135                 old_sdb->group_sid;
136
137         secdesc_type = new_sdb->type;
138
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. */
142
143         sacl = NULL;
144         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
145
146         /* Copy across discretionary ACL */
147
148         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
149                 dacl = new_sdb->dacl;
150         } else {
151                 dacl = old_sdb->dacl;
152         }
153
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);
157
158         return psd;
159 }
160
161 /*******************************************************************
162  Creates a struct security_descriptor structure
163 ********************************************************************/
164
165 #define  SEC_DESC_HEADER_SIZE (2 * sizeof(uint16_t) + 4 * sizeof(uint32_t))
166
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)
172 {
173         struct security_descriptor *dst;
174         uint32_t offset     = 0;
175
176         if (sd_size != NULL) {
177                 *sd_size = 0;
178         }
179
180         if(( dst = talloc_zero(ctx, struct security_descriptor)) == NULL)
181                 return NULL;
182
183         dst->revision = revision;
184         dst->type = type;
185
186         if (sacl)
187                 dst->type |= SEC_DESC_SACL_PRESENT;
188         if (dacl)
189                 dst->type |= SEC_DESC_DACL_PRESENT;
190
191         dst->owner_sid = NULL;
192         dst->group_sid   = NULL;
193         dst->sacl      = NULL;
194         dst->dacl      = NULL;
195
196         if(owner_sid && ((dst->owner_sid = dom_sid_dup(dst,owner_sid)) == NULL))
197                 goto error_exit;
198
199         if(grp_sid && ((dst->group_sid = dom_sid_dup(dst,grp_sid)) == NULL))
200                 goto error_exit;
201
202         if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
203                 goto error_exit;
204
205         if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
206                 goto error_exit;
207
208         if (sd_size == NULL) {
209                 return dst;
210         }
211
212         offset = SEC_DESC_HEADER_SIZE;
213
214         /*
215          * Work out the linearization sizes.
216          */
217
218         if (dst->sacl != NULL) {
219                 offset += dst->sacl->size;
220         }
221         if (dst->dacl != NULL) {
222                 offset += dst->dacl->size;
223         }
224
225         if (dst->owner_sid != NULL) {
226                 offset += ndr_size_dom_sid(dst->owner_sid, 0);
227         }
228
229         if (dst->group_sid != NULL) {
230                 offset += ndr_size_dom_sid(dst->group_sid, 0);
231         }
232
233         *sd_size = (size_t)offset;
234         return dst;
235
236 error_exit:
237
238         if (sd_size != NULL) {
239                 *sd_size = 0;
240         }
241         return NULL;
242 }
243
244 /*******************************************************************
245  Duplicate a struct security_descriptor structure.
246 ********************************************************************/
247
248 struct security_descriptor *dup_sec_desc(TALLOC_CTX *ctx, const struct security_descriptor *src)
249 {
250         size_t dummy;
251
252         if(src == NULL)
253                 return NULL;
254
255         return make_sec_desc( ctx, src->revision, src->type,
256                                 src->owner_sid, src->group_sid, src->sacl,
257                                 src->dacl, &dummy);
258 }
259
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)
266 {
267         DATA_BLOB blob;
268         enum ndr_err_code ndr_err;
269
270         ndr_err = ndr_push_struct_blob(
271                 &blob, mem_ctx, secdesc,
272                 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
273
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);
278         }
279
280         *data = blob.data;
281         *len = blob.length;
282         return NT_STATUS_OK;
283 }
284
285 /*******************************************************************
286  Convert a secdesc_buf into a byte stream
287 ********************************************************************/
288
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)
292 {
293         DATA_BLOB blob;
294         enum ndr_err_code ndr_err;
295
296         ndr_err = ndr_push_struct_blob(
297                 &blob, mem_ctx, secdesc_buf,
298                 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
299
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);
304         }
305
306         *data = blob.data;
307         *len = blob.length;
308         return NT_STATUS_OK;
309 }
310
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)
316 {
317         DATA_BLOB blob;
318         enum ndr_err_code ndr_err;
319         struct security_descriptor *result;
320
321         if ((data == NULL) || (len == 0)) {
322                 return NT_STATUS_INVALID_PARAMETER;
323         }
324
325         result = talloc_zero(mem_ctx, struct security_descriptor);
326         if (result == NULL) {
327                 return NT_STATUS_NO_MEMORY;
328         }
329
330         blob = data_blob_const(data, len);
331
332         ndr_err = ndr_pull_struct_blob(&blob, result, result,
333                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
334
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);
340         }
341
342         *psecdesc = result;
343         return NT_STATUS_OK;
344 }
345
346 /*******************************************************************
347  Parse a byte stream into a sec_desc_buf
348 ********************************************************************/
349
350 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
351                                  struct sec_desc_buf **psecdesc_buf)
352 {
353         DATA_BLOB blob;
354         enum ndr_err_code ndr_err;
355         struct sec_desc_buf *result;
356
357         if ((data == NULL) || (len == 0)) {
358                 return NT_STATUS_INVALID_PARAMETER;
359         }
360
361         result = talloc_zero(mem_ctx, struct sec_desc_buf);
362         if (result == NULL) {
363                 return NT_STATUS_NO_MEMORY;
364         }
365
366         blob = data_blob_const(data, len);
367
368         ndr_err = ndr_pull_struct_blob(&blob, result, result,
369                 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
370
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);
376         }
377
378         *psecdesc_buf = result;
379         return NT_STATUS_OK;
380 }
381
382 /*******************************************************************
383  Creates a struct security_descriptor structure with typical defaults.
384 ********************************************************************/
385
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)
388 {
389         return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
390                              SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
391                              dacl, sd_size);
392 }
393
394 /*******************************************************************
395  Creates a struct sec_desc_buf structure.
396 ********************************************************************/
397
398 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
399 {
400         struct sec_desc_buf *dst;
401
402         if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL)
403                 return NULL;
404
405         /* max buffer size (allocated size) */
406         dst->sd_size = (uint32_t)len;
407
408         if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
409                 return NULL;
410         }
411
412         return dst;
413 }
414
415 /*******************************************************************
416  Duplicates a struct sec_desc_buf structure.
417 ********************************************************************/
418
419 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
420 {
421         if(src == NULL)
422                 return NULL;
423
424         return make_sec_desc_buf( ctx, src->sd_size, src->sd);
425 }
426
427 /*******************************************************************
428  Add a new SID with its permissions to struct security_descriptor.
429 ********************************************************************/
430
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)
432 {
433         struct security_descriptor *sd   = 0;
434         struct security_acl  *dacl = 0;
435         struct security_ace  *ace  = 0;
436         NTSTATUS  status;
437
438         if (!ctx || !psd || !sid || !sd_size)
439                 return NT_STATUS_INVALID_PARAMETER;
440
441         *sd_size = 0;
442
443         status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
444
445         if (!NT_STATUS_IS_OK(status))
446                 return status;
447
448         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
449                 return NT_STATUS_UNSUCCESSFUL;
450
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;
454
455         *psd = sd;
456          sd  = 0;
457         return NT_STATUS_OK;
458 }
459
460 /*******************************************************************
461  Modify a SID's permissions in a struct security_descriptor.
462 ********************************************************************/
463
464 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32_t mask)
465 {
466         NTSTATUS status;
467
468         if (!sd || !sid)
469                 return NT_STATUS_INVALID_PARAMETER;
470
471         status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
472
473         if (!NT_STATUS_IS_OK(status))
474                 return status;
475
476         return NT_STATUS_OK;
477 }
478
479 /*******************************************************************
480  Delete a SID from a struct security_descriptor.
481 ********************************************************************/
482
483 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, size_t *sd_size)
484 {
485         struct security_descriptor *sd   = 0;
486         struct security_acl  *dacl = 0;
487         struct security_ace  *ace  = 0;
488         NTSTATUS  status;
489
490         if (!ctx || !psd[0] || !sid || !sd_size)
491                 return NT_STATUS_INVALID_PARAMETER;
492
493         *sd_size = 0;
494
495         status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
496
497         if (!NT_STATUS_IS_OK(status))
498                 return status;
499
500         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
501                 return NT_STATUS_UNSUCCESSFUL;
502
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;
506
507         *psd = sd;
508          sd  = 0;
509         return NT_STATUS_OK;
510 }
511
512 /*
513  * Determine if an struct security_ace is inheritable
514  */
515
516 static bool is_inheritable_ace(const struct security_ace *ace,
517                                 bool container)
518 {
519         if (!container) {
520                 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
521         }
522
523         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
524                 return true;
525         }
526
527         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
528                         !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
529                 return true;
530         }
531
532         return false;
533 }
534
535 /*
536  * Does a security descriptor have any inheritable components for
537  * the newly created type ?
538  */
539
540 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
541 {
542         unsigned int i;
543         const struct security_acl *the_acl = parent_ctr->dacl;
544
545         for (i = 0; i < the_acl->num_aces; i++) {
546                 const struct security_ace *ace = &the_acl->aces[i];
547
548                 if (is_inheritable_ace(ace, container)) {
549                         return true;
550                 }
551         }
552         return false;
553 }
554
555 /* Create a child security descriptor using another security descriptor as
556    the parent container.  This child object can either be a container or
557    non-container object. */
558
559 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
560                                         struct security_descriptor **ppsd,
561                                         size_t *psize,
562                                         const struct security_descriptor *parent_ctr,
563                                         const struct dom_sid *owner_sid,
564                                         const struct dom_sid *group_sid,
565                                         bool container)
566 {
567         struct security_acl *new_dacl = NULL, *the_acl = NULL;
568         struct security_ace *new_ace_list = NULL;
569         unsigned int new_ace_list_ndx = 0, i;
570
571         TALLOC_CTX *frame;
572
573         *ppsd = NULL;
574         *psize = 0;
575
576         /* Currently we only process the dacl when creating the child.  The
577            sacl should also be processed but this is left out as sacls are
578            not implemented in Samba at the moment.*/
579
580         the_acl = parent_ctr->dacl;
581
582         if (the_acl->num_aces) {
583                 if (2*the_acl->num_aces < the_acl->num_aces) {
584                         return NT_STATUS_NO_MEMORY;
585                 }
586
587                 if (!(new_ace_list = talloc_array(ctx, struct security_ace,
588                                                   2*the_acl->num_aces))) {
589                         return NT_STATUS_NO_MEMORY;
590                 }
591         } else {
592                 new_ace_list = NULL;
593         }
594
595         frame = talloc_stackframe();
596
597         for (i = 0; i < the_acl->num_aces; i++) {
598                 const struct security_ace *ace = &the_acl->aces[i];
599                 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
600                 const struct dom_sid *ptrustee = &ace->trustee;
601                 const struct dom_sid *creator = NULL;
602                 uint8_t new_flags = ace->flags;
603
604                 if (!is_inheritable_ace(ace, container)) {
605                         continue;
606                 }
607
608                 /* see the RAW-ACLS inheritance test for details on these rules */
609                 if (!container) {
610                         new_flags = 0;
611                 } else {
612                         new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
613
614                         if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
615                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
616                         }
617                         if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
618                                 new_flags = 0;
619                         }
620                 }
621
622                 /* The CREATOR sids are special when inherited */
623                 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
624                         creator = &global_sid_Creator_Owner;
625                         ptrustee = owner_sid;
626                 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
627                         creator = &global_sid_Creator_Group;
628                         ptrustee = group_sid;
629                 }
630
631                 if (creator && container &&
632                                 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
633
634                         /* First add the regular ACE entry. */
635                         init_sec_ace(new_ace, ptrustee, ace->type,
636                                 ace->access_mask, 0);
637
638                         DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
639                                  " inherited as %s:%d/0x%02x/0x%08x\n",
640                                  dom_sid_string(frame, &ace->trustee),
641                                  ace->type, ace->flags, ace->access_mask,
642                                  dom_sid_string(frame, &new_ace->trustee),
643                                  new_ace->type, new_ace->flags,
644                                  new_ace->access_mask));
645
646                         new_ace_list_ndx++;
647
648                         /* Now add the extra creator ACE. */
649                         new_ace = &new_ace_list[new_ace_list_ndx];
650
651                         ptrustee = creator;
652                         new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
653
654                 } else if (container &&
655                                 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
656                         ptrustee = &ace->trustee;
657                 }
658
659                 init_sec_ace(new_ace, ptrustee, ace->type,
660                              ace->access_mask, new_flags);
661
662                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
663                           " inherited as %s:%d/0x%02x/0x%08x\n",
664                           dom_sid_string(frame, &ace->trustee),
665                           ace->type, ace->flags, ace->access_mask,
666                           dom_sid_string(frame, &ace->trustee),
667                           new_ace->type, new_ace->flags,
668                           new_ace->access_mask));
669
670                 new_ace_list_ndx++;
671         }
672
673         talloc_free(frame);
674
675         /* Create child security descriptor to return */
676         if (new_ace_list_ndx) {
677                 new_dacl = make_sec_acl(ctx,
678                                 NT4_ACL_REVISION,
679                                 new_ace_list_ndx,
680                                 new_ace_list);
681
682                 if (!new_dacl) {
683                         return NT_STATUS_NO_MEMORY;
684                 }
685         }
686
687         *ppsd = make_sec_desc(ctx,
688                         SECURITY_DESCRIPTOR_REVISION_1,
689                         SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
690                         owner_sid,
691                         group_sid,
692                         NULL,
693                         new_dacl,
694                         psize);
695         if (!*ppsd) {
696                 return NT_STATUS_NO_MEMORY;
697         }
698         return NT_STATUS_OK;
699 }
700
701 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
702                                         struct sec_desc_buf **ppsdb,
703                                         const struct security_descriptor *parent_ctr,
704                                         bool container)
705 {
706         NTSTATUS status;
707         size_t size = 0;
708         struct security_descriptor *sd = NULL;
709
710         *ppsdb = NULL;
711         status = se_create_child_secdesc(ctx,
712                                         &sd,
713                                         &size,
714                                         parent_ctr,
715                                         parent_ctr->owner_sid,
716                                         parent_ctr->group_sid,
717                                         container);
718         if (!NT_STATUS_IS_OK(status)) {
719                 return status;
720         }
721
722         *ppsdb = make_sec_desc_buf(ctx, size, sd);
723         if (!*ppsdb) {
724                 return NT_STATUS_NO_MEMORY;
725         }
726         return NT_STATUS_OK;
727 }