/src/samba/libcli/security/security_descriptor.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | |
4 | | security descriptor utility functions |
5 | | |
6 | | Copyright (C) Andrew Tridgell 2004 |
7 | | |
8 | | This program is free software; you can redistribute it and/or modify |
9 | | it under the terms of the GNU General Public License as published by |
10 | | the Free Software Foundation; either version 3 of the License, or |
11 | | (at your option) any later version. |
12 | | |
13 | | This program is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU General Public License for more details. |
17 | | |
18 | | You should have received a copy of the GNU General Public License |
19 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #include "replace.h" |
23 | | #include "libcli/security/security.h" |
24 | | #include "librpc/ndr/libndr.h" |
25 | | #include "librpc/gen_ndr/ndr_security.h" |
26 | | |
27 | | /* |
28 | | return a blank security descriptor (no owners, dacl or sacl) |
29 | | */ |
30 | | struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx) |
31 | 20.0k | { |
32 | 20.0k | struct security_descriptor *sd; |
33 | | |
34 | 20.0k | sd = talloc(mem_ctx, struct security_descriptor); |
35 | 20.0k | if (!sd) { |
36 | 0 | return NULL; |
37 | 0 | } |
38 | 20.0k | *sd = (struct security_descriptor){ |
39 | 20.0k | .revision = SD_REVISION, |
40 | | |
41 | | /* |
42 | | * we mark as self relative, even though it isn't |
43 | | * while it remains a pointer in memory because this |
44 | | * simplifies the ndr code later. All SDs that we |
45 | | * store/emit are in fact SELF_RELATIVE |
46 | | */ |
47 | 20.0k | .type = SEC_DESC_SELF_RELATIVE, |
48 | 20.0k | }; |
49 | | |
50 | 20.0k | return sd; |
51 | 20.0k | } |
52 | | |
53 | | struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, |
54 | | const struct security_acl *oacl) |
55 | 0 | { |
56 | 0 | struct security_acl *nacl; |
57 | 0 | enum ndr_err_code ndr_err; |
58 | |
|
59 | 0 | if (oacl == NULL) { |
60 | 0 | return NULL; |
61 | 0 | } |
62 | | |
63 | 0 | if (oacl->aces == NULL && oacl->num_aces > 0) { |
64 | 0 | return NULL; |
65 | 0 | } |
66 | | |
67 | 0 | nacl = talloc (mem_ctx, struct security_acl); |
68 | 0 | if (nacl == NULL) { |
69 | 0 | return NULL; |
70 | 0 | } |
71 | | |
72 | 0 | ndr_err = ndr_deepcopy_struct(security_acl, oacl, nacl, nacl); |
73 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
74 | 0 | goto failed; |
75 | 0 | } |
76 | | |
77 | 0 | return nacl; |
78 | | |
79 | 0 | failed: |
80 | 0 | talloc_free (nacl); |
81 | 0 | return NULL; |
82 | |
|
83 | 0 | } |
84 | | |
85 | | struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx, |
86 | | const struct security_acl *acl1, |
87 | | const struct security_acl *acl2) |
88 | 0 | { |
89 | 0 | struct security_acl *nacl; |
90 | 0 | uint32_t i; |
91 | |
|
92 | 0 | if (!acl1 && !acl2) |
93 | 0 | return NULL; |
94 | | |
95 | 0 | if (!acl1){ |
96 | 0 | nacl = security_acl_dup(mem_ctx, acl2); |
97 | 0 | return nacl; |
98 | 0 | } |
99 | | |
100 | 0 | if (!acl2){ |
101 | 0 | nacl = security_acl_dup(mem_ctx, acl1); |
102 | 0 | return nacl; |
103 | 0 | } |
104 | | |
105 | 0 | nacl = talloc (mem_ctx, struct security_acl); |
106 | 0 | if (nacl == NULL) { |
107 | 0 | return NULL; |
108 | 0 | } |
109 | | |
110 | 0 | nacl->revision = acl1->revision; |
111 | 0 | nacl->size = acl1->size + acl2->size; |
112 | 0 | nacl->num_aces = acl1->num_aces + acl2->num_aces; |
113 | |
|
114 | 0 | if (nacl->num_aces == 0) |
115 | 0 | return nacl; |
116 | | |
117 | 0 | nacl->aces = (struct security_ace *)talloc_array (mem_ctx, struct security_ace, acl1->num_aces+acl2->num_aces); |
118 | 0 | if ((nacl->aces == NULL) && (nacl->num_aces > 0)) { |
119 | 0 | goto failed; |
120 | 0 | } |
121 | | |
122 | 0 | for (i = 0; i < acl1->num_aces; i++) |
123 | 0 | nacl->aces[i] = acl1->aces[i]; |
124 | 0 | for (i = 0; i < acl2->num_aces; i++) |
125 | 0 | nacl->aces[i + acl1->num_aces] = acl2->aces[i]; |
126 | |
|
127 | 0 | return nacl; |
128 | | |
129 | 0 | failed: |
130 | 0 | talloc_free (nacl); |
131 | 0 | return NULL; |
132 | |
|
133 | 0 | } |
134 | | |
135 | | /* |
136 | | talloc and copy a security descriptor |
137 | | */ |
138 | | struct security_descriptor *security_descriptor_copy(TALLOC_CTX *mem_ctx, |
139 | | const struct security_descriptor *osd) |
140 | 0 | { |
141 | 0 | struct security_descriptor *nsd; |
142 | |
|
143 | 0 | nsd = talloc_zero(mem_ctx, struct security_descriptor); |
144 | 0 | if (!nsd) { |
145 | 0 | return NULL; |
146 | 0 | } |
147 | | |
148 | 0 | if (osd->owner_sid) { |
149 | 0 | nsd->owner_sid = dom_sid_dup(nsd, osd->owner_sid); |
150 | 0 | if (nsd->owner_sid == NULL) { |
151 | 0 | goto failed; |
152 | 0 | } |
153 | 0 | } |
154 | | |
155 | 0 | if (osd->group_sid) { |
156 | 0 | nsd->group_sid = dom_sid_dup(nsd, osd->group_sid); |
157 | 0 | if (nsd->group_sid == NULL) { |
158 | 0 | goto failed; |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | 0 | if (osd->sacl) { |
163 | 0 | nsd->sacl = security_acl_dup(nsd, osd->sacl); |
164 | 0 | if (nsd->sacl == NULL) { |
165 | 0 | goto failed; |
166 | 0 | } |
167 | 0 | } |
168 | | |
169 | 0 | if (osd->dacl) { |
170 | 0 | nsd->dacl = security_acl_dup(nsd, osd->dacl); |
171 | 0 | if (nsd->dacl == NULL) { |
172 | 0 | goto failed; |
173 | 0 | } |
174 | 0 | } |
175 | | |
176 | 0 | nsd->revision = osd->revision; |
177 | 0 | nsd->type = osd->type; |
178 | |
|
179 | 0 | return nsd; |
180 | | |
181 | 0 | failed: |
182 | 0 | talloc_free(nsd); |
183 | |
|
184 | 0 | return NULL; |
185 | 0 | } |
186 | | |
187 | | NTSTATUS security_descriptor_for_client(TALLOC_CTX *mem_ctx, |
188 | | const struct security_descriptor *ssd, |
189 | | uint32_t sec_info, |
190 | | uint32_t access_granted, |
191 | | struct security_descriptor **_csd) |
192 | 0 | { |
193 | 0 | struct security_descriptor *csd = NULL; |
194 | 0 | uint32_t access_required = 0; |
195 | |
|
196 | 0 | *_csd = NULL; |
197 | |
|
198 | 0 | if (sec_info & (SECINFO_OWNER|SECINFO_GROUP)) { |
199 | 0 | access_required |= SEC_STD_READ_CONTROL; |
200 | 0 | } |
201 | 0 | if (sec_info & SECINFO_DACL) { |
202 | 0 | access_required |= SEC_STD_READ_CONTROL; |
203 | 0 | } |
204 | 0 | if (sec_info & SECINFO_SACL) { |
205 | 0 | access_required |= SEC_FLAG_SYSTEM_SECURITY; |
206 | 0 | } |
207 | |
|
208 | 0 | if (access_required & (~access_granted)) { |
209 | 0 | return NT_STATUS_ACCESS_DENIED; |
210 | 0 | } |
211 | | |
212 | | /* |
213 | | * make a copy... |
214 | | */ |
215 | 0 | csd = security_descriptor_copy(mem_ctx, ssd); |
216 | 0 | if (csd == NULL) { |
217 | 0 | return NT_STATUS_NO_MEMORY; |
218 | 0 | } |
219 | | |
220 | | /* |
221 | | * ... and remove everything not wanted |
222 | | */ |
223 | | |
224 | 0 | if (!(sec_info & SECINFO_OWNER)) { |
225 | 0 | TALLOC_FREE(csd->owner_sid); |
226 | 0 | csd->type &= ~SEC_DESC_OWNER_DEFAULTED; |
227 | 0 | } |
228 | 0 | if (!(sec_info & SECINFO_GROUP)) { |
229 | 0 | TALLOC_FREE(csd->group_sid); |
230 | 0 | csd->type &= ~SEC_DESC_GROUP_DEFAULTED; |
231 | 0 | } |
232 | 0 | if (!(sec_info & SECINFO_DACL)) { |
233 | 0 | TALLOC_FREE(csd->dacl); |
234 | 0 | csd->type &= ~( |
235 | 0 | SEC_DESC_DACL_PRESENT | |
236 | 0 | SEC_DESC_DACL_DEFAULTED| |
237 | 0 | SEC_DESC_DACL_AUTO_INHERIT_REQ | |
238 | 0 | SEC_DESC_DACL_AUTO_INHERITED | |
239 | 0 | SEC_DESC_DACL_PROTECTED | |
240 | 0 | SEC_DESC_DACL_TRUSTED); |
241 | 0 | } |
242 | 0 | if (!(sec_info & SECINFO_SACL)) { |
243 | 0 | TALLOC_FREE(csd->sacl); |
244 | 0 | csd->type &= ~( |
245 | 0 | SEC_DESC_SACL_PRESENT | |
246 | 0 | SEC_DESC_SACL_DEFAULTED | |
247 | 0 | SEC_DESC_SACL_AUTO_INHERIT_REQ | |
248 | 0 | SEC_DESC_SACL_AUTO_INHERITED | |
249 | 0 | SEC_DESC_SACL_PROTECTED | |
250 | 0 | SEC_DESC_SERVER_SECURITY); |
251 | 0 | } |
252 | |
|
253 | 0 | *_csd = csd; |
254 | 0 | return NT_STATUS_OK; |
255 | 0 | } |
256 | | |
257 | | /* |
258 | | add an ACE to an ACL of a security_descriptor |
259 | | */ |
260 | | |
261 | | static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd, |
262 | | bool add_to_sacl, |
263 | | const struct security_ace *ace, |
264 | | ssize_t _idx) |
265 | 0 | { |
266 | 0 | struct security_acl *acl = NULL; |
267 | 0 | ssize_t idx; |
268 | |
|
269 | 0 | if (add_to_sacl) { |
270 | 0 | acl = sd->sacl; |
271 | 0 | } else { |
272 | 0 | acl = sd->dacl; |
273 | 0 | } |
274 | |
|
275 | 0 | if (acl == NULL) { |
276 | 0 | acl = talloc(sd, struct security_acl); |
277 | 0 | if (acl == NULL) { |
278 | 0 | return NT_STATUS_NO_MEMORY; |
279 | 0 | } |
280 | 0 | acl->revision = SECURITY_ACL_REVISION_NT4; |
281 | 0 | acl->size = 0; |
282 | 0 | acl->num_aces = 0; |
283 | 0 | acl->aces = NULL; |
284 | 0 | } |
285 | | |
286 | 0 | if (_idx < 0) { |
287 | 0 | idx = (acl->num_aces + 1) + _idx; |
288 | 0 | } else { |
289 | 0 | idx = _idx; |
290 | 0 | } |
291 | |
|
292 | 0 | if (idx < 0) { |
293 | 0 | return NT_STATUS_ARRAY_BOUNDS_EXCEEDED; |
294 | 0 | } |
295 | 0 | if (idx > acl->num_aces) { |
296 | 0 | return NT_STATUS_ARRAY_BOUNDS_EXCEEDED; |
297 | 0 | } |
298 | | |
299 | 0 | acl->aces = talloc_realloc(acl, acl->aces, |
300 | 0 | struct security_ace, acl->num_aces+1); |
301 | 0 | if (acl->aces == NULL) { |
302 | 0 | return NT_STATUS_NO_MEMORY; |
303 | 0 | } |
304 | | |
305 | 0 | ARRAY_INSERT_ELEMENT(acl->aces, acl->num_aces, *ace, idx); |
306 | 0 | acl->num_aces++; |
307 | |
|
308 | 0 | if (sec_ace_object(acl->aces[idx].type)) { |
309 | 0 | acl->revision = SECURITY_ACL_REVISION_ADS; |
310 | 0 | } |
311 | |
|
312 | 0 | if (add_to_sacl) { |
313 | 0 | sd->sacl = acl; |
314 | 0 | sd->type |= SEC_DESC_SACL_PRESENT; |
315 | 0 | } else { |
316 | 0 | sd->dacl = acl; |
317 | 0 | sd->type |= SEC_DESC_DACL_PRESENT; |
318 | 0 | } |
319 | |
|
320 | 0 | return NT_STATUS_OK; |
321 | 0 | } |
322 | | |
323 | | /* |
324 | | add an ACE to the SACL of a security_descriptor |
325 | | */ |
326 | | |
327 | | NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd, |
328 | | const struct security_ace *ace) |
329 | 0 | { |
330 | 0 | return security_descriptor_acl_add(sd, true, ace, -1); |
331 | 0 | } |
332 | | |
333 | | /* |
334 | | insert an ACE at a given index to the SACL of a security_descriptor |
335 | | |
336 | | idx can be negative, which means it's related to the new size from the |
337 | | end, so -1 means the ace is appended at the end. |
338 | | */ |
339 | | |
340 | | NTSTATUS security_descriptor_sacl_insert(struct security_descriptor *sd, |
341 | | const struct security_ace *ace, |
342 | | ssize_t idx) |
343 | 0 | { |
344 | 0 | return security_descriptor_acl_add(sd, true, ace, idx); |
345 | 0 | } |
346 | | |
347 | | /* |
348 | | add an ACE to the DACL of a security_descriptor |
349 | | */ |
350 | | |
351 | | NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd, |
352 | | const struct security_ace *ace) |
353 | 0 | { |
354 | 0 | return security_descriptor_acl_add(sd, false, ace, -1); |
355 | 0 | } |
356 | | |
357 | | /* |
358 | | insert an ACE at a given index to the DACL of a security_descriptor |
359 | | |
360 | | idx can be negative, which means it's related to the new size from the |
361 | | end, so -1 means the ace is appended at the end. |
362 | | */ |
363 | | |
364 | | NTSTATUS security_descriptor_dacl_insert(struct security_descriptor *sd, |
365 | | const struct security_ace *ace, |
366 | | ssize_t idx) |
367 | 0 | { |
368 | 0 | return security_descriptor_acl_add(sd, false, ace, idx); |
369 | 0 | } |
370 | | |
371 | | /* |
372 | | delete the ACE corresponding to the given trustee in an ACL of a |
373 | | security_descriptor |
374 | | */ |
375 | | |
376 | | static NTSTATUS security_descriptor_acl_del(struct security_descriptor *sd, |
377 | | bool sacl_del, |
378 | | const struct dom_sid *trustee) |
379 | 0 | { |
380 | 0 | uint32_t i; |
381 | 0 | bool found = false; |
382 | 0 | struct security_acl *acl = NULL; |
383 | |
|
384 | 0 | if (sacl_del) { |
385 | 0 | acl = sd->sacl; |
386 | 0 | } else { |
387 | 0 | acl = sd->dacl; |
388 | 0 | } |
389 | |
|
390 | 0 | if (acl == NULL) { |
391 | 0 | return NT_STATUS_OBJECT_NAME_NOT_FOUND; |
392 | 0 | } |
393 | | |
394 | | /* there can be multiple ace's for one trustee */ |
395 | | |
396 | 0 | i = 0; |
397 | |
|
398 | 0 | while (i<acl->num_aces) { |
399 | 0 | if (dom_sid_equal(trustee, &acl->aces[i].trustee)) { |
400 | 0 | ARRAY_DEL_ELEMENT(acl->aces, i, acl->num_aces); |
401 | 0 | acl->num_aces--; |
402 | 0 | if (acl->num_aces == 0) { |
403 | 0 | acl->aces = NULL; |
404 | 0 | } |
405 | 0 | found = true; |
406 | 0 | } else { |
407 | 0 | i += 1; |
408 | 0 | } |
409 | 0 | } |
410 | |
|
411 | 0 | if (!found) { |
412 | 0 | return NT_STATUS_OBJECT_NAME_NOT_FOUND; |
413 | 0 | } |
414 | | |
415 | 0 | acl->revision = SECURITY_ACL_REVISION_NT4; |
416 | |
|
417 | 0 | for (i=0;i<acl->num_aces;i++) { |
418 | 0 | if (sec_ace_object(acl->aces[i].type)) { |
419 | 0 | acl->revision = SECURITY_ACL_REVISION_ADS; |
420 | 0 | break; |
421 | 0 | } |
422 | 0 | } |
423 | |
|
424 | 0 | return NT_STATUS_OK; |
425 | 0 | } |
426 | | |
427 | | /* |
428 | | delete the ACE corresponding to the given trustee in the DACL of a |
429 | | security_descriptor |
430 | | */ |
431 | | |
432 | | NTSTATUS security_descriptor_dacl_del(struct security_descriptor *sd, |
433 | | const struct dom_sid *trustee) |
434 | 0 | { |
435 | 0 | return security_descriptor_acl_del(sd, false, trustee); |
436 | 0 | } |
437 | | |
438 | | /* |
439 | | delete the ACE corresponding to the given trustee in the SACL of a |
440 | | security_descriptor |
441 | | */ |
442 | | |
443 | | NTSTATUS security_descriptor_sacl_del(struct security_descriptor *sd, |
444 | | const struct dom_sid *trustee) |
445 | 0 | { |
446 | 0 | return security_descriptor_acl_del(sd, true, trustee); |
447 | 0 | } |
448 | | |
449 | | /* |
450 | | delete the given ACE in the SACL or DACL of a security_descriptor |
451 | | */ |
452 | | static NTSTATUS security_descriptor_acl_del_ace(struct security_descriptor *sd, |
453 | | bool sacl_del, |
454 | | const struct security_ace *ace) |
455 | 0 | { |
456 | 0 | uint32_t i; |
457 | 0 | bool found = false; |
458 | 0 | struct security_acl *acl = NULL; |
459 | |
|
460 | 0 | if (sacl_del) { |
461 | 0 | acl = sd->sacl; |
462 | 0 | } else { |
463 | 0 | acl = sd->dacl; |
464 | 0 | } |
465 | |
|
466 | 0 | if (acl == NULL) { |
467 | 0 | return NT_STATUS_OBJECT_NAME_NOT_FOUND; |
468 | 0 | } |
469 | | |
470 | 0 | for (i=0;i<acl->num_aces;i++) { |
471 | 0 | if (security_ace_equal(ace, &acl->aces[i])) { |
472 | 0 | ARRAY_DEL_ELEMENT(acl->aces, i, acl->num_aces); |
473 | 0 | acl->num_aces--; |
474 | 0 | if (acl->num_aces == 0) { |
475 | 0 | acl->aces = NULL; |
476 | 0 | } |
477 | 0 | found = true; |
478 | 0 | i--; |
479 | 0 | } |
480 | 0 | } |
481 | |
|
482 | 0 | if (!found) { |
483 | 0 | return NT_STATUS_OBJECT_NAME_NOT_FOUND; |
484 | 0 | } |
485 | | |
486 | 0 | acl->revision = SECURITY_ACL_REVISION_NT4; |
487 | |
|
488 | 0 | for (i=0;i<acl->num_aces;i++) { |
489 | 0 | if (sec_ace_object(acl->aces[i].type)) { |
490 | 0 | acl->revision = SECURITY_ACL_REVISION_ADS; |
491 | 0 | break; |
492 | 0 | } |
493 | 0 | } |
494 | |
|
495 | 0 | return NT_STATUS_OK; |
496 | 0 | } |
497 | | |
498 | | NTSTATUS security_descriptor_dacl_del_ace(struct security_descriptor *sd, |
499 | | const struct security_ace *ace) |
500 | 0 | { |
501 | 0 | return security_descriptor_acl_del_ace(sd, false, ace); |
502 | 0 | } |
503 | | |
504 | | NTSTATUS security_descriptor_sacl_del_ace(struct security_descriptor *sd, |
505 | | const struct security_ace *ace) |
506 | 0 | { |
507 | 0 | return security_descriptor_acl_del_ace(sd, true, ace); |
508 | 0 | } |
509 | | |
510 | | static bool security_ace_object_equal(const struct security_ace_object *object1, |
511 | | const struct security_ace_object *object2) |
512 | 6.14k | { |
513 | 6.14k | if (object1 == object2) { |
514 | 0 | return true; |
515 | 0 | } |
516 | 6.14k | if ((object1 == NULL) || (object2 == NULL)) { |
517 | 0 | return false; |
518 | 0 | } |
519 | 6.14k | if (object1->flags != object2->flags) { |
520 | 0 | return false; |
521 | 0 | } |
522 | 6.14k | if (object1->flags & SEC_ACE_OBJECT_TYPE_PRESENT |
523 | 486 | && !GUID_equal(&object1->type.type, &object2->type.type)) { |
524 | 0 | return false; |
525 | 0 | } |
526 | 6.14k | if (object1->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT |
527 | 547 | && !GUID_equal(&object1->inherited_type.inherited_type, |
528 | 547 | &object2->inherited_type.inherited_type)) { |
529 | 0 | return false; |
530 | 0 | } |
531 | | |
532 | 6.14k | return true; |
533 | 6.14k | } |
534 | | |
535 | | |
536 | | static bool security_ace_claim_equal(const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim1, |
537 | | const struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim2) |
538 | 2.26k | { |
539 | 2.26k | uint32_t i; |
540 | | |
541 | 2.26k | if (claim1 == claim2) { |
542 | 0 | return true; |
543 | 0 | } |
544 | 2.26k | if (claim1 == NULL || claim2 == NULL) { |
545 | 0 | return false; |
546 | 0 | } |
547 | 2.26k | if (claim1->name != NULL && claim2->name != NULL) { |
548 | 2.26k | if (strcasecmp_m(claim1->name, claim2->name) != 0) { |
549 | 0 | return false; |
550 | 0 | } |
551 | 2.26k | } else if (claim1->name != NULL || claim2->name != NULL) { |
552 | 0 | return false; |
553 | 0 | } |
554 | 2.26k | if (claim1->value_type != claim2->value_type) { |
555 | 0 | return false; |
556 | 0 | } |
557 | 2.26k | if (claim1->flags != claim2->flags) { |
558 | 0 | return false; |
559 | 0 | } |
560 | 2.26k | if (claim1->value_count != claim2->value_count) { |
561 | 0 | return false; |
562 | 0 | } |
563 | 17.4k | for (i = 0; i < claim1->value_count; ++i) { |
564 | 15.1k | const union claim_values *values1 = claim1->values; |
565 | 15.1k | const union claim_values *values2 = claim2->values; |
566 | | |
567 | 15.1k | switch (claim1->value_type) { |
568 | 1.19k | case CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64: |
569 | 1.19k | if (values1[i].int_value != NULL && values2[i].int_value != NULL) { |
570 | 1.19k | if (*values1[i].int_value != *values2[i].int_value) { |
571 | 0 | return false; |
572 | 0 | } |
573 | 1.19k | } else if (values1[i].int_value != NULL || values2[i].int_value != NULL) { |
574 | 0 | return false; |
575 | 0 | } |
576 | 1.19k | break; |
577 | 8.05k | case CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64: |
578 | 8.05k | case CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN: |
579 | 8.05k | if (values1[i].uint_value != NULL && values2[i].uint_value != NULL) { |
580 | 8.05k | if (*values1[i].uint_value != *values2[i].uint_value) { |
581 | 0 | return false; |
582 | 0 | } |
583 | 8.05k | } else if (values1[i].uint_value != NULL || values2[i].uint_value != NULL) { |
584 | 0 | return false; |
585 | 0 | } |
586 | 8.05k | break; |
587 | 8.05k | case CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING: |
588 | 1.15k | if (values1[i].string_value != NULL && values2[i].string_value != NULL) { |
589 | 1.15k | if (strcasecmp_m(values1[i].string_value, values2[i].string_value) != 0) { |
590 | 0 | return false; |
591 | 0 | } |
592 | 1.15k | } else if (values1[i].string_value != NULL || values2[i].string_value != NULL) { |
593 | 0 | return false; |
594 | 0 | } |
595 | 1.15k | break; |
596 | 3.83k | case CLAIM_SECURITY_ATTRIBUTE_TYPE_SID: |
597 | 3.83k | if (values1[i].sid_value != NULL && values2[i].sid_value != NULL) { |
598 | 3.83k | if (data_blob_cmp(values1[i].sid_value, values2[i].sid_value) != 0) { |
599 | 0 | return false; |
600 | 0 | } |
601 | 3.83k | } else if (values1[i].sid_value != NULL || values2[i].sid_value != NULL) { |
602 | 0 | return false; |
603 | 0 | } |
604 | 3.83k | break; |
605 | 3.83k | case CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING: |
606 | 912 | if (values1[i].octet_value != NULL && values2[i].octet_value != NULL) { |
607 | 912 | if (data_blob_cmp(values1[i].octet_value, values2[i].octet_value) != 0) { |
608 | 0 | return false; |
609 | 0 | } |
610 | 912 | } else if (values1[i].octet_value != NULL || values2[i].octet_value != NULL) { |
611 | 0 | return false; |
612 | 0 | } |
613 | 912 | break; |
614 | 912 | default: |
615 | 0 | break; |
616 | 15.1k | } |
617 | 15.1k | } |
618 | | |
619 | 2.26k | return true; |
620 | 2.26k | } |
621 | | |
622 | | /* |
623 | | compare two security ace structures |
624 | | */ |
625 | | bool security_ace_equal(const struct security_ace *ace1, |
626 | | const struct security_ace *ace2) |
627 | 13.0k | { |
628 | 13.0k | if (ace1 == ace2) { |
629 | 0 | return true; |
630 | 0 | } |
631 | 13.0k | if ((ace1 == NULL) || (ace2 == NULL)) { |
632 | 0 | return false; |
633 | 0 | } |
634 | 13.0k | if (ace1->type != ace2->type) { |
635 | 0 | return false; |
636 | 0 | } |
637 | 13.0k | if (ace1->flags != ace2->flags) { |
638 | 0 | return false; |
639 | 0 | } |
640 | 13.0k | if (ace1->access_mask != ace2->access_mask) { |
641 | 0 | return false; |
642 | 0 | } |
643 | 13.0k | if (sec_ace_object(ace1->type) && |
644 | 6.14k | !security_ace_object_equal(&ace1->object.object, |
645 | 6.14k | &ace2->object.object)) |
646 | 0 | { |
647 | 0 | return false; |
648 | 0 | } |
649 | 13.0k | if (!dom_sid_equal(&ace1->trustee, &ace2->trustee)) { |
650 | 0 | return false; |
651 | 0 | } |
652 | | |
653 | 13.0k | if (sec_ace_callback(ace1->type)) { |
654 | 3.67k | if (data_blob_cmp(&ace1->coda.conditions, &ace2->coda.conditions) != 0) { |
655 | 0 | return false; |
656 | 0 | } |
657 | 9.40k | } else if (sec_ace_resource(ace1->type)) { |
658 | 2.26k | if (!security_ace_claim_equal(&ace1->coda.claim, &ace2->coda.claim)) { |
659 | 0 | return false; |
660 | 0 | } |
661 | 7.14k | } else { |
662 | | /* |
663 | | * Don’t require ace1->coda.ignored to match ace2->coda.ignored. |
664 | | */ |
665 | 7.14k | } |
666 | | |
667 | 13.0k | return true; |
668 | 13.0k | } |
669 | | |
670 | | |
671 | | /* |
672 | | compare two security acl structures |
673 | | */ |
674 | | bool security_acl_equal(const struct security_acl *acl1, |
675 | | const struct security_acl *acl2) |
676 | 5.84k | { |
677 | 5.84k | uint32_t i; |
678 | | |
679 | 5.84k | if (acl1 == acl2) return true; |
680 | 2.63k | if (!acl1 || !acl2) return false; |
681 | 2.63k | if (acl1->revision != acl2->revision) return false; |
682 | 2.63k | if (acl1->num_aces != acl2->num_aces) return false; |
683 | | |
684 | 15.7k | for (i=0;i<acl1->num_aces;i++) { |
685 | 13.0k | if (!security_ace_equal(&acl1->aces[i], &acl2->aces[i])) return false; |
686 | 13.0k | } |
687 | 2.63k | return true; |
688 | 2.63k | } |
689 | | |
690 | | /* |
691 | | compare two security descriptors. |
692 | | */ |
693 | | bool security_descriptor_equal(const struct security_descriptor *sd1, |
694 | | const struct security_descriptor *sd2) |
695 | 2.92k | { |
696 | 2.92k | if (sd1 == sd2) return true; |
697 | 2.92k | if (!sd1 || !sd2) return false; |
698 | 2.92k | if (sd1->revision != sd2->revision) return false; |
699 | 2.92k | if (sd1->type != sd2->type) return false; |
700 | | |
701 | 2.92k | if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false; |
702 | 2.92k | if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false; |
703 | 2.92k | if (!security_acl_equal(sd1->sacl, sd2->sacl)) return false; |
704 | 2.92k | if (!security_acl_equal(sd1->dacl, sd2->dacl)) return false; |
705 | | |
706 | 2.92k | return true; |
707 | 2.92k | } |
708 | | |
709 | | /* |
710 | | compare two security descriptors, but allow certain (missing) parts |
711 | | to be masked out of the comparison |
712 | | */ |
713 | | bool security_descriptor_mask_equal(const struct security_descriptor *sd1, |
714 | | const struct security_descriptor *sd2, |
715 | | uint32_t mask) |
716 | 0 | { |
717 | 0 | if (sd1 == sd2) return true; |
718 | 0 | if (!sd1 || !sd2) return false; |
719 | 0 | if (sd1->revision != sd2->revision) return false; |
720 | 0 | if ((sd1->type & mask) != (sd2->type & mask)) return false; |
721 | | |
722 | 0 | if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false; |
723 | 0 | if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false; |
724 | 0 | if ((mask & SEC_DESC_DACL_PRESENT) && !security_acl_equal(sd1->dacl, sd2->dacl)) return false; |
725 | 0 | if ((mask & SEC_DESC_SACL_PRESENT) && !security_acl_equal(sd1->sacl, sd2->sacl)) return false; |
726 | | |
727 | 0 | return true; |
728 | 0 | } |
729 | | |
730 | | |
731 | | static struct security_descriptor *security_descriptor_appendv(struct security_descriptor *sd, |
732 | | bool add_ace_to_sacl, |
733 | | va_list ap) |
734 | 0 | { |
735 | 0 | const char *sidstr; |
736 | |
|
737 | 0 | while ((sidstr = va_arg(ap, const char *))) { |
738 | 0 | struct dom_sid *sid; |
739 | 0 | struct security_ace *ace = talloc_zero(sd, struct security_ace); |
740 | 0 | NTSTATUS status; |
741 | |
|
742 | 0 | if (ace == NULL) { |
743 | 0 | talloc_free(sd); |
744 | 0 | return NULL; |
745 | 0 | } |
746 | 0 | ace->type = va_arg(ap, unsigned int); |
747 | 0 | ace->access_mask = va_arg(ap, unsigned int); |
748 | 0 | ace->flags = va_arg(ap, unsigned int); |
749 | 0 | sid = dom_sid_parse_talloc(ace, sidstr); |
750 | 0 | if (sid == NULL) { |
751 | 0 | talloc_free(sd); |
752 | 0 | return NULL; |
753 | 0 | } |
754 | 0 | ace->trustee = *sid; |
755 | 0 | if (add_ace_to_sacl) { |
756 | 0 | status = security_descriptor_sacl_add(sd, ace); |
757 | 0 | } else { |
758 | 0 | status = security_descriptor_dacl_add(sd, ace); |
759 | 0 | } |
760 | | /* TODO: check: would talloc_free(ace) here be correct? */ |
761 | 0 | if (!NT_STATUS_IS_OK(status)) { |
762 | 0 | talloc_free(sd); |
763 | 0 | return NULL; |
764 | 0 | } |
765 | 0 | } |
766 | | |
767 | 0 | return sd; |
768 | 0 | } |
769 | | |
770 | | static struct security_descriptor *security_descriptor_createv(TALLOC_CTX *mem_ctx, |
771 | | uint16_t sd_type, |
772 | | const char *owner_sid, |
773 | | const char *group_sid, |
774 | | bool add_ace_to_sacl, |
775 | | va_list ap) |
776 | 0 | { |
777 | 0 | struct security_descriptor *sd; |
778 | |
|
779 | 0 | sd = security_descriptor_initialise(mem_ctx); |
780 | 0 | if (sd == NULL) { |
781 | 0 | return NULL; |
782 | 0 | } |
783 | | |
784 | 0 | sd->type |= sd_type; |
785 | |
|
786 | 0 | if (owner_sid) { |
787 | 0 | sd->owner_sid = dom_sid_parse_talloc(sd, owner_sid); |
788 | 0 | if (sd->owner_sid == NULL) { |
789 | 0 | talloc_free(sd); |
790 | 0 | return NULL; |
791 | 0 | } |
792 | 0 | } |
793 | 0 | if (group_sid) { |
794 | 0 | sd->group_sid = dom_sid_parse_talloc(sd, group_sid); |
795 | 0 | if (sd->group_sid == NULL) { |
796 | 0 | talloc_free(sd); |
797 | 0 | return NULL; |
798 | 0 | } |
799 | 0 | } |
800 | | |
801 | 0 | return security_descriptor_appendv(sd, add_ace_to_sacl, ap); |
802 | 0 | } |
803 | | |
804 | | /* |
805 | | create a security descriptor using string SIDs. This is used by the |
806 | | torture code to allow the easy creation of complex ACLs |
807 | | This is a varargs function. The list of DACL ACEs ends with a NULL sid. |
808 | | |
809 | | Each ACE contains a set of 4 parameters: |
810 | | SID, ACCESS_TYPE, MASK, FLAGS |
811 | | |
812 | | a typical call would be: |
813 | | |
814 | | sd = security_descriptor_dacl_create(mem_ctx, |
815 | | sd_type_flags, |
816 | | mysid, |
817 | | mygroup, |
818 | | SID_NT_AUTHENTICATED_USERS, |
819 | | SEC_ACE_TYPE_ACCESS_ALLOWED, |
820 | | SEC_FILE_ALL, |
821 | | SEC_ACE_FLAG_OBJECT_INHERIT, |
822 | | NULL); |
823 | | that would create a sd with one DACL ACE |
824 | | */ |
825 | | |
826 | | struct security_descriptor *security_descriptor_dacl_create(TALLOC_CTX *mem_ctx, |
827 | | uint16_t sd_type, |
828 | | const char *owner_sid, |
829 | | const char *group_sid, |
830 | | ...) |
831 | 0 | { |
832 | 0 | struct security_descriptor *sd = NULL; |
833 | 0 | va_list ap; |
834 | 0 | va_start(ap, group_sid); |
835 | 0 | sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid, |
836 | 0 | group_sid, false, ap); |
837 | 0 | va_end(ap); |
838 | |
|
839 | 0 | return sd; |
840 | 0 | } |
841 | | |
842 | | struct security_descriptor *security_descriptor_sacl_create(TALLOC_CTX *mem_ctx, |
843 | | uint16_t sd_type, |
844 | | const char *owner_sid, |
845 | | const char *group_sid, |
846 | | ...) |
847 | 0 | { |
848 | 0 | struct security_descriptor *sd = NULL; |
849 | 0 | va_list ap; |
850 | 0 | va_start(ap, group_sid); |
851 | 0 | sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid, |
852 | 0 | group_sid, true, ap); |
853 | 0 | va_end(ap); |
854 | |
|
855 | 0 | return sd; |
856 | 0 | } |
857 | | |
858 | | struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx, |
859 | | const char *sid_str, |
860 | | enum security_ace_type type, |
861 | | uint32_t access_mask, |
862 | | uint8_t flags) |
863 | | |
864 | 0 | { |
865 | 0 | struct security_ace *ace; |
866 | 0 | bool ok; |
867 | |
|
868 | 0 | ace = talloc_zero(mem_ctx, struct security_ace); |
869 | 0 | if (ace == NULL) { |
870 | 0 | return NULL; |
871 | 0 | } |
872 | | |
873 | 0 | ok = dom_sid_parse(sid_str, &ace->trustee); |
874 | 0 | if (!ok) { |
875 | 0 | talloc_free(ace); |
876 | 0 | return NULL; |
877 | 0 | } |
878 | 0 | ace->type = type; |
879 | 0 | ace->access_mask = access_mask; |
880 | 0 | ace->flags = flags; |
881 | |
|
882 | 0 | return ace; |
883 | 0 | } |
884 | | |
885 | | /******************************************************************* |
886 | | Check for MS NFS ACEs in a sd |
887 | | *******************************************************************/ |
888 | | bool security_descriptor_with_ms_nfs(const struct security_descriptor *psd) |
889 | 0 | { |
890 | 0 | uint32_t i; |
891 | |
|
892 | 0 | if (psd->dacl == NULL) { |
893 | 0 | return false; |
894 | 0 | } |
895 | | |
896 | 0 | for (i = 0; i < psd->dacl->num_aces; i++) { |
897 | 0 | if (dom_sid_compare_domain( |
898 | 0 | &global_sid_Unix_NFS, |
899 | 0 | &psd->dacl->aces[i].trustee) == 0) { |
900 | 0 | return true; |
901 | 0 | } |
902 | 0 | } |
903 | | |
904 | 0 | return false; |
905 | 0 | } |