/src/samba/libcli/security/secdesc.c
Line | Count | Source |
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 | | uint32_t get_sec_info(const struct security_descriptor *sd) |
43 | 0 | { |
44 | 0 | uint32_t sec_info = 0; |
45 | |
|
46 | 0 | SMB_ASSERT(sd); |
47 | | |
48 | 0 | if (sd->owner_sid != NULL) { |
49 | 0 | sec_info |= SECINFO_OWNER; |
50 | 0 | } |
51 | 0 | if (sd->group_sid != NULL) { |
52 | 0 | sec_info |= SECINFO_GROUP; |
53 | 0 | } |
54 | 0 | if (sd->sacl != NULL) { |
55 | 0 | sec_info |= SECINFO_SACL; |
56 | 0 | } |
57 | 0 | if (sd->dacl != NULL) { |
58 | 0 | sec_info |= SECINFO_DACL; |
59 | 0 | } |
60 | |
|
61 | 0 | if (sd->type & SEC_DESC_SACL_PROTECTED) { |
62 | 0 | sec_info |= SECINFO_PROTECTED_SACL; |
63 | 0 | } else if (sd->type & SEC_DESC_SACL_AUTO_INHERITED) { |
64 | 0 | sec_info |= SECINFO_UNPROTECTED_SACL; |
65 | 0 | } |
66 | 0 | if (sd->type & SEC_DESC_DACL_PROTECTED) { |
67 | 0 | sec_info |= SECINFO_PROTECTED_DACL; |
68 | 0 | } else if (sd->type & SEC_DESC_DACL_AUTO_INHERITED) { |
69 | 0 | sec_info |= SECINFO_UNPROTECTED_DACL; |
70 | 0 | } |
71 | |
|
72 | 0 | return sec_info; |
73 | 0 | } |
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 | | struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb) |
82 | 0 | { |
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 | 0 | } else { |
113 | 0 | dacl = old_sdb->sd->dacl; |
114 | 0 | } |
115 | | |
116 | | /* Create new security descriptor from bits */ |
117 | |
|
118 | 0 | psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type, |
119 | 0 | 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 | 0 | } |
125 | | |
126 | | struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb) |
127 | 0 | { |
128 | 0 | struct dom_sid *owner_sid, *group_sid; |
129 | 0 | struct security_acl *dacl, *sacl; |
130 | 0 | 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 | 0 | owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid : |
138 | 0 | old_sdb->owner_sid; |
139 | |
|
140 | 0 | group_sid = new_sdb->group_sid ? new_sdb->group_sid : |
141 | 0 | old_sdb->group_sid; |
142 | |
|
143 | 0 | 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 | 0 | sacl = NULL; |
150 | 0 | secdesc_type &= ~SEC_DESC_SACL_PRESENT; |
151 | | |
152 | | /* Copy across discretionary ACL */ |
153 | |
|
154 | 0 | if (secdesc_type & SEC_DESC_DACL_PRESENT) { |
155 | 0 | dacl = new_sdb->dacl; |
156 | 0 | } else { |
157 | 0 | dacl = old_sdb->dacl; |
158 | 0 | } |
159 | | |
160 | | /* Create new security descriptor from bits */ |
161 | 0 | psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type, |
162 | 0 | owner_sid, group_sid, sacl, dacl, &secdesc_size); |
163 | |
|
164 | 0 | return psd; |
165 | 0 | } |
166 | | |
167 | | /******************************************************************* |
168 | | Creates a struct security_descriptor structure |
169 | | ********************************************************************/ |
170 | | 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 | 0 | { |
176 | 0 | struct security_descriptor *dst; |
177 | |
|
178 | 0 | if (sd_size != NULL) { |
179 | 0 | *sd_size = 0; |
180 | 0 | } |
181 | |
|
182 | 0 | dst = security_descriptor_initialise(ctx); |
183 | 0 | if (dst == NULL) { |
184 | 0 | return NULL; |
185 | 0 | } |
186 | | |
187 | 0 | dst->revision = revision; |
188 | 0 | dst->type = type; |
189 | |
|
190 | 0 | if (sacl != NULL) { |
191 | 0 | dst->sacl = security_acl_dup(dst, sacl); |
192 | 0 | if (dst->sacl == NULL) { |
193 | 0 | goto err_sd_free; |
194 | 0 | } |
195 | 0 | dst->type |= SEC_DESC_SACL_PRESENT; |
196 | 0 | } |
197 | | |
198 | 0 | if (dacl != NULL) { |
199 | 0 | dst->dacl = security_acl_dup(dst, dacl); |
200 | 0 | if (dst->dacl == NULL) { |
201 | 0 | goto err_sd_free; |
202 | 0 | } |
203 | 0 | dst->type |= SEC_DESC_DACL_PRESENT; |
204 | 0 | } |
205 | | |
206 | 0 | if (owner_sid != NULL) { |
207 | 0 | dst->owner_sid = dom_sid_dup(dst, owner_sid); |
208 | 0 | if (dst->owner_sid == NULL) { |
209 | 0 | goto err_sd_free; |
210 | 0 | } |
211 | 0 | } |
212 | | |
213 | 0 | if (grp_sid != NULL) { |
214 | 0 | dst->group_sid = dom_sid_dup(dst, grp_sid); |
215 | 0 | if (dst->group_sid == NULL) { |
216 | 0 | goto err_sd_free; |
217 | 0 | } |
218 | 0 | } |
219 | | |
220 | 0 | if (sd_size != NULL) { |
221 | 0 | *sd_size = ndr_size_security_descriptor(dst, 0); |
222 | 0 | } |
223 | |
|
224 | 0 | return dst; |
225 | | |
226 | 0 | err_sd_free: |
227 | 0 | talloc_free(dst); |
228 | 0 | return NULL; |
229 | 0 | } |
230 | | |
231 | | /******************************************************************* |
232 | | Convert a secdesc into a byte stream |
233 | | ********************************************************************/ |
234 | | NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx, |
235 | | const struct security_descriptor *secdesc, |
236 | | uint8_t **data, size_t *len) |
237 | 0 | { |
238 | 0 | DATA_BLOB blob; |
239 | 0 | enum ndr_err_code ndr_err; |
240 | |
|
241 | 0 | ndr_err = ndr_push_struct_blob( |
242 | 0 | &blob, mem_ctx, secdesc, |
243 | 0 | (ndr_push_flags_fn_t)ndr_push_security_descriptor); |
244 | |
|
245 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
246 | 0 | DEBUG(0, ("ndr_push_security_descriptor failed: %s\n", |
247 | 0 | ndr_errstr(ndr_err))); |
248 | 0 | return ndr_map_error2ntstatus(ndr_err); |
249 | 0 | } |
250 | | |
251 | 0 | *data = blob.data; |
252 | 0 | *len = blob.length; |
253 | 0 | return NT_STATUS_OK; |
254 | 0 | } |
255 | | |
256 | | /******************************************************************* |
257 | | Convert a secdesc_buf into a byte stream |
258 | | ********************************************************************/ |
259 | | |
260 | | 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 | 0 | { |
264 | 0 | DATA_BLOB blob; |
265 | 0 | enum ndr_err_code ndr_err; |
266 | |
|
267 | 0 | ndr_err = ndr_push_struct_blob( |
268 | 0 | &blob, mem_ctx, secdesc_buf, |
269 | 0 | (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 | 0 | ndr_errstr(ndr_err))); |
274 | 0 | return ndr_map_error2ntstatus(ndr_err); |
275 | 0 | } |
276 | | |
277 | 0 | *data = blob.data; |
278 | 0 | *len = blob.length; |
279 | 0 | return NT_STATUS_OK; |
280 | 0 | } |
281 | | |
282 | | /******************************************************************* |
283 | | Parse a byte stream into a secdesc |
284 | | ********************************************************************/ |
285 | | NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len, |
286 | | struct security_descriptor **psecdesc) |
287 | 1.35k | { |
288 | 1.35k | DATA_BLOB blob; |
289 | 1.35k | enum ndr_err_code ndr_err; |
290 | 1.35k | struct security_descriptor *result; |
291 | | |
292 | 1.35k | if ((data == NULL) || (len == 0)) { |
293 | 0 | return NT_STATUS_INVALID_PARAMETER; |
294 | 0 | } |
295 | | |
296 | 1.35k | result = talloc_zero(mem_ctx, struct security_descriptor); |
297 | 1.35k | if (result == NULL) { |
298 | 0 | return NT_STATUS_NO_MEMORY; |
299 | 0 | } |
300 | | |
301 | 1.35k | blob = data_blob_const(data, len); |
302 | | |
303 | 1.35k | ndr_err = ndr_pull_struct_blob(&blob, result, result, |
304 | 1.35k | (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); |
305 | | |
306 | 1.35k | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
307 | 1.19k | DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n", |
308 | 1.19k | ndr_errstr(ndr_err))); |
309 | 1.19k | TALLOC_FREE(result); |
310 | 1.19k | return ndr_map_error2ntstatus(ndr_err); |
311 | 1.19k | } |
312 | | |
313 | 159 | *psecdesc = result; |
314 | 159 | return NT_STATUS_OK; |
315 | 1.35k | } |
316 | | |
317 | | /******************************************************************* |
318 | | Parse a byte stream into a sec_desc_buf |
319 | | ********************************************************************/ |
320 | | |
321 | | NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len, |
322 | | struct sec_desc_buf **psecdesc_buf) |
323 | 0 | { |
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 | 0 | } |
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 | 0 | } |
336 | | |
337 | 0 | blob = data_blob_const(data, len); |
338 | |
|
339 | 0 | ndr_err = ndr_pull_struct_blob(&blob, result, result, |
340 | 0 | (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 | 0 | ndr_errstr(ndr_err))); |
345 | 0 | TALLOC_FREE(result); |
346 | 0 | return ndr_map_error2ntstatus(ndr_err); |
347 | 0 | } |
348 | | |
349 | 0 | *psecdesc_buf = result; |
350 | 0 | return NT_STATUS_OK; |
351 | 0 | } |
352 | | |
353 | | /******************************************************************* |
354 | | Creates a struct security_descriptor structure with typical defaults. |
355 | | ********************************************************************/ |
356 | | |
357 | | 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 | 0 | { |
360 | 0 | return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1, |
361 | 0 | SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL, |
362 | 0 | dacl, sd_size); |
363 | 0 | } |
364 | | |
365 | | /******************************************************************* |
366 | | Creates a struct sec_desc_buf structure. |
367 | | ********************************************************************/ |
368 | | |
369 | | struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc) |
370 | 0 | { |
371 | 0 | struct sec_desc_buf *dst; |
372 | |
|
373 | 0 | if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL) |
374 | 0 | return NULL; |
375 | | |
376 | | /* max buffer size (allocated size) */ |
377 | 0 | dst->sd_size = (uint32_t)len; |
378 | |
|
379 | 0 | if (sec_desc != NULL) { |
380 | 0 | dst->sd = security_descriptor_copy(ctx, sec_desc); |
381 | 0 | if (dst->sd == NULL) { |
382 | 0 | return NULL; |
383 | 0 | } |
384 | 0 | } |
385 | | |
386 | 0 | return dst; |
387 | 0 | } |
388 | | |
389 | | /* |
390 | | * Determine if an struct security_ace is inheritable |
391 | | */ |
392 | | |
393 | | static bool is_inheritable_ace(const struct security_ace *ace, |
394 | | bool container) |
395 | 0 | { |
396 | 0 | if (!container) { |
397 | 0 | return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0); |
398 | 0 | } |
399 | | |
400 | 0 | if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { |
401 | 0 | return true; |
402 | 0 | } |
403 | | |
404 | 0 | if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) && |
405 | 0 | !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) { |
406 | 0 | return true; |
407 | 0 | } |
408 | | |
409 | 0 | return false; |
410 | 0 | } |
411 | | |
412 | | /* |
413 | | * Does a security descriptor have any inheritable components for |
414 | | * the newly created type ? |
415 | | */ |
416 | | |
417 | | bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container) |
418 | 0 | { |
419 | 0 | unsigned int i; |
420 | 0 | const struct security_acl *the_acl = parent_ctr->dacl; |
421 | |
|
422 | 0 | if (the_acl == NULL) { |
423 | 0 | return false; |
424 | 0 | } |
425 | | |
426 | 0 | for (i = 0; i < the_acl->num_aces; i++) { |
427 | 0 | const struct security_ace *ace = &the_acl->aces[i]; |
428 | |
|
429 | 0 | if (is_inheritable_ace(ace, container)) { |
430 | 0 | return true; |
431 | 0 | } |
432 | 0 | } |
433 | 0 | return false; |
434 | 0 | } |
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 | | 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 | 0 | { |
448 | 0 | struct security_acl *new_dacl = NULL, *the_acl = NULL; |
449 | 0 | struct security_ace *new_ace_list = NULL; |
450 | 0 | unsigned int new_ace_list_ndx = 0, i; |
451 | 0 | bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED); |
452 | |
|
453 | 0 | *ppsd = NULL; |
454 | 0 | *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 | 0 | the_acl = parent_ctr->dacl; |
461 | |
|
462 | 0 | if (the_acl->num_aces) { |
463 | 0 | if (2*the_acl->num_aces < the_acl->num_aces) { |
464 | 0 | return NT_STATUS_NO_MEMORY; |
465 | 0 | } |
466 | | |
467 | 0 | if (!(new_ace_list = talloc_array(ctx, struct security_ace, |
468 | 0 | 2*the_acl->num_aces))) { |
469 | 0 | return NT_STATUS_NO_MEMORY; |
470 | 0 | } |
471 | 0 | } else { |
472 | 0 | new_ace_list = NULL; |
473 | 0 | } |
474 | | |
475 | 0 | for (i = 0; i < the_acl->num_aces; i++) { |
476 | 0 | const struct security_ace *ace = &the_acl->aces[i]; |
477 | 0 | struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx]; |
478 | 0 | const struct dom_sid *ptrustee = &ace->trustee; |
479 | 0 | const struct dom_sid *creator = NULL; |
480 | 0 | uint8_t new_flags = ace->flags; |
481 | 0 | struct dom_sid_buf sidbuf1, sidbuf2; |
482 | |
|
483 | 0 | if (!is_inheritable_ace(ace, container)) { |
484 | 0 | continue; |
485 | 0 | } |
486 | | |
487 | | /* see the RAW-ACLS inheritance test for details on these rules */ |
488 | 0 | if (!container) { |
489 | 0 | new_flags = 0; |
490 | 0 | } 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 | 0 | new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY |
501 | 0 | | SEC_ACE_FLAG_INHERITED_ACE); |
502 | |
|
503 | 0 | if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) { |
504 | 0 | new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; |
505 | 0 | } |
506 | 0 | if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { |
507 | 0 | new_flags = 0; |
508 | 0 | } |
509 | 0 | } |
510 | | |
511 | | /* The CREATOR sids are special when inherited */ |
512 | 0 | if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) { |
513 | 0 | creator = &global_sid_Creator_Owner; |
514 | 0 | ptrustee = owner_sid; |
515 | 0 | } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) { |
516 | 0 | creator = &global_sid_Creator_Group; |
517 | 0 | ptrustee = group_sid; |
518 | 0 | } |
519 | |
|
520 | 0 | if (creator && container && |
521 | 0 | (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) { |
522 | | |
523 | | /* First add the regular ACE entry. */ |
524 | 0 | init_sec_ace(new_ace, ptrustee, ace->type, |
525 | 0 | ace->access_mask, |
526 | 0 | set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0); |
527 | |
|
528 | 0 | DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x" |
529 | 0 | " inherited as %s:%d/0x%02x/0x%08x\n", |
530 | 0 | dom_sid_str_buf(&ace->trustee, &sidbuf1), |
531 | 0 | ace->type, ace->flags, ace->access_mask, |
532 | 0 | dom_sid_str_buf(&new_ace->trustee, &sidbuf2), |
533 | 0 | new_ace->type, new_ace->flags, |
534 | 0 | new_ace->access_mask)); |
535 | |
|
536 | 0 | new_ace_list_ndx++; |
537 | | |
538 | | /* Now add the extra creator ACE. */ |
539 | 0 | new_ace = &new_ace_list[new_ace_list_ndx]; |
540 | |
|
541 | 0 | ptrustee = creator; |
542 | 0 | new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; |
543 | |
|
544 | 0 | } else if (container && |
545 | 0 | !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) { |
546 | 0 | ptrustee = &ace->trustee; |
547 | 0 | } |
548 | |
|
549 | 0 | init_sec_ace(new_ace, ptrustee, ace->type, |
550 | 0 | ace->access_mask, new_flags | |
551 | 0 | (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0)); |
552 | |
|
553 | 0 | DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " |
554 | 0 | " inherited as %s:%d/0x%02x/0x%08x\n", |
555 | 0 | dom_sid_str_buf(&ace->trustee, &sidbuf1), |
556 | 0 | ace->type, ace->flags, ace->access_mask, |
557 | 0 | dom_sid_str_buf(&new_ace->trustee, &sidbuf2), |
558 | 0 | new_ace->type, new_ace->flags, |
559 | 0 | new_ace->access_mask)); |
560 | |
|
561 | 0 | new_ace_list_ndx++; |
562 | 0 | } |
563 | | |
564 | | /* |
565 | | * remove duplicates |
566 | | */ |
567 | 0 | for (i=1; i < new_ace_list_ndx;) { |
568 | 0 | struct security_ace *ai = &new_ace_list[i]; |
569 | 0 | unsigned int remaining, j; |
570 | 0 | bool remove_ace = false; |
571 | |
|
572 | 0 | for (j=0; j < i; j++) { |
573 | 0 | struct security_ace *aj = &new_ace_list[j]; |
574 | |
|
575 | 0 | if (!security_ace_equal(ai, aj)) { |
576 | 0 | continue; |
577 | 0 | } |
578 | | |
579 | 0 | remove_ace = true; |
580 | 0 | break; |
581 | 0 | } |
582 | |
|
583 | 0 | if (!remove_ace) { |
584 | 0 | i++; |
585 | 0 | continue; |
586 | 0 | } |
587 | | |
588 | 0 | new_ace_list_ndx--; |
589 | 0 | remaining = new_ace_list_ndx - i; |
590 | 0 | if (remaining == 0) { |
591 | 0 | ZERO_STRUCT(new_ace_list[i]); |
592 | 0 | continue; |
593 | 0 | } |
594 | 0 | memmove(&new_ace_list[i], &new_ace_list[i+1], |
595 | 0 | sizeof(new_ace_list[i]) * remaining); |
596 | 0 | } |
597 | | |
598 | | /* Create child security descriptor to return */ |
599 | 0 | if (new_ace_list_ndx) { |
600 | 0 | new_dacl = make_sec_acl(ctx, |
601 | 0 | NT4_ACL_REVISION, |
602 | 0 | new_ace_list_ndx, |
603 | 0 | new_ace_list); |
604 | |
|
605 | 0 | if (!new_dacl) { |
606 | 0 | return NT_STATUS_NO_MEMORY; |
607 | 0 | } |
608 | 0 | } |
609 | | |
610 | 0 | *ppsd = make_sec_desc(ctx, |
611 | 0 | SECURITY_DESCRIPTOR_REVISION_1, |
612 | 0 | SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT| |
613 | 0 | (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0), |
614 | 0 | owner_sid, |
615 | 0 | group_sid, |
616 | 0 | NULL, |
617 | 0 | new_dacl, |
618 | 0 | psize); |
619 | 0 | if (!*ppsd) { |
620 | 0 | return NT_STATUS_NO_MEMORY; |
621 | 0 | } |
622 | 0 | return NT_STATUS_OK; |
623 | 0 | } |