messaging4: Fix a memleak in an error path
[Samba.git] / libcli / security / secdesc.c
blob052bafbe1d5acb4cf964c210d027333c5883c134
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.
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.
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.
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/>.
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "libcli/security/security.h"
27 #define ALL_SECURITY_INFORMATION (SECINFO_OWNER|SECINFO_GROUP|\
28 SECINFO_DACL|SECINFO_SACL|\
29 SECINFO_UNPROTECTED_SACL|\
30 SECINFO_UNPROTECTED_DACL|\
31 SECINFO_PROTECTED_SACL|\
32 SECINFO_PROTECTED_DACL)
34 /* Map generic permissions to file object specific permissions */
36 const struct generic_mapping file_generic_mapping = {
37 FILE_GENERIC_READ,
38 FILE_GENERIC_WRITE,
39 FILE_GENERIC_EXECUTE,
40 FILE_GENERIC_ALL
43 /*******************************************************************
44 Given a security_descriptor return the sec_info.
45 ********************************************************************/
47 uint32_t get_sec_info(const struct security_descriptor *sd)
49 uint32_t sec_info = ALL_SECURITY_INFORMATION;
51 SMB_ASSERT(sd);
53 if (sd->owner_sid == NULL) {
54 sec_info &= ~SECINFO_OWNER;
56 if (sd->group_sid == NULL) {
57 sec_info &= ~SECINFO_GROUP;
59 if (sd->sacl == NULL) {
60 sec_info &= ~SECINFO_SACL;
62 if (sd->dacl == NULL) {
63 sec_info &= ~SECINFO_DACL;
66 return sec_info;
70 /*******************************************************************
71 Merge part of security descriptor old_sec in to the empty sections of
72 security descriptor new_sec.
73 ********************************************************************/
75 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
77 struct dom_sid *owner_sid, *group_sid;
78 struct sec_desc_buf *return_sdb;
79 struct security_acl *dacl, *sacl;
80 struct security_descriptor *psd = NULL;
81 uint16_t secdesc_type;
82 size_t secdesc_size;
84 /* Copy over owner and group sids. There seems to be no flag for
85 this so just check the pointer values. */
87 owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
88 old_sdb->sd->owner_sid;
90 group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
91 old_sdb->sd->group_sid;
93 secdesc_type = new_sdb->sd->type;
95 /* Ignore changes to the system ACL. This has the effect of making
96 changes through the security tab audit button not sticking.
97 Perhaps in future Samba could implement these settings somehow. */
99 sacl = NULL;
100 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
102 /* Copy across discretionary ACL */
104 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
105 dacl = new_sdb->sd->dacl;
106 } else {
107 dacl = old_sdb->sd->dacl;
110 /* Create new security descriptor from bits */
112 psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
113 owner_sid, group_sid, sacl, dacl, &secdesc_size);
115 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
117 return(return_sdb);
120 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
122 struct dom_sid *owner_sid, *group_sid;
123 struct security_acl *dacl, *sacl;
124 struct security_descriptor *psd = NULL;
125 uint16_t secdesc_type;
126 size_t secdesc_size;
128 /* Copy over owner and group sids. There seems to be no flag for
129 this so just check the pointer values. */
131 owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
132 old_sdb->owner_sid;
134 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
135 old_sdb->group_sid;
137 secdesc_type = new_sdb->type;
139 /* Ignore changes to the system ACL. This has the effect of making
140 changes through the security tab audit button not sticking.
141 Perhaps in future Samba could implement these settings somehow. */
143 sacl = NULL;
144 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
146 /* Copy across discretionary ACL */
148 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
149 dacl = new_sdb->dacl;
150 } else {
151 dacl = old_sdb->dacl;
154 /* Create new security descriptor from bits */
155 psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
156 owner_sid, group_sid, sacl, dacl, &secdesc_size);
158 return psd;
161 /*******************************************************************
162 Creates a struct security_descriptor structure
163 ********************************************************************/
164 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
165 enum security_descriptor_revision revision,
166 uint16_t type,
167 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
168 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
170 struct security_descriptor *dst;
172 if (sd_size != NULL) {
173 *sd_size = 0;
176 dst = security_descriptor_initialise(ctx);
177 if (dst == NULL) {
178 return NULL;
181 dst->revision = revision;
182 dst->type = type;
184 if (sacl != NULL) {
185 dst->sacl = security_acl_dup(dst, sacl);
186 if (dst->sacl == NULL) {
187 goto err_sd_free;
189 dst->type |= SEC_DESC_SACL_PRESENT;
192 if (dacl != NULL) {
193 dst->dacl = security_acl_dup(dst, dacl);
194 if (dst->dacl == NULL) {
195 goto err_sd_free;
197 dst->type |= SEC_DESC_DACL_PRESENT;
200 if (owner_sid != NULL) {
201 dst->owner_sid = dom_sid_dup(dst, owner_sid);
202 if (dst->owner_sid == NULL) {
203 goto err_sd_free;
207 if (grp_sid != NULL) {
208 dst->group_sid = dom_sid_dup(dst, grp_sid);
209 if (dst->group_sid == NULL) {
210 goto err_sd_free;
214 if (sd_size != NULL) {
215 *sd_size = ndr_size_security_descriptor(dst, 0);
218 return dst;
220 err_sd_free:
221 talloc_free(dst);
222 return NULL;
225 /*******************************************************************
226 Convert a secdesc into a byte stream
227 ********************************************************************/
228 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
229 const struct security_descriptor *secdesc,
230 uint8_t **data, size_t *len)
232 DATA_BLOB blob;
233 enum ndr_err_code ndr_err;
235 ndr_err = ndr_push_struct_blob(
236 &blob, mem_ctx, secdesc,
237 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
239 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
240 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
241 ndr_errstr(ndr_err)));
242 return ndr_map_error2ntstatus(ndr_err);
245 *data = blob.data;
246 *len = blob.length;
247 return NT_STATUS_OK;
250 /*******************************************************************
251 Convert a secdesc_buf into a byte stream
252 ********************************************************************/
254 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
255 const struct sec_desc_buf *secdesc_buf,
256 uint8_t **data, size_t *len)
258 DATA_BLOB blob;
259 enum ndr_err_code ndr_err;
261 ndr_err = ndr_push_struct_blob(
262 &blob, mem_ctx, secdesc_buf,
263 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
265 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
266 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
267 ndr_errstr(ndr_err)));
268 return ndr_map_error2ntstatus(ndr_err);
271 *data = blob.data;
272 *len = blob.length;
273 return NT_STATUS_OK;
276 /*******************************************************************
277 Parse a byte stream into a secdesc
278 ********************************************************************/
279 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
280 struct security_descriptor **psecdesc)
282 DATA_BLOB blob;
283 enum ndr_err_code ndr_err;
284 struct security_descriptor *result;
286 if ((data == NULL) || (len == 0)) {
287 return NT_STATUS_INVALID_PARAMETER;
290 result = talloc_zero(mem_ctx, struct security_descriptor);
291 if (result == NULL) {
292 return NT_STATUS_NO_MEMORY;
295 blob = data_blob_const(data, len);
297 ndr_err = ndr_pull_struct_blob(&blob, result, result,
298 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
300 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
301 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
302 ndr_errstr(ndr_err)));
303 TALLOC_FREE(result);
304 return ndr_map_error2ntstatus(ndr_err);
307 *psecdesc = result;
308 return NT_STATUS_OK;
311 /*******************************************************************
312 Parse a byte stream into a sec_desc_buf
313 ********************************************************************/
315 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
316 struct sec_desc_buf **psecdesc_buf)
318 DATA_BLOB blob;
319 enum ndr_err_code ndr_err;
320 struct sec_desc_buf *result;
322 if ((data == NULL) || (len == 0)) {
323 return NT_STATUS_INVALID_PARAMETER;
326 result = talloc_zero(mem_ctx, struct sec_desc_buf);
327 if (result == NULL) {
328 return NT_STATUS_NO_MEMORY;
331 blob = data_blob_const(data, len);
333 ndr_err = ndr_pull_struct_blob(&blob, result, result,
334 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
336 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
337 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
338 ndr_errstr(ndr_err)));
339 TALLOC_FREE(result);
340 return ndr_map_error2ntstatus(ndr_err);
343 *psecdesc_buf = result;
344 return NT_STATUS_OK;
347 /*******************************************************************
348 Creates a struct security_descriptor structure with typical defaults.
349 ********************************************************************/
351 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
352 struct security_acl *dacl, size_t *sd_size)
354 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
355 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
356 dacl, sd_size);
359 /*******************************************************************
360 Creates a struct sec_desc_buf structure.
361 ********************************************************************/
363 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
365 struct sec_desc_buf *dst;
367 if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL)
368 return NULL;
370 /* max buffer size (allocated size) */
371 dst->sd_size = (uint32_t)len;
373 if (sec_desc != NULL) {
374 dst->sd = security_descriptor_copy(ctx, sec_desc);
375 if (dst->sd == NULL) {
376 return NULL;
380 return dst;
383 /*******************************************************************
384 Duplicates a struct sec_desc_buf structure.
385 ********************************************************************/
387 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
389 if(src == NULL)
390 return NULL;
392 return make_sec_desc_buf( ctx, src->sd_size, src->sd);
395 /*******************************************************************
396 Modify a SID's permissions in a struct security_descriptor.
397 ********************************************************************/
399 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32_t mask)
401 NTSTATUS status;
403 if (!sd || !sid)
404 return NT_STATUS_INVALID_PARAMETER;
406 status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
408 if (!NT_STATUS_IS_OK(status))
409 return status;
411 return NT_STATUS_OK;
415 * Determine if an struct security_ace is inheritable
418 static bool is_inheritable_ace(const struct security_ace *ace,
419 bool container)
421 if (!container) {
422 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
425 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
426 return true;
429 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
430 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
431 return true;
434 return false;
438 * Does a security descriptor have any inheritable components for
439 * the newly created type ?
442 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
444 unsigned int i;
445 const struct security_acl *the_acl = parent_ctr->dacl;
447 if (the_acl == NULL) {
448 return false;
451 for (i = 0; i < the_acl->num_aces; i++) {
452 const struct security_ace *ace = &the_acl->aces[i];
454 if (is_inheritable_ace(ace, container)) {
455 return true;
458 return false;
461 /* Create a child security descriptor using another security descriptor as
462 the parent container. This child object can either be a container or
463 non-container object. */
465 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
466 struct security_descriptor **ppsd,
467 size_t *psize,
468 const struct security_descriptor *parent_ctr,
469 const struct dom_sid *owner_sid,
470 const struct dom_sid *group_sid,
471 bool container)
473 struct security_acl *new_dacl = NULL, *the_acl = NULL;
474 struct security_ace *new_ace_list = NULL;
475 unsigned int new_ace_list_ndx = 0, i;
476 bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED);
478 TALLOC_CTX *frame;
480 *ppsd = NULL;
481 *psize = 0;
483 /* Currently we only process the dacl when creating the child. The
484 sacl should also be processed but this is left out as sacls are
485 not implemented in Samba at the moment.*/
487 the_acl = parent_ctr->dacl;
489 if (the_acl->num_aces) {
490 if (2*the_acl->num_aces < the_acl->num_aces) {
491 return NT_STATUS_NO_MEMORY;
494 if (!(new_ace_list = talloc_array(ctx, struct security_ace,
495 2*the_acl->num_aces))) {
496 return NT_STATUS_NO_MEMORY;
498 } else {
499 new_ace_list = NULL;
502 frame = talloc_stackframe();
504 for (i = 0; i < the_acl->num_aces; i++) {
505 const struct security_ace *ace = &the_acl->aces[i];
506 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
507 const struct dom_sid *ptrustee = &ace->trustee;
508 const struct dom_sid *creator = NULL;
509 uint8_t new_flags = ace->flags;
511 if (!is_inheritable_ace(ace, container)) {
512 continue;
515 /* see the RAW-ACLS inheritance test for details on these rules */
516 if (!container) {
517 new_flags = 0;
518 } else {
520 * We need to remove SEC_ACE_FLAG_INHERITED_ACE here
521 * if present because it should only be set if the
522 * parent has the AUTO_INHERITED bit set in the
523 * type/control field. If we don't it will slip through
524 * and create DACLs with incorrectly ordered ACEs
525 * when there are CREATOR_OWNER or CREATOR_GROUP
526 * ACEs.
528 new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY
529 | SEC_ACE_FLAG_INHERITED_ACE);
531 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
532 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
534 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
535 new_flags = 0;
539 /* The CREATOR sids are special when inherited */
540 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
541 creator = &global_sid_Creator_Owner;
542 ptrustee = owner_sid;
543 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
544 creator = &global_sid_Creator_Group;
545 ptrustee = group_sid;
548 if (creator && container &&
549 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
551 /* First add the regular ACE entry. */
552 init_sec_ace(new_ace, ptrustee, ace->type,
553 ace->access_mask,
554 set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
556 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
557 " inherited as %s:%d/0x%02x/0x%08x\n",
558 dom_sid_string(frame, &ace->trustee),
559 ace->type, ace->flags, ace->access_mask,
560 dom_sid_string(frame, &new_ace->trustee),
561 new_ace->type, new_ace->flags,
562 new_ace->access_mask));
564 new_ace_list_ndx++;
566 /* Now add the extra creator ACE. */
567 new_ace = &new_ace_list[new_ace_list_ndx];
569 ptrustee = creator;
570 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
572 } else if (container &&
573 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
574 ptrustee = &ace->trustee;
577 init_sec_ace(new_ace, ptrustee, ace->type,
578 ace->access_mask, new_flags |
579 (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
581 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
582 " inherited as %s:%d/0x%02x/0x%08x\n",
583 dom_sid_string(frame, &ace->trustee),
584 ace->type, ace->flags, ace->access_mask,
585 dom_sid_string(frame, &ace->trustee),
586 new_ace->type, new_ace->flags,
587 new_ace->access_mask));
589 new_ace_list_ndx++;
592 talloc_free(frame);
595 * remove duplicates
597 for (i=1; i < new_ace_list_ndx;) {
598 struct security_ace *ai = &new_ace_list[i];
599 unsigned int remaining, j;
600 bool remove_ace = false;
602 for (j=0; j < i; j++) {
603 struct security_ace *aj = &new_ace_list[j];
605 if (!security_ace_equal(ai, aj)) {
606 continue;
609 remove_ace = true;
610 break;
613 if (!remove_ace) {
614 i++;
615 continue;
618 new_ace_list_ndx--;
619 remaining = new_ace_list_ndx - i;
620 if (remaining == 0) {
621 ZERO_STRUCT(new_ace_list[i]);
622 continue;
624 memmove(&new_ace_list[i], &new_ace_list[i+1],
625 sizeof(new_ace_list[i]) * remaining);
628 /* Create child security descriptor to return */
629 if (new_ace_list_ndx) {
630 new_dacl = make_sec_acl(ctx,
631 NT4_ACL_REVISION,
632 new_ace_list_ndx,
633 new_ace_list);
635 if (!new_dacl) {
636 return NT_STATUS_NO_MEMORY;
640 *ppsd = make_sec_desc(ctx,
641 SECURITY_DESCRIPTOR_REVISION_1,
642 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
643 (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
644 owner_sid,
645 group_sid,
646 NULL,
647 new_dacl,
648 psize);
649 if (!*ppsd) {
650 return NT_STATUS_NO_MEMORY;
652 return NT_STATUS_OK;
655 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
656 struct sec_desc_buf **ppsdb,
657 const struct security_descriptor *parent_ctr,
658 bool container)
660 NTSTATUS status;
661 size_t size = 0;
662 struct security_descriptor *sd = NULL;
664 *ppsdb = NULL;
665 status = se_create_child_secdesc(ctx,
666 &sd,
667 &size,
668 parent_ctr,
669 parent_ctr->owner_sid,
670 parent_ctr->group_sid,
671 container);
672 if (!NT_STATUS_IS_OK(status)) {
673 return status;
676 *ppsdb = make_sec_desc_buf(ctx, size, sd);
677 if (!*ppsdb) {
678 return NT_STATUS_NO_MEMORY;
680 return NT_STATUS_OK;