From 762e7e1dff89cc14b0130fc9a22038b0845630a2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 6 Oct 2003 01:24:48 +0000 Subject: [PATCH] split some security related functions in their own files. (no need to include all of smbd files to use some basic sec functions) also minor compile fixes (This used to be commit 66074d3b097d8cf2a231bf08c7f4db62da68189d) --- source3/Makefile.in | 7 +- source3/include/privileges.h | 2 + source3/include/rpc_lsa.h | 6 +- source3/include/talloc.h | 21 + source3/lib/privileges.c | 345 +++++++++++++++ source3/lib/secace.c | 285 +++++++++++++ source3/lib/secacl.c | 118 ++++++ source3/lib/secdesc.c | 522 +++++++++++++++++++++++ source3/lib/talloc.c | 21 - source3/lib/util_seaccess.c | 129 ------ source3/lib/util_sid.c | 2 +- source3/passdb/pdb_get_set.c | 4 +- source3/rpc_client/cli_lsarpc.c | 6 +- source3/rpc_parse/parse_lsa.c | 43 +- source3/rpc_parse/parse_rpc.c | 6 +- source3/rpc_parse/parse_sec.c | 727 -------------------------------- source3/rpc_server/srv_lsa.c | 2 +- source3/rpc_server/srv_lsa_nt.c | 70 +-- source3/script/mkproto.awk | 2 +- source3/tdb/tdbback.c | 3 +- 20 files changed, 1376 insertions(+), 945 deletions(-) create mode 100644 source3/lib/privileges.c create mode 100644 source3/lib/secace.c create mode 100644 source3/lib/secacl.c create mode 100644 source3/lib/secdesc.c diff --git a/source3/Makefile.in b/source3/Makefile.in index 0ea2c4411f8..57950bebdeb 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -181,7 +181,8 @@ LIB_OBJ = lib/version.o lib/charcnv.o lib/debug.o lib/fault.o \ nsswitch/wb_client.o nsswitch/wb_common.o \ lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \ - lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ + lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \ + lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o @@ -218,7 +219,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \ libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \ libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \ - libsmb/clistr.o \ + libsmb/clistr.o lib/util_seaccess.o \ libsmb/cliquota.o libsmb/clifsinfo.o \ libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \ libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \ @@ -345,7 +346,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \ smbd/posix_acls.o lib/sysacls.o lib/server_mutex.o \ smbd/process.o smbd/service.o smbd/error.o \ - printing/printfsp.o lib/util_seaccess.o \ + printing/printfsp.o \ lib/sysquotas.o smbd/change_trust_pw.o smbd/fake_file.o \ smbd/quotas.o smbd/ntquotas.o lib/afs.o \ $(MANGLE_OBJ) @VFS_STATIC@ diff --git a/source3/include/privileges.h b/source3/include/privileges.h index 67d8a2cbcc1..b7e1b44c2af 100644 --- a/source3/include/privileges.h +++ b/source3/include/privileges.h @@ -53,6 +53,8 @@ typedef struct LUID_ATTR typedef struct privilege_set { + TALLOC_CTX *mem_ctx; + BOOL ext_ctx; uint32 count; uint32 control; LUID_ATTR *set; diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index 93bc08a0ce0..2064a38056e 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -657,7 +657,7 @@ typedef struct lsa_r_enumprivsaccount { uint32 ptr; uint32 count; - PRIVILEGE_SET set; + PRIVILEGE_SET *set; NTSTATUS status; } LSA_R_ENUMPRIVSACCOUNT; @@ -703,7 +703,7 @@ typedef struct lsa_q_addprivs { POLICY_HND pol; /* policy handle */ uint32 count; - PRIVILEGE_SET set; + PRIVILEGE_SET *set; } LSA_Q_ADDPRIVS; typedef struct lsa_r_addprivs @@ -718,7 +718,7 @@ typedef struct lsa_q_removeprivs uint32 allrights; uint32 ptr; uint32 count; - PRIVILEGE_SET set; + PRIVILEGE_SET *set; } LSA_Q_REMOVEPRIVS; typedef struct lsa_r_removeprivs diff --git a/source3/include/talloc.h b/source3/include/talloc.h index 4badddbb880..433b52ec954 100644 --- a/source3/include/talloc.h +++ b/source3/include/talloc.h @@ -30,6 +30,27 @@ /** * talloc allocation pool. All allocated blocks can be freed in one go. **/ + +struct talloc_chunk { + struct talloc_chunk *next; + size_t size; + void *ptr; +}; + +struct talloc_ctx { + struct talloc_chunk *list; + size_t total_alloc_size; + + /** The name recorded for this pool, if any. Should describe + * the purpose for which it was allocated. The string is + * allocated within the pool. **/ + char *name; + + /** Pointer to the next allocate talloc pool, so that we can + * summarize all talloc memory usage. **/ + struct talloc_ctx *next_ctx; +}; + typedef struct talloc_ctx TALLOC_CTX; TALLOC_CTX *talloc_init(char const *fmt, ...) PRINTF_ATTRIBUTE(1, 2); diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c new file mode 100644 index 00000000000..1c23d9e40e5 --- /dev/null +++ b/source3/lib/privileges.c @@ -0,0 +1,345 @@ +/* + Unix SMB/CIFS implementation. + Privileges handling functions + Copyright (C) Jean François Micouleau 1998-2001 + Copyright (C) Simo Sorce 2002-2003 + + 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" + +/* defines */ + +#define ALLOC_CHECK(ptr, err, label, str) do { if ((ptr) == NULL) { DEBUG(0, ("%s: out of memory!\n", str)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0) +#define NTSTATUS_CHECK(err, label, str1, str2) do { if (!NT_STATUS_IS_OK(err)) { DEBUG(0, ("%s: %s failed!\n", str1, str2)); } } while(0) + +/**************************************************************************** + Check if a user is a mapped group. + + This function will check if the group SID is mapped onto a + system managed gid or onto a winbind manged sid. + In the first case it will be threated like a mapped group + and the backend should take the member list with a getgrgid + and ignore any user that have been possibly set into the group + object. + + In the second case, the group is a fully SAM managed group + served back to the system through winbind. In this case the + members of a Local group are "unrolled" to cope with the fact + that unix cannot contain groups inside groups. + The backend MUST never call any getgr* / getpw* function or + loops with winbind may happen. + ****************************************************************************/ + +#if 0 +NTSTATUS is_mapped_group(BOOL *mapped, const DOM_SID *sid) +{ + NTSTATUS result; + gid_t id; + + /* look if mapping exist, do not make idmap alloc an uid if SID is not found */ + result = idmap_get_gid_from_sid(&id, sid, False); + if (NT_STATUS_IS_OK(result)) { + *mapped = gid_is_in_winbind_range(id); + } else { + *mapped = False; + } + + return result; +} +#endif + +/**************************************************************************** + duplicate alloc luid_attr + ****************************************************************************/ +NTSTATUS dupalloc_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la) +{ + NTSTATUS ret; + + *new_la = (LUID_ATTR *)talloc(mem_ctx, sizeof(LUID_ATTR)); + ALLOC_CHECK(new_la, ret, done, "dupalloc_luid_attr"); + + (*new_la)->luid.high = old_la->luid.high; + (*new_la)->luid.low = old_la->luid.low; + (*new_la)->attr = old_la->attr; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + initialise a privilege list + ****************************************************************************/ +NTSTATUS init_privilege(PRIVILEGE_SET **priv_set) +{ + NTSTATUS ret; + TALLOC_CTX *mem_ctx = talloc_init("privilege set"); + ALLOC_CHECK(mem_ctx, ret, done, "init_privilege"); + + *priv_set = talloc_zero(mem_ctx, sizeof(PRIVILEGE_SET)); + ALLOC_CHECK(*priv_set, ret, done, "init_privilege"); + + (*priv_set)->mem_ctx = mem_ctx; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +NTSTATUS init_priv_with_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET **priv_set) +{ + NTSTATUS ret; + + *priv_set = talloc_zero(mem_ctx, sizeof(PRIVILEGE_SET)); + ALLOC_CHECK(*priv_set, ret, done, "init_privilege"); + + (*priv_set)->mem_ctx = mem_ctx; + (*priv_set)->ext_ctx = True; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +void reset_privilege(PRIVILEGE_SET *priv_set) +{ + priv_set->count = 0; + priv_set->control = 0; + priv_set->set = NULL; +} + +void destroy_privilege(PRIVILEGE_SET **priv_set) +{ + reset_privilege(*priv_set); + if (!((*priv_set)->ext_ctx)) + /* mem_ctx is local, destroy it */ + talloc_destroy((*priv_set)->mem_ctx); + *priv_set = NULL; +} + +/**************************************************************************** + add a privilege to a privilege array + ****************************************************************************/ +NTSTATUS add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + + /* check if the privilege is not already in the list */ + if (NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set))) + return NT_STATUS_UNSUCCESSFUL; + + /* we can allocate memory to add the new privilege */ + + new_set = (LUID_ATTR *)talloc_realloc(priv_set->mem_ctx, priv_set->set, (priv_set->count + 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "add_privilege"); + + new_set[priv_set->count].luid.high = set.luid.high; + new_set[priv_set->count].luid.low = set.luid.low; + new_set[priv_set->count].attr = set.attr; + + priv_set->count++; + priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + add all the privileges to a privilege array + ****************************************************************************/ +NTSTATUS add_all_privilege(PRIVILEGE_SET *priv_set) +{ + NTSTATUS result = NT_STATUS_OK; + LUID_ATTR set; + + set.attr = 0; + set.luid.high = 0; + + /* TODO: set a proper list of privileges */ + set.luid.low = SE_PRIV_ADD_USERS; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + + set.luid.low = SE_PRIV_ADD_MACHINES; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + + set.luid.low = SE_PRIV_PRINT_OPERATOR; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + +done: + return result; +} + +/**************************************************************************** + check if the privilege list is empty + ****************************************************************************/ +NTSTATUS check_empty_privilege(PRIVILEGE_SET *priv_set) +{ + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + if (priv_set->count == 0) + return NT_STATUS_OK; + + return NT_STATUS_UNSUCCESSFUL; +} + +/**************************************************************************** + check if the privilege is in the privilege list + ****************************************************************************/ +NTSTATUS check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + int i; + + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* if the list is empty, obviously we can't have it */ + if (NT_STATUS_IS_OK(check_empty_privilege(priv_set))) + return NT_STATUS_UNSUCCESSFUL; + + for (i = 0; i < priv_set->count; i++) { + LUID_ATTR *cur_set; + + cur_set = &priv_set->set[i]; + /* check only the low and high part. Checking the attr field has no meaning */ + if ( (cur_set->luid.low == set.luid.low) && + (cur_set->luid.high == set.luid.high) ) { + return NT_STATUS_OK; + } + } + + return NT_STATUS_UNSUCCESSFUL; +} + +/**************************************************************************** + remove a privilege from a privilege array + ****************************************************************************/ +NTSTATUS remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + LUID_ATTR *old_set; + int i,j; + + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* check if the privilege is in the list */ + if (!NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set))) + return NT_STATUS_UNSUCCESSFUL; + + /* special case if it's the only privilege in the list */ + if (priv_set->count == 1) { + reset_privilege(priv_set); + return NT_STATUS_OK; + } + + /* + * the privilege is there, create a new list, + * and copy the other privileges + */ + + old_set = priv_set->set; + + new_set = (LUID_ATTR *)talloc(priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "remove_privilege"); + + for (i=0, j=0; i < priv_set->count; i++) { + if ( (old_set[i].luid.low == set.luid.low) && + (old_set[i].luid.high == set.luid.high) ) { + continue; + } + + new_set[j].luid.low = old_set[i].luid.low; + new_set[j].luid.high = old_set[i].luid.high; + new_set[j].attr = old_set[i].attr; + + j++; + } + + if (j != priv_set->count - 1) { + DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n")); + DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j)); + return NT_STATUS_INTERNAL_ERROR; + } + + /* ok everything is fine */ + + priv_set->count--; + priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + duplicates a privilege array + the new privilege set must be passed inited + (use init_privilege or init_priv_with_ctx) + ****************************************************************************/ +NTSTATUS dup_priv_set(PRIVILEGE_SET *new_priv_set, PRIVILEGE_SET *priv_set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + LUID_ATTR *old_set; + int i; + + if (!new_priv_set || !priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* special case if there are no privileges in the list */ + if (priv_set->count == 0) { + return NT_STATUS_OK; + } + + /* + * create a new list, + * and copy the other privileges + */ + + old_set = priv_set->set; + + new_set = (LUID_ATTR *)talloc(new_priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "dup_priv_set"); + + for (i=0; i < priv_set->count; i++) { + + new_set[i].luid.low = old_set[i].luid.low; + new_set[i].luid.high = old_set[i].luid.high; + new_set[i].attr = old_set[i].attr; + } + + new_priv_set->count = priv_set->count; + new_priv_set->control = priv_set->control; + new_priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} diff --git a/source3/lib/secace.c b/source3/lib/secace.c new file mode 100644 index 00000000000..6769f1288a2 --- /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; +} diff --git a/source3/lib/secacl.c b/source3/lib/secacl.c new file mode 100644 index 00000000000..756685a8216 --- /dev/null +++ b/source3/lib/secacl.c @@ -0,0 +1,118 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_ACL handling routines + * 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" + +/******************************************************************* + Create a SEC_ACL structure. +********************************************************************/ + +SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list) +{ + SEC_ACL *dst; + int i; + + if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL) + return NULL; + + dst->revision = revision; + dst->num_aces = num_aces; + dst->size = SEC_ACL_HEADER_SIZE; + + /* Now we need to return a non-NULL address for the ace list even + if the number of aces required is zero. This is because there + is a distinct difference between a NULL ace and an ace with zero + entries in it. This is achieved by checking that num_aces is a + positive number. */ + + if ((num_aces) && + ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces)) + == NULL)) { + return NULL; + } + + for (i = 0; i < num_aces; i++) { + dst->ace[i] = ace_list[i]; /* Structure copy. */ + dst->size += ace_list[i].size; + } + + return dst; +} + +/******************************************************************* + Duplicate a SEC_ACL structure. +********************************************************************/ + +SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src) +{ + if(src == NULL) + return NULL; + + return make_sec_acl(ctx, src->revision, src->num_aces, src->ace); +} + +/******************************************************************* + Compares two SEC_ACL structures +********************************************************************/ + +BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2) +{ + unsigned int i, j; + + /* Trivial cases */ + + if (!s1 && !s2) return True; + if (!s1 || !s2) return False; + + /* Check top level stuff */ + + if (s1->revision != s2->revision) { + DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + if (s1->num_aces != s2->num_aces) { + DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + /* The ACEs could be in any order so check each ACE in s1 against + each ACE in s2. */ + + for (i = 0; i < s1->num_aces; i++) { + BOOL found = False; + + for (j = 0; j < s2->num_aces; j++) { + if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) { + found = True; + break; + } + } + + if (!found) return False; + } + + return True; +} diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c new file mode 100644 index 00000000000..411185dbfa6 --- /dev/null +++ b/source3/lib/secdesc.c @@ -0,0 +1,522 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_DESC 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" + +/******************************************************************* + Works out the linearization size of a SEC_DESC. +********************************************************************/ + +size_t sec_desc_size(SEC_DESC *psd) +{ + size_t offset; + + if (!psd) return 0; + + offset = SEC_DESC_HEADER_SIZE; + + /* don't align */ + + if (psd->owner_sid != NULL) + offset += sid_size(psd->owner_sid); + + if (psd->grp_sid != NULL) + offset += sid_size(psd->grp_sid); + + if (psd->sacl != NULL) + offset += psd->sacl->size; + + if (psd->dacl != NULL) + offset += psd->dacl->size; + + return offset; +} + +/******************************************************************* + Compares two SEC_DESC structures +********************************************************************/ + +BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2) +{ + /* Trivial case */ + + if (!s1 && !s2) { + goto done; + } + + /* Check top level stuff */ + + if (s1->revision != s2->revision) { + DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + if (s1->type!= s2->type) { + DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n", + s1->type, s2->type)); + return False; + } + + /* Check owner and group */ + + if (!sid_equal(s1->owner_sid, s2->owner_sid)) { + fstring str1, str2; + + sid_to_string(str1, s1->owner_sid); + sid_to_string(str2, s2->owner_sid); + + DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n", + str1, str2)); + return False; + } + + if (!sid_equal(s1->grp_sid, s2->grp_sid)) { + fstring str1, str2; + + sid_to_string(str1, s1->grp_sid); + sid_to_string(str2, s2->grp_sid); + + DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n", + str1, str2)); + return False; + } + + /* Check ACLs present in one but not the other */ + + if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) || + (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) { + DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n")); + return False; + } + + /* Sigh - we have to do it the hard way by iterating over all + the ACEs in the ACLs */ + + if (!sec_acl_equal(s1->dacl, s2->dacl) || + !sec_acl_equal(s1->sacl, s2->sacl)) { + DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n")); + return False; + } + + done: + DEBUG(10, ("sec_desc_equal(): secdescs are identical\n")); + return True; +} + +/******************************************************************* + Merge part of security descriptor old_sec in to the empty sections of + security descriptor new_sec. +********************************************************************/ + +SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb) +{ + DOM_SID *owner_sid, *group_sid; + SEC_DESC_BUF *return_sdb; + SEC_ACL *dacl, *sacl; + SEC_DESC *psd = NULL; + uint16 secdesc_type; + size_t secdesc_size; + + /* Copy over owner and group sids. There seems to be no flag for + this so just check the pointer values. */ + + owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid : + old_sdb->sec->owner_sid; + + group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid : + old_sdb->sec->grp_sid; + + secdesc_type = new_sdb->sec->type; + + /* Ignore changes to the system ACL. This has the effect of making + changes through the security tab audit button not sticking. + Perhaps in future Samba could implement these settings somehow. */ + + sacl = NULL; + secdesc_type &= ~SEC_DESC_SACL_PRESENT; + + /* Copy across discretionary ACL */ + + if (secdesc_type & SEC_DESC_DACL_PRESENT) { + dacl = new_sdb->sec->dacl; + } else { + dacl = old_sdb->sec->dacl; + } + + /* Create new security descriptor from bits */ + + psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type, + owner_sid, group_sid, sacl, dacl, &secdesc_size); + + return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd); + + return(return_sdb); +} + +/******************************************************************* + Creates a SEC_DESC structure +********************************************************************/ + +SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, + DOM_SID *owner_sid, DOM_SID *grp_sid, + SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) +{ + SEC_DESC *dst; + uint32 offset = 0; + + *sd_size = 0; + + if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL) + return NULL; + + dst->revision = revision; + dst->type = type; + + if (sacl) + dst->type |= SEC_DESC_SACL_PRESENT; + if (dacl) + dst->type |= SEC_DESC_DACL_PRESENT; + + dst->off_owner_sid = 0; + dst->off_grp_sid = 0; + dst->off_sacl = 0; + dst->off_dacl = 0; + + if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL)) + goto error_exit; + + if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL)) + goto error_exit; + + if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL)) + goto error_exit; + + if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL)) + goto error_exit; + + offset = SEC_DESC_HEADER_SIZE; + + /* + * Work out the linearization sizes. + */ + + if (dst->sacl != NULL) { + dst->off_sacl = offset; + offset += dst->sacl->size; + } + if (dst->dacl != NULL) { + dst->off_dacl = offset; + offset += dst->dacl->size; + } + + if (dst->owner_sid != NULL) { + dst->off_owner_sid = offset; + offset += sid_size(dst->owner_sid); + } + + if (dst->grp_sid != NULL) { + dst->off_grp_sid = offset; + offset += sid_size(dst->grp_sid); + } + + *sd_size = (size_t)offset; + return dst; + +error_exit: + + *sd_size = 0; + return NULL; +} + +/******************************************************************* + Duplicate a SEC_DESC structure. +********************************************************************/ + +SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src) +{ + size_t dummy; + + if(src == NULL) + return NULL; + + return make_sec_desc( ctx, src->revision, src->type, + src->owner_sid, src->grp_sid, src->sacl, + src->dacl, &dummy); +} + +/******************************************************************* + Creates a SEC_DESC structure with typical defaults. +********************************************************************/ + +SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid, + SEC_ACL *dacl, size_t *sd_size) +{ + return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + owner_sid, grp_sid, NULL, dacl, sd_size); +} + +/******************************************************************* + Creates a SEC_DESC_BUF structure. +********************************************************************/ + +SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc) +{ + SEC_DESC_BUF *dst; + + if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL) + return NULL; + + /* max buffer size (allocated size) */ + dst->max_len = (uint32)len; + dst->len = (uint32)len; + + if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) { + return NULL; + } + + dst->ptr = 0x1; + + return dst; +} + +/******************************************************************* + Duplicates a SEC_DESC_BUF structure. +********************************************************************/ + +SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src) +{ + if(src == NULL) + return NULL; + + return make_sec_desc_buf( ctx, src->len, src->sec); +} + +/******************************************************************* + Add a new SID with its permissions to SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size) +{ + SEC_DESC *sd = 0; + SEC_ACL *dacl = 0; + SEC_ACE *ace = 0; + NTSTATUS status; + + *sd_size = 0; + + if (!ctx || !psd || !sid || !sd_size) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask); + + if (!NT_STATUS_IS_OK(status)) + return status; + + if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) + return NT_STATUS_UNSUCCESSFUL; + + if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, + psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) + return NT_STATUS_UNSUCCESSFUL; + + *psd = sd; + sd = 0; + return NT_STATUS_OK; +} + +/******************************************************************* + Modify a SID's permissions in a SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask) +{ + NTSTATUS status; + + if (!sd || !sid) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask); + + if (!NT_STATUS_IS_OK(status)) + return status; + + return NT_STATUS_OK; +} + +/******************************************************************* + Delete a SID from a SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size) +{ + SEC_DESC *sd = 0; + SEC_ACL *dacl = 0; + SEC_ACE *ace = 0; + NTSTATUS status; + + *sd_size = 0; + + if (!ctx || !psd[0] || !sid || !sd_size) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid); + + if (!NT_STATUS_IS_OK(status)) + return status; + + if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) + return NT_STATUS_UNSUCCESSFUL; + + if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, + psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) + return NT_STATUS_UNSUCCESSFUL; + + *psd = sd; + sd = 0; + return NT_STATUS_OK; +} + +/* Create a child security descriptor using another security descriptor as + the parent container. This child object can either be a container or + non-container object. */ + +SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, + BOOL child_container) +{ + SEC_DESC_BUF *sdb; + SEC_DESC *sd; + SEC_ACL *new_dacl, *the_acl; + SEC_ACE *new_ace_list = NULL; + unsigned int new_ace_list_ndx = 0, i; + size_t size; + + /* Currently we only process the dacl when creating the child. The + sacl should also be processed but this is left out as sacls are + not implemented in Samba at the moment.*/ + + the_acl = parent_ctr->dacl; + + if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) + return NULL; + + for (i = 0; the_acl && i < the_acl->num_aces; i++) { + SEC_ACE *ace = &the_acl->ace[i]; + SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; + uint8 new_flags = 0; + BOOL inherit = False; + fstring sid_str; + + /* The OBJECT_INHERIT_ACE flag causes the ACE to be + inherited by non-container children objects. Container + children objects will inherit it as an INHERIT_ONLY + ACE. */ + + if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) { + + if (!child_container) { + new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT; + } else { + new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; + } + + inherit = True; + } + + /* The CONAINER_INHERIT_ACE flag means all child container + objects will inherit and use the ACE. */ + + if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { + if (!child_container) { + inherit = False; + } else { + new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT; + } + } + + /* The INHERIT_ONLY_ACE is not used by the se_access_check() + function for the parent container, but is inherited by + all child objects as a normal ACE. */ + + if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + /* Move along, nothing to see here */ + } + + /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE + is inherited by child objects but not grandchildren + objects. We clear the object inherit and container + inherit flags in the inherited ACE. */ + + if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { + new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_CONTAINER_INHERIT); + } + + /* Add ACE to ACE list */ + + if (!inherit) + continue; + + init_sec_access(&new_ace->info, ace->info.mask); + init_sec_ace(new_ace, &ace->trustee, ace->type, + new_ace->info, new_flags); + + sid_to_string(sid_str, &ace->trustee); + + DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " + " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, + ace->type, ace->flags, ace->info.mask, + sid_str, new_ace->type, new_ace->flags, + new_ace->info.mask)); + + new_ace_list_ndx++; + } + + /* Create child security descriptor to return */ + + new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list); + + /* Use the existing user and group sids. I don't think this is + correct. Perhaps the user and group should be passed in as + parameters by the caller? */ + + sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + parent_ctr->owner_sid, + parent_ctr->grp_sid, + parent_ctr->sacl, + new_dacl, &size); + + sdb = make_sec_desc_buf(ctx, size, sd); + + return sdb; +} + +/******************************************************************* + Sets up a SEC_ACCESS structure. +********************************************************************/ + +void init_sec_access(SEC_ACCESS *t, uint32 mask) +{ + t->mask = mask; +} + diff --git a/source3/lib/talloc.c b/source3/lib/talloc.c index b6c8b2efdf0..485dc28f31d 100644 --- a/source3/lib/talloc.c +++ b/source3/lib/talloc.c @@ -54,27 +54,6 @@ #include "includes.h" -struct talloc_chunk { - struct talloc_chunk *next; - size_t size; - void *ptr; -}; - - -struct talloc_ctx { - struct talloc_chunk *list; - size_t total_alloc_size; - - /** The name recorded for this pool, if any. Should describe - * the purpose for which it was allocated. The string is - * allocated within the pool. **/ - char *name; - - /** Pointer to the next allocate talloc pool, so that we can - * summarize all talloc memory usage. **/ - struct talloc_ctx *next_ctx; -}; - /** * Start of linked list of all talloc pools. diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index 2482d582d2c..cb0f46e2f9d 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -23,22 +23,6 @@ extern DOM_SID global_sid_Builtin; -/********************************************************************************** - Check if this ACE has a SID in common with the token. -**********************************************************************************/ - -static 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; -} - /********************************************************************************* Check an ACE against a SID. We return the remaining needed permission bits not yet granted. Zero means permission allowed (no more needed bits). @@ -332,119 +316,6 @@ BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, return False; } -/* Create a child security descriptor using another security descriptor as - the parent container. This child object can either be a container or - non-container object. */ - -SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, - BOOL child_container) -{ - SEC_DESC_BUF *sdb; - SEC_DESC *sd; - SEC_ACL *new_dacl, *the_acl; - SEC_ACE *new_ace_list = NULL; - unsigned int new_ace_list_ndx = 0, i; - size_t size; - - /* Currently we only process the dacl when creating the child. The - sacl should also be processed but this is left out as sacls are - not implemented in Samba at the moment.*/ - - the_acl = parent_ctr->dacl; - - if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) - return NULL; - - for (i = 0; the_acl && i < the_acl->num_aces; i++) { - SEC_ACE *ace = &the_acl->ace[i]; - SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; - uint8 new_flags = 0; - BOOL inherit = False; - fstring sid_str; - - /* The OBJECT_INHERIT_ACE flag causes the ACE to be - inherited by non-container children objects. Container - children objects will inherit it as an INHERIT_ONLY - ACE. */ - - if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) { - - if (!child_container) { - new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT; - } else { - new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } - - inherit = True; - } - - /* The CONAINER_INHERIT_ACE flag means all child container - objects will inherit and use the ACE. */ - - if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { - if (!child_container) { - inherit = False; - } else { - new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT; - } - } - - /* The INHERIT_ONLY_ACE is not used by the se_access_check() - function for the parent container, but is inherited by - all child objects as a normal ACE. */ - - if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - /* Move along, nothing to see here */ - } - - /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE - is inherited by child objects but not grandchildren - objects. We clear the object inherit and container - inherit flags in the inherited ACE. */ - - if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { - new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT | - SEC_ACE_FLAG_CONTAINER_INHERIT); - } - - /* Add ACE to ACE list */ - - if (!inherit) - continue; - - init_sec_access(&new_ace->info, ace->info.mask); - init_sec_ace(new_ace, &ace->trustee, ace->type, - new_ace->info, new_flags); - - sid_to_string(sid_str, &ace->trustee); - - DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " - " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, - ace->type, ace->flags, ace->info.mask, - sid_str, new_ace->type, new_ace->flags, - new_ace->info.mask)); - - new_ace_list_ndx++; - } - - /* Create child security descriptor to return */ - - new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list); - - /* Use the existing user and group sids. I don't think this is - correct. Perhaps the user and group should be passed in as - parameters by the caller? */ - - sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, - parent_ctr->owner_sid, - parent_ctr->grp_sid, - parent_ctr->sacl, - new_dacl, &size); - - sdb = make_sec_desc_buf(ctx, size, sd); - - return sdb; -} /******************************************************************* samr_make_sam_obj_sd diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index fbb393770d5..50bbb4c72c6 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -638,7 +638,7 @@ void print_guid(GUID *guid) Tallocs a duplicate SID. ********************************************************************/ -DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src) +DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src) { DOM_SID *dst; diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 9c2b7e4c700..46c49be8b11 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -509,7 +509,7 @@ BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum p return True; } -BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, DOM_SID *u_sid, enum pdb_value_state flag) +BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, const DOM_SID *u_sid, enum pdb_value_state flag) { if (!sampass || !u_sid) return False; @@ -545,7 +545,7 @@ BOOL pdb_set_user_sid_from_string (SAM_ACCOUNT *sampass, fstring u_sid, enum pdb return True; } -BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, DOM_SID *g_sid, enum pdb_value_state flag) +BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, const DOM_SID *g_sid, enum pdb_value_state flag) { if (!sampass || !g_sid) return False; diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index db873236e46..65115419b47 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -1035,9 +1035,9 @@ NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx, } for (i=0; iset[i].luid.low; + (*set)[i].luid.high = r.set->set[i].luid.high; + (*set)[i].attr = r.set->set[i].attr; } *count=r.count; diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index 3a5b232dc31..22dbd5307a0 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -1809,14 +1809,20 @@ static BOOL lsa_io_privilege_set(const char *desc, PRIVILEGE_SET *r_c, prs_struc return True; } -void init_lsa_r_enum_privsaccount(LSA_R_ENUMPRIVSACCOUNT *r_u, LUID_ATTR *set, uint32 count, uint32 control) +NTSTATUS init_lsa_r_enum_privsaccount(TALLOC_CTX *mem_ctx, LSA_R_ENUMPRIVSACCOUNT *r_u, LUID_ATTR *set, uint32 count, uint32 control) { - r_u->ptr=1; - r_u->count=count; - r_u->set.set=set; - r_u->set.count=count; - r_u->set.control=control; - DEBUG(10,("init_lsa_r_enum_privsaccount: %d %d privileges\n", r_u->count, r_u->set.count)); + NTSTATUS ret; + + r_u->ptr = 1; + r_u->count = count; + + if (!NT_STATUS_IS_OK(ret = init_priv_with_ctx(mem_ctx, &(r_u->set)))) + return ret; + + if (!NT_STATUS_IS_OK(ret = dupalloc_luid_attr(r_u->set->mem_ctx, &(r_u->set->set), set))) + return ret; + + DEBUG(10,("init_lsa_r_enum_privsaccount: %d %d privileges\n", r_u->count, r_u->set->count)); } /******************************************************************* @@ -1840,13 +1846,16 @@ BOOL lsa_io_r_enum_privsaccount(const char *desc, LSA_R_ENUMPRIVSACCOUNT *r_c, p /* malloc memory if unmarshalling here */ - if (UNMARSHALLING(ps) && r_c->count!=0) { - if (!(r_c->set.set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) + if (UNMARSHALLING(ps) && r_c->count != 0) { + if (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set)))) + return False; + + if (!(r_c->set->set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) return False; } - if(!lsa_io_privilege_set(desc, &r_c->set, ps, depth)) + if(!lsa_io_privilege_set(desc, r_c->set, ps, depth)) return False; } @@ -2008,11 +2017,14 @@ BOOL lsa_io_q_addprivs(const char *desc, LSA_Q_ADDPRIVS *r_c, prs_struct *ps, in return False; if (UNMARSHALLING(ps) && r_c->count!=0) { - if (!(r_c->set.set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) + if (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set)))) + return False; + + if (!(r_c->set->set = (LUID_ATTR *)prs_alloc_mem(ps, sizeof(LUID_ATTR) * r_c->count))) return False; } - if(!lsa_io_privilege_set(desc, &r_c->set, ps, depth)) + if(!lsa_io_privilege_set(desc, r_c->set, ps, depth)) return False; return True; @@ -2067,11 +2079,14 @@ BOOL lsa_io_q_removeprivs(const char *desc, LSA_Q_REMOVEPRIVS *r_c, prs_struct * return False; if (UNMARSHALLING(ps) && r_c->count!=0) { - if (!(r_c->set.set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) + if (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set)))) + return False; + + if (!(r_c->set->set = (LUID_ATTR *)prs_alloc_mem(ps, sizeof(LUID_ATTR) * r_c->count))) return False; } - if(!lsa_io_privilege_set(desc, &r_c->set, ps, depth)) + if(!lsa_io_privilege_set(desc, r_c->set, ps, depth)) return False; } diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index c1e663f8778..7e51f1e35b6 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -248,7 +248,7 @@ BOOL smb_io_rpc_hdr(const char *desc, RPC_HDR *rpc, prs_struct *ps, int depth) static BOOL smb_io_rpc_uuid(const char *desc, RPC_UUID *uuid, prs_struct *ps, int depth) { - if (ifc == NULL) + if (uuid == NULL) return False; prs_debug(ps, depth, desc, "smb_io_rpc_uuid"); @@ -267,7 +267,7 @@ static BOOL smb_io_rpc_uuid(const char *desc, RPC_UUID *uuid, prs_struct *ps, in if(!prs_uint8s (False, "data ", ps, depth, uuid->remaining, sizeof(uuid->remaining))) return False; - return true; + return True; } /******************************************************************* @@ -282,7 +282,7 @@ static BOOL smb_io_rpc_iface(const char *desc, RPC_IFACE *ifc, prs_struct *ps, i prs_debug(ps, depth, desc, "smb_io_rpc_iface"); depth++; - if (!smb_io_rpc_uuid( "uuid", ps, depth, &ifc->uuid)) + if (!smb_io_rpc_uuid( "uuid", &ifc->uuid, ps, depth)) return False; if(!prs_uint32 ( "version", ps, depth, &ifc->version)) diff --git a/source3/rpc_parse/parse_sec.c b/source3/rpc_parse/parse_sec.c index 0ed930c08d8..bf43ef288ae 100644 --- a/source3/rpc_parse/parse_sec.c +++ b/source3/rpc_parse/parse_sec.c @@ -27,15 +27,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE -/******************************************************************* - Sets up a SEC_ACCESS structure. -********************************************************************/ - -void init_sec_access(SEC_ACCESS *t, uint32 mask) -{ - t->mask = mask; -} - /******************************************************************* Reads or writes a SEC_ACCESS structure. ********************************************************************/ @@ -54,51 +45,6 @@ BOOL sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth) return True; } -/******************************************************************* - 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); -} - /******************************************************************* Reads or writes a SEC_ACE structure. ********************************************************************/ @@ -153,127 +99,6 @@ BOOL sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth) return True; } -/******************************************************************* - 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 -********************************************************************/ - -static 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; - } -} - -/******************************************************************* - Create a SEC_ACL structure. -********************************************************************/ - -SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list) -{ - SEC_ACL *dst; - int i; - - if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL) - return NULL; - - dst->revision = revision; - dst->num_aces = num_aces; - dst->size = SEC_ACL_HEADER_SIZE; - - /* Now we need to return a non-NULL address for the ace list even - if the number of aces required is zero. This is because there - is a distinct difference between a NULL ace and an ace with zero - entries in it. This is achieved by checking that num_aces is a - positive number. */ - - if ((num_aces) && - ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces)) - == NULL)) { - return NULL; - } - - for (i = 0; i < num_aces; i++) { - dst->ace[i] = ace_list[i]; /* Structure copy. */ - dst->size += ace_list[i].size; - } - - return dst; -} - -/******************************************************************* - Duplicate a SEC_ACL structure. -********************************************************************/ - -SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src) -{ - if(src == NULL) - return NULL; - - return make_sec_acl(ctx, src->revision, src->num_aces, src->ace); -} - /******************************************************************* Reads or writes a SEC_ACL structure. @@ -346,332 +171,6 @@ BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth) return True; } -/******************************************************************* - Works out the linearization size of a SEC_DESC. -********************************************************************/ - -size_t sec_desc_size(SEC_DESC *psd) -{ - size_t offset; - - if (!psd) return 0; - - offset = SEC_DESC_HEADER_SIZE; - - /* don't align */ - - if (psd->owner_sid != NULL) - offset += sid_size(psd->owner_sid); - - if (psd->grp_sid != NULL) - offset += sid_size(psd->grp_sid); - - if (psd->sacl != NULL) - offset += psd->sacl->size; - - if (psd->dacl != NULL) - offset += psd->dacl->size; - - return offset; -} - -/******************************************************************* - 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; -} - -/******************************************************************* - Compares two SEC_ACL structures -********************************************************************/ - -BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2) -{ - unsigned int i, j; - - /* Trivial cases */ - - if (!s1 && !s2) return True; - if (!s1 || !s2) return False; - - /* Check top level stuff */ - - if (s1->revision != s2->revision) { - DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n", - s1->revision, s2->revision)); - return False; - } - - if (s1->num_aces != s2->num_aces) { - DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n", - s1->revision, s2->revision)); - return False; - } - - /* The ACEs could be in any order so check each ACE in s1 against - each ACE in s2. */ - - for (i = 0; i < s1->num_aces; i++) { - BOOL found = False; - - for (j = 0; j < s2->num_aces; j++) { - if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) { - found = True; - break; - } - } - - if (!found) return False; - } - - return True; -} - -/******************************************************************* - Compares two SEC_DESC structures -********************************************************************/ - -BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2) -{ - /* Trivial case */ - - if (!s1 && !s2) { - goto done; - } - - /* Check top level stuff */ - - if (s1->revision != s2->revision) { - DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n", - s1->revision, s2->revision)); - return False; - } - - if (s1->type!= s2->type) { - DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n", - s1->type, s2->type)); - return False; - } - - /* Check owner and group */ - - if (!sid_equal(s1->owner_sid, s2->owner_sid)) { - fstring str1, str2; - - sid_to_string(str1, s1->owner_sid); - sid_to_string(str2, s2->owner_sid); - - DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n", - str1, str2)); - return False; - } - - if (!sid_equal(s1->grp_sid, s2->grp_sid)) { - fstring str1, str2; - - sid_to_string(str1, s1->grp_sid); - sid_to_string(str2, s2->grp_sid); - - DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n", - str1, str2)); - return False; - } - - /* Check ACLs present in one but not the other */ - - if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) || - (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) { - DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n")); - return False; - } - - /* Sigh - we have to do it the hard way by iterating over all - the ACEs in the ACLs */ - - if (!sec_acl_equal(s1->dacl, s2->dacl) || - !sec_acl_equal(s1->sacl, s2->sacl)) { - DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n")); - return False; - } - - done: - DEBUG(10, ("sec_desc_equal(): secdescs are identical\n")); - return True; -} - -/******************************************************************* - Merge part of security descriptor old_sec in to the empty sections of - security descriptor new_sec. -********************************************************************/ - -SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb) -{ - DOM_SID *owner_sid, *group_sid; - SEC_DESC_BUF *return_sdb; - SEC_ACL *dacl, *sacl; - SEC_DESC *psd = NULL; - uint16 secdesc_type; - size_t secdesc_size; - - /* Copy over owner and group sids. There seems to be no flag for - this so just check the pointer values. */ - - owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid : - old_sdb->sec->owner_sid; - - group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid : - old_sdb->sec->grp_sid; - - secdesc_type = new_sdb->sec->type; - - /* Ignore changes to the system ACL. This has the effect of making - changes through the security tab audit button not sticking. - Perhaps in future Samba could implement these settings somehow. */ - - sacl = NULL; - secdesc_type &= ~SEC_DESC_SACL_PRESENT; - - /* Copy across discretionary ACL */ - - if (secdesc_type & SEC_DESC_DACL_PRESENT) { - dacl = new_sdb->sec->dacl; - } else { - dacl = old_sdb->sec->dacl; - } - - /* Create new security descriptor from bits */ - - psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type, - owner_sid, group_sid, sacl, dacl, &secdesc_size); - - return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd); - - return(return_sdb); -} - -/******************************************************************* - Creates a SEC_DESC structure -********************************************************************/ - -SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, - DOM_SID *owner_sid, DOM_SID *grp_sid, - SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) -{ - SEC_DESC *dst; - uint32 offset = 0; - - *sd_size = 0; - - if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL) - return NULL; - - dst->revision = revision; - dst->type = type; - - if (sacl) - dst->type |= SEC_DESC_SACL_PRESENT; - if (dacl) - dst->type |= SEC_DESC_DACL_PRESENT; - - dst->off_owner_sid = 0; - dst->off_grp_sid = 0; - dst->off_sacl = 0; - dst->off_dacl = 0; - - if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL)) - goto error_exit; - - if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL)) - goto error_exit; - - if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL)) - goto error_exit; - - if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL)) - goto error_exit; - - offset = SEC_DESC_HEADER_SIZE; - - /* - * Work out the linearization sizes. - */ - - if (dst->sacl != NULL) { - dst->off_sacl = offset; - offset += dst->sacl->size; - } - - if (dst->dacl != NULL) { - dst->off_dacl = offset; - offset += dst->dacl->size; - } - - if (dst->owner_sid != NULL) { - dst->off_owner_sid = offset; - offset += sid_size(dst->owner_sid); - } - - if (dst->grp_sid != NULL) { - dst->off_grp_sid = offset; - offset += sid_size(dst->grp_sid); - } - - *sd_size = (size_t)offset; - return dst; - -error_exit: - - *sd_size = 0; - return NULL; -} - -/******************************************************************* - Duplicate a SEC_DESC structure. -********************************************************************/ - -SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src) -{ - size_t dummy; - - if(src == NULL) - return NULL; - - return make_sec_desc( ctx, src->revision, src->type, - src->owner_sid, src->grp_sid, src->sacl, - src->dacl, &dummy); -} - -/******************************************************************* - Creates a SEC_DESC structure with typical defaults. -********************************************************************/ - -SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid, - SEC_ACL *dacl, size_t *sd_size) -{ - return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, - owner_sid, grp_sid, NULL, dacl, sd_size); -} - /******************************************************************* Reads or writes a SEC_DESC structure. If reading and the *ppsd = NULL, allocates the structure. @@ -807,42 +306,6 @@ BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth) return True; } -/******************************************************************* - Creates a SEC_DESC_BUF structure. -********************************************************************/ - -SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc) -{ - SEC_DESC_BUF *dst; - - if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL) - return NULL; - - /* max buffer size (allocated size) */ - dst->max_len = (uint32)len; - dst->len = (uint32)len; - - if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) { - return NULL; - } - - dst->ptr = 0x1; - - return dst; -} - -/******************************************************************* - Duplicates a SEC_DESC_BUF structure. -********************************************************************/ - -SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src) -{ - if(src == NULL) - return NULL; - - return make_sec_desc_buf( ctx, src->len, src->sec); -} - /******************************************************************* Reads or writes a SEC_DESC_BUF structure. ********************************************************************/ @@ -901,193 +364,3 @@ BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int return True; } - -/******************************************************************* - Add a new SID with its permissions to SEC_DESC. -********************************************************************/ - -NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size) -{ - SEC_DESC *sd = 0; - SEC_ACL *dacl = 0; - SEC_ACE *ace = 0; - NTSTATUS status; - - *sd_size = 0; - - if (!ctx || !psd || !sid || !sd_size) - return NT_STATUS_INVALID_PARAMETER; - - status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask); - - if (!NT_STATUS_IS_OK(status)) - return status; - - if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) - return NT_STATUS_UNSUCCESSFUL; - - if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, - psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) - return NT_STATUS_UNSUCCESSFUL; - - *psd = sd; - sd = 0; - return NT_STATUS_OK; -} - -/******************************************************************* - Modify a SID's permissions in a SEC_DESC. -********************************************************************/ - -NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask) -{ - NTSTATUS status; - - if (!sd || !sid) - return NT_STATUS_INVALID_PARAMETER; - - status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask); - - if (!NT_STATUS_IS_OK(status)) - return status; - - return NT_STATUS_OK; -} - -/******************************************************************* - Delete a SID from a SEC_DESC. -********************************************************************/ - -NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size) -{ - SEC_DESC *sd = 0; - SEC_ACL *dacl = 0; - SEC_ACE *ace = 0; - NTSTATUS status; - - *sd_size = 0; - - if (!ctx || !psd[0] || !sid || !sd_size) - return NT_STATUS_INVALID_PARAMETER; - - status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid); - - if (!NT_STATUS_IS_OK(status)) - return status; - - if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) - return NT_STATUS_UNSUCCESSFUL; - - if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, - psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) - return NT_STATUS_UNSUCCESSFUL; - - *psd = sd; - sd = 0; - return NT_STATUS_OK; -} - -/******************************************************************* - Comparison function to sort non-inherited first. -*******************************************************************/ - -static 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. -*******************************************************************/ - -static 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); -} diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index 138fb1d7ef9..5d6c1551c91 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -443,7 +443,7 @@ static BOOL api_lsa_enum_privsaccount(pipes_struct *p) return False; } - r_u.status = _lsa_enum_privsaccount(p, &q_u, &r_u); + r_u.status = _lsa_enum_privsaccount(p, rdata, &q_u, &r_u); /* store the response in the SMB stream */ if(!lsa_io_r_enum_privsaccount("", &r_u, rdata, 0)) { diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 0921824cadd..0a8ad404cb3 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -955,7 +955,7 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC For a given SID, enumerate all the privilege this account has. ***************************************************************************/ -NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LSA_R_ENUMPRIVSACCOUNT *r_u) +NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVSACCOUNT *q_u, LSA_R_ENUMPRIVSACCOUNT *r_u) { struct lsa_info *info=NULL; GROUP_MAP map; @@ -971,29 +971,29 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LS return NT_STATUS_NO_SUCH_GROUP; #if 0 /* privileges currently not implemented! */ - DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set.count)); - if (map.priv_set.count!=0) { + DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set->count)); + if (map.priv_set->count!=0) { - set=(LUID_ATTR *)talloc(p->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR)); + set=(LUID_ATTR *)talloc(map.priv_set->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR)); if (set == NULL) { - free_privilege(&map.priv_set); + destroy_privilege(&map.priv_set); return NT_STATUS_NO_MEMORY; } - for (i=0; iset[i].luid.low; + set[i].luid.high = map.priv_set->set[i].luid.high; + set[i].attr = map.priv_set->set[i].attr; DEBUG(10,("_lsa_enum_privsaccount: priv %d: %d:%d:%d\n", i, set[i].luid.high, set[i].luid.low, set[i].attr)); } } - init_lsa_r_enum_privsaccount(r_u, set, map.priv_set.count, 0); - free_privilege(&map.priv_set); + init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, map.priv_set->count, 0); + destroy_privilege(&map.priv_set); #endif - init_lsa_r_enum_privsaccount(r_u, set, 0, 0); + init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, 0, 0); return r_u->status; } @@ -1059,11 +1059,11 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u) { #if 0 - struct lsa_info *info=NULL; + struct lsa_info *info = NULL; GROUP_MAP map; - int i=0; - LUID_ATTR *luid_attr=NULL; - PRIVILEGE_SET *set=NULL; + int i = 0; + LUID_ATTR *luid_attr = NULL; + PRIVILEGE_SET *set = NULL; #endif r_u->status = NT_STATUS_OK; @@ -1076,24 +1076,24 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; - set=&q_u->set; + set = &q_u->set; - for (i=0; icount; i++) { - luid_attr=&set->set[i]; + for (i = 0; i < set->count; i++) { + luid_attr = &set->set[i]; /* check if the privilege is already there */ - if (check_priv_in_privilege(&map.priv_set, *luid_attr)){ - free_privilege(&map.priv_set); + if (check_priv_in_privilege(map.priv_set, *luid_attr)){ + destroy_privilege(&map.priv_set); return NT_STATUS_NO_SUCH_PRIVILEGE; } - add_privilege(&map.priv_set, *luid_attr); + add_privilege(map.priv_set, *luid_attr); } if(!pdb_update_group_mapping_entry(&map)) return NT_STATUS_NO_SUCH_GROUP; - free_privilege(&map.priv_set); + destroy_privilege(&map.priv_set); #endif return r_u->status; @@ -1106,11 +1106,11 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u) { #if 0 - struct lsa_info *info=NULL; + struct lsa_info *info = NULL; GROUP_MAP map; int i=0; - LUID_ATTR *luid_attr=NULL; - PRIVILEGE_SET *set=NULL; + LUID_ATTR *luid_attr = NULL; + PRIVILEGE_SET *set = NULL; #endif r_u->status = NT_STATUS_OK; @@ -1123,37 +1123,37 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; - if (q_u->allrights!=0) { + if (q_u->allrights != 0) { /* log it and return, until I see one myself don't do anything */ DEBUG(5,("_lsa_removeprivs: trying to remove all privileges ?\n")); return NT_STATUS_OK; } - if (q_u->ptr==0) { + if (q_u->ptr == 0) { /* log it and return, until I see one myself don't do anything */ DEBUG(5,("_lsa_removeprivs: no privileges to remove ?\n")); return NT_STATUS_OK; } - set=&q_u->set; + set = &q_u->set; - for (i=0; icount; i++) { - luid_attr=&set->set[i]; + for (i = 0; i < set->count; i++) { + luid_attr = &set->set[i]; /* if we don't have the privilege, we're trying to remove, give up */ /* what else can we do ??? JFM. */ - if (!check_priv_in_privilege(&map.priv_set, *luid_attr)){ - free_privilege(&map.priv_set); + if (!check_priv_in_privilege(map.priv_set, *luid_attr)){ + destroy_privilege(&map.priv_set); return NT_STATUS_NO_SUCH_PRIVILEGE; } - remove_privilege(&map.priv_set, *luid_attr); + remove_privilege(map.priv_set, *luid_attr); } if(!pdb_update_group_mapping_entry(&map)) return NT_STATUS_NO_SUCH_GROUP; - free_privilege(&map.priv_set); + destroy_privilege(&map.priv_set); #endif return r_u->status; } diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index b6e911699eb..3835ea3af37 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -120,7 +120,7 @@ END { gotstart = 1; } - if( $0 ~ /^ADS_STRUCT|^ADS_STATUS|^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT/ ) { + if( $0 ~ /^ADS_STRUCT|^ADS_STATUS|^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT|^NTTIME/ ) { gotstart = 1; } diff --git a/source3/tdb/tdbback.c b/source3/tdb/tdbback.c index 9466c299910..68b6fadc882 100644 --- a/source3/tdb/tdbback.c +++ b/source3/tdb/tdbback.c @@ -55,8 +55,7 @@ char *add_suffix(const char *name, const char *suffix) fprintf(stderr,"Out of memory!\n"); exit(1); } - strncpy(ret, name, len); - strncat(ret, suffix, len); + snprintf(ret, len, "%s%s", name, suffix); return ret; } -- 2.34.1