s3-security: move ALL_SECURITY_INFORMATION to the only user.
[Samba/ekacnet.git] / source3 / lib / secdesc.c
blobb9ed955dee04bbbe961d39ebc68ce2be539c19fe
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"
24 #include "../librpc/gen_ndr/ndr_security.h"
26 #define ALL_SECURITY_INFORMATION (SECINFO_OWNER|SECINFO_GROUP|\
27 SECINFO_DACL|SECINFO_SACL|\
28 SECINFO_UNPROTECTED_SACL|\
29 SECINFO_UNPROTECTED_DACL|\
30 SECINFO_PROTECTED_SACL|\
31 SECINFO_PROTECTED_DACL)
33 /* Map generic permissions to file object specific permissions */
35 const struct generic_mapping file_generic_mapping = {
36 FILE_GENERIC_READ,
37 FILE_GENERIC_WRITE,
38 FILE_GENERIC_EXECUTE,
39 FILE_GENERIC_ALL
42 /*******************************************************************
43 Given a security_descriptor return the sec_info.
44 ********************************************************************/
46 uint32_t get_sec_info(const struct security_descriptor *sd)
48 uint32_t sec_info = ALL_SECURITY_INFORMATION;
50 SMB_ASSERT(sd);
52 if (sd->owner_sid == NULL) {
53 sec_info &= ~SECINFO_OWNER;
55 if (sd->group_sid == NULL) {
56 sec_info &= ~SECINFO_GROUP;
58 if (sd->sacl == NULL) {
59 sec_info &= ~SECINFO_SACL;
61 if (sd->dacl == NULL) {
62 sec_info &= ~SECINFO_DACL;
65 return sec_info;
69 /*******************************************************************
70 Merge part of security descriptor old_sec in to the empty sections of
71 security descriptor new_sec.
72 ********************************************************************/
74 struct sec_desc_buf *sec_desc_merge_buf(TALLOC_CTX *ctx, struct sec_desc_buf *new_sdb, struct sec_desc_buf *old_sdb)
76 struct dom_sid *owner_sid, *group_sid;
77 struct sec_desc_buf *return_sdb;
78 struct security_acl *dacl, *sacl;
79 struct security_descriptor *psd = NULL;
80 uint16 secdesc_type;
81 size_t secdesc_size;
83 /* Copy over owner and group sids. There seems to be no flag for
84 this so just check the pointer values. */
86 owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
87 old_sdb->sd->owner_sid;
89 group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
90 old_sdb->sd->group_sid;
92 secdesc_type = new_sdb->sd->type;
94 /* Ignore changes to the system ACL. This has the effect of making
95 changes through the security tab audit button not sticking.
96 Perhaps in future Samba could implement these settings somehow. */
98 sacl = NULL;
99 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
101 /* Copy across discretionary ACL */
103 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
104 dacl = new_sdb->sd->dacl;
105 } else {
106 dacl = old_sdb->sd->dacl;
109 /* Create new security descriptor from bits */
111 psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
112 owner_sid, group_sid, sacl, dacl, &secdesc_size);
114 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
116 return(return_sdb);
119 struct security_descriptor *sec_desc_merge(TALLOC_CTX *ctx, struct security_descriptor *new_sdb, struct security_descriptor *old_sdb)
121 struct dom_sid *owner_sid, *group_sid;
122 struct security_acl *dacl, *sacl;
123 struct security_descriptor *psd = NULL;
124 uint16 secdesc_type;
125 size_t secdesc_size;
127 /* Copy over owner and group sids. There seems to be no flag for
128 this so just check the pointer values. */
130 owner_sid = new_sdb->owner_sid ? new_sdb->owner_sid :
131 old_sdb->owner_sid;
133 group_sid = new_sdb->group_sid ? new_sdb->group_sid :
134 old_sdb->group_sid;
136 secdesc_type = new_sdb->type;
138 /* Ignore changes to the system ACL. This has the effect of making
139 changes through the security tab audit button not sticking.
140 Perhaps in future Samba could implement these settings somehow. */
142 sacl = NULL;
143 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
145 /* Copy across discretionary ACL */
147 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
148 dacl = new_sdb->dacl;
149 } else {
150 dacl = old_sdb->dacl;
153 /* Create new security descriptor from bits */
154 psd = make_sec_desc(ctx, new_sdb->revision, secdesc_type,
155 owner_sid, group_sid, sacl, dacl, &secdesc_size);
157 return psd;
160 /*******************************************************************
161 Creates a struct security_descriptor structure
162 ********************************************************************/
164 #define SEC_DESC_HEADER_SIZE (2 * sizeof(uint16) + 4 * sizeof(uint32))
166 struct security_descriptor *make_sec_desc(TALLOC_CTX *ctx,
167 enum security_descriptor_revision revision,
168 uint16 type,
169 const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
170 struct security_acl *sacl, struct security_acl *dacl, size_t *sd_size)
172 struct security_descriptor *dst;
173 uint32 offset = 0;
175 *sd_size = 0;
177 if(( dst = TALLOC_ZERO_P(ctx, struct security_descriptor)) == NULL)
178 return NULL;
180 dst->revision = revision;
181 dst->type = type;
183 if (sacl)
184 dst->type |= SEC_DESC_SACL_PRESENT;
185 if (dacl)
186 dst->type |= SEC_DESC_DACL_PRESENT;
188 dst->owner_sid = NULL;
189 dst->group_sid = NULL;
190 dst->sacl = NULL;
191 dst->dacl = NULL;
193 if(owner_sid && ((dst->owner_sid = sid_dup_talloc(dst,owner_sid)) == NULL))
194 goto error_exit;
196 if(grp_sid && ((dst->group_sid = sid_dup_talloc(dst,grp_sid)) == NULL))
197 goto error_exit;
199 if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
200 goto error_exit;
202 if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
203 goto error_exit;
205 offset = SEC_DESC_HEADER_SIZE;
208 * Work out the linearization sizes.
211 if (dst->sacl != NULL) {
212 offset += dst->sacl->size;
214 if (dst->dacl != NULL) {
215 offset += dst->dacl->size;
218 if (dst->owner_sid != NULL) {
219 offset += ndr_size_dom_sid(dst->owner_sid, 0);
222 if (dst->group_sid != NULL) {
223 offset += ndr_size_dom_sid(dst->group_sid, 0);
226 *sd_size = (size_t)offset;
227 return dst;
229 error_exit:
231 *sd_size = 0;
232 return NULL;
235 /*******************************************************************
236 Duplicate a struct security_descriptor structure.
237 ********************************************************************/
239 struct security_descriptor *dup_sec_desc(TALLOC_CTX *ctx, const struct security_descriptor *src)
241 size_t dummy;
243 if(src == NULL)
244 return NULL;
246 return make_sec_desc( ctx, src->revision, src->type,
247 src->owner_sid, src->group_sid, src->sacl,
248 src->dacl, &dummy);
251 /*******************************************************************
252 Convert a secdesc into a byte stream
253 ********************************************************************/
254 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
255 struct security_descriptor *secdesc,
256 uint8 **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,
263 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
265 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
266 DEBUG(0, ("ndr_push_security_descriptor 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 Convert a secdesc_buf into a byte stream
278 ********************************************************************/
280 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
281 struct sec_desc_buf *secdesc_buf,
282 uint8_t **data, size_t *len)
284 DATA_BLOB blob;
285 enum ndr_err_code ndr_err;
287 ndr_err = ndr_push_struct_blob(
288 &blob, mem_ctx, secdesc_buf,
289 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
291 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
292 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
293 ndr_errstr(ndr_err)));
294 return ndr_map_error2ntstatus(ndr_err);;
297 *data = blob.data;
298 *len = blob.length;
299 return NT_STATUS_OK;
302 /*******************************************************************
303 Parse a byte stream into a secdesc
304 ********************************************************************/
305 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
306 struct security_descriptor **psecdesc)
308 DATA_BLOB blob;
309 enum ndr_err_code ndr_err;
310 struct security_descriptor *result;
312 if ((data == NULL) || (len == 0)) {
313 return NT_STATUS_INVALID_PARAMETER;
316 result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor);
317 if (result == NULL) {
318 return NT_STATUS_NO_MEMORY;
321 blob = data_blob_const(data, len);
323 ndr_err = ndr_pull_struct_blob(&blob, result, result,
324 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
326 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
327 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
328 ndr_errstr(ndr_err)));
329 TALLOC_FREE(result);
330 return ndr_map_error2ntstatus(ndr_err);;
333 *psecdesc = result;
334 return NT_STATUS_OK;
337 /*******************************************************************
338 Parse a byte stream into a sec_desc_buf
339 ********************************************************************/
341 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
342 struct sec_desc_buf **psecdesc_buf)
344 DATA_BLOB blob;
345 enum ndr_err_code ndr_err;
346 struct sec_desc_buf *result;
348 if ((data == NULL) || (len == 0)) {
349 return NT_STATUS_INVALID_PARAMETER;
352 result = TALLOC_ZERO_P(mem_ctx, struct sec_desc_buf);
353 if (result == NULL) {
354 return NT_STATUS_NO_MEMORY;
357 blob = data_blob_const(data, len);
359 ndr_err = ndr_pull_struct_blob(&blob, result, result,
360 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
362 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
363 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
364 ndr_errstr(ndr_err)));
365 TALLOC_FREE(result);
366 return ndr_map_error2ntstatus(ndr_err);;
369 *psecdesc_buf = result;
370 return NT_STATUS_OK;
373 /*******************************************************************
374 Creates a struct security_descriptor structure with typical defaults.
375 ********************************************************************/
377 struct security_descriptor *make_standard_sec_desc(TALLOC_CTX *ctx, const struct dom_sid *owner_sid, const struct dom_sid *grp_sid,
378 struct security_acl *dacl, size_t *sd_size)
380 return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
381 SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
382 dacl, sd_size);
385 /*******************************************************************
386 Creates a struct sec_desc_buf structure.
387 ********************************************************************/
389 struct sec_desc_buf *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, struct security_descriptor *sec_desc)
391 struct sec_desc_buf *dst;
393 if((dst = TALLOC_ZERO_P(ctx, struct sec_desc_buf)) == NULL)
394 return NULL;
396 /* max buffer size (allocated size) */
397 dst->sd_size = (uint32)len;
399 if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
400 return NULL;
403 return dst;
406 /*******************************************************************
407 Duplicates a struct sec_desc_buf structure.
408 ********************************************************************/
410 struct sec_desc_buf *dup_sec_desc_buf(TALLOC_CTX *ctx, struct sec_desc_buf *src)
412 if(src == NULL)
413 return NULL;
415 return make_sec_desc_buf( ctx, src->sd_size, src->sd);
418 /*******************************************************************
419 Add a new SID with its permissions to struct security_descriptor.
420 ********************************************************************/
422 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, uint32 mask, size_t *sd_size)
424 struct security_descriptor *sd = 0;
425 struct security_acl *dacl = 0;
426 struct security_ace *ace = 0;
427 NTSTATUS status;
429 if (!ctx || !psd || !sid || !sd_size)
430 return NT_STATUS_INVALID_PARAMETER;
432 *sd_size = 0;
434 status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
436 if (!NT_STATUS_IS_OK(status))
437 return status;
439 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
440 return NT_STATUS_UNSUCCESSFUL;
442 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
443 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
444 return NT_STATUS_UNSUCCESSFUL;
446 *psd = sd;
447 sd = 0;
448 return NT_STATUS_OK;
451 /*******************************************************************
452 Modify a SID's permissions in a struct security_descriptor.
453 ********************************************************************/
455 NTSTATUS sec_desc_mod_sid(struct security_descriptor *sd, struct dom_sid *sid, uint32 mask)
457 NTSTATUS status;
459 if (!sd || !sid)
460 return NT_STATUS_INVALID_PARAMETER;
462 status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
464 if (!NT_STATUS_IS_OK(status))
465 return status;
467 return NT_STATUS_OK;
470 /*******************************************************************
471 Delete a SID from a struct security_descriptor.
472 ********************************************************************/
474 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, struct security_descriptor **psd, struct dom_sid *sid, size_t *sd_size)
476 struct security_descriptor *sd = 0;
477 struct security_acl *dacl = 0;
478 struct security_ace *ace = 0;
479 NTSTATUS status;
481 if (!ctx || !psd[0] || !sid || !sd_size)
482 return NT_STATUS_INVALID_PARAMETER;
484 *sd_size = 0;
486 status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
488 if (!NT_STATUS_IS_OK(status))
489 return status;
491 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
492 return NT_STATUS_UNSUCCESSFUL;
494 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
495 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
496 return NT_STATUS_UNSUCCESSFUL;
498 *psd = sd;
499 sd = 0;
500 return NT_STATUS_OK;
504 * Determine if an struct security_ace is inheritable
507 static bool is_inheritable_ace(const struct security_ace *ace,
508 bool container)
510 if (!container) {
511 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
514 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
515 return true;
518 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
519 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
520 return true;
523 return false;
527 * Does a security descriptor have any inheritable components for
528 * the newly created type ?
531 bool sd_has_inheritable_components(const struct security_descriptor *parent_ctr, bool container)
533 unsigned int i;
534 const struct security_acl *the_acl = parent_ctr->dacl;
536 for (i = 0; i < the_acl->num_aces; i++) {
537 const struct security_ace *ace = &the_acl->aces[i];
539 if (is_inheritable_ace(ace, container)) {
540 return true;
543 return false;
546 /* Create a child security descriptor using another security descriptor as
547 the parent container. This child object can either be a container or
548 non-container object. */
550 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
551 struct security_descriptor **ppsd,
552 size_t *psize,
553 const struct security_descriptor *parent_ctr,
554 const struct dom_sid *owner_sid,
555 const struct dom_sid *group_sid,
556 bool container)
558 struct security_acl *new_dacl = NULL, *the_acl = NULL;
559 struct security_ace *new_ace_list = NULL;
560 unsigned int new_ace_list_ndx = 0, i;
562 *ppsd = NULL;
563 *psize = 0;
565 /* Currently we only process the dacl when creating the child. The
566 sacl should also be processed but this is left out as sacls are
567 not implemented in Samba at the moment.*/
569 the_acl = parent_ctr->dacl;
571 if (the_acl->num_aces) {
572 if (2*the_acl->num_aces < the_acl->num_aces) {
573 return NT_STATUS_NO_MEMORY;
576 if (!(new_ace_list = TALLOC_ARRAY(ctx, struct security_ace,
577 2*the_acl->num_aces))) {
578 return NT_STATUS_NO_MEMORY;
580 } else {
581 new_ace_list = NULL;
584 for (i = 0; i < the_acl->num_aces; i++) {
585 const struct security_ace *ace = &the_acl->aces[i];
586 struct security_ace *new_ace = &new_ace_list[new_ace_list_ndx];
587 const struct dom_sid *ptrustee = &ace->trustee;
588 const struct dom_sid *creator = NULL;
589 uint8 new_flags = ace->flags;
591 if (!is_inheritable_ace(ace, container)) {
592 continue;
595 /* see the RAW-ACLS inheritance test for details on these rules */
596 if (!container) {
597 new_flags = 0;
598 } else {
599 new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
601 if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
602 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
604 if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
605 new_flags = 0;
609 /* The CREATOR sids are special when inherited */
610 if (sid_equal(ptrustee, &global_sid_Creator_Owner)) {
611 creator = &global_sid_Creator_Owner;
612 ptrustee = owner_sid;
613 } else if (sid_equal(ptrustee, &global_sid_Creator_Group)) {
614 creator = &global_sid_Creator_Group;
615 ptrustee = group_sid;
618 if (creator && container &&
619 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
621 /* First add the regular ACE entry. */
622 init_sec_ace(new_ace, ptrustee, ace->type,
623 ace->access_mask, 0);
625 DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
626 " inherited as %s:%d/0x%02x/0x%08x\n",
627 sid_string_dbg(&ace->trustee),
628 ace->type, ace->flags, ace->access_mask,
629 sid_string_dbg(&new_ace->trustee),
630 new_ace->type, new_ace->flags,
631 new_ace->access_mask));
633 new_ace_list_ndx++;
635 /* Now add the extra creator ACE. */
636 new_ace = &new_ace_list[new_ace_list_ndx];
638 ptrustee = creator;
639 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
640 } else if (container &&
641 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
642 ptrustee = &ace->trustee;
645 init_sec_ace(new_ace, ptrustee, ace->type,
646 ace->access_mask, new_flags);
648 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
649 " inherited as %s:%d/0x%02x/0x%08x\n",
650 sid_string_dbg(&ace->trustee),
651 ace->type, ace->flags, ace->access_mask,
652 sid_string_dbg(&ace->trustee),
653 new_ace->type, new_ace->flags,
654 new_ace->access_mask));
656 new_ace_list_ndx++;
659 /* Create child security descriptor to return */
660 if (new_ace_list_ndx) {
661 new_dacl = make_sec_acl(ctx,
662 NT4_ACL_REVISION,
663 new_ace_list_ndx,
664 new_ace_list);
666 if (!new_dacl) {
667 return NT_STATUS_NO_MEMORY;
671 *ppsd = make_sec_desc(ctx,
672 SECURITY_DESCRIPTOR_REVISION_1,
673 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
674 owner_sid,
675 group_sid,
676 NULL,
677 new_dacl,
678 psize);
679 if (!*ppsd) {
680 return NT_STATUS_NO_MEMORY;
682 return NT_STATUS_OK;
685 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
686 struct sec_desc_buf **ppsdb,
687 const struct security_descriptor *parent_ctr,
688 bool container)
690 NTSTATUS status;
691 size_t size = 0;
692 struct security_descriptor *sd = NULL;
694 *ppsdb = NULL;
695 status = se_create_child_secdesc(ctx,
696 &sd,
697 &size,
698 parent_ctr,
699 parent_ctr->owner_sid,
700 parent_ctr->group_sid,
701 container);
702 if (!NT_STATUS_IS_OK(status)) {
703 return status;
706 *ppsdb = make_sec_desc_buf(ctx, size, sd);
707 if (!*ppsdb) {
708 return NT_STATUS_NO_MEMORY;
710 return NT_STATUS_OK;