third_party: Only link cmocka against librt if really needed
[Samba.git] / libcli / security / secdesc.c
blobcd944306ee165af34df7c5b23c0c41721f747b99
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 /* Map generic permissions to file object specific permissions */
29 const struct generic_mapping file_generic_mapping = {
30 FILE_GENERIC_READ,
31 FILE_GENERIC_WRITE,
32 FILE_GENERIC_EXECUTE,
33 FILE_GENERIC_ALL
36 /*******************************************************************
37 Given a security_descriptor return the sec_info.
38 ********************************************************************/
40 uint32_t get_sec_info(const struct security_descriptor *sd)
42 uint32_t sec_info = 0;
44 SMB_ASSERT(sd);
46 if (sd->owner_sid != NULL) {
47 sec_info |= SECINFO_OWNER;
49 if (sd->group_sid != NULL) {
50 sec_info |= SECINFO_GROUP;
52 if (sd->sacl != NULL) {
53 sec_info |= SECINFO_SACL;
55 if (sd->dacl != NULL) {
56 sec_info |= SECINFO_DACL;
59 if (sd->type & SEC_DESC_SACL_PROTECTED) {
60 sec_info |= SECINFO_PROTECTED_SACL;
61 } else if (sd->type & SEC_DESC_SACL_AUTO_INHERITED) {
62 sec_info |= SECINFO_UNPROTECTED_SACL;
64 if (sd->type & SEC_DESC_DACL_PROTECTED) {
65 sec_info |= SECINFO_PROTECTED_DACL;
66 } else if (sd->type & SEC_DESC_DACL_AUTO_INHERITED) {
67 sec_info |= SECINFO_UNPROTECTED_DACL;
70 return sec_info;
74 /*******************************************************************
75 Merge part of security descriptor old_sec in to the empty sections of
76 security descriptor new_sec.
77 ********************************************************************/
79 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
81 struct dom_sid *owner_sid, *group_sid;
82 struct sec_desc_buf *return_sdb;
83 struct security_acl *dacl, *sacl;
84 struct security_descriptor *psd = NULL;
85 uint16_t secdesc_type;
86 size_t secdesc_size;
88 /* Copy over owner and group sids. There seems to be no flag for
89 this so just check the pointer values. */
91 owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
92 old_sdb->sd->owner_sid;
94 group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
95 old_sdb->sd->group_sid;
97 secdesc_type = new_sdb->sd->type;
99 /* Ignore changes to the system ACL. This has the effect of making
100 changes through the security tab audit button not sticking.
101 Perhaps in future Samba could implement these settings somehow. */
103 sacl = NULL;
104 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
106 /* Copy across discretionary ACL */
108 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
109 dacl = new_sdb->sd->dacl;
110 } else {
111 dacl = old_sdb->sd->dacl;
114 /* Create new security descriptor from bits */
116 psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
117 owner_sid, group_sid, sacl, dacl, &secdesc_size);
119 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
121 return(return_sdb);
124 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
126 struct dom_sid *owner_sid, *group_sid;
127 struct security_acl *dacl, *sacl;
128 struct security_descriptor *psd = NULL;
129 uint16_t secdesc_type;
130 size_t secdesc_size;
132 /* Copy over owner and group sids. There seems to be no flag for
133 this so just check the pointer values. */
135 owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
136 old_sdb->owner_sid;
138 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
139 old_sdb->group_sid;
141 secdesc_type = new_sdb->type;
143 /* Ignore changes to the system ACL. This has the effect of making
144 changes through the security tab audit button not sticking.
145 Perhaps in future Samba could implement these settings somehow. */
147 sacl = NULL;
148 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
150 /* Copy across discretionary ACL */
152 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
153 dacl = new_sdb->dacl;
154 } else {
155 dacl = old_sdb->dacl;
158 /* Create new security descriptor from bits */
159 psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
160 owner_sid, group_sid, sacl, dacl, &secdesc_size);
162 return psd;
165 /*******************************************************************
166 Creates a struct security_descriptor structure
167 ********************************************************************/
168 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
169 enum security_descriptor_revision revision,
170 uint16_t type,
171 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
172 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
174 struct security_descriptor *dst;
176 if (sd_size != NULL) {
177 *sd_size = 0;
180 dst = security_descriptor_initialise(ctx);
181 if (dst == NULL) {
182 return NULL;
185 dst->revision = revision;
186 dst->type = type;
188 if (sacl != NULL) {
189 dst->sacl = security_acl_dup(dst, sacl);
190 if (dst->sacl == NULL) {
191 goto err_sd_free;
193 dst->type |= SEC_DESC_SACL_PRESENT;
196 if (dacl != NULL) {
197 dst->dacl = security_acl_dup(dst, dacl);
198 if (dst->dacl == NULL) {
199 goto err_sd_free;
201 dst->type |= SEC_DESC_DACL_PRESENT;
204 if (owner_sid != NULL) {
205 dst->owner_sid = dom_sid_dup(dst, owner_sid);
206 if (dst->owner_sid == NULL) {
207 goto err_sd_free;
211 if (grp_sid != NULL) {
212 dst->group_sid = dom_sid_dup(dst, grp_sid);
213 if (dst->group_sid == NULL) {
214 goto err_sd_free;
218 if (sd_size != NULL) {
219 *sd_size = ndr_size_security_descriptor(dst, 0);
222 return dst;
224 err_sd_free:
225 talloc_free(dst);
226 return NULL;
229 /*******************************************************************
230 Convert a secdesc into a byte stream
231 ********************************************************************/
232 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
233 const struct security_descriptor *secdesc,
234 uint8_t **data, size_t *len)
236 DATA_BLOB blob;
237 enum ndr_err_code ndr_err;
239 ndr_err = ndr_push_struct_blob(
240 &blob, mem_ctx, secdesc,
241 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
243 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
244 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
245 ndr_errstr(ndr_err)));
246 return ndr_map_error2ntstatus(ndr_err);
249 *data = blob.data;
250 *len = blob.length;
251 return NT_STATUS_OK;
254 /*******************************************************************
255 Convert a secdesc_buf into a byte stream
256 ********************************************************************/
258 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
259 const struct sec_desc_buf *secdesc_buf,
260 uint8_t **data, size_t *len)
262 DATA_BLOB blob;
263 enum ndr_err_code ndr_err;
265 ndr_err = ndr_push_struct_blob(
266 &blob, mem_ctx, secdesc_buf,
267 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
269 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
270 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
271 ndr_errstr(ndr_err)));
272 return ndr_map_error2ntstatus(ndr_err);
275 *data = blob.data;
276 *len = blob.length;
277 return NT_STATUS_OK;
280 /*******************************************************************
281 Parse a byte stream into a secdesc
282 ********************************************************************/
283 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
284 struct security_descriptor **psecdesc)
286 DATA_BLOB blob;
287 enum ndr_err_code ndr_err;
288 struct security_descriptor *result;
290 if ((data == NULL) || (len == 0)) {
291 return NT_STATUS_INVALID_PARAMETER;
294 result = talloc_zero(mem_ctx, struct security_descriptor);
295 if (result == NULL) {
296 return NT_STATUS_NO_MEMORY;
299 blob = data_blob_const(data, len);
301 ndr_err = ndr_pull_struct_blob(&blob, result, result,
302 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
304 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
305 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
306 ndr_errstr(ndr_err)));
307 TALLOC_FREE(result);
308 return ndr_map_error2ntstatus(ndr_err);
311 *psecdesc = result;
312 return NT_STATUS_OK;
315 /*******************************************************************
316 Parse a byte stream into a sec_desc_buf
317 ********************************************************************/
319 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
320 struct sec_desc_buf **psecdesc_buf)
322 DATA_BLOB blob;
323 enum ndr_err_code ndr_err;
324 struct sec_desc_buf *result;
326 if ((data == NULL) || (len == 0)) {
327 return NT_STATUS_INVALID_PARAMETER;
330 result = talloc_zero(mem_ctx, struct sec_desc_buf);
331 if (result == NULL) {
332 return NT_STATUS_NO_MEMORY;
335 blob = data_blob_const(data, len);
337 ndr_err = ndr_pull_struct_blob(&blob, result, result,
338 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
340 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
342 ndr_errstr(ndr_err)));
343 TALLOC_FREE(result);
344 return ndr_map_error2ntstatus(ndr_err);
347 *psecdesc_buf = result;
348 return NT_STATUS_OK;
351 /*******************************************************************
352 Creates a struct security_descriptor structure with typical defaults.
353 ********************************************************************/
355 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
356 struct security_acl *dacl, size_t *sd_size)
358 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
359 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
360 dacl, sd_size);
363 /*******************************************************************
364 Creates a struct sec_desc_buf structure.
365 ********************************************************************/
367 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
369 struct sec_desc_buf *dst;
371 if((dst = talloc_zero(ctx, struct sec_desc_buf)) == NULL)
372 return NULL;
374 /* max buffer size (allocated size) */
375 dst->sd_size = (uint32_t)len;
377 if (sec_desc != NULL) {
378 dst->sd = security_descriptor_copy(ctx, sec_desc);
379 if (dst->sd == NULL) {
380 return NULL;
384 return dst;
388 * Determine if an struct security_ace is inheritable
391 static bool is_inheritable_ace(const struct security_ace *ace,
392 bool container)
394 if (!container) {
395 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
398 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
399 return true;
402 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
403 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
404 return true;
407 return false;
411 * Does a security descriptor have any inheritable components for
412 * the newly created type ?
415 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
417 unsigned int i;
418 const struct security_acl *the_acl = parent_ctr->dacl;
420 if (the_acl == NULL) {
421 return false;
424 for (i = 0; i < the_acl->num_aces; i++) {
425 const struct security_ace *ace = &the_acl->aces[i];
427 if (is_inheritable_ace(ace, container)) {
428 return true;
431 return false;
434 /* Create a child security descriptor using another security descriptor as
435 the parent container. This child object can either be a container or
436 non-container object. */
438 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
439 struct security_descriptor **ppsd,
440 size_t *psize,
441 const struct security_descriptor *parent_ctr,
442 const struct dom_sid *owner_sid,
443 const struct dom_sid *group_sid,
444 bool container)
446 struct security_acl *new_dacl = NULL, *the_acl = NULL;
447 struct security_ace *new_ace_list = NULL;
448 unsigned int new_ace_list_ndx = 0, i;
449 bool set_inherited_flags = (parent_ctr->type & SEC_DESC_DACL_AUTO_INHERITED);
451 TALLOC_CTX *frame;
453 *ppsd = NULL;
454 *psize = 0;
456 /* Currently we only process the dacl when creating the child. The
457 sacl should also be processed but this is left out as sacls are
458 not implemented in Samba at the moment.*/
460 the_acl = parent_ctr->dacl;
462 if (the_acl->num_aces) {
463 if (2*the_acl->num_aces < the_acl->num_aces) {
464 return NT_STATUS_NO_MEMORY;
467 if (!(new_ace_list = talloc_array(ctx, struct security_ace,
468 2*the_acl->num_aces))) {
469 return NT_STATUS_NO_MEMORY;
471 } else {
472 new_ace_list = NULL;
475 frame = talloc_stackframe();
477 for (i = 0; i < the_acl->num_aces; i++) {
478 const struct security_ace *ace = &the_acl->aces[i];
479 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
480 const struct dom_sid *ptrustee = &ace->trustee;
481 const struct dom_sid *creator = NULL;
482 uint8_t new_flags = ace->flags;
483 struct dom_sid_buf sidbuf1, sidbuf2;
485 if (!is_inheritable_ace(ace, container)) {
486 continue;
489 /* see the RAW-ACLS inheritance test for details on these rules */
490 if (!container) {
491 new_flags = 0;
492 } else {
494 * We need to remove SEC_ACE_FLAG_INHERITED_ACE here
495 * if present because it should only be set if the
496 * parent has the AUTO_INHERITED bit set in the
497 * type/control field. If we don't it will slip through
498 * and create DACLs with incorrectly ordered ACEs
499 * when there are CREATOR_OWNER or CREATOR_GROUP
500 * ACEs.
502 new_flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY
503 | SEC_ACE_FLAG_INHERITED_ACE);
505 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
506 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
508 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
509 new_flags = 0;
513 /* The CREATOR sids are special when inherited */
514 if (dom_sid_equal(ptrustee, &global_sid_Creator_Owner)) {
515 creator = &global_sid_Creator_Owner;
516 ptrustee = owner_sid;
517 } else if (dom_sid_equal(ptrustee, &global_sid_Creator_Group)) {
518 creator = &global_sid_Creator_Group;
519 ptrustee = group_sid;
522 if (creator && container &&
523 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
525 /* First add the regular ACE entry. */
526 init_sec_ace(new_ace, ptrustee, ace->type,
527 ace->access_mask,
528 set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0);
530 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
531 " inherited as %s:%d/0x%02x/0x%08x\n",
532 dom_sid_str_buf(&ace->trustee, &sidbuf1),
533 ace->type, ace->flags, ace->access_mask,
534 dom_sid_str_buf(&new_ace->trustee, &sidbuf2),
535 new_ace->type, new_ace->flags,
536 new_ace->access_mask));
538 new_ace_list_ndx++;
540 /* Now add the extra creator ACE. */
541 new_ace = &new_ace_list[new_ace_list_ndx];
543 ptrustee = creator;
544 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
546 } else if (container &&
547 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
548 ptrustee = &ace->trustee;
551 init_sec_ace(new_ace, ptrustee, ace->type,
552 ace->access_mask, new_flags |
553 (set_inherited_flags ? SEC_ACE_FLAG_INHERITED_ACE : 0));
555 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
556 " inherited as %s:%d/0x%02x/0x%08x\n",
557 dom_sid_str_buf(&ace->trustee, &sidbuf1),
558 ace->type, ace->flags, ace->access_mask,
559 dom_sid_str_buf(&new_ace->trustee, &sidbuf2),
560 new_ace->type, new_ace->flags,
561 new_ace->access_mask));
563 new_ace_list_ndx++;
566 talloc_free(frame);
569 * remove duplicates
571 for (i=1; i < new_ace_list_ndx;) {
572 struct security_ace *ai = &new_ace_list[i];
573 unsigned int remaining, j;
574 bool remove_ace = false;
576 for (j=0; j < i; j++) {
577 struct security_ace *aj = &new_ace_list[j];
579 if (!security_ace_equal(ai, aj)) {
580 continue;
583 remove_ace = true;
584 break;
587 if (!remove_ace) {
588 i++;
589 continue;
592 new_ace_list_ndx--;
593 remaining = new_ace_list_ndx - i;
594 if (remaining == 0) {
595 ZERO_STRUCT(new_ace_list[i]);
596 continue;
598 memmove(&new_ace_list[i], &new_ace_list[i+1],
599 sizeof(new_ace_list[i]) * remaining);
602 /* Create child security descriptor to return */
603 if (new_ace_list_ndx) {
604 new_dacl = make_sec_acl(ctx,
605 NT4_ACL_REVISION,
606 new_ace_list_ndx,
607 new_ace_list);
609 if (!new_dacl) {
610 return NT_STATUS_NO_MEMORY;
614 *ppsd = make_sec_desc(ctx,
615 SECURITY_DESCRIPTOR_REVISION_1,
616 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT|
617 (set_inherited_flags ? SEC_DESC_DACL_AUTO_INHERITED : 0),
618 owner_sid,
619 group_sid,
620 NULL,
621 new_dacl,
622 psize);
623 if (!*ppsd) {
624 return NT_STATUS_NO_MEMORY;
626 return NT_STATUS_OK;