libcli/security: remove duplicate aces in se_create_child_secdesc()
[kai/samba.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         if (the_acl == NULL) {
546                 return false;
547         }
548
549         for (i = 0; i < the_acl->num_aces; i++) {
550                 const struct security_ace *ace = &the_acl->aces[i];
551
552                 if (is_inheritable_ace(ace, container)) {
553                         return true;
554                 }
555         }
556         return false;
557 }
558
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. */
562
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)
570 {
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);
575
576         TALLOC_CTX *frame;
577
578         *ppsd = NULL;
579         *psize = 0;
580
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.*/
584
585         the_acl = parent_ctr->dacl;
586
587         if (the_acl->num_aces) {
588                 if (2*the_acl->num_aces < the_acl->num_aces) {
589                         return NT_STATUS_NO_MEMORY;
590                 }
591
592                 if (!(new_ace_list = talloc_array(ctx, struct security_ace,
593                                                   2*the_acl->num_aces))) {
594                         return NT_STATUS_NO_MEMORY;
595                 }
596         } else {
597                 new_ace_list = NULL;
598         }
599
600         frame = talloc_stackframe();
601
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;
608
609                 if (!is_inheritable_ace(ace, container)) {
610                         continue;
611                 }
612
613                 /* see the RAW-ACLS inheritance test for details on these rules */
614                 if (!container) {
615                         new_flags = 0;
616                 } else {
617                         new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
618
619                         if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
620                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
621                         }
622                         if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
623                                 new_flags = 0;
624                         }
625                 }
626
627                 /* The CREATOR sids are special when inherited */
628                 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
629                         creator = &global_sid_Creator_Owner;
630                         ptrustee = owner_sid;
631                 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
632                         creator = &global_sid_Creator_Group;
633                         ptrustee = group_sid;
634                 }
635
636                 if (creator && container &&
637                                 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
638
639                         /* First add the regular ACE entry. */
640                         init_sec_ace(new_ace, ptrustee, ace->type,
641                                 ace->access_mask,
642                                 set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
643
644                         DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
645                                  " inherited as %s:%d/0x%02x/0x%08x\n",
646                                  dom_sid_string(frame, &ace->trustee),
647                                  ace->type, ace->flags, ace->access_mask,
648                                  dom_sid_string(frame, &new_ace->trustee),
649                                  new_ace->type, new_ace->flags,
650                                  new_ace->access_mask));
651
652                         new_ace_list_ndx++;
653
654                         /* Now add the extra creator ACE. */
655                         new_ace = &new_ace_list[new_ace_list_ndx];
656
657                         ptrustee = creator;
658                         new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
659
660                 } else if (container &&
661                                 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
662                         ptrustee = &ace->trustee;
663                 }
664
665                 init_sec_ace(new_ace, ptrustee, ace->type,
666                              ace->access_mask, new_flags |
667                                 (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
668
669                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
670                           " inherited as %s:%d/0x%02x/0x%08x\n",
671                           dom_sid_string(frame, &ace->trustee),
672                           ace->type, ace->flags, ace->access_mask,
673                           dom_sid_string(frame, &ace->trustee),
674                           new_ace->type, new_ace->flags,
675                           new_ace->access_mask));
676
677                 new_ace_list_ndx++;
678         }
679
680         talloc_free(frame);
681
682         /*
683          * remove duplicates
684          */
685         for (i=1; i < new_ace_list_ndx;) {
686                 struct security_ace *ai = &new_ace_list[i];
687                 unsigned int remaining, j;
688                 bool remove = false;
689
690                 for (j=0; j < i; j++) {
691                         struct security_ace *aj = &new_ace_list[j];
692
693                         if (!sec_ace_equal(ai, aj)) {
694                                 continue;
695                         }
696
697                         remove = true;
698                         break;
699                 }
700
701                 if (!remove) {
702                         i++;
703                         continue;
704                 }
705
706                 new_ace_list_ndx--;
707                 remaining = new_ace_list_ndx - i;
708                 if (remaining == 0) {
709                         ZERO_STRUCT(new_ace_list[i]);
710                         continue;
711                 }
712                 memmove(&new_ace_list[i], &new_ace_list[i+1],
713                         sizeof(new_ace_list[i]) * remaining);
714         }
715
716         /* Create child security descriptor to return */
717         if (new_ace_list_ndx) {
718                 new_dacl = make_sec_acl(ctx,
719                                 NT4_ACL_REVISION,
720                                 new_ace_list_ndx,
721                                 new_ace_list);
722
723                 if (!new_dacl) {
724                         return NT_STATUS_NO_MEMORY;
725                 }
726         }
727
728         *ppsd = make_sec_desc(ctx,
729                         SECURITY_DESCRIPTOR_REVISION_1,
730                         SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
731                                 (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
732                         owner_sid,
733                         group_sid,
734                         NULL,
735                         new_dacl,
736                         psize);
737         if (!*ppsd) {
738                 return NT_STATUS_NO_MEMORY;
739         }
740         return NT_STATUS_OK;
741 }
742
743 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
744                                         struct sec_desc_buf **ppsdb,
745                                         const struct security_descriptor *parent_ctr,
746                                         bool container)
747 {
748         NTSTATUS status;
749         size_t size = 0;
750         struct security_descriptor *sd = NULL;
751
752         *ppsdb = NULL;
753         status = se_create_child_secdesc(ctx,
754                                         &sd,
755                                         &size,
756                                         parent_ctr,
757                                         parent_ctr->owner_sid,
758                                         parent_ctr->group_sid,
759                                         container);
760         if (!NT_STATUS_IS_OK(status)) {
761                 return status;
762         }
763
764         *ppsdb = make_sec_desc_buf(ctx, size, sd);
765         if (!*ppsdb) {
766                 return NT_STATUS_NO_MEMORY;
767         }
768         return NT_STATUS_OK;
769 }