libndr: add support for relative_rap_convert.
[Samba/ekacnet.git] / source3 / lib / secdesc.c
bloba1599a845e2c5fc2b475b87cbe27319d228903b2
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.
8 *
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"
25 /* Map generic permissions to file object specific permissions */
27 const struct generic_mapping file_generic_mapping = {
28 FILE_GENERIC_READ,
29 FILE_GENERIC_WRITE,
30 FILE_GENERIC_EXECUTE,
31 FILE_GENERIC_ALL
34 /*******************************************************************
35 Given a security_descriptor return the sec_info.
36 ********************************************************************/
38 uint32_t get_sec_info(const struct security_descriptor *sd)
40 uint32_t sec_info = ALL_SECURITY_INFORMATION;
42 SMB_ASSERT(sd);
44 if (sd->owner_sid == NULL) {
45 sec_info &= ~OWNER_SECURITY_INFORMATION;
47 if (sd->group_sid == NULL) {
48 sec_info &= ~GROUP_SECURITY_INFORMATION;
50 if (sd->sacl == NULL) {
51 sec_info &= ~SACL_SECURITY_INFORMATION;
53 if (sd->dacl == NULL) {
54 sec_info &= ~DACL_SECURITY_INFORMATION;
57 return sec_info;
61 /*******************************************************************
62 Merge part of security descriptor old_sec in to the empty sections of
63 security descriptor new_sec.
64 ********************************************************************/
66 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
68 struct dom_sid *owner_sid, *group_sid;
69 struct sec_desc_buf *return_sdb;
70 struct security_acl *dacl, *sacl;
71 struct security_descriptor *psd = NULL;
72 uint16 secdesc_type;
73 size_t secdesc_size;
75 /* Copy over owner and group sids. There seems to be no flag for
76 this so just check the pointer values. */
78 owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
79 old_sdb->sd->owner_sid;
81 group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
82 old_sdb->sd->group_sid;
84 secdesc_type = new_sdb->sd->type;
86 /* Ignore changes to the system ACL. This has the effect of making
87 changes through the security tab audit button not sticking.
88 Perhaps in future Samba could implement these settings somehow. */
90 sacl = NULL;
91 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
93 /* Copy across discretionary ACL */
95 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
96 dacl = new_sdb->sd->dacl;
97 } else {
98 dacl = old_sdb->sd->dacl;
101 /* Create new security descriptor from bits */
103 psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
104 owner_sid, group_sid, sacl, dacl, &secdesc_size);
106 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
108 return(return_sdb);
111 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
113 struct dom_sid *owner_sid, *group_sid;
114 struct security_acl *dacl, *sacl;
115 struct security_descriptor *psd = NULL;
116 uint16 secdesc_type;
117 size_t secdesc_size;
119 /* Copy over owner and group sids. There seems to be no flag for
120 this so just check the pointer values. */
122 owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
123 old_sdb->owner_sid;
125 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
126 old_sdb->group_sid;
128 secdesc_type = new_sdb->type;
130 /* Ignore changes to the system ACL. This has the effect of making
131 changes through the security tab audit button not sticking.
132 Perhaps in future Samba could implement these settings somehow. */
134 sacl = NULL;
135 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
137 /* Copy across discretionary ACL */
139 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
140 dacl = new_sdb->dacl;
141 } else {
142 dacl = old_sdb->dacl;
145 /* Create new security descriptor from bits */
146 psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
147 owner_sid, group_sid, sacl, dacl, &secdesc_size);
149 return psd;
152 /*******************************************************************
153 Creates a struct security_descriptor structure
154 ********************************************************************/
156 #define SEC_DESC_HEADER_SIZE (2 * sizeof(uint16) + 4 * sizeof(uint32))
158 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
159 enum security_descriptor_revision revision,
160 uint16 type,
161 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
162 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
164 struct security_descriptor *dst;
165 uint32 offset = 0;
167 *sd_size = 0;
169 if(( dst = TALLOC_ZERO_P(ctx, struct security_descriptor)) == NULL)
170 return NULL;
172 dst->revision = revision;
173 dst->type = type;
175 if (sacl)
176 dst->type |= SEC_DESC_SACL_PRESENT;
177 if (dacl)
178 dst->type |= SEC_DESC_DACL_PRESENT;
180 dst->owner_sid = NULL;
181 dst->group_sid = NULL;
182 dst->sacl = NULL;
183 dst->dacl = NULL;
185 if(owner_sid && ((dst->owner_sid = sid_dup_talloc(dst,owner_sid)) == NULL))
186 goto error_exit;
188 if(grp_sid && ((dst->group_sid = sid_dup_talloc(dst,grp_sid)) == NULL))
189 goto error_exit;
191 if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
192 goto error_exit;
194 if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
195 goto error_exit;
197 offset = SEC_DESC_HEADER_SIZE;
200 * Work out the linearization sizes.
203 if (dst->sacl != NULL) {
204 offset += dst->sacl->size;
206 if (dst->dacl != NULL) {
207 offset += dst->dacl->size;
210 if (dst->owner_sid != NULL) {
211 offset += ndr_size_dom_sid(dst->owner_sid, 0);
214 if (dst->group_sid != NULL) {
215 offset += ndr_size_dom_sid(dst->group_sid, 0);
218 *sd_size = (size_t)offset;
219 return dst;
221 error_exit:
223 *sd_size = 0;
224 return NULL;
227 /*******************************************************************
228 Duplicate a struct security_descriptor structure.
229 ********************************************************************/
231 struct security_descriptor *dup_sec_desc(TALLOC_CTX *ctx, const struct security_descriptor *src)
233 size_t dummy;
235 if(src == NULL)
236 return NULL;
238 return make_sec_desc( ctx, src->revision, src->type,
239 src->owner_sid, src->group_sid, src->sacl,
240 src->dacl, &dummy);
243 /*******************************************************************
244 Convert a secdesc into a byte stream
245 ********************************************************************/
246 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
247 struct security_descriptor *secdesc,
248 uint8 **data, size_t *len)
250 DATA_BLOB blob;
251 enum ndr_err_code ndr_err;
253 ndr_err = ndr_push_struct_blob(
254 &blob, mem_ctx, secdesc,
255 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
257 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
258 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
259 ndr_errstr(ndr_err)));
260 return ndr_map_error2ntstatus(ndr_err);;
263 *data = blob.data;
264 *len = blob.length;
265 return NT_STATUS_OK;
268 /*******************************************************************
269 Convert a secdesc_buf into a byte stream
270 ********************************************************************/
272 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
273 struct sec_desc_buf *secdesc_buf,
274 uint8_t **data, size_t *len)
276 DATA_BLOB blob;
277 enum ndr_err_code ndr_err;
279 ndr_err = ndr_push_struct_blob(
280 &blob, mem_ctx, secdesc_buf,
281 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
283 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
284 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
285 ndr_errstr(ndr_err)));
286 return ndr_map_error2ntstatus(ndr_err);;
289 *data = blob.data;
290 *len = blob.length;
291 return NT_STATUS_OK;
294 /*******************************************************************
295 Parse a byte stream into a secdesc
296 ********************************************************************/
297 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
298 struct security_descriptor **psecdesc)
300 DATA_BLOB blob;
301 enum ndr_err_code ndr_err;
302 struct security_descriptor *result;
304 if ((data == NULL) || (len == 0)) {
305 return NT_STATUS_INVALID_PARAMETER;
308 result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor);
309 if (result == NULL) {
310 return NT_STATUS_NO_MEMORY;
313 blob = data_blob_const(data, len);
315 ndr_err = ndr_pull_struct_blob(&blob, result, result,
316 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
318 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
319 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
320 ndr_errstr(ndr_err)));
321 TALLOC_FREE(result);
322 return ndr_map_error2ntstatus(ndr_err);;
325 *psecdesc = result;
326 return NT_STATUS_OK;
329 /*******************************************************************
330 Parse a byte stream into a sec_desc_buf
331 ********************************************************************/
333 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
334 struct sec_desc_buf **psecdesc_buf)
336 DATA_BLOB blob;
337 enum ndr_err_code ndr_err;
338 struct sec_desc_buf *result;
340 if ((data == NULL) || (len == 0)) {
341 return NT_STATUS_INVALID_PARAMETER;
344 result = TALLOC_ZERO_P(mem_ctx, struct sec_desc_buf);
345 if (result == NULL) {
346 return NT_STATUS_NO_MEMORY;
349 blob = data_blob_const(data, len);
351 ndr_err = ndr_pull_struct_blob(&blob, result, result,
352 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
354 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
355 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
356 ndr_errstr(ndr_err)));
357 TALLOC_FREE(result);
358 return ndr_map_error2ntstatus(ndr_err);;
361 *psecdesc_buf = result;
362 return NT_STATUS_OK;
365 /*******************************************************************
366 Creates a struct security_descriptor structure with typical defaults.
367 ********************************************************************/
369 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
370 struct security_acl *dacl, size_t *sd_size)
372 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
373 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
374 dacl, sd_size);
377 /*******************************************************************
378 Creates a struct sec_desc_buf structure.
379 ********************************************************************/
381 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
383 struct sec_desc_buf *dst;
385 if((dst = TALLOC_ZERO_P(ctx, struct sec_desc_buf)) == NULL)
386 return NULL;
388 /* max buffer size (allocated size) */
389 dst->sd_size = (uint32)len;
391 if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
392 return NULL;
395 return dst;
398 /*******************************************************************
399 Duplicates a struct sec_desc_buf structure.
400 ********************************************************************/
402 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
404 if(src == NULL)
405 return NULL;
407 return make_sec_desc_buf( ctx, src->sd_size, src->sd);
410 /*******************************************************************
411 Add a new SID with its permissions to struct security_descriptor.
412 ********************************************************************/
414 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, uint32 mask, size_t *sd_size)
416 struct security_descriptor *sd = 0;
417 struct security_acl *dacl = 0;
418 struct security_ace *ace = 0;
419 NTSTATUS status;
421 if (!ctx || !psd || !sid || !sd_size)
422 return NT_STATUS_INVALID_PARAMETER;
424 *sd_size = 0;
426 status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
428 if (!NT_STATUS_IS_OK(status))
429 return status;
431 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
432 return NT_STATUS_UNSUCCESSFUL;
434 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
435 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
436 return NT_STATUS_UNSUCCESSFUL;
438 *psd = sd;
439 sd = 0;
440 return NT_STATUS_OK;
443 /*******************************************************************
444 Modify a SID's permissions in a struct security_descriptor.
445 ********************************************************************/
447 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32 mask)
449 NTSTATUS status;
451 if (!sd || !sid)
452 return NT_STATUS_INVALID_PARAMETER;
454 status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
456 if (!NT_STATUS_IS_OK(status))
457 return status;
459 return NT_STATUS_OK;
462 /*******************************************************************
463 Delete a SID from a struct security_descriptor.
464 ********************************************************************/
466 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, size_t *sd_size)
468 struct security_descriptor *sd = 0;
469 struct security_acl *dacl = 0;
470 struct security_ace *ace = 0;
471 NTSTATUS status;
473 if (!ctx || !psd[0] || !sid || !sd_size)
474 return NT_STATUS_INVALID_PARAMETER;
476 *sd_size = 0;
478 status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
480 if (!NT_STATUS_IS_OK(status))
481 return status;
483 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
484 return NT_STATUS_UNSUCCESSFUL;
486 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
487 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
488 return NT_STATUS_UNSUCCESSFUL;
490 *psd = sd;
491 sd = 0;
492 return NT_STATUS_OK;
496 * Determine if an struct security_ace is inheritable
499 static bool is_inheritable_ace(const struct security_ace *ace,
500 bool container)
502 if (!container) {
503 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
506 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
507 return true;
510 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
511 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
512 return true;
515 return false;
519 * Does a security descriptor have any inheritable components for
520 * the newly created type ?
523 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
525 unsigned int i;
526 const struct security_acl *the_acl = parent_ctr->dacl;
528 for (i = 0; i < the_acl->num_aces; i++) {
529 const struct security_ace *ace = &the_acl->aces[i];
531 if (is_inheritable_ace(ace, container)) {
532 return true;
535 return false;
538 /* Create a child security descriptor using another security descriptor as
539 the parent container. This child object can either be a container or
540 non-container object. */
542 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
543 struct security_descriptor **ppsd,
544 size_t *psize,
545 const struct security_descriptor *parent_ctr,
546 const struct dom_sid *owner_sid,
547 const struct dom_sid *group_sid,
548 bool container)
550 struct security_acl *new_dacl = NULL, *the_acl = NULL;
551 struct security_ace *new_ace_list = NULL;
552 unsigned int new_ace_list_ndx = 0, i;
554 *ppsd = NULL;
555 *psize = 0;
557 /* Currently we only process the dacl when creating the child. The
558 sacl should also be processed but this is left out as sacls are
559 not implemented in Samba at the moment.*/
561 the_acl = parent_ctr->dacl;
563 if (the_acl->num_aces) {
564 if (2*the_acl->num_aces < the_acl->num_aces) {
565 return NT_STATUS_NO_MEMORY;
568 if (!(new_ace_list = TALLOC_ARRAY(ctx, struct security_ace,
569 2*the_acl->num_aces))) {
570 return NT_STATUS_NO_MEMORY;
572 } else {
573 new_ace_list = NULL;
576 for (i = 0; i < the_acl->num_aces; i++) {
577 const struct security_ace *ace = &the_acl->aces[i];
578 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
579 const struct dom_sid *ptrustee = &ace->trustee;
580 const struct dom_sid *creator = NULL;
581 uint8 new_flags = ace->flags;
583 if (!is_inheritable_ace(ace, container)) {
584 continue;
587 /* see the RAW-ACLS inheritance test for details on these rules */
588 if (!container) {
589 new_flags = 0;
590 } else {
591 new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
593 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
594 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
596 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
597 new_flags = 0;
601 /* The CREATOR sids are special when inherited */
602 if (sid_equal(ptrustee, &global_sid_Creator_Owner)) {
603 creator = &global_sid_Creator_Owner;
604 ptrustee = owner_sid;
605 } else if (sid_equal(ptrustee, &global_sid_Creator_Group)) {
606 creator = &global_sid_Creator_Group;
607 ptrustee = group_sid;
610 if (creator && container &&
611 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
613 /* First add the regular ACE entry. */
614 init_sec_ace(new_ace, ptrustee, ace->type,
615 ace->access_mask, 0);
617 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
618 " inherited as %s:%d/0x%02x/0x%08x\n",
619 sid_string_dbg(&ace->trustee),
620 ace->type, ace->flags, ace->access_mask,
621 sid_string_dbg(&new_ace->trustee),
622 new_ace->type, new_ace->flags,
623 new_ace->access_mask));
625 new_ace_list_ndx++;
627 /* Now add the extra creator ACE. */
628 new_ace = &new_ace_list[new_ace_list_ndx];
630 ptrustee = creator;
631 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
632 } else if (container &&
633 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
634 ptrustee = &ace->trustee;
637 init_sec_ace(new_ace, ptrustee, ace->type,
638 ace->access_mask, new_flags);
640 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
641 " inherited as %s:%d/0x%02x/0x%08x\n",
642 sid_string_dbg(&ace->trustee),
643 ace->type, ace->flags, ace->access_mask,
644 sid_string_dbg(&ace->trustee),
645 new_ace->type, new_ace->flags,
646 new_ace->access_mask));
648 new_ace_list_ndx++;
651 /* Create child security descriptor to return */
652 if (new_ace_list_ndx) {
653 new_dacl = make_sec_acl(ctx,
654 NT4_ACL_REVISION,
655 new_ace_list_ndx,
656 new_ace_list);
658 if (!new_dacl) {
659 return NT_STATUS_NO_MEMORY;
663 *ppsd = make_sec_desc(ctx,
664 SECURITY_DESCRIPTOR_REVISION_1,
665 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
666 owner_sid,
667 group_sid,
668 NULL,
669 new_dacl,
670 psize);
671 if (!*ppsd) {
672 return NT_STATUS_NO_MEMORY;
674 return NT_STATUS_OK;
677 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
678 struct sec_desc_buf **ppsdb,
679 const struct security_descriptor *parent_ctr,
680 bool container)
682 NTSTATUS status;
683 size_t size = 0;
684 struct security_descriptor *sd = NULL;
686 *ppsdb = NULL;
687 status = se_create_child_secdesc(ctx,
688 &sd,
689 &size,
690 parent_ctr,
691 parent_ctr->owner_sid,
692 parent_ctr->group_sid,
693 container);
694 if (!NT_STATUS_IS_OK(status)) {
695 return status;
698 *ppsdb = make_sec_desc_buf(ctx, size, sd);
699 if (!*ppsdb) {
700 return NT_STATUS_NO_MEMORY;
702 return NT_STATUS_OK;