source: vendor/3.6.0/source3/lib/secdesc.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

File size: 19.9 KB
Line 
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
36const 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
47uint32_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
75struct 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
120struct 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
167struct 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
230error_exit:
231
232 *sd_size = 0;
233 return NULL;
234}
235
236/*******************************************************************
237 Duplicate a struct security_descriptor structure.
238********************************************************************/
239
240struct 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********************************************************************/
255NTSTATUS 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
281NTSTATUS 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********************************************************************/
306NTSTATUS 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
342NTSTATUS 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
378struct 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
390struct 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
411struct 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
423NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, const 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
456NTSTATUS 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
475NTSTATUS 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
508static 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
532bool 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
551NTSTATUS 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
686NTSTATUS 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}
Note: See TracBrowser for help on using the repository browser.