Merge branch 'v4-0-stable' into newmaster
[sfrench/samba-autobuild/.git] / source3 / lib / 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/dom_sid.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 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 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) + 4 * sizeof(uint32))
166
167 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
168                         enum security_descriptor_revision revision,
169                         uint16 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 offset     = 0;
175
176         *sd_size = 0;
177
178         if(( dst = TALLOC_ZERO_P(ctx, struct security_descriptor)) == NULL)
179                 return NULL;
180
181         dst->revision = revision;
182         dst->type = type;
183
184         if (sacl)
185                 dst->type |= SEC_DESC_SACL_PRESENT;
186         if (dacl)
187                 dst->type |= SEC_DESC_DACL_PRESENT;
188
189         dst->owner_sid = NULL;
190         dst->group_sid   = NULL;
191         dst->sacl      = NULL;
192         dst->dacl      = NULL;
193
194         if(owner_sid && ((dst->owner_sid = dom_sid_dup(dst,owner_sid)) == NULL))
195                 goto error_exit;
196
197         if(grp_sid && ((dst->group_sid = dom_sid_dup(dst,grp_sid)) == NULL))
198                 goto error_exit;
199
200         if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
201                 goto error_exit;
202
203         if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
204                 goto error_exit;
205
206         offset = SEC_DESC_HEADER_SIZE;
207
208         /*
209          * Work out the linearization sizes.
210          */
211
212         if (dst->sacl != NULL) {
213                 offset += dst->sacl->size;
214         }
215         if (dst->dacl != NULL) {
216                 offset += dst->dacl->size;
217         }
218
219         if (dst->owner_sid != NULL) {
220                 offset += ndr_size_dom_sid(dst->owner_sid, 0);
221         }
222
223         if (dst->group_sid != NULL) {
224                 offset += ndr_size_dom_sid(dst->group_sid, 0);
225         }
226
227         *sd_size = (size_t)offset;
228         return dst;
229
230 error_exit:
231
232         *sd_size = 0;
233         return NULL;
234 }
235
236 /*******************************************************************
237  Duplicate a struct security_descriptor structure.
238 ********************************************************************/
239
240 struct security_descriptor *dup_sec_desc(TALLOC_CTX *ctx, const struct security_descriptor *src)
241 {
242         size_t dummy;
243
244         if(src == NULL)
245                 return NULL;
246
247         return make_sec_desc( ctx, src->revision, src->type,
248                                 src->owner_sid, src->group_sid, src->sacl,
249                                 src->dacl, &dummy);
250 }
251
252 /*******************************************************************
253  Convert a secdesc into a byte stream
254 ********************************************************************/
255 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
256                            struct security_descriptor *secdesc,
257                            uint8 **data, size_t *len)
258 {
259         DATA_BLOB blob;
260         enum ndr_err_code ndr_err;
261
262         ndr_err = ndr_push_struct_blob(
263                 &blob, mem_ctx, secdesc,
264                 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
265
266         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
267                 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
268                           ndr_errstr(ndr_err)));
269                 return ndr_map_error2ntstatus(ndr_err);;
270         }
271
272         *data = blob.data;
273         *len = blob.length;
274         return NT_STATUS_OK;
275 }
276
277 /*******************************************************************
278  Convert a secdesc_buf into a byte stream
279 ********************************************************************/
280
281 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
282                                struct sec_desc_buf *secdesc_buf,
283                                uint8_t **data, size_t *len)
284 {
285         DATA_BLOB blob;
286         enum ndr_err_code ndr_err;
287
288         ndr_err = ndr_push_struct_blob(
289                 &blob, mem_ctx, secdesc_buf,
290                 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
291
292         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
293                 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
294                           ndr_errstr(ndr_err)));
295                 return ndr_map_error2ntstatus(ndr_err);;
296         }
297
298         *data = blob.data;
299         *len = blob.length;
300         return NT_STATUS_OK;
301 }
302
303 /*******************************************************************
304  Parse a byte stream into a secdesc
305 ********************************************************************/
306 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
307                              struct security_descriptor **psecdesc)
308 {
309         DATA_BLOB blob;
310         enum ndr_err_code ndr_err;
311         struct security_descriptor *result;
312
313         if ((data == NULL) || (len == 0)) {
314                 return NT_STATUS_INVALID_PARAMETER;
315         }
316
317         result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor);
318         if (result == NULL) {
319                 return NT_STATUS_NO_MEMORY;
320         }
321
322         blob = data_blob_const(data, len);
323
324         ndr_err = ndr_pull_struct_blob(&blob, result, result,
325                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
326
327         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
328                 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
329                           ndr_errstr(ndr_err)));
330                 TALLOC_FREE(result);
331                 return ndr_map_error2ntstatus(ndr_err);;
332         }
333
334         *psecdesc = result;
335         return NT_STATUS_OK;
336 }
337
338 /*******************************************************************
339  Parse a byte stream into a sec_desc_buf
340 ********************************************************************/
341
342 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
343                                  struct sec_desc_buf **psecdesc_buf)
344 {
345         DATA_BLOB blob;
346         enum ndr_err_code ndr_err;
347         struct sec_desc_buf *result;
348
349         if ((data == NULL) || (len == 0)) {
350                 return NT_STATUS_INVALID_PARAMETER;
351         }
352
353         result = TALLOC_ZERO_P(mem_ctx, struct sec_desc_buf);
354         if (result == NULL) {
355                 return NT_STATUS_NO_MEMORY;
356         }
357
358         blob = data_blob_const(data, len);
359
360         ndr_err = ndr_pull_struct_blob(&blob, result, result,
361                 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
362
363         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
364                 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
365                           ndr_errstr(ndr_err)));
366                 TALLOC_FREE(result);
367                 return ndr_map_error2ntstatus(ndr_err);;
368         }
369
370         *psecdesc_buf = result;
371         return NT_STATUS_OK;
372 }
373
374 /*******************************************************************
375  Creates a struct security_descriptor structure with typical defaults.
376 ********************************************************************/
377
378 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
379                                  struct security_acl *dacl, size_t *sd_size)
380 {
381         return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
382                              SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
383                              dacl, sd_size);
384 }
385
386 /*******************************************************************
387  Creates a struct sec_desc_buf structure.
388 ********************************************************************/
389
390 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
391 {
392         struct sec_desc_buf *dst;
393
394         if((dst = TALLOC_ZERO_P(ctx, struct sec_desc_buf)) == NULL)
395                 return NULL;
396
397         /* max buffer size (allocated size) */
398         dst->sd_size = (uint32)len;
399         
400         if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
401                 return NULL;
402         }
403
404         return dst;
405 }
406
407 /*******************************************************************
408  Duplicates a struct sec_desc_buf structure.
409 ********************************************************************/
410
411 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
412 {
413         if(src == NULL)
414                 return NULL;
415
416         return make_sec_desc_buf( ctx, src->sd_size, src->sd);
417 }
418
419 /*******************************************************************
420  Add a new SID with its permissions to struct security_descriptor.
421 ********************************************************************/
422
423 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, uint32 mask, size_t *sd_size)
424 {
425         struct security_descriptor *sd   = 0;
426         struct security_acl  *dacl = 0;
427         struct security_ace  *ace  = 0;
428         NTSTATUS  status;
429
430         if (!ctx || !psd || !sid || !sd_size)
431                 return NT_STATUS_INVALID_PARAMETER;
432
433         *sd_size = 0;
434
435         status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
436         
437         if (!NT_STATUS_IS_OK(status))
438                 return status;
439
440         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
441                 return NT_STATUS_UNSUCCESSFUL;
442         
443         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
444                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
445                 return NT_STATUS_UNSUCCESSFUL;
446
447         *psd = sd;
448          sd  = 0;
449         return NT_STATUS_OK;
450 }
451
452 /*******************************************************************
453  Modify a SID's permissions in a struct security_descriptor.
454 ********************************************************************/
455
456 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32 mask)
457 {
458         NTSTATUS status;
459
460         if (!sd || !sid)
461                 return NT_STATUS_INVALID_PARAMETER;
462
463         status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
464
465         if (!NT_STATUS_IS_OK(status))
466                 return status;
467         
468         return NT_STATUS_OK;
469 }
470
471 /*******************************************************************
472  Delete a SID from a struct security_descriptor.
473 ********************************************************************/
474
475 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, size_t *sd_size)
476 {
477         struct security_descriptor *sd   = 0;
478         struct security_acl  *dacl = 0;
479         struct security_ace  *ace  = 0;
480         NTSTATUS  status;
481
482         if (!ctx || !psd[0] || !sid || !sd_size)
483                 return NT_STATUS_INVALID_PARAMETER;
484
485         *sd_size = 0;
486         
487         status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
488
489         if (!NT_STATUS_IS_OK(status))
490                 return status;
491
492         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
493                 return NT_STATUS_UNSUCCESSFUL;
494         
495         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
496                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
497                 return NT_STATUS_UNSUCCESSFUL;
498
499         *psd = sd;
500          sd  = 0;
501         return NT_STATUS_OK;
502 }
503
504 /*
505  * Determine if an struct security_ace is inheritable
506  */
507
508 static bool is_inheritable_ace(const struct security_ace *ace,
509                                 bool container)
510 {
511         if (!container) {
512                 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
513         }
514
515         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
516                 return true;
517         }
518
519         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
520                         !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
521                 return true;
522         }
523
524         return false;
525 }
526
527 /*
528  * Does a security descriptor have any inheritable components for
529  * the newly created type ?
530  */
531
532 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
533 {
534         unsigned int i;
535         const struct security_acl *the_acl = parent_ctr->dacl;
536
537         for (i = 0; i < the_acl->num_aces; i++) {
538                 const struct security_ace *ace = &the_acl->aces[i];
539
540                 if (is_inheritable_ace(ace, container)) {
541                         return true;
542                 }
543         }
544         return false;
545 }
546
547 /* Create a child security descriptor using another security descriptor as
548    the parent container.  This child object can either be a container or
549    non-container object. */
550
551 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
552                                         struct security_descriptor **ppsd,
553                                         size_t *psize,
554                                         const struct security_descriptor *parent_ctr,
555                                         const struct dom_sid *owner_sid,
556                                         const struct dom_sid *group_sid,
557                                         bool container)
558 {
559         struct security_acl *new_dacl = NULL, *the_acl = NULL;
560         struct security_ace *new_ace_list = NULL;
561         unsigned int new_ace_list_ndx = 0, i;
562
563         *ppsd = NULL;
564         *psize = 0;
565
566         /* Currently we only process the dacl when creating the child.  The
567            sacl should also be processed but this is left out as sacls are
568            not implemented in Samba at the moment.*/
569
570         the_acl = parent_ctr->dacl;
571
572         if (the_acl->num_aces) {
573                 if (2*the_acl->num_aces < the_acl->num_aces) {
574                         return NT_STATUS_NO_MEMORY;
575                 }
576
577                 if (!(new_ace_list = TALLOC_ARRAY(ctx, struct security_ace,
578                                                 2*the_acl->num_aces))) {
579                         return NT_STATUS_NO_MEMORY;
580                 }
581         } else {
582                 new_ace_list = NULL;
583         }
584
585         for (i = 0; i < the_acl->num_aces; i++) {
586                 const struct security_ace *ace = &the_acl->aces[i];
587                 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
588                 const struct dom_sid *ptrustee = &ace->trustee;
589                 const struct dom_sid *creator = NULL;
590                 uint8 new_flags = ace->flags;
591
592                 if (!is_inheritable_ace(ace, container)) {
593                         continue;
594                 }
595
596                 /* see the RAW-ACLS inheritance test for details on these rules */
597                 if (!container) {
598                         new_flags = 0;
599                 } else {
600                         new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
601
602                         if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
603                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
604                         }
605                         if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
606                                 new_flags = 0;
607                         }
608                 }
609
610                 /* The CREATOR sids are special when inherited */
611                 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
612                         creator = &global_sid_Creator_Owner;
613                         ptrustee = owner_sid;
614                 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
615                         creator = &global_sid_Creator_Group;
616                         ptrustee = group_sid;
617                 }
618
619                 if (creator && container &&
620                                 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
621
622                         /* First add the regular ACE entry. */
623                         init_sec_ace(new_ace, ptrustee, ace->type,
624                                 ace->access_mask, 0);
625
626                         DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
627                                 " inherited as %s:%d/0x%02x/0x%08x\n",
628                                 sid_string_dbg(&ace->trustee),
629                                 ace->type, ace->flags, ace->access_mask,
630                                 sid_string_dbg(&new_ace->trustee),
631                                 new_ace->type, new_ace->flags,
632                                 new_ace->access_mask));
633
634                         new_ace_list_ndx++;
635
636                         /* Now add the extra creator ACE. */
637                         new_ace = &new_ace_list[new_ace_list_ndx];
638
639                         ptrustee = creator;
640                         new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
641                 } else if (container &&
642                                 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
643                         ptrustee = &ace->trustee;
644                 }
645
646                 init_sec_ace(new_ace, ptrustee, ace->type,
647                              ace->access_mask, new_flags);
648
649                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
650                           " inherited as %s:%d/0x%02x/0x%08x\n",
651                           sid_string_dbg(&ace->trustee),
652                           ace->type, ace->flags, ace->access_mask,
653                           sid_string_dbg(&ace->trustee),
654                           new_ace->type, new_ace->flags,
655                           new_ace->access_mask));
656
657                 new_ace_list_ndx++;
658         }
659
660         /* Create child security descriptor to return */
661         if (new_ace_list_ndx) {
662                 new_dacl = make_sec_acl(ctx,
663                                 NT4_ACL_REVISION,
664                                 new_ace_list_ndx,
665                                 new_ace_list);
666
667                 if (!new_dacl) {
668                         return NT_STATUS_NO_MEMORY;
669                 }
670         }
671
672         *ppsd = make_sec_desc(ctx,
673                         SECURITY_DESCRIPTOR_REVISION_1,
674                         SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
675                         owner_sid,
676                         group_sid,
677                         NULL,
678                         new_dacl,
679                         psize);
680         if (!*ppsd) {
681                 return NT_STATUS_NO_MEMORY;
682         }
683         return NT_STATUS_OK;
684 }
685
686 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
687                                         struct sec_desc_buf **ppsdb,
688                                         const struct security_descriptor *parent_ctr,
689                                         bool container)
690 {
691         NTSTATUS status;
692         size_t size = 0;
693         struct security_descriptor *sd = NULL;
694
695         *ppsdb = NULL;
696         status = se_create_child_secdesc(ctx,
697                                         &sd,
698                                         &size,
699                                         parent_ctr,
700                                         parent_ctr->owner_sid,
701                                         parent_ctr->group_sid,
702                                         container);
703         if (!NT_STATUS_IS_OK(status)) {
704                 return status;
705         }
706
707         *ppsdb = make_sec_desc_buf(ctx, size, sd);
708         if (!*ppsdb) {
709                 return NT_STATUS_NO_MEMORY;
710         }
711         return NT_STATUS_OK;
712 }