/src/samba/libcli/security/create_descriptor.c
Line | Count | Source |
1 | | /* |
2 | | Copyright (C) Nadezhda Ivanova 2009 |
3 | | |
4 | | This program is free software; you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation; either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | This program is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | |
18 | | /* |
19 | | * Name: create_descriptor |
20 | | * |
21 | | * Component: routines for calculating and creating security descriptors |
22 | | * as described in MS-DTYP 2.5.3.x |
23 | | * |
24 | | * Description: |
25 | | * |
26 | | * |
27 | | * Author: Nadezhda Ivanova |
28 | | */ |
29 | | #include "replace.h" |
30 | | #include "lib/util/debug.h" |
31 | | #include "libcli/security/security.h" |
32 | | #include "librpc/gen_ndr/ndr_security.h" |
33 | | |
34 | | /* Todos: |
35 | | * build the security token dacl as follows: |
36 | | * SYSTEM: GA, OWNER: GA, LOGIN_SID:GW|GE |
37 | | * Need session id information for the login SID. Probably |
38 | | * the best place for this is during token creation |
39 | | * |
40 | | * Implement SD Invariants |
41 | | * ACE sorting rules |
42 | | * LDAP_SERVER_SD_FLAGS_OID control |
43 | | * ADTS 7.1.3.3 needs to be clarified |
44 | | */ |
45 | | |
46 | | /* the mapping function for generic rights for DS.(GA,GR,GW,GX) |
47 | | * The mapping function is passed as an argument to the |
48 | | * descriptor calculating routine and depends on the security |
49 | | * manager that calls the calculating routine. |
50 | | * TODO: need similar mappings for the file system and |
51 | | * registry security managers in order to make this code |
52 | | * generic for all security managers |
53 | | */ |
54 | | |
55 | | uint32_t map_generic_rights_ds(uint32_t access_mask) |
56 | 0 | { |
57 | 0 | if (access_mask & SEC_GENERIC_ALL) { |
58 | 0 | access_mask |= SEC_ADS_GENERIC_ALL; |
59 | 0 | access_mask &= ~SEC_GENERIC_ALL; |
60 | 0 | } |
61 | |
|
62 | 0 | if (access_mask & SEC_GENERIC_EXECUTE) { |
63 | 0 | access_mask |= SEC_ADS_GENERIC_EXECUTE; |
64 | 0 | access_mask &= ~SEC_GENERIC_EXECUTE; |
65 | 0 | } |
66 | |
|
67 | 0 | if (access_mask & SEC_GENERIC_WRITE) { |
68 | 0 | access_mask |= SEC_ADS_GENERIC_WRITE; |
69 | 0 | access_mask &= ~SEC_GENERIC_WRITE; |
70 | 0 | } |
71 | |
|
72 | 0 | if (access_mask & SEC_GENERIC_READ) { |
73 | 0 | access_mask |= SEC_ADS_GENERIC_READ; |
74 | 0 | access_mask &= ~SEC_GENERIC_READ; |
75 | 0 | } |
76 | |
|
77 | 0 | return access_mask; |
78 | 0 | } |
79 | | |
80 | | /* Not sure what this has to be, |
81 | | * and it does not seem to have any influence */ |
82 | | static bool object_in_list(const struct GUID *object_list, const struct GUID *object) |
83 | 0 | { |
84 | 0 | size_t i; |
85 | |
|
86 | 0 | if (object_list == NULL) { |
87 | 0 | return true; |
88 | 0 | } |
89 | | |
90 | 0 | if (GUID_all_zero(object)) { |
91 | 0 | return true; |
92 | 0 | } |
93 | | |
94 | 0 | for (i=0; ; i++) { |
95 | 0 | if (GUID_all_zero(&object_list[i])) { |
96 | 0 | return false; |
97 | 0 | } |
98 | 0 | if (!GUID_equal(&object_list[i], object)) { |
99 | 0 | continue; |
100 | 0 | } |
101 | | |
102 | 0 | return true; |
103 | 0 | } |
104 | | |
105 | 0 | return false; |
106 | 0 | } |
107 | | |
108 | | /* returns true if the ACE contains generic information |
109 | | * that needs to be processed additionally */ |
110 | | |
111 | | static bool desc_ace_has_generic(const struct security_ace *ace) |
112 | 0 | { |
113 | 0 | if (ace->access_mask & SEC_GENERIC_ALL || ace->access_mask & SEC_GENERIC_READ || |
114 | 0 | ace->access_mask & SEC_GENERIC_WRITE || ace->access_mask & SEC_GENERIC_EXECUTE) { |
115 | 0 | return true; |
116 | 0 | } |
117 | 0 | if (dom_sid_equal(&ace->trustee, &global_sid_Creator_Owner) || |
118 | 0 | dom_sid_equal(&ace->trustee, &global_sid_Creator_Group)) { |
119 | 0 | return true; |
120 | 0 | } |
121 | 0 | return false; |
122 | 0 | } |
123 | | |
124 | | /* creates an ace in which the generic information is expanded */ |
125 | | |
126 | | static void desc_expand_generic(struct security_ace *new_ace, |
127 | | const struct dom_sid *owner, |
128 | | const struct dom_sid *group) |
129 | 0 | { |
130 | 0 | new_ace->access_mask = map_generic_rights_ds(new_ace->access_mask); |
131 | 0 | if (dom_sid_equal(&new_ace->trustee, &global_sid_Creator_Owner)) { |
132 | 0 | new_ace->trustee = *owner; |
133 | 0 | } |
134 | 0 | if (dom_sid_equal(&new_ace->trustee, &global_sid_Creator_Group)) { |
135 | 0 | new_ace->trustee = *group; |
136 | 0 | } |
137 | 0 | new_ace->flags = 0x0; |
138 | 0 | } |
139 | | |
140 | | static struct security_acl *calculate_inherited_from_parent( |
141 | | TALLOC_CTX *mem_ctx, |
142 | | struct security_acl *acl, |
143 | | bool is_container, |
144 | | const struct dom_sid *owner, |
145 | | const struct dom_sid *group, |
146 | | struct GUID *object_list) |
147 | 0 | { |
148 | 0 | uint32_t i; |
149 | 0 | struct security_acl *tmp_acl = NULL; |
150 | |
|
151 | 0 | if (!acl) { |
152 | 0 | return NULL; |
153 | 0 | } |
154 | 0 | tmp_acl = talloc_zero(mem_ctx, struct security_acl); |
155 | 0 | if (!tmp_acl) { |
156 | 0 | return NULL; |
157 | 0 | } |
158 | | |
159 | 0 | for (i=0; i < acl->num_aces; i++) { |
160 | 0 | const struct security_ace *ace = &acl->aces[i]; |
161 | 0 | const struct GUID *inherited_object = NULL; |
162 | 0 | const struct GUID *inherited_property = NULL; |
163 | 0 | struct security_ace *tmp_ace = NULL; |
164 | 0 | bool applies = false; |
165 | 0 | bool inherited_only = false; |
166 | 0 | bool expand_ace = false; |
167 | 0 | bool expand_only = false; |
168 | |
|
169 | 0 | if (is_container && (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) { |
170 | 0 | applies = true; |
171 | 0 | } else if (!is_container && (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) { |
172 | 0 | applies = true; |
173 | 0 | } |
174 | |
|
175 | 0 | if (!applies) { |
176 | | /* |
177 | | * If the ace doesn't apply to the |
178 | | * current node, we should only keep |
179 | | * it as SEC_ACE_FLAG_OBJECT_INHERIT |
180 | | * on a container. We'll add |
181 | | * SEC_ACE_FLAG_INHERITED_ACE |
182 | | * and SEC_ACE_FLAG_INHERIT_ONLY below. |
183 | | * |
184 | | * Otherwise we should completely ignore it. |
185 | | */ |
186 | 0 | if (!(ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) { |
187 | 0 | continue; |
188 | 0 | } |
189 | 0 | } |
190 | | |
191 | 0 | switch (ace->type) { |
192 | 0 | case SEC_ACE_TYPE_ACCESS_ALLOWED: |
193 | 0 | case SEC_ACE_TYPE_ACCESS_DENIED: |
194 | 0 | case SEC_ACE_TYPE_SYSTEM_AUDIT: |
195 | 0 | case SEC_ACE_TYPE_SYSTEM_ALARM: |
196 | 0 | case SEC_ACE_TYPE_ALLOWED_COMPOUND: |
197 | 0 | break; |
198 | | |
199 | 0 | case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: |
200 | 0 | case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: |
201 | 0 | case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: |
202 | 0 | case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: |
203 | 0 | case SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT: |
204 | 0 | case SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT: |
205 | 0 | case SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT: |
206 | 0 | if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) { |
207 | 0 | inherited_property = &ace->object.object.type.type; |
208 | 0 | } |
209 | 0 | if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) { |
210 | 0 | inherited_object = &ace->object.object.inherited_type.inherited_type; |
211 | 0 | } |
212 | |
|
213 | 0 | if (inherited_object != NULL && !object_in_list(object_list, inherited_object)) { |
214 | | /* |
215 | | * An explicit object class schemaId is given, |
216 | | * but doesn't belong to the current object. |
217 | | */ |
218 | 0 | applies = false; |
219 | 0 | } |
220 | |
|
221 | 0 | break; |
222 | | |
223 | 0 | case SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK: |
224 | 0 | case SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK: |
225 | 0 | case SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK: |
226 | 0 | break; |
227 | 0 | case SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE: |
228 | 0 | break; |
229 | 0 | case SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK: |
230 | 0 | case SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT: |
231 | 0 | case SEC_ACE_TYPE_SYSTEM_MANDATORY_LABEL: |
232 | 0 | case SEC_ACE_TYPE_SYSTEM_SCOPED_POLICY_ID: |
233 | 0 | default: |
234 | 0 | DBG_WARNING("ACE type %d is not handled\n", ace->type); |
235 | 0 | TALLOC_FREE(tmp_acl); |
236 | 0 | return NULL; |
237 | 0 | } |
238 | | |
239 | 0 | if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { |
240 | 0 | if (!applies) { |
241 | | /* |
242 | | * If the ACE doesn't apply to |
243 | | * the current object, we should |
244 | | * ignore it as it should not be |
245 | | * inherited any further |
246 | | */ |
247 | 0 | continue; |
248 | 0 | } |
249 | | /* |
250 | | * We should only keep the expanded version |
251 | | * of the ACE on the current object. |
252 | | */ |
253 | 0 | expand_ace = true; |
254 | 0 | expand_only = true; |
255 | 0 | } else if (applies) { |
256 | | /* |
257 | | * We check if should also add |
258 | | * the expanded version of the ACE |
259 | | * in addition, in case we should |
260 | | * expand generic access bits or |
261 | | * special sids. |
262 | | * |
263 | | * In that case we need to |
264 | | * keep the original ACE with |
265 | | * SEC_ACE_FLAG_INHERIT_ONLY. |
266 | | */ |
267 | 0 | expand_ace = desc_ace_has_generic(ace); |
268 | 0 | if (expand_ace) { |
269 | 0 | inherited_only = true; |
270 | 0 | } |
271 | 0 | } else { |
272 | | /* |
273 | | * If the ACE doesn't apply |
274 | | * to the current object, |
275 | | * we need to keep it with |
276 | | * SEC_ACE_FLAG_INHERIT_ONLY |
277 | | * in order to apply them to |
278 | | * grandchildren |
279 | | */ |
280 | 0 | inherited_only = true; |
281 | 0 | } |
282 | | |
283 | 0 | if (expand_ace) { |
284 | 0 | tmp_acl->aces = talloc_realloc(tmp_acl, |
285 | 0 | tmp_acl->aces, |
286 | 0 | struct security_ace, |
287 | 0 | tmp_acl->num_aces+1); |
288 | 0 | if (tmp_acl->aces == NULL) { |
289 | 0 | TALLOC_FREE(tmp_acl); |
290 | 0 | return NULL; |
291 | 0 | } |
292 | | |
293 | 0 | tmp_ace = &tmp_acl->aces[tmp_acl->num_aces]; |
294 | 0 | tmp_acl->num_aces++; |
295 | |
|
296 | 0 | *tmp_ace = *ace; |
297 | | |
298 | | /* |
299 | | * Expand generic access bits as well as special |
300 | | * sids. |
301 | | */ |
302 | 0 | desc_expand_generic(tmp_ace, owner, group); |
303 | | |
304 | | /* |
305 | | * Expanded ACEs are marked as inherited, |
306 | | * but never inherited any further to |
307 | | * grandchildren. |
308 | | */ |
309 | 0 | tmp_ace->flags |= SEC_ACE_FLAG_INHERITED_ACE; |
310 | 0 | tmp_ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT; |
311 | 0 | tmp_ace->flags &= ~SEC_ACE_FLAG_OBJECT_INHERIT; |
312 | 0 | tmp_ace->flags &= ~SEC_ACE_FLAG_NO_PROPAGATE_INHERIT; |
313 | | |
314 | | /* |
315 | | * Expanded ACEs never have an explicit |
316 | | * object class schemaId, so clear it |
317 | | * if present. |
318 | | */ |
319 | 0 | if (inherited_object != NULL) { |
320 | 0 | tmp_ace->object.object.flags &= ~SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT; |
321 | 0 | } |
322 | | |
323 | | /* |
324 | | * If the ACE had an explicit object class |
325 | | * schemaId, but no attribute/propertySet |
326 | | * we need to downgrade the _OBJECT variants |
327 | | * to the normal ones. |
328 | | */ |
329 | 0 | if (inherited_property == NULL) { |
330 | 0 | switch (tmp_ace->type) { |
331 | 0 | case SEC_ACE_TYPE_ACCESS_ALLOWED: |
332 | 0 | case SEC_ACE_TYPE_ACCESS_DENIED: |
333 | 0 | case SEC_ACE_TYPE_SYSTEM_AUDIT: |
334 | 0 | case SEC_ACE_TYPE_SYSTEM_ALARM: |
335 | 0 | case SEC_ACE_TYPE_ALLOWED_COMPOUND: |
336 | 0 | break; |
337 | 0 | case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: |
338 | 0 | tmp_ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED; |
339 | 0 | break; |
340 | 0 | case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: |
341 | 0 | tmp_ace->type = SEC_ACE_TYPE_ACCESS_DENIED; |
342 | 0 | break; |
343 | 0 | case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: |
344 | 0 | tmp_ace->type = SEC_ACE_TYPE_SYSTEM_ALARM; |
345 | 0 | break; |
346 | 0 | case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: |
347 | 0 | tmp_ace->type = SEC_ACE_TYPE_SYSTEM_AUDIT; |
348 | 0 | break; |
349 | 0 | case SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT: |
350 | 0 | tmp_ace->type = SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK; |
351 | 0 | break; |
352 | 0 | case SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT: |
353 | 0 | tmp_ace->type = SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK; |
354 | 0 | break; |
355 | 0 | case SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT: |
356 | 0 | tmp_ace->type = SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK; |
357 | 0 | break; |
358 | 0 | default: |
359 | | /* |
360 | | * SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT |
361 | | * is reserved. |
362 | | */ |
363 | 0 | break; |
364 | 0 | } |
365 | 0 | } |
366 | | |
367 | 0 | if (expand_only) { |
368 | 0 | continue; |
369 | 0 | } |
370 | 0 | } |
371 | | |
372 | 0 | tmp_acl->aces = talloc_realloc(tmp_acl, |
373 | 0 | tmp_acl->aces, |
374 | 0 | struct security_ace, |
375 | 0 | tmp_acl->num_aces+1); |
376 | 0 | if (tmp_acl->aces == NULL) { |
377 | 0 | TALLOC_FREE(tmp_acl); |
378 | 0 | return NULL; |
379 | 0 | } |
380 | | |
381 | 0 | tmp_ace = &tmp_acl->aces[tmp_acl->num_aces]; |
382 | 0 | tmp_acl->num_aces++; |
383 | |
|
384 | 0 | *tmp_ace = *ace; |
385 | 0 | tmp_ace->flags |= SEC_ACE_FLAG_INHERITED_ACE; |
386 | |
|
387 | 0 | if (inherited_only) { |
388 | 0 | tmp_ace->flags |= SEC_ACE_FLAG_INHERIT_ONLY; |
389 | 0 | } else { |
390 | 0 | tmp_ace->flags &= ~SEC_ACE_FLAG_INHERIT_ONLY; |
391 | 0 | } |
392 | |
|
393 | 0 | if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { |
394 | 0 | tmp_ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT; |
395 | 0 | tmp_ace->flags &= ~SEC_ACE_FLAG_OBJECT_INHERIT; |
396 | 0 | tmp_ace->flags &= ~SEC_ACE_FLAG_NO_PROPAGATE_INHERIT; |
397 | 0 | } |
398 | 0 | } |
399 | 0 | if (tmp_acl->num_aces == 0) { |
400 | 0 | TALLOC_FREE(tmp_acl); |
401 | 0 | return NULL; |
402 | 0 | } |
403 | 0 | if (acl) { |
404 | 0 | tmp_acl->revision = acl->revision; |
405 | 0 | } |
406 | 0 | return tmp_acl; |
407 | 0 | } |
408 | | |
409 | | static struct security_acl *process_user_acl(TALLOC_CTX *mem_ctx, |
410 | | struct security_acl *acl, |
411 | | bool is_container, |
412 | | const struct dom_sid *owner, |
413 | | const struct dom_sid *group, |
414 | | struct GUID *object_list, |
415 | | bool is_protected) |
416 | 0 | { |
417 | 0 | uint32_t i; |
418 | 0 | TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); |
419 | 0 | struct security_acl *tmp_acl = talloc_zero(tmp_ctx, struct security_acl); |
420 | 0 | struct security_acl *new_acl; |
421 | |
|
422 | 0 | if (!acl) |
423 | 0 | return NULL; |
424 | | |
425 | 0 | if (!tmp_acl) |
426 | 0 | return NULL; |
427 | | |
428 | 0 | tmp_acl->revision = acl->revision; |
429 | 0 | DBG_DEBUG("acl revision %d\n", acl->revision); |
430 | |
|
431 | 0 | for (i=0; i < acl->num_aces; i++){ |
432 | 0 | struct security_ace *ace = &acl->aces[i]; |
433 | | /* Remove ID flags from user-provided ACEs |
434 | | * if we break inheritance, ignore them otherwise */ |
435 | 0 | if (ace->flags & SEC_ACE_FLAG_INHERITED_ACE) { |
436 | 0 | if (is_protected) { |
437 | 0 | ace->flags &= ~SEC_ACE_FLAG_INHERITED_ACE; |
438 | 0 | } else { |
439 | 0 | continue; |
440 | 0 | } |
441 | 0 | } |
442 | | |
443 | 0 | if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY && |
444 | 0 | !(ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT || |
445 | 0 | ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) |
446 | 0 | continue; |
447 | | |
448 | 0 | tmp_acl->aces = talloc_realloc(tmp_acl, |
449 | 0 | tmp_acl->aces, |
450 | 0 | struct security_ace, |
451 | 0 | tmp_acl->num_aces+1); |
452 | 0 | tmp_acl->aces[tmp_acl->num_aces] = *ace; |
453 | 0 | tmp_acl->num_aces++; |
454 | 0 | if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { |
455 | 0 | continue; |
456 | 0 | } |
457 | | /* if the ACE contains CO, CG, GA, GE, GR or GW, and is inheritable |
458 | | * it has to be expanded to two aces, the original as IO, |
459 | | * and another one where these are translated */ |
460 | 0 | if (desc_ace_has_generic(ace)) { |
461 | 0 | if (!(ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) { |
462 | 0 | desc_expand_generic(&tmp_acl->aces[tmp_acl->num_aces-1], |
463 | 0 | owner, |
464 | 0 | group); |
465 | 0 | } else { |
466 | | /*The original ACE becomes read only */ |
467 | 0 | tmp_acl->aces[tmp_acl->num_aces-1].flags |= SEC_ACE_FLAG_INHERIT_ONLY; |
468 | 0 | tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, |
469 | 0 | struct security_ace, |
470 | 0 | tmp_acl->num_aces+1); |
471 | | /* add a new ACE with expanded generic info */ |
472 | 0 | tmp_acl->aces[tmp_acl->num_aces] = *ace; |
473 | 0 | desc_expand_generic(&tmp_acl->aces[tmp_acl->num_aces], |
474 | 0 | owner, |
475 | 0 | group); |
476 | 0 | tmp_acl->num_aces++; |
477 | 0 | } |
478 | 0 | } |
479 | 0 | } |
480 | 0 | new_acl = security_acl_dup(mem_ctx,tmp_acl); |
481 | |
|
482 | 0 | if (new_acl) |
483 | 0 | new_acl->revision = acl->revision; |
484 | |
|
485 | 0 | talloc_free(tmp_ctx); |
486 | 0 | return new_acl; |
487 | 0 | } |
488 | | |
489 | | static void cr_descr_log_descriptor(struct security_descriptor *sd, |
490 | | const char *message, |
491 | | int level) |
492 | 0 | { |
493 | 0 | if (sd) { |
494 | 0 | DEBUG(level,("%s: %s\n", message, |
495 | 0 | ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_descriptor, |
496 | 0 | "", sd))); |
497 | 0 | } |
498 | 0 | else { |
499 | 0 | DEBUG(level,("%s: NULL\n", message)); |
500 | 0 | } |
501 | 0 | } |
502 | | |
503 | | #if 0 |
504 | | static void cr_descr_log_acl(struct security_acl *acl, |
505 | | const char *message, |
506 | | int level) |
507 | | { |
508 | | if (acl) { |
509 | | DEBUG(level,("%s: %s\n", message, |
510 | | ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_acl, |
511 | | "", acl))); |
512 | | } |
513 | | else { |
514 | | DEBUG(level,("%s: NULL\n", message)); |
515 | | } |
516 | | } |
517 | | #endif |
518 | | |
519 | | static bool compute_acl(struct security_descriptor *parent_sd, |
520 | | struct security_descriptor *creator_sd, |
521 | | bool is_container, |
522 | | uint32_t inherit_flags, |
523 | | struct GUID *object_list, |
524 | | uint32_t (*generic_map)(uint32_t access_mask), |
525 | | struct security_token *token, |
526 | | struct security_descriptor *new_sd) /* INOUT argument */ |
527 | 0 | { |
528 | 0 | struct security_acl *user_dacl, *user_sacl, *inherited_dacl, *inherited_sacl; |
529 | 0 | int level = 10; |
530 | |
|
531 | 0 | if (!parent_sd || !(inherit_flags & SEC_DACL_AUTO_INHERIT)) { |
532 | 0 | inherited_dacl = NULL; |
533 | 0 | } else if (creator_sd && (creator_sd->type & SEC_DESC_DACL_PROTECTED)) { |
534 | 0 | inherited_dacl = NULL; |
535 | 0 | } else { |
536 | 0 | inherited_dacl = calculate_inherited_from_parent(new_sd, |
537 | 0 | parent_sd->dacl, |
538 | 0 | is_container, |
539 | 0 | new_sd->owner_sid, |
540 | 0 | new_sd->group_sid, |
541 | 0 | object_list); |
542 | 0 | } |
543 | | |
544 | |
|
545 | 0 | if (!parent_sd || !(inherit_flags & SEC_SACL_AUTO_INHERIT)) { |
546 | 0 | inherited_sacl = NULL; |
547 | 0 | } else if (creator_sd && (creator_sd->type & SEC_DESC_SACL_PROTECTED)) { |
548 | 0 | inherited_sacl = NULL; |
549 | 0 | } else { |
550 | 0 | inherited_sacl = calculate_inherited_from_parent(new_sd, |
551 | 0 | parent_sd->sacl, |
552 | 0 | is_container, |
553 | 0 | new_sd->owner_sid, |
554 | 0 | new_sd->group_sid, |
555 | 0 | object_list); |
556 | 0 | } |
557 | |
|
558 | 0 | if (!creator_sd || (inherit_flags & SEC_DEFAULT_DESCRIPTOR)) { |
559 | 0 | user_dacl = NULL; |
560 | 0 | user_sacl = NULL; |
561 | 0 | } else { |
562 | 0 | user_dacl = process_user_acl(new_sd, |
563 | 0 | creator_sd->dacl, |
564 | 0 | is_container, |
565 | 0 | new_sd->owner_sid, |
566 | 0 | new_sd->group_sid, |
567 | 0 | object_list, |
568 | 0 | creator_sd->type & SEC_DESC_DACL_PROTECTED); |
569 | 0 | user_sacl = process_user_acl(new_sd, |
570 | 0 | creator_sd->sacl, |
571 | 0 | is_container, |
572 | 0 | new_sd->owner_sid, |
573 | 0 | new_sd->group_sid, |
574 | 0 | object_list, |
575 | 0 | creator_sd->type & SEC_DESC_SACL_PROTECTED); |
576 | 0 | } |
577 | 0 | cr_descr_log_descriptor(parent_sd, __location__"parent_sd", level); |
578 | 0 | cr_descr_log_descriptor(creator_sd,__location__ "creator_sd", level); |
579 | |
|
580 | 0 | new_sd->dacl = security_acl_concatenate(new_sd, user_dacl, inherited_dacl); |
581 | 0 | if (new_sd->dacl) { |
582 | 0 | new_sd->type |= SEC_DESC_DACL_PRESENT; |
583 | 0 | } |
584 | 0 | if (inherited_dacl) { |
585 | 0 | new_sd->type |= SEC_DESC_DACL_AUTO_INHERITED; |
586 | 0 | } |
587 | |
|
588 | 0 | new_sd->sacl = security_acl_concatenate(new_sd, user_sacl, inherited_sacl); |
589 | 0 | if (new_sd->sacl) { |
590 | 0 | new_sd->type |= SEC_DESC_SACL_PRESENT; |
591 | 0 | } |
592 | 0 | if (inherited_sacl) { |
593 | 0 | new_sd->type |= SEC_DESC_SACL_AUTO_INHERITED; |
594 | 0 | } |
595 | | /* This is a hack to handle the fact that |
596 | | * apprantly any AI flag provided by the user is preserved */ |
597 | 0 | if (creator_sd) |
598 | 0 | new_sd->type |= creator_sd->type; |
599 | 0 | cr_descr_log_descriptor(new_sd, __location__"final sd", level); |
600 | 0 | return true; |
601 | 0 | } |
602 | | |
603 | | struct security_descriptor *create_security_descriptor( |
604 | | TALLOC_CTX *mem_ctx, |
605 | | struct security_descriptor *parent_sd, |
606 | | struct security_descriptor *creator_sd, |
607 | | bool is_container, |
608 | | struct GUID *object_list, |
609 | | uint32_t inherit_flags, |
610 | | struct security_token *token, |
611 | | const struct dom_sid |
612 | | *default_owner, /* valid only for DS, NULL for the other RSs */ |
613 | | const struct dom_sid |
614 | | *default_group, /* valid only for DS, NULL for the other RSs */ |
615 | | uint32_t (*generic_map)(uint32_t access_mask)) |
616 | 0 | { |
617 | 0 | struct security_descriptor *new_sd; |
618 | 0 | const struct dom_sid *new_owner = NULL; |
619 | 0 | const struct dom_sid *new_group = NULL; |
620 | |
|
621 | 0 | new_sd = security_descriptor_initialise(mem_ctx); |
622 | 0 | if (!new_sd) { |
623 | 0 | return NULL; |
624 | 0 | } |
625 | | |
626 | 0 | if (!creator_sd || !creator_sd->owner_sid) { |
627 | 0 | if ((inherit_flags & SEC_OWNER_FROM_PARENT) && parent_sd) { |
628 | 0 | new_owner = parent_sd->owner_sid; |
629 | 0 | } else if (!default_owner) { |
630 | 0 | new_owner = &token->sids[PRIMARY_USER_SID_INDEX]; |
631 | 0 | } else { |
632 | 0 | new_owner = default_owner; |
633 | 0 | new_sd->type |= SEC_DESC_OWNER_DEFAULTED; |
634 | 0 | } |
635 | 0 | } else { |
636 | 0 | new_owner = creator_sd->owner_sid; |
637 | 0 | } |
638 | |
|
639 | 0 | if (!creator_sd || !creator_sd->group_sid){ |
640 | 0 | if ((inherit_flags & SEC_GROUP_FROM_PARENT) && parent_sd) { |
641 | 0 | new_group = parent_sd->group_sid; |
642 | 0 | } else if (!default_group && token->num_sids > PRIMARY_GROUP_SID_INDEX) { |
643 | 0 | new_group = &token->sids[PRIMARY_GROUP_SID_INDEX]; |
644 | 0 | } else if (!default_group) { |
645 | | /* This will happen only for anonymous, which has no other groups */ |
646 | 0 | new_group = &token->sids[PRIMARY_USER_SID_INDEX]; |
647 | 0 | } else { |
648 | 0 | new_group = default_group; |
649 | 0 | new_sd->type |= SEC_DESC_GROUP_DEFAULTED; |
650 | 0 | } |
651 | 0 | } else { |
652 | 0 | new_group = creator_sd->group_sid; |
653 | 0 | } |
654 | |
|
655 | 0 | new_sd->owner_sid = dom_sid_dup(new_sd, new_owner); |
656 | 0 | new_sd->group_sid = dom_sid_dup(new_sd, new_group); |
657 | 0 | if (!new_sd->owner_sid || !new_sd->group_sid){ |
658 | 0 | talloc_free(new_sd); |
659 | 0 | return NULL; |
660 | 0 | } |
661 | | |
662 | 0 | if (!compute_acl(parent_sd, creator_sd, |
663 | 0 | is_container, inherit_flags, object_list, |
664 | 0 | generic_map,token,new_sd)){ |
665 | 0 | talloc_free(new_sd); |
666 | 0 | return NULL; |
667 | 0 | } |
668 | | |
669 | 0 | return new_sd; |
670 | 0 | } |