source: branches/samba-3.5.x/libcli/security/security_descriptor.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 13.9 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 security descriptror 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 "includes.h"
23#include "libcli/security/security_descriptor.h"
24#include "libcli/security/dom_sid.h"
25
26/*
27 return a blank security descriptor (no owners, dacl or sacl)
28*/
29struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx)
30{
31 struct security_descriptor *sd;
32
33 sd = talloc(mem_ctx, struct security_descriptor);
34 if (!sd) {
35 return NULL;
36 }
37
38 sd->revision = SD_REVISION;
39 /* we mark as self relative, even though it isn't while it remains
40 a pointer in memory because this simplifies the ndr code later.
41 All SDs that we store/emit are in fact SELF_RELATIVE
42 */
43 sd->type = SEC_DESC_SELF_RELATIVE;
44
45 sd->owner_sid = NULL;
46 sd->group_sid = NULL;
47 sd->sacl = NULL;
48 sd->dacl = NULL;
49
50 return sd;
51}
52
53struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx,
54 const struct security_acl *oacl)
55{
56 struct security_acl *nacl;
57
58 nacl = talloc (mem_ctx, struct security_acl);
59 if (nacl == NULL) {
60 return NULL;
61 }
62
63 nacl->aces = (struct security_ace *)talloc_memdup (nacl, oacl->aces, sizeof(struct security_ace) * oacl->num_aces);
64 if ((nacl->aces == NULL) && (oacl->num_aces > 0)) {
65 goto failed;
66 }
67
68 nacl->revision = oacl->revision;
69 nacl->size = oacl->size;
70 nacl->num_aces = oacl->num_aces;
71
72 return nacl;
73
74 failed:
75 talloc_free (nacl);
76 return NULL;
77
78}
79
80struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx,
81 const struct security_acl *acl1,
82 const struct security_acl *acl2)
83{
84 struct security_acl *nacl;
85 int i;
86
87 if (!acl1 && !acl2)
88 return NULL;
89
90 if (!acl1){
91 nacl = security_acl_dup(mem_ctx, acl2);
92 return nacl;
93 }
94
95 if (!acl2){
96 nacl = security_acl_dup(mem_ctx, acl1);
97 return nacl;
98 }
99
100 nacl = talloc (mem_ctx, struct security_acl);
101 if (nacl == NULL) {
102 return NULL;
103 }
104
105 nacl->revision = acl1->revision;
106 nacl->size = acl1->size + acl2->size;
107 nacl->num_aces = acl1->num_aces + acl2->num_aces;
108
109 if (nacl->num_aces == 0)
110 return nacl;
111
112 nacl->aces = (struct security_ace *)talloc_array (mem_ctx, struct security_ace, acl1->num_aces+acl2->num_aces);
113 if ((nacl->aces == NULL) && (nacl->num_aces > 0)) {
114 goto failed;
115 }
116
117 for (i = 0; i < acl1->num_aces; i++)
118 nacl->aces[i] = acl1->aces[i];
119 for (i = 0; i < acl2->num_aces; i++)
120 nacl->aces[i + acl1->num_aces] = acl2->aces[i];
121
122 return nacl;
123
124 failed:
125 talloc_free (nacl);
126 return NULL;
127
128}
129
130/*
131 talloc and copy a security descriptor
132 */
133struct security_descriptor *security_descriptor_copy(TALLOC_CTX *mem_ctx,
134 const struct security_descriptor *osd)
135{
136 struct security_descriptor *nsd;
137
138 nsd = talloc_zero(mem_ctx, struct security_descriptor);
139 if (!nsd) {
140 return NULL;
141 }
142
143 if (osd->owner_sid) {
144 nsd->owner_sid = dom_sid_dup(nsd, osd->owner_sid);
145 if (nsd->owner_sid == NULL) {
146 goto failed;
147 }
148 }
149
150 if (osd->group_sid) {
151 nsd->group_sid = dom_sid_dup(nsd, osd->group_sid);
152 if (nsd->group_sid == NULL) {
153 goto failed;
154 }
155 }
156
157 if (osd->sacl) {
158 nsd->sacl = security_acl_dup(nsd, osd->sacl);
159 if (nsd->sacl == NULL) {
160 goto failed;
161 }
162 }
163
164 if (osd->dacl) {
165 nsd->dacl = security_acl_dup(nsd, osd->dacl);
166 if (nsd->dacl == NULL) {
167 goto failed;
168 }
169 }
170
171 nsd->revision = osd->revision;
172 nsd->type = osd->type;
173
174 return nsd;
175
176 failed:
177 talloc_free(nsd);
178
179 return NULL;
180}
181
182/*
183 add an ACE to an ACL of a security_descriptor
184*/
185
186static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
187 bool add_to_sacl,
188 const struct security_ace *ace)
189{
190 struct security_acl *acl = NULL;
191
192 if (add_to_sacl) {
193 acl = sd->sacl;
194 } else {
195 acl = sd->dacl;
196 }
197
198 if (acl == NULL) {
199 acl = talloc(sd, struct security_acl);
200 if (acl == NULL) {
201 return NT_STATUS_NO_MEMORY;
202 }
203 acl->revision = SECURITY_ACL_REVISION_NT4;
204 acl->size = 0;
205 acl->num_aces = 0;
206 acl->aces = NULL;
207 }
208
209 acl->aces = talloc_realloc(acl, acl->aces,
210 struct security_ace, acl->num_aces+1);
211 if (acl->aces == NULL) {
212 return NT_STATUS_NO_MEMORY;
213 }
214
215 acl->aces[acl->num_aces] = *ace;
216
217 switch (acl->aces[acl->num_aces].type) {
218 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
219 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
220 case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
221 case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
222 acl->revision = SECURITY_ACL_REVISION_ADS;
223 break;
224 default:
225 break;
226 }
227
228 acl->num_aces++;
229
230 if (add_to_sacl) {
231 sd->sacl = acl;
232 sd->type |= SEC_DESC_SACL_PRESENT;
233 } else {
234 sd->dacl = acl;
235 sd->type |= SEC_DESC_DACL_PRESENT;
236 }
237
238 return NT_STATUS_OK;
239}
240
241/*
242 add an ACE to the SACL of a security_descriptor
243*/
244
245NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd,
246 const struct security_ace *ace)
247{
248 return security_descriptor_acl_add(sd, true, ace);
249}
250
251/*
252 add an ACE to the DACL of a security_descriptor
253*/
254
255NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd,
256 const struct security_ace *ace)
257{
258 return security_descriptor_acl_add(sd, false, ace);
259}
260
261/*
262 delete the ACE corresponding to the given trustee in an ACL of a
263 security_descriptor
264*/
265
266static NTSTATUS security_descriptor_acl_del(struct security_descriptor *sd,
267 bool sacl_del,
268 const struct dom_sid *trustee)
269{
270 int i;
271 bool found = false;
272 struct security_acl *acl = NULL;
273
274 if (sacl_del) {
275 acl = sd->sacl;
276 } else {
277 acl = sd->dacl;
278 }
279
280 if (acl == NULL) {
281 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
282 }
283
284 /* there can be multiple ace's for one trustee */
285 for (i=0;i<acl->num_aces;i++) {
286 if (dom_sid_equal(trustee, &acl->aces[i].trustee)) {
287 memmove(&acl->aces[i], &acl->aces[i+1],
288 sizeof(acl->aces[i]) * (acl->num_aces - (i+1)));
289 acl->num_aces--;
290 if (acl->num_aces == 0) {
291 acl->aces = NULL;
292 }
293 found = true;
294 }
295 }
296
297 if (!found) {
298 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
299 }
300
301 acl->revision = SECURITY_ACL_REVISION_NT4;
302
303 for (i=0;i<acl->num_aces;i++) {
304 switch (acl->aces[i].type) {
305 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
306 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
307 case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
308 case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
309 acl->revision = SECURITY_ACL_REVISION_ADS;
310 return NT_STATUS_OK;
311 default:
312 break; /* only for the switch statement */
313 }
314 }
315
316 return NT_STATUS_OK;
317}
318
319/*
320 delete the ACE corresponding to the given trustee in the DACL of a
321 security_descriptor
322*/
323
324NTSTATUS security_descriptor_dacl_del(struct security_descriptor *sd,
325 const struct dom_sid *trustee)
326{
327 return security_descriptor_acl_del(sd, false, trustee);
328}
329
330/*
331 delete the ACE corresponding to the given trustee in the SACL of a
332 security_descriptor
333*/
334
335NTSTATUS security_descriptor_sacl_del(struct security_descriptor *sd,
336 const struct dom_sid *trustee)
337{
338 return security_descriptor_acl_del(sd, true, trustee);
339}
340
341/*
342 compare two security ace structures
343*/
344bool security_ace_equal(const struct security_ace *ace1,
345 const struct security_ace *ace2)
346{
347 if (ace1 == ace2) return true;
348 if (!ace1 || !ace2) return false;
349 if (ace1->type != ace2->type) return false;
350 if (ace1->flags != ace2->flags) return false;
351 if (ace1->access_mask != ace2->access_mask) return false;
352 if (!dom_sid_equal(&ace1->trustee, &ace2->trustee)) return false;
353
354 return true;
355}
356
357
358/*
359 compare two security acl structures
360*/
361bool security_acl_equal(const struct security_acl *acl1,
362 const struct security_acl *acl2)
363{
364 int i;
365
366 if (acl1 == acl2) return true;
367 if (!acl1 || !acl2) return false;
368 if (acl1->revision != acl2->revision) return false;
369 if (acl1->num_aces != acl2->num_aces) return false;
370
371 for (i=0;i<acl1->num_aces;i++) {
372 if (!security_ace_equal(&acl1->aces[i], &acl2->aces[i])) return false;
373 }
374 return true;
375}
376
377/*
378 compare two security descriptors.
379*/
380bool security_descriptor_equal(const struct security_descriptor *sd1,
381 const struct security_descriptor *sd2)
382{
383 if (sd1 == sd2) return true;
384 if (!sd1 || !sd2) return false;
385 if (sd1->revision != sd2->revision) return false;
386 if (sd1->type != sd2->type) return false;
387
388 if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false;
389 if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false;
390 if (!security_acl_equal(sd1->sacl, sd2->sacl)) return false;
391 if (!security_acl_equal(sd1->dacl, sd2->dacl)) return false;
392
393 return true;
394}
395
396/*
397 compare two security descriptors, but allow certain (missing) parts
398 to be masked out of the comparison
399*/
400bool security_descriptor_mask_equal(const struct security_descriptor *sd1,
401 const struct security_descriptor *sd2,
402 uint32_t mask)
403{
404 if (sd1 == sd2) return true;
405 if (!sd1 || !sd2) return false;
406 if (sd1->revision != sd2->revision) return false;
407 if ((sd1->type & mask) != (sd2->type & mask)) return false;
408
409 if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false;
410 if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false;
411 if ((mask & SEC_DESC_DACL_PRESENT) && !security_acl_equal(sd1->dacl, sd2->dacl)) return false;
412 if ((mask & SEC_DESC_SACL_PRESENT) && !security_acl_equal(sd1->sacl, sd2->sacl)) return false;
413
414 return true;
415}
416
417
418static struct security_descriptor *security_descriptor_appendv(struct security_descriptor *sd,
419 bool add_ace_to_sacl,
420 va_list ap)
421{
422 const char *sidstr;
423
424 while ((sidstr = va_arg(ap, const char *))) {
425 struct dom_sid *sid;
426 struct security_ace *ace = talloc_zero(sd, struct security_ace);
427 NTSTATUS status;
428
429 if (ace == NULL) {
430 talloc_free(sd);
431 return NULL;
432 }
433 ace->type = va_arg(ap, unsigned int);
434 ace->access_mask = va_arg(ap, unsigned int);
435 ace->flags = va_arg(ap, unsigned int);
436 sid = dom_sid_parse_talloc(ace, sidstr);
437 if (sid == NULL) {
438 talloc_free(sd);
439 return NULL;
440 }
441 ace->trustee = *sid;
442 if (add_ace_to_sacl) {
443 status = security_descriptor_sacl_add(sd, ace);
444 } else {
445 status = security_descriptor_dacl_add(sd, ace);
446 }
447 /* TODO: check: would talloc_free(ace) here be correct? */
448 if (!NT_STATUS_IS_OK(status)) {
449 talloc_free(sd);
450 return NULL;
451 }
452 }
453
454 return sd;
455}
456
457struct security_descriptor *security_descriptor_append(struct security_descriptor *sd,
458 ...)
459{
460 va_list ap;
461
462 va_start(ap, sd);
463 sd = security_descriptor_appendv(sd, false, ap);
464 va_end(ap);
465
466 return sd;
467}
468
469static struct security_descriptor *security_descriptor_createv(TALLOC_CTX *mem_ctx,
470 uint16_t sd_type,
471 const char *owner_sid,
472 const char *group_sid,
473 bool add_ace_to_sacl,
474 va_list ap)
475{
476 struct security_descriptor *sd;
477
478 sd = security_descriptor_initialise(mem_ctx);
479 if (sd == NULL) {
480 return NULL;
481 }
482
483 sd->type |= sd_type;
484
485 if (owner_sid) {
486 sd->owner_sid = dom_sid_parse_talloc(sd, owner_sid);
487 if (sd->owner_sid == NULL) {
488 talloc_free(sd);
489 return NULL;
490 }
491 }
492 if (group_sid) {
493 sd->group_sid = dom_sid_parse_talloc(sd, group_sid);
494 if (sd->group_sid == NULL) {
495 talloc_free(sd);
496 return NULL;
497 }
498 }
499
500 return security_descriptor_appendv(sd, add_ace_to_sacl, ap);
501}
502
503/*
504 create a security descriptor using string SIDs. This is used by the
505 torture code to allow the easy creation of complex ACLs
506 This is a varargs function. The list of DACL ACEs ends with a NULL sid.
507
508 Each ACE contains a set of 4 parameters:
509 SID, ACCESS_TYPE, MASK, FLAGS
510
511 a typical call would be:
512
513 sd = security_descriptor_dacl_create(mem_ctx,
514 sd_type_flags,
515 mysid,
516 mygroup,
517 SID_NT_AUTHENTICATED_USERS,
518 SEC_ACE_TYPE_ACCESS_ALLOWED,
519 SEC_FILE_ALL,
520 SEC_ACE_FLAG_OBJECT_INHERIT,
521 NULL);
522 that would create a sd with one DACL ACE
523*/
524
525struct security_descriptor *security_descriptor_dacl_create(TALLOC_CTX *mem_ctx,
526 uint16_t sd_type,
527 const char *owner_sid,
528 const char *group_sid,
529 ...)
530{
531 struct security_descriptor *sd = NULL;
532 va_list ap;
533 va_start(ap, group_sid);
534 sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid,
535 group_sid, false, ap);
536 va_end(ap);
537
538 return sd;
539}
540
541struct security_descriptor *security_descriptor_sacl_create(TALLOC_CTX *mem_ctx,
542 uint16_t sd_type,
543 const char *owner_sid,
544 const char *group_sid,
545 ...)
546{
547 struct security_descriptor *sd = NULL;
548 va_list ap;
549 va_start(ap, group_sid);
550 sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid,
551 group_sid, true, ap);
552 va_end(ap);
553
554 return sd;
555}
556
557struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx,
558 const char *sid_str,
559 enum security_ace_type type,
560 uint32_t access_mask,
561 uint8_t flags)
562
563{
564 struct dom_sid *sid;
565 struct security_ace *ace;
566
567 ace = talloc_zero(mem_ctx, struct security_ace);
568 if (ace == NULL) {
569 return NULL;
570 }
571
572 sid = dom_sid_parse_talloc(ace, sid_str);
573 if (sid == NULL) {
574 talloc_free(ace);
575 return NULL;
576 }
577
578 ace->trustee = *sid;
579 ace->type = type;
580 ace->access_mask = access_mask;
581 ace->flags = flags;
582
583 return ace;
584}
Note: See TracBrowser for help on using the repository browser.