diff options
Diffstat (limited to 'source3/lib/secace.c')
-rw-r--r-- | source3/lib/secace.c | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/source3/lib/secace.c b/source3/lib/secace.c new file mode 100644 index 0000000000..6769f1288a --- /dev/null +++ b/source3/lib/secace.c @@ -0,0 +1,285 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_ACE handling functions + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Jeremy R. Allison 1995-2003. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1997-1998. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/******************************************************************* + Check if ACE has OBJECT type. +********************************************************************/ + +BOOL sec_ace_object(uint8 type) +{ + if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || + type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT || + type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) { + return True; + } + return False; +} + +/******************************************************************* + copy a SEC_ACE structure. +********************************************************************/ +void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) +{ + ace_dest->type = ace_src->type; + ace_dest->flags = ace_src->flags; + ace_dest->size = ace_src->size; + ace_dest->info.mask = ace_src->info.mask; + ace_dest->obj_flags = ace_src->obj_flags; + memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, GUID_SIZE); + memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, GUID_SIZE); + sid_copy(&ace_dest->trustee, &ace_src->trustee); +} + +/******************************************************************* + Sets up a SEC_ACE structure. +********************************************************************/ + +void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag) +{ + t->type = type; + t->flags = flag; + t->size = sid_size(sid) + 8; + t->info = mask; + + ZERO_STRUCTP(&t->trustee); + sid_copy(&t->trustee, sid); +} + +/******************************************************************* + adds new SID with its permissions to ACE list +********************************************************************/ + +NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask) +{ + unsigned int i = 0; + + if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; + + *num += 1; + + if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0) + return NT_STATUS_NO_MEMORY; + + for (i = 0; i < *num - 1; i ++) + sec_ace_copy(&(*new)[i], &old[i]); + + (*new)[i].type = 0; + (*new)[i].flags = 0; + (*new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid); + (*new)[i].info.mask = mask; + sid_copy(&(*new)[i].trustee, sid); + return NT_STATUS_OK; +} + +/******************************************************************* + modify SID's permissions at ACL +********************************************************************/ + +NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask) +{ + unsigned int i = 0; + + if (!ace || !sid) return NT_STATUS_INVALID_PARAMETER; + + for (i = 0; i < num; i ++) { + if (sid_compare(&ace[i].trustee, sid) == 0) { + ace[i].info.mask = mask; + return NT_STATUS_OK; + } + } + return NT_STATUS_NOT_FOUND; +} + +/******************************************************************* + delete SID from ACL +********************************************************************/ + +NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, uint32 *num, DOM_SID *sid) +{ + unsigned int i = 0; + unsigned int n_del = 0; + + if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; + + if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0) + return NT_STATUS_NO_MEMORY; + + for (i = 0; i < *num; i ++) { + if (sid_compare(&old[i].trustee, sid) != 0) + sec_ace_copy(&(*new)[i], &old[i]); + else + n_del ++; + } + if (n_del == 0) + return NT_STATUS_NOT_FOUND; + else { + *num -= n_del; + return NT_STATUS_OK; + } +} + +/******************************************************************* + Compares two SEC_ACE structures +********************************************************************/ + +BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2) +{ + /* Trivial case */ + + if (!s1 && !s2) return True; + + /* Check top level stuff */ + + if (s1->type != s2->type || s1->flags != s2->flags || + s1->info.mask != s2->info.mask) { + return False; + } + + /* Check SID */ + + if (!sid_equal(&s1->trustee, &s2->trustee)) { + return False; + } + + return True; +} + +int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE; + int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE; + + if (a1_inh == a2_inh) + return 0; + + if (!a1_inh && a2_inh) + return -1; + return 1; +} + +/******************************************************************* + Comparison function to apply the order explained below in a group. +*******************************************************************/ + +int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) && + (a2->type != SEC_ACE_TYPE_ACCESS_DENIED)) + return -1; + + if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) && + (a1->type != SEC_ACE_TYPE_ACCESS_DENIED)) + return 1; + + /* Both access denied or access allowed. */ + + /* 1. ACEs that apply to the object itself */ + + if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) && + (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY)) + return -1; + else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) && + (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY)) + return 1; + + /* 2. ACEs that apply to a subobject of the object, such as + * a property set or property. */ + + if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && + !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) + return -1; + else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && + !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) + return 1; + + return 0; +} + +/******************************************************************* + Functions to convert a SEC_DESC ACE DACL list into canonical order. + JRA. + +--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp + +The following describes the preferred order: + + To ensure that noninherited ACEs have precedence over inherited ACEs, + place all noninherited ACEs in a group before any inherited ACEs. + This ordering ensures, for example, that a noninherited access-denied ACE + is enforced regardless of any inherited ACE that allows access. + + Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows: + 1. Access-denied ACEs that apply to the object itself + 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property + 3. Access-allowed ACEs that apply to the object itself + 4. Access-allowed ACEs that apply to a subobject of the object" + +********************************************************************/ + +void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces) +{ + unsigned int i; + + if (!srclist || num_aces == 0) + return; + + /* Sort so that non-inherited ACE's come first. */ + qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp); + + /* Find the boundary between non-inherited ACEs. */ + for (i = 0; i < num_aces; i++ ) { + SEC_ACE *curr_ace = &srclist[i]; + + if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE) + break; + } + + /* i now points at entry number of the first inherited ACE. */ + + /* Sort the non-inherited ACEs. */ + if (i) + qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); + + /* Now sort the inherited ACEs. */ + if (num_aces - i) + qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); +} + +/******************************************************************* + Check if this ACE has a SID in common with the token. +********************************************************************/ + +BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace) +{ + size_t i; + + for (i = 0; i < token->num_sids; i++) { + if (sid_equal(&ace->trustee, &token->user_sids[i])) + return True; + } + + return False; +} |