s3-spoolss: let _spoolss_SetPrinterData call into _spoolss_SetPrinterDataEx.
[Samba/bb.git] / libcli / security / security_descriptor.c
blobb77a28185261b9f1e8353a88e6fda93bab31f64d
1 /*
2 Unix SMB/CIFS implementation.
4 security descriptror utility functions
6 Copyright (C) Andrew Tridgell 2004
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.
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.
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/>.
22 #include "includes.h"
23 #include "libcli/security/security_descriptor.h"
24 #include "libcli/security/dom_sid.h"
27 return a blank security descriptor (no owners, dacl or sacl)
29 struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx)
31 struct security_descriptor *sd;
33 sd = talloc(mem_ctx, struct security_descriptor);
34 if (!sd) {
35 return NULL;
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
43 sd->type = SEC_DESC_SELF_RELATIVE;
45 sd->owner_sid = NULL;
46 sd->group_sid = NULL;
47 sd->sacl = NULL;
48 sd->dacl = NULL;
50 return sd;
53 struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx,
54 const struct security_acl *oacl)
56 struct security_acl *nacl;
58 nacl = talloc (mem_ctx, struct security_acl);
59 if (nacl == NULL) {
60 return NULL;
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;
68 nacl->revision = oacl->revision;
69 nacl->size = oacl->size;
70 nacl->num_aces = oacl->num_aces;
72 return nacl;
74 failed:
75 talloc_free (nacl);
76 return NULL;
80 struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx,
81 const struct security_acl *acl1,
82 const struct security_acl *acl2)
84 struct security_acl *nacl;
85 int i;
87 if (!acl1 && !acl2)
88 return NULL;
90 if (!acl1){
91 nacl = security_acl_dup(mem_ctx, acl2);
92 return nacl;
95 if (!acl2){
96 nacl = security_acl_dup(mem_ctx, acl1);
97 return nacl;
100 nacl = talloc (mem_ctx, struct security_acl);
101 if (nacl == NULL) {
102 return NULL;
105 nacl->revision = acl1->revision;
106 nacl->size = acl1->size + acl2->size;
107 nacl->num_aces = acl1->num_aces + acl2->num_aces;
109 if (nacl->num_aces == 0)
110 return nacl;
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;
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];
122 return nacl;
124 failed:
125 talloc_free (nacl);
126 return NULL;
131 talloc and copy a security descriptor
133 struct security_descriptor *security_descriptor_copy(TALLOC_CTX *mem_ctx,
134 const struct security_descriptor *osd)
136 struct security_descriptor *nsd;
138 nsd = talloc_zero(mem_ctx, struct security_descriptor);
139 if (!nsd) {
140 return NULL;
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;
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;
157 if (osd->sacl) {
158 nsd->sacl = security_acl_dup(nsd, osd->sacl);
159 if (nsd->sacl == NULL) {
160 goto failed;
164 if (osd->dacl) {
165 nsd->dacl = security_acl_dup(nsd, osd->dacl);
166 if (nsd->dacl == NULL) {
167 goto failed;
171 nsd->revision = osd->revision;
172 nsd->type = osd->type;
174 return nsd;
176 failed:
177 talloc_free(nsd);
179 return NULL;
183 add an ACE to an ACL of a security_descriptor
186 static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
187 bool add_to_sacl,
188 const struct security_ace *ace)
190 struct security_acl *acl = NULL;
192 if (add_to_sacl) {
193 acl = sd->sacl;
194 } else {
195 acl = sd->dacl;
198 if (acl == NULL) {
199 acl = talloc(sd, struct security_acl);
200 if (acl == NULL) {
201 return NT_STATUS_NO_MEMORY;
203 acl->revision = SECURITY_ACL_REVISION_NT4;
204 acl->size = 0;
205 acl->num_aces = 0;
206 acl->aces = NULL;
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;
215 acl->aces[acl->num_aces] = *ace;
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;
228 acl->num_aces++;
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;
238 return NT_STATUS_OK;
242 add an ACE to the SACL of a security_descriptor
245 NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd,
246 const struct security_ace *ace)
248 return security_descriptor_acl_add(sd, true, ace);
252 add an ACE to the DACL of a security_descriptor
255 NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd,
256 const struct security_ace *ace)
258 return security_descriptor_acl_add(sd, false, ace);
262 delete the ACE corresponding to the given trustee in an ACL of a
263 security_descriptor
266 static NTSTATUS security_descriptor_acl_del(struct security_descriptor *sd,
267 bool sacl_del,
268 const struct dom_sid *trustee)
270 int i;
271 bool found = false;
272 struct security_acl *acl = NULL;
274 if (sacl_del) {
275 acl = sd->sacl;
276 } else {
277 acl = sd->dacl;
280 if (acl == NULL) {
281 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
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;
293 found = true;
297 if (!found) {
298 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
301 acl->revision = SECURITY_ACL_REVISION_NT4;
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 */
316 return NT_STATUS_OK;
320 delete the ACE corresponding to the given trustee in the DACL of a
321 security_descriptor
324 NTSTATUS security_descriptor_dacl_del(struct security_descriptor *sd,
325 const struct dom_sid *trustee)
327 return security_descriptor_acl_del(sd, false, trustee);
331 delete the ACE corresponding to the given trustee in the SACL of a
332 security_descriptor
335 NTSTATUS security_descriptor_sacl_del(struct security_descriptor *sd,
336 const struct dom_sid *trustee)
338 return security_descriptor_acl_del(sd, true, trustee);
342 compare two security ace structures
344 bool security_ace_equal(const struct security_ace *ace1,
345 const struct security_ace *ace2)
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;
354 return true;
359 compare two security acl structures
361 bool security_acl_equal(const struct security_acl *acl1,
362 const struct security_acl *acl2)
364 int i;
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;
371 for (i=0;i<acl1->num_aces;i++) {
372 if (!security_ace_equal(&acl1->aces[i], &acl2->aces[i])) return false;
374 return true;
378 compare two security descriptors.
380 bool security_descriptor_equal(const struct security_descriptor *sd1,
381 const struct security_descriptor *sd2)
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;
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;
393 return true;
397 compare two security descriptors, but allow certain (missing) parts
398 to be masked out of the comparison
400 bool security_descriptor_mask_equal(const struct security_descriptor *sd1,
401 const struct security_descriptor *sd2,
402 uint32_t mask)
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;
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;
414 return true;
418 static struct security_descriptor *security_descriptor_appendv(struct security_descriptor *sd,
419 bool add_ace_to_sacl,
420 va_list ap)
422 const char *sidstr;
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;
429 if (ace == NULL) {
430 talloc_free(sd);
431 return NULL;
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;
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);
447 /* TODO: check: would talloc_free(ace) here be correct? */
448 if (!NT_STATUS_IS_OK(status)) {
449 talloc_free(sd);
450 return NULL;
454 return sd;
457 struct security_descriptor *security_descriptor_append(struct security_descriptor *sd,
458 ...)
460 va_list ap;
462 va_start(ap, sd);
463 sd = security_descriptor_appendv(sd, false, ap);
464 va_end(ap);
466 return sd;
469 static 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)
476 struct security_descriptor *sd;
478 sd = security_descriptor_initialise(mem_ctx);
479 if (sd == NULL) {
480 return NULL;
483 sd->type |= sd_type;
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;
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;
500 return security_descriptor_appendv(sd, add_ace_to_sacl, ap);
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.
508 Each ACE contains a set of 4 parameters:
509 SID, ACCESS_TYPE, MASK, FLAGS
511 a typical call would be:
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
525 struct 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 ...)
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);
538 return sd;
541 struct 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 ...)
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);
554 return sd;
557 struct 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)
564 struct dom_sid *sid;
565 struct security_ace *ace;
567 ace = talloc_zero(mem_ctx, struct security_ace);
568 if (ace == NULL) {
569 return NULL;
572 sid = dom_sid_parse_talloc(ace, sid_str);
573 if (sid == NULL) {
574 talloc_free(ace);
575 return NULL;
578 ace->trustee = *sid;
579 ace->type = type;
580 ace->access_mask = access_mask;
581 ace->flags = flags;
583 return ace;