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