diff options
author | Gerald Carter <jerry@samba.org> | 2005-01-13 18:20:37 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:53:51 -0500 |
commit | d94d87472ca2f3875caa146424caa178ce20274f (patch) | |
tree | a4c6f78f7b22c649b7d9405aa27f64daf749c1fb /source3/passdb | |
parent | 94b88f8f26342b6ca4afecec459235c523355f6c (diff) | |
download | samba-d94d87472ca2f3875caa146424caa178ce20274f.tar.gz samba-d94d87472ca2f3875caa146424caa178ce20274f.tar.bz2 samba-d94d87472ca2f3875caa146424caa178ce20274f.zip |
r4724: Add support for Windows privileges in Samba 3.0
(based on Simo's code in trunk). Rewritten with the
following changes:
* privilege set is based on a 32-bit mask instead of strings
(plans are to extend this to a 64 or 128-bit mask before
the next 3.0.11preX release).
* Remove the privilege code from the passdb API
(replication to come later)
* Only support the minimum amount of privileges that make
sense.
* Rewrite the domain join checks to use the SeMachineAccountPrivilege
instead of the 'is a member of "Domain Admins"?' check that started
all this.
Still todo:
* Utilize the SePrintOperatorPrivilege in addition to the 'printer admin'
parameter
* Utilize the SeAddUserPrivilege for adding users and groups
* Fix some of the hard coded _lsa_*() calls
* Start work on enough of SAM replication to get privileges from one
Samba DC to another.
* Come up with some management tool for manipultaing privileges
instead of user manager since it is buggy when run on a 2k client
(haven't tried xp). Works ok on NT4.
(This used to be commit 77c10ff9aa6414a31eece6dfec00793f190a9d6c)
Diffstat (limited to 'source3/passdb')
-rw-r--r-- | source3/passdb/pdb_tdb.c | 15 | ||||
-rw-r--r-- | source3/passdb/privileges.c | 341 | ||||
-rw-r--r-- | source3/passdb/util_sam_sid.c | 24 |
3 files changed, 14 insertions, 366 deletions
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index c792d229b9..53baaf580d 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -2,7 +2,7 @@ * Unix SMB/CIFS implementation. * SMB parameters and setup * Copyright (C) Andrew Tridgell 1992-1998 - * Copyright (C) Simo Sorce 2000-2002 + * Copyright (C) Simo Sorce 2000-2003 * Copyright (C) Gerald Carter 2000 * Copyright (C) Jeremy Allison 2001 * Copyright (C) Andrew Bartlett 2002 @@ -42,6 +42,7 @@ static int tdbsam_debug_level = DBGC_ALL; #define PASSDB_FILE_NAME "passdb.tdb" #define USERPREFIX "USER_" #define RIDPREFIX "RID_" +#define PRIVPREFIX "PRIV_" #define tdbsamver_t int32 struct tdbsam_privates { @@ -704,6 +705,18 @@ static void free_private_data(void **vp) } + + +/** + * Init tdbsam backend + * + * @param pdb_context initialised passdb context + * @param pdb_method backend methods structure to be filled with function pointers + * @param location the backend tdb file location + * + * @return nt_status code + **/ + static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; diff --git a/source3/passdb/privileges.c b/source3/passdb/privileges.c deleted file mode 100644 index 69fc75a618..0000000000 --- a/source3/passdb/privileges.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * - * default privileges backend for passdb - * - * Copyright (C) Andrew Tridgell 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" - -/* - this is a local implementation of a privileges backend, with - privileges stored in a tdb. Most passdb implementations will - probably use this backend, although some (such as pdb_ldap) will - store the privileges in another manner. - - The basic principle is that the backend should store a list of SIDs - associated with each right, where a right is a string name such as - 'SeTakeOwnershipPrivilege'. The SIDs can be of any type, and do not - need to belong to the local domain. - - The way this is used is that certain places in the code which - require access control will ask the privileges backend 'does this - user have the following privilege'. The 'user' will be a NT_TOKEN, - which is essentially just a list of SIDs. If any of those SIDs are - listed in the list of SIDs for that privilege then the answer will - be 'yes'. That will usually mean that the user gets unconditional - access to that functionality, regradless of any ACLs. In this way - privileges act in a similar fashion to unix setuid bits. -*/ - -/* - The terms 'right' and 'privilege' are used interchangably in this - file. This follows MSDN convention where the LSA calls are calls on - 'rights', which really means privileges. My apologies for the - confusion. -*/ - - -/* 15 seconds seems like an ample time for timeouts on the privileges db */ -#define LOCK_TIMEOUT 15 - - -/* the tdb handle for the privileges database */ -static TDB_CONTEXT *tdb; - - -/* initialise the privilege database */ -BOOL privilege_init(void) -{ - tdb = tdb_open_log(lock_path("privilege.tdb"), 0, TDB_DEFAULT, - O_RDWR|O_CREAT, 0600); - if (!tdb) { - DEBUG(0,("Failed to open privilege database\n")); - return False; - } - - return True; -} - -/* - lock the record for a particular privilege (write lock) -*/ -static NTSTATUS privilege_lock_right(const char *right) -{ - if (tdb_lock_bystring(tdb, right, LOCK_TIMEOUT) != 0) { - return NT_STATUS_INTERNAL_ERROR; - } - return NT_STATUS_OK; -} - -/* - unlock the record for a particular privilege (write lock) -*/ -static void privilege_unlock_right(const char *right) -{ - tdb_unlock_bystring(tdb, right); -} - - -/* - return a list of SIDs that have a particular right -*/ -NTSTATUS privilege_enum_account_with_right(const char *right, - uint32 *count, - DOM_SID **sids) -{ - TDB_DATA data; - char *p; - int i; - - if (!tdb) { - return NT_STATUS_INTERNAL_ERROR; - } - - data = tdb_fetch_bystring(tdb, right); - if (!data.dptr) { - *count = 0; - *sids = NULL; - return NT_STATUS_OK; - } - - /* count them */ - for (i=0, p=data.dptr; p<data.dptr+data.dsize; i++) { - p += strlen(p) + 1; - } - *count = i; - - /* allocate and parse */ - *sids = SMB_MALLOC_ARRAY(DOM_SID, *count); - if (! *sids) { - return NT_STATUS_NO_MEMORY; - } - for (i=0, p=data.dptr; p<data.dptr+data.dsize; i++) { - if (!string_to_sid(&(*sids)[i], p)) { - free(data.dptr); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - p += strlen(p) + 1; - } - - free(data.dptr); - - return NT_STATUS_OK; -} - -/* - set what accounts have a given right - this is an internal interface -*/ -static NTSTATUS privilege_set_accounts_with_right(const char *right, - uint32 count, - DOM_SID *sids) -{ - TDB_DATA data; - char *p; - int i; - - if (!tdb) { - return NT_STATUS_INTERNAL_ERROR; - } - - /* allocate the maximum size that we might use */ - data.dptr = SMB_MALLOC(count * ((MAXSUBAUTHS*11) + 30)); - if (!data.dptr) { - return NT_STATUS_NO_MEMORY; - } - - p = data.dptr; - - for (i=0;i<count;i++) { - sid_to_string(p, &sids[i]); - p += strlen(p) + 1; - } - - data.dsize = PTR_DIFF(p, data.dptr); - - if (tdb_store_bystring(tdb, right, data, TDB_REPLACE) != 0) { - free(data.dptr); - return NT_STATUS_INTERNAL_ERROR; - } - - free(data.dptr); - return NT_STATUS_OK; -} - - -/* - add a SID to the list of SIDs for a right -*/ -NTSTATUS privilege_add_account_right(const char *right, - DOM_SID *sid) -{ - NTSTATUS status; - DOM_SID *current_sids; - uint32 current_count; - int i; - - status = privilege_lock_right(right); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = privilege_enum_account_with_right(right, ¤t_count, ¤t_sids); - if (!NT_STATUS_IS_OK(status)) { - privilege_unlock_right(right); - return status; - } - - /* maybe that SID is already listed? this is not an error */ - for (i=0;i<current_count;i++) { - if (sid_equal(¤t_sids[i], sid)) { - privilege_unlock_right(right); - free(current_sids); - return NT_STATUS_OK; - } - } - - /* add it in */ - current_sids = SMB_REALLOC_ARRAY(current_sids, DOM_SID, current_count+1); - if (!current_sids) { - privilege_unlock_right(right); - return NT_STATUS_NO_MEMORY; - } - - sid_copy(¤t_sids[current_count], sid); - current_count++; - - status = privilege_set_accounts_with_right(right, current_count, current_sids); - - free(current_sids); - privilege_unlock_right(right); - - return status; -} - - -/* - remove a SID from the list of SIDs for a right -*/ -NTSTATUS privilege_remove_account_right(const char *right, - DOM_SID *sid) -{ - NTSTATUS status; - DOM_SID *current_sids; - uint32 current_count; - int i; - - status = privilege_lock_right(right); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = privilege_enum_account_with_right(right, ¤t_count, ¤t_sids); - if (!NT_STATUS_IS_OK(status)) { - privilege_unlock_right(right); - return status; - } - - for (i=0;i<current_count;i++) { - if (sid_equal(¤t_sids[i], sid)) { - /* found it - so remove it */ - if (current_count-i > 1) { - memmove(¤t_sids[i], ¤t_sids[i+1], - sizeof(current_sids[0]) * ((current_count-i)-1)); - } - current_count--; - status = privilege_set_accounts_with_right(right, - current_count, - current_sids); - free(current_sids); - privilege_unlock_right(right); - return status; - } - } - - /* removing a right that you don't have is not an error */ - - safe_free(current_sids); - privilege_unlock_right(right); - return NT_STATUS_OK; -} - - -/* - an internal function for checking if a SID has a right -*/ -static BOOL privilege_sid_has_right(DOM_SID *sid, const char *right) -{ - NTSTATUS status; - uint32 count; - DOM_SID *sids; - int i; - - status = privilege_enum_account_with_right(right, &count, &sids); - if (!NT_STATUS_IS_OK(status)) { - return False; - } - for (i=0;i<count;i++) { - if (sid_equal(sid, &sids[i])) { - free(sids); - return True; - } - } - - safe_free(sids); - return False; -} - -/* - list the rights for an account. This involves traversing the database -*/ -NTSTATUS privilege_enum_account_rights(DOM_SID *sid, - uint32 *count, - char ***rights) -{ - TDB_DATA key, nextkey; - char *right; - - if (!tdb) { - return NT_STATUS_INTERNAL_ERROR; - } - - *rights = NULL; - *count = 0; - - for (key = tdb_firstkey(tdb); key.dptr; key = nextkey) { - nextkey = tdb_nextkey(tdb, key); - - right = key.dptr; - - if (privilege_sid_has_right(sid, right)) { - (*rights) = SMB_REALLOC_ARRAY(*rights,char *, (*count)+1); - if (! *rights) { - safe_free(nextkey.dptr); - free(key.dptr); - return NT_STATUS_NO_MEMORY; - } - - (*rights)[*count] = SMB_STRDUP(right); - (*count)++; - } - - free(key.dptr); - } - - return NT_STATUS_OK; -} diff --git a/source3/passdb/util_sam_sid.c b/source3/passdb/util_sam_sid.c index c93c3400bd..1fddfc7925 100644 --- a/source3/passdb/util_sam_sid.c +++ b/source3/passdb/util_sam_sid.c @@ -315,28 +315,4 @@ BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char return False; } -void add_sid_to_array(const DOM_SID *sid, DOM_SID **sids, int *num) -{ - *sids = SMB_REALLOC_ARRAY(*sids, DOM_SID, (*num)+1); - - if (*sids == NULL) - return; - - sid_copy(&((*sids)[*num]), sid); - *num += 1; - - return; -} - -void add_sid_to_array_unique(const DOM_SID *sid, DOM_SID **sids, int *num_sids) -{ - int i; - - for (i=0; i<(*num_sids); i++) { - if (sid_compare(sid, &(*sids)[i]) == 0) - return; - } - - add_sid_to_array(sid, sids, num_sids); -} |