Line data Source code
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 : /* Map generic permissions to file object specific permissions */
28 :
29 : const struct generic_mapping file_generic_mapping = {
30 : FILE_GENERIC_READ,
31 : FILE_GENERIC_WRITE,
32 : FILE_GENERIC_EXECUTE,
33 : FILE_GENERIC_ALL
34 : };
35 :
36 : /*******************************************************************
37 : Given a security_descriptor return the sec_info.
38 : ********************************************************************/
39 :
40 7 : uint32_t get_sec_info(const struct security_descriptor *sd)
41 : {
42 7 : uint32_t sec_info = 0;
43 :
44 7 : SMB_ASSERT(sd);
45 :
46 7 : if (sd->owner_sid != NULL) {
47 6 : sec_info |= SECINFO_OWNER;
48 : }
49 7 : if (sd->group_sid != NULL) {
50 6 : sec_info |= SECINFO_GROUP;
51 : }
52 7 : if (sd->sacl != NULL) {
53 0 : sec_info |= SECINFO_SACL;
54 : }
55 7 : if (sd->dacl != NULL) {
56 6 : sec_info |= SECINFO_DACL;
57 : }
58 :
59 7 : if (sd->type & SEC_DESC_SACL_PROTECTED) {
60 0 : sec_info |= SECINFO_PROTECTED_SACL;
61 7 : } else if (sd->type & SEC_DESC_SACL_AUTO_INHERITED) {
62 0 : sec_info |= SECINFO_UNPROTECTED_SACL;
63 : }
64 7 : if (sd->type & SEC_DESC_DACL_PROTECTED) {
65 0 : sec_info |= SECINFO_PROTECTED_DACL;
66 7 : } else if (sd->type & SEC_DESC_DACL_AUTO_INHERITED) {
67 0 : sec_info |= SECINFO_UNPROTECTED_DACL;
68 : }
69 :
70 7 : return sec_info;
71 : }
72 :
73 :
74 : /*******************************************************************
75 : Merge part of security descriptor old_sec in to the empty sections of
76 : security descriptor new_sec.
77 : ********************************************************************/
78 :
79 0 : struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
80 : {
81 : struct dom_sid *owner_sid, *group_sid;
82 : struct sec_desc_buf *return_sdb;
83 : struct security_acl *dacl, *sacl;
84 0 : struct security_descriptor *psd = NULL;
85 : uint16_t secdesc_type;
86 : size_t secdesc_size;
87 :
88 : /* Copy over owner and group sids. There seems to be no flag for
89 : this so just check the pointer values. */
90 :
91 0 : owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
92 0 : old_sdb->sd->owner_sid;
93 :
94 0 : group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
95 0 : old_sdb->sd->group_sid;
96 :
97 0 : secdesc_type = new_sdb->sd->type;
98 :
99 : /* Ignore changes to the system ACL. This has the effect of making
100 : changes through the security tab audit button not sticking.
101 : Perhaps in future Samba could implement these settings somehow. */
102 :
103 0 : sacl = NULL;
104 0 : secdesc_type &= ~SEC_DESC_SACL_PRESENT;
105 :
106 : /* Copy across discretionary ACL */
107 :
108 0 : if (secdesc_type & SEC_DESC_DACL_PRESENT) {
109 0 : dacl = new_sdb->sd->dacl;
110 : } else {
111 0 : dacl = old_sdb->sd->dacl;
112 : }
113 :
114 : /* Create new security descriptor from bits */
115 :
116 0 : psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
117 : owner_sid, group_sid, sacl, dacl, &secdesc_size);
118 :
119 0 : return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
120 :
121 0 : return(return_sdb);
122 : }
123 :
124 0 : struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
125 : {
126 : struct dom_sid *owner_sid, *group_sid;
127 : struct security_acl *dacl, *sacl;
128 0 : struct security_descriptor *psd = NULL;
129 : uint16_t secdesc_type;
130 : size_t secdesc_size;
131 :
132 : /* Copy over owner and group sids. There seems to be no flag for
133 : this so just check the pointer values. */
134 :
135 0 : owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
136 : old_sdb->owner_sid;
137 :
138 0 : group_sid = new_sdb->group_sid ? new_sdb->group_sid :
139 : old_sdb->group_sid;
140 :
141 0 : secdesc_type = new_sdb->type;
142 :
143 : /* Ignore changes to the system ACL. This has the effect of making
144 : changes through the security tab audit button not sticking.
145 : Perhaps in future Samba could implement these settings somehow. */
146 :
147 0 : sacl = NULL;
148 0 : secdesc_type &= ~SEC_DESC_SACL_PRESENT;
149 :
150 : /* Copy across discretionary ACL */
151 :
152 0 : if (secdesc_type & SEC_DESC_DACL_PRESENT) {
153 0 : dacl = new_sdb->dacl;
154 : } else {
155 0 : dacl = old_sdb->dacl;
156 : }
157 :
158 : /* Create new security descriptor from bits */
159 0 : psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
160 : owner_sid, group_sid, sacl, dacl, &secdesc_size);
161 :
162 0 : return psd;
163 : }
164 :
165 : /*******************************************************************
166 : Creates a struct security_descriptor structure
167 : ********************************************************************/
168 26778 : struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
169 : enum security_descriptor_revision revision,
170 : uint16_t type,
171 : const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
172 : struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
173 : {
174 : struct security_descriptor *dst;
175 :
176 26778 : if (sd_size != NULL) {
177 26778 : *sd_size = 0;
178 : }
179 :
180 26778 : dst = security_descriptor_initialise(ctx);
181 26778 : if (dst == NULL) {
182 0 : return NULL;
183 : }
184 :
185 26778 : dst->revision = revision;
186 26778 : dst->type = type;
187 :
188 26778 : if (sacl != NULL) {
189 8 : dst->sacl = security_acl_dup(dst, sacl);
190 8 : if (dst->sacl == NULL) {
191 0 : goto err_sd_free;
192 : }
193 8 : dst->type |= SEC_DESC_SACL_PRESENT;
194 : }
195 :
196 26778 : if (dacl != NULL) {
197 26769 : dst->dacl = security_acl_dup(dst, dacl);
198 26769 : if (dst->dacl == NULL) {
199 0 : goto err_sd_free;
200 : }
201 26769 : dst->type |= SEC_DESC_DACL_PRESENT;
202 : }
203 :
204 26778 : if (owner_sid != NULL) {
205 12412 : dst->owner_sid = dom_sid_dup(dst, owner_sid);
206 12412 : if (dst->owner_sid == NULL) {
207 0 : goto err_sd_free;
208 : }
209 : }
210 :
211 26778 : if (grp_sid != NULL) {
212 12332 : dst->group_sid = dom_sid_dup(dst, grp_sid);
213 12332 : if (dst->group_sid == NULL) {
214 0 : goto err_sd_free;
215 : }
216 : }
217 :
218 26778 : if (sd_size != NULL) {
219 26778 : *sd_size = ndr_size_security_descriptor(dst, 0);
220 : }
221 :
222 26778 : return dst;
223 :
224 0 : err_sd_free:
225 0 : talloc_free(dst);
226 0 : return NULL;
227 : }
228 :
229 : /*******************************************************************
230 : Convert a secdesc into a byte stream
231 : ********************************************************************/
232 493 : NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
233 : const struct security_descriptor *secdesc,
234 : uint8_t **data, size_t *len)
235 : {
236 : DATA_BLOB blob;
237 : enum ndr_err_code ndr_err;
238 :
239 493 : ndr_err = ndr_push_struct_blob(
240 : &blob, mem_ctx, secdesc,
241 : (ndr_push_flags_fn_t)ndr_push_security_descriptor);
242 :
243 493 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
244 0 : DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
245 : ndr_errstr(ndr_err)));
246 0 : return ndr_map_error2ntstatus(ndr_err);
247 : }
248 :
249 493 : *data = blob.data;
250 493 : *len = blob.length;
251 493 : return NT_STATUS_OK;
252 : }
253 :
254 : /*******************************************************************
255 : Convert a secdesc_buf into a byte stream
256 : ********************************************************************/
257 :
258 0 : NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
259 : const struct sec_desc_buf *secdesc_buf,
260 : uint8_t **data, size_t *len)
261 : {
262 : DATA_BLOB blob;
263 : enum ndr_err_code ndr_err;
264 :
265 0 : ndr_err = ndr_push_struct_blob(
266 : &blob, mem_ctx, secdesc_buf,
267 : (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
268 :
269 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
270 0 : DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
271 : ndr_errstr(ndr_err)));
272 0 : return ndr_map_error2ntstatus(ndr_err);
273 : }
274 :
275 0 : *data = blob.data;
276 0 : *len = blob.length;
277 0 : return NT_STATUS_OK;
278 : }
279 :
280 : /*******************************************************************
281 : Parse a byte stream into a secdesc
282 : ********************************************************************/
283 436 : NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
284 : struct security_descriptor **psecdesc)
285 : {
286 : DATA_BLOB blob;
287 : enum ndr_err_code ndr_err;
288 : struct security_descriptor *result;
289 :
290 436 : if ((data == NULL) || (len == 0)) {
291 0 : return NT_STATUS_INVALID_PARAMETER;
292 : }
293 :
294 436 : result = talloc_zero(mem_ctx, struct security_descriptor);
295 436 : if (result == NULL) {
296 0 : return NT_STATUS_NO_MEMORY;
297 : }
298 :
299 436 : blob = data_blob_const(data, len);
300 :
301 436 : ndr_err = ndr_pull_struct_blob(&blob, result, result,
302 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
303 :
304 436 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
305 0 : DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
306 : ndr_errstr(ndr_err)));
307 0 : TALLOC_FREE(result);
308 0 : return ndr_map_error2ntstatus(ndr_err);
309 : }
310 :
311 436 : *psecdesc = result;
312 436 : return NT_STATUS_OK;
313 : }
314 :
315 : /*******************************************************************
316 : Parse a byte stream into a sec_desc_buf
317 : ********************************************************************/
318 :
319 0 : NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
320 : struct sec_desc_buf **psecdesc_buf)
321 : {
322 : DATA_BLOB blob;
323 : enum ndr_err_code ndr_err;
324 : struct sec_desc_buf *result;
325 :
326 0 : if ((data == NULL) || (len == 0)) {
327 0 : return NT_STATUS_INVALID_PARAMETER;
328 : }
329 :
330 0 : result = talloc_zero(mem_ctx, struct sec_desc_buf);
331 0 : if (result == NULL) {
332 0 : return NT_STATUS_NO_MEMORY;
333 : }
334 :
335 0 : blob = data_blob_const(data, len);
336 :
337 0 : ndr_err = ndr_pull_struct_blob(&blob, result, result,
338 : (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
339 :
340 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341 0 : DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
342 : ndr_errstr(ndr_err)));
343 0 : TALLOC_FREE(result);
344 0 : return ndr_map_error2ntstatus(ndr_err);
345 : }
346 :
347 0 : *psecdesc_buf = result;
348 0 : return NT_STATUS_OK;
349 : }
350 :
351 : /*******************************************************************
352 : Creates a struct security_descriptor structure with typical defaults.
353 : ********************************************************************/
354 :
355 6192 : struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
356 : struct security_acl *dacl, size_t *sd_size)
357 : {
358 6192 : return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
359 : SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
360 : dacl, sd_size);
361 : }
362 :
363 : /*******************************************************************
364 : Creates a struct sec_desc_buf structure.
365 : ********************************************************************/
366 :
367 28 : struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
368 : {
369 : struct sec_desc_buf *dst;
370 :
371 28 : if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL)
372 0 : return NULL;
373 :
374 : /* max buffer size (allocated size) */
375 28 : dst->sd_size = (uint32_t)len;
376 :
377 28 : if (sec_desc != NULL) {
378 28 : dst->sd = security_descriptor_copy(ctx, sec_desc);
379 28 : if (dst->sd == NULL) {
380 0 : return NULL;
381 : }
382 : }
383 :
384 28 : return dst;
385 : }
386 :
387 : /*
388 : * Determine if an struct security_ace is inheritable
389 : */
390 :
391 20533 : static bool is_inheritable_ace(const struct security_ace *ace,
392 : bool container)
393 : {
394 20533 : if (!container) {
395 5210 : return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
396 : }
397 :
398 15323 : if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
399 5265 : return true;
400 : }
401 :
402 10058 : if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
403 0 : !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
404 0 : return true;
405 : }
406 :
407 10058 : return false;
408 : }
409 :
410 : /*
411 : * Does a security descriptor have any inheritable components for
412 : * the newly created type ?
413 : */
414 :
415 4369 : bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
416 : {
417 : unsigned int i;
418 4369 : const struct security_acl *the_acl = parent_ctr->dacl;
419 :
420 4369 : if (the_acl == NULL) {
421 0 : return false;
422 : }
423 :
424 14390 : for (i = 0; i < the_acl->num_aces; i++) {
425 11342 : const struct security_ace *ace = &the_acl->aces[i];
426 :
427 11342 : if (is_inheritable_ace(ace, container)) {
428 1321 : return true;
429 : }
430 : }
431 3048 : return false;
432 : }
433 :
434 : /* Create a child security descriptor using another security descriptor as
435 : the parent container. This child object can either be a container or
436 : non-container object. */
437 :
438 1321 : NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
439 : struct security_descriptor **ppsd,
440 : size_t *psize,
441 : const struct security_descriptor *parent_ctr,
442 : const struct dom_sid *owner_sid,
443 : const struct dom_sid *group_sid,
444 : bool container)
445 : {
446 1321 : struct security_acl *new_dacl = NULL, *the_acl = NULL;
447 1321 : struct security_ace *new_ace_list = NULL;
448 1321 : unsigned int new_ace_list_ndx = 0, i;
449 1321 : bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED);
450 :
451 : TALLOC_CTX *frame;
452 :
453 1321 : *ppsd = NULL;
454 1321 : *psize = 0;
455 :
456 : /* Currently we only process the dacl when creating the child. The
457 : sacl should also be processed but this is left out as sacls are
458 : not implemented in Samba at the moment.*/
459 :
460 1321 : the_acl = parent_ctr->dacl;
461 :
462 1321 : if (the_acl->num_aces) {
463 1321 : if (2*the_acl->num_aces < the_acl->num_aces) {
464 0 : return NT_STATUS_NO_MEMORY;
465 : }
466 :
467 1321 : if (!(new_ace_list = talloc_array(ctx, struct security_ace,
468 : 2*the_acl->num_aces))) {
469 0 : return NT_STATUS_NO_MEMORY;
470 : }
471 : } else {
472 0 : new_ace_list = NULL;
473 : }
474 :
475 1321 : frame = talloc_stackframe();
476 :
477 10512 : for (i = 0; i < the_acl->num_aces; i++) {
478 9191 : const struct security_ace *ace = &the_acl->aces[i];
479 9191 : struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
480 9191 : const struct dom_sid *ptrustee = &ace->trustee;
481 9191 : const struct dom_sid *creator = NULL;
482 9191 : uint8_t new_flags = ace->flags;
483 : struct dom_sid_buf sidbuf1, sidbuf2;
484 :
485 9191 : if (!is_inheritable_ace(ace, container)) {
486 1483 : continue;
487 : }
488 :
489 : /* see the RAW-ACLS inheritance test for details on these rules */
490 7708 : if (!container) {
491 3181 : new_flags = 0;
492 : } else {
493 : /*
494 : * We need to remove SEC_ACE_FLAG_INHERITED_ACE here
495 : * if present because it should only be set if the
496 : * parent has the AUTO_INHERITED bit set in the
497 : * type/control field. If we don't it will slip through
498 : * and create DACLs with incorrectly ordered ACEs
499 : * when there are CREATOR_OWNER or CREATOR_GROUP
500 : * ACEs.
501 : */
502 4527 : new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY
503 : | SEC_ACE_FLAG_INHERITED_ACE);
504 :
505 4527 : if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
506 0 : new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
507 : }
508 4527 : if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
509 0 : new_flags = 0;
510 : }
511 : }
512 :
513 : /* The CREATOR sids are special when inherited */
514 7708 : if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
515 1193 : creator = &global_sid_Creator_Owner;
516 1193 : ptrustee = owner_sid;
517 6515 : } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
518 401 : creator = &global_sid_Creator_Group;
519 401 : ptrustee = group_sid;
520 : }
521 :
522 8408 : if (creator && container &&
523 804 : (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
524 :
525 : /* First add the regular ACE entry. */
526 804 : init_sec_ace(new_ace, ptrustee, ace->type,
527 104 : ace->access_mask,
528 : set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
529 :
530 804 : DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
531 : " inherited as %s:%d/0x%02x/0x%08x\n",
532 : dom_sid_str_buf(&ace->trustee, &sidbuf1),
533 : ace->type, ace->flags, ace->access_mask,
534 : dom_sid_str_buf(&new_ace->trustee, &sidbuf2),
535 : new_ace->type, new_ace->flags,
536 : new_ace->access_mask));
537 :
538 804 : new_ace_list_ndx++;
539 :
540 : /* Now add the extra creator ACE. */
541 804 : new_ace = &new_ace_list[new_ace_list_ndx];
542 :
543 804 : ptrustee = creator;
544 804 : new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
545 :
546 10575 : } else if (container &&
547 3723 : !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
548 3723 : ptrustee = &ace->trustee;
549 : }
550 :
551 7708 : init_sec_ace(new_ace, ptrustee, ace->type,
552 7708 : ace->access_mask, new_flags |
553 : (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
554 :
555 7708 : DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
556 : " inherited as %s:%d/0x%02x/0x%08x\n",
557 : dom_sid_str_buf(&ace->trustee, &sidbuf1),
558 : ace->type, ace->flags, ace->access_mask,
559 : dom_sid_str_buf(&new_ace->trustee, &sidbuf2),
560 : new_ace->type, new_ace->flags,
561 : new_ace->access_mask));
562 :
563 7708 : new_ace_list_ndx++;
564 : }
565 :
566 1321 : talloc_free(frame);
567 :
568 : /*
569 : * remove duplicates
570 : */
571 9682 : for (i=1; i < new_ace_list_ndx;) {
572 7191 : struct security_ace *ai = &new_ace_list[i];
573 : unsigned int remaining, j;
574 7191 : bool remove_ace = false;
575 :
576 60095 : for (j=0; j < i; j++) {
577 23819 : struct security_ace *aj = &new_ace_list[j];
578 :
579 23819 : if (!security_ace_equal(ai, aj)) {
580 23468 : continue;
581 : }
582 :
583 351 : remove_ace = true;
584 351 : break;
585 : }
586 :
587 7191 : if (!remove_ace) {
588 6840 : i++;
589 6840 : continue;
590 : }
591 :
592 351 : new_ace_list_ndx--;
593 351 : remaining = new_ace_list_ndx - i;
594 351 : if (remaining == 0) {
595 0 : ZERO_STRUCT(new_ace_list[i]);
596 0 : continue;
597 : }
598 351 : memmove(&new_ace_list[i], &new_ace_list[i+1],
599 : sizeof(new_ace_list[i]) * remaining);
600 : }
601 :
602 : /* Create child security descriptor to return */
603 1321 : if (new_ace_list_ndx) {
604 1321 : new_dacl = make_sec_acl(ctx,
605 : NT4_ACL_REVISION,
606 : new_ace_list_ndx,
607 : new_ace_list);
608 :
609 1321 : if (!new_dacl) {
610 0 : return NT_STATUS_NO_MEMORY;
611 : }
612 : }
613 :
614 1321 : *ppsd = make_sec_desc(ctx,
615 : SECURITY_DESCRIPTOR_REVISION_1,
616 : SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
617 : (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
618 : owner_sid,
619 : group_sid,
620 : NULL,
621 : new_dacl,
622 : psize);
623 1321 : if (!*ppsd) {
624 0 : return NT_STATUS_NO_MEMORY;
625 : }
626 1321 : return NT_STATUS_OK;
627 : }
|