summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-01-13 18:20:37 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:53:51 -0500
commitd94d87472ca2f3875caa146424caa178ce20274f (patch)
treea4c6f78f7b22c649b7d9405aa27f64daf749c1fb
parent94b88f8f26342b6ca4afecec459235c523355f6c (diff)
downloadsamba-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)
-rw-r--r--source3/Makefile.in6
-rw-r--r--source3/auth/auth_util.c54
-rw-r--r--source3/groupdb/mapping.c13
-rw-r--r--source3/include/includes.h2
-rw-r--r--source3/include/privileges.h74
-rw-r--r--source3/include/rpc_lsa.h20
-rw-r--r--source3/include/smb.h6
-rw-r--r--source3/lib/account_pol.c34
-rw-r--r--source3/lib/privileges.c647
-rw-r--r--source3/lib/util_sid.c64
-rw-r--r--source3/passdb/pdb_tdb.c15
-rw-r--r--source3/passdb/privileges.c341
-rw-r--r--source3/passdb/util_sam_sid.c24
-rw-r--r--source3/rpc_client/cli_lsarpc.c6
-rw-r--r--source3/rpc_parse/parse_lsa.c81
-rw-r--r--source3/rpc_server/srv_lsa.c32
-rw-r--r--source3/rpc_server/srv_lsa_nt.c299
-rw-r--r--source3/rpc_server/srv_samr_nt.c44
18 files changed, 937 insertions, 825 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 79579b21c1..aeb6c456d2 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -310,7 +310,7 @@ PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o
PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
passdb/util_sam_sid.o passdb/pdb_compat.o \
- passdb/privileges.o passdb/lookup_sid.o \
+ passdb/lookup_sid.o \
passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \
lib/system_smbd.o
@@ -460,7 +460,7 @@ TESTPARM_OBJ = utils/testparm.o \
$(SECRETS_OBJ) $(LIBSAMBA_OBJ)
TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) $(UBIQX_OBJ) \
- $(LIB_NONSMBD_OBJ)
+ $(LIB_NONSMBD_OBJ) libsmb/nterr.o
SMBPASSWD_OBJ = utils/smbpasswd.o $(PASSCHANGE_OBJ) $(PARAM_OBJ) $(SECRETS_OBJ) \
$(LIBSMB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ)\
@@ -592,7 +592,7 @@ SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(UBIQX_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \
$(LIBMSRPC_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
-TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ)
+TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) libsmb/nterr.o
RPCTORTURE_OBJ = torture/rpctorture.o \
rpcclient/display.o \
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 98ecd00d1c..e4793c3df3 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -493,6 +493,11 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
for (i = 0; i < token->num_sids; i++)
DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i,
sid_to_string(sid_str, &token->user_sids[i])));
+
+ DEBUGADDC(dbg_class, dbg_lev, ("Privileges: [%d]\n", token->privileges.count));
+ for ( i=0; i<token->privileges.count; i++ ) {
+ DEBUGADDC(dbg_class, dbg_lev, ("\t%s\n", luid_to_privilege_name(&token->privileges.set[i].luid) ));
+ }
}
/****************************************************************************
@@ -583,6 +588,13 @@ static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *gro
ptoken->num_sids--;
}
}
+
+ /* add privileges assigned to this user */
+
+ privilege_set_init( &ptoken->privileges );
+
+ get_privileges_for_sids( &ptoken->privileges, ptoken->user_sids, ptoken->num_sids );
+
debug_nt_user_token(DBGC_AUTH, 10, ptoken);
@@ -1410,12 +1422,15 @@ BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_me
void delete_nt_token(NT_USER_TOKEN **pptoken)
{
- if (*pptoken) {
- NT_USER_TOKEN *ptoken = *pptoken;
- SAFE_FREE( ptoken->user_sids );
- ZERO_STRUCTP(ptoken);
- }
- SAFE_FREE(*pptoken);
+ if (*pptoken) {
+ NT_USER_TOKEN *ptoken = *pptoken;
+
+ SAFE_FREE( ptoken->user_sids );
+ privilege_set_free( &ptoken->privileges );
+
+ ZERO_STRUCTP(ptoken);
+ }
+ SAFE_FREE(*pptoken);
}
/****************************************************************************
@@ -1429,17 +1444,26 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
if (!ptoken)
return NULL;
- if ((token = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL)
- return NULL;
-
- ZERO_STRUCTP(token);
+ if ((token = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL)
+ return NULL;
- if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) {
- SAFE_FREE(token);
- return NULL;
- }
+ ZERO_STRUCTP(token);
+
+ token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids );
+
+ if ( !token ) {
+ SAFE_FREE(token);
+ return NULL;
+ }
- token->num_sids = ptoken->num_sids;
+ token->num_sids = ptoken->num_sids;
+
+ /* copy the privileges; don't consider failure to be critical here */
+
+ privilege_set_init( &token->privileges);
+ if ( !dup_privilege_set( &token->privileges, &ptoken->privileges ) ) {
+ DEBUG(0,("dup_nt_token: Failure to copy PRIVILEGE_SET!. Continuing with 0 privileges assigned.\n"));
+ }
return token;
}
diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c
index 7095997dc8..e574a7cf20 100644
--- a/source3/groupdb/mapping.c
+++ b/source3/groupdb/mapping.c
@@ -2,7 +2,7 @@
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-2000,
- * Copyright (C) Jean François Micouleau 1998-2001.
+ * Copyright (C) Jean François Micouleau 1998-2001.
*
* 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
@@ -35,17 +35,6 @@ static TDB_CONTEXT *tdb; /* used for driver files */
*/
#define MEMBEROF_PREFIX "MEMBEROF/"
-PRIVS privs[] = {
- {SE_PRIV_NONE, "no_privs", "No privilege" }, /* this one MUST be first */
- {SE_PRIV_ADD_MACHINES, "SeMachineAccountPrivilege", "Add workstations to the domain" },
- {SE_PRIV_SEC_PRIV, "SeSecurityPrivilege", "Manage the audit logs" },
- {SE_PRIV_TAKE_OWNER, "SeTakeOwnershipPrivilege", "Take ownership of file" },
- {SE_PRIV_ADD_USERS, "SaAddUsers", "Add users to the domain - Samba" },
- {SE_PRIV_PRINT_OPERATOR, "SaPrintOp", "Add or remove printers - Samba" },
- {SE_PRIV_ALL, "SaAllPrivs", "all privileges" }
-};
-
-
/****************************************************************************
dump the mapping group mapping to a text file
****************************************************************************/
diff --git a/source3/include/includes.h b/source3/include/includes.h
index 66ff4fa9f0..45c7133f1e 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -814,6 +814,8 @@ extern int errno;
#include "version.h"
+#include "privileges.h"
+
#include "smb.h"
#include "nameserv.h"
diff --git a/source3/include/privileges.h b/source3/include/privileges.h
index b7e1b44c2a..cdf62b7f85 100644
--- a/source3/include/privileges.h
+++ b/source3/include/privileges.h
@@ -4,6 +4,8 @@
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
+ Copyright (C) Simo Sorce 2003
+ Copyright (C) Gerald (Jerry) Carter 2004
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
@@ -23,22 +25,73 @@
#ifndef PRIVILEGES_H
#define PRIVILEGES_H
-#define PRIV_ALL_INDEX 5
+/* common privilege defines */
-#define SE_PRIV_NONE 0x0000
-#define SE_PRIV_ADD_MACHINES 0x0006
-#define SE_PRIV_SEC_PRIV 0x0008
-#define SE_PRIV_TAKE_OWNER 0x0009
-#define SE_PRIV_ADD_USERS 0xff01
-#define SE_PRIV_PRINT_OPERATOR 0xff03
-#define SE_PRIV_ALL 0xffff
+#define SE_END 0x00000000
+#define SE_NONE 0x00000000
+#define SE_ALL_PRIVS 0xFFFFFFFF
+
+/*
+ * We will use our own set of privileges since it makes no sense
+ * to implement all of the Windows set when only a portion will
+ * be used.
+ */
+
+#define SE_NETWORK_LOGON 0x00000001
+#define SE_INTERACTIVE_LOGON 0x00000002
+#define SE_BATCH_LOGON 0x00000004
+#define SE_SERVICE_LOGON 0x00000008
+#define SE_MACHINE_ACCOUNT 0x00000010
+#define SE_PRINT_OPERATOR 0x00000020
+#define SE_ADD_USERS 0x00000040
+
+#if 0 /* not needed currently */
+
+#define SE_ASSIGN_PRIMARY_TOKEN
+#define SE_CREATE_TOKEN
+#define SE_LOCK_MEMORY
+#define SE_INCREASE_QUOTA
+#define SE_UNSOLICITED_INPUT
+#define SE_TCB
+#define SE_SECURITY
+#define SE_TAKE_OWNERSHIP
+#define SE_LOAD_DRIVER
+#define SE_SYSTEM_PROFILE
+#define SE_SYSTEM_TIME
+#define SE_PROF_SINGLE_PROCESS
+#define SE_INC_BASE_PRIORITY
+#define SE_CREATE_PAGEFILE
+#define SE_CREATE_PERMANENT
+#define SE_BACKUP
+#define SE_RESTORE
+#define SE_SHUTDOWN
+#define SE_DEBUG
+#define SE_AUDIT
+#define SE_SYSTEM_ENVIRONMENT
+#define SE_CHANGE_NOTIFY
+#define SE_REMOTE_SHUTDOWN
+#define SE_UNDOCK
+#define SE_SYNC_AGENT
+#define SE_ENABLE_DELEGATION
+
+#endif /* not needed currently */
+
+/*
+ * These are used in Lsa replies (srv_lsa_nt.c)
+ */
#define PR_NONE 0x0000
#define PR_LOG_ON_LOCALLY 0x0001
#define PR_ACCESS_FROM_NETWORK 0x0002
#define PR_LOG_ON_BATCH_JOB 0x0004
#define PR_LOG_ON_SERVICE 0x0010
+
+#ifndef _BOOL
+typedef int BOOL;
+#define _BOOL /* So we don't typedef BOOL again in vfs.h */
+#endif
+
typedef struct LUID
{
uint32 low;
@@ -49,7 +102,7 @@ typedef struct LUID_ATTR
{
LUID luid;
uint32 attr;
-} LUID_ATTR ;
+} LUID_ATTR;
typedef struct privilege_set
{
@@ -62,9 +115,8 @@ typedef struct privilege_set
typedef struct _PRIVS {
uint32 se_priv;
- const char *priv;
+ const char *name;
const char *description;
} PRIVS;
-
#endif /* PRIVILEGES_H */
diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h
index 43ffa37d59..a2bc72d2b2 100644
--- a/source3/include/rpc_lsa.h
+++ b/source3/include/rpc_lsa.h
@@ -635,6 +635,20 @@ typedef struct lsa_r_unk_get_connuser
} LSA_R_UNK_GET_CONNUSER;
+typedef struct lsa_q_createaccount
+{
+ POLICY_HND pol; /* policy handle */
+ DOM_SID2 sid;
+ uint32 access; /* access */
+} LSA_Q_CREATEACCOUNT;
+
+typedef struct lsa_r_createaccount
+{
+ POLICY_HND pol; /* policy handle */
+ NTSTATUS status;
+} LSA_R_CREATEACCOUNT;
+
+
typedef struct lsa_q_openaccount
{
POLICY_HND pol; /* policy handle */
@@ -657,7 +671,7 @@ typedef struct lsa_r_enumprivsaccount
{
uint32 ptr;
uint32 count;
- PRIVILEGE_SET *set;
+ PRIVILEGE_SET set;
NTSTATUS status;
} LSA_R_ENUMPRIVSACCOUNT;
@@ -703,7 +717,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 +732,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/smb.h b/source3/include/smb.h
index d15f630507..1cf5aac0c5 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -281,6 +281,11 @@ typedef struct sid_info
} DOM_SID;
+typedef struct sid_list {
+ uint32 count;
+ DOM_SID *list;
+} SID_LIST;
+
/*
* The complete list of SIDS belonging to this user.
* Created when a vuid is registered.
@@ -297,6 +302,7 @@ typedef struct sid_info
typedef struct _nt_user_token {
size_t num_sids;
DOM_SID *user_sids;
+ PRIVILEGE_SET privileges;
} NT_USER_TOKEN;
/*** query a local group, get a list of these: shows who is in that group ***/
diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c
index c62396c22d..72d6e77ddd 100644
--- a/source3/lib/account_pol.c
+++ b/source3/lib/account_pol.c
@@ -20,10 +20,18 @@
*/
#include "includes.h"
-static TDB_CONTEXT *tdb; /* used for driver files */
+static TDB_CONTEXT *tdb;
#define DATABASE_VERSION 2
+extern DOM_SID global_sid_World;
+extern DOM_SID global_sid_Builtin_Administrators;
+extern DOM_SID global_sid_Builtin_Account_Operators;
+extern DOM_SID global_sid_Builtin_Server_Operators;
+extern DOM_SID global_sid_Builtin_Print_Operators;
+extern DOM_SID global_sid_Builtin_Backup_Operators;
+
+
/****************************************************************************
Set default for a field if it is empty
****************************************************************************/
@@ -91,6 +99,15 @@ BOOL init_account_policy(void)
}
tdb_unlock_bystring(tdb, vstring);
+ /* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */
+
+ privilege_create_account( &global_sid_World );
+ privilege_create_account( &global_sid_Builtin_Administrators );
+ privilege_create_account( &global_sid_Builtin_Account_Operators );
+ privilege_create_account( &global_sid_Builtin_Server_Operators );
+ privilege_create_account( &global_sid_Builtin_Print_Operators );
+ privilege_create_account( &global_sid_Builtin_Backup_Operators );
+
return True;
}
@@ -218,3 +235,18 @@ BOOL account_policy_set(int field, uint32 value)
return True;
}
+
+/****************************************************************************
+****************************************************************************/
+
+TDB_CONTEXT *get_account_pol_tdb( void )
+{
+
+ if ( !tdb ) {
+ if ( !init_account_policy() )
+ return NULL;
+ }
+
+ return tdb;
+}
+
diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c
index 2b8d7613c1..eabb652c3e 100644
--- a/source3/lib/privileges.c
+++ b/source3/lib/privileges.c
@@ -3,6 +3,7 @@
Privileges handling functions
Copyright (C) Jean François Micouleau 1998-2001
Copyright (C) Simo Sorce 2002-2003
+ Copyright (C) Gerald (Jerry) Carter 2004
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
@@ -19,138 +20,152 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include "includes.h"
-/* defines */
+#define PRIVPREFIX "PRIV_"
-#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;
- }
+#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)
+
+PRIVS privs[] = {
+ {SE_NETWORK_LOGON, "SeNetworkLogonRight", "Access this computer from the network"},
+ {SE_INTERACTIVE_LOGON, "SeInteractiveLogonRight", "Log on locally"},
+ {SE_BATCH_LOGON, "SeBatchLogonRight", "Log on as a batch job"},
+ {SE_SERVICE_LOGON, "SeServiceLogonRight", "Log on as a service"},
+
+ {SE_MACHINE_ACCOUNT, "SeMachineAccountPrivilege", "Add machines to domain"},
+ {SE_PRINT_OPERATOR, "SePrintOperatorPrivilege", "Printer Admin"},
+ {SE_ADD_USERS, "SeAddUsersPrivilege", "Add users and groups to the domain"},
+
+ {SE_END, "", ""}
+};
+
- return result;
-}
+#if 0 /* not needed currently */
+PRIVS privs[] = {
+ {SE_ASSIGN_PRIMARY_TOKEN, "SeAssignPrimaryTokenPrivilege", "Assign Primary Token"},
+ {SE_CREATE_TOKEN, "SeCreateTokenPrivilege", "Create Token"},
+ {SE_LOCK_MEMORY, "SeLockMemoryPrivilege", "Lock Memory"},
+ {SE_INCREASE_QUOTA, "SeIncreaseQuotaPrivilege", "Increase Quota"},
+ {SE_UNSOLICITED_INPUT, "SeUnsolicitedInputPrivilege", "Unsolicited Input"},
+ {SE_MACHINE_ACCOUNT, "SeMachineAccountPrivilege", "Can add Machine Accounts to the Domain"},
+ {SE_TCB, "SeTcbPrivilege", "Act as part of the operating system"},
+ {SE_SECURITY, "SeSecurityPrivilege", "Security Privilege"},
+ {SE_TAKE_OWNERSHIP, "SeTakeOwnershipPrivilege", "Take Ownership Privilege"},
+ {SE_LOAD_DRIVER, "SeLocalDriverPrivilege", "Local Driver Privilege"},
+ {SE_SYSTEM_PROFILE, "SeSystemProfilePrivilege", "System Profile Privilege"},
+ {SE_SYSTEM_TIME, "SeSystemtimePrivilege", "System Time"},
+ {SE_PROF_SINGLE_PROCESS, "SeProfileSingleProcessPrivilege", "Profile Single Process Privilege"},
+ {SE_INC_BASE_PRIORITY, "SeIncreaseBasePriorityPrivilege", "Increase Base Priority Privilege"},
+ {SE_CREATE_PAGEFILE, "SeCreatePagefilePrivilege", "Create Pagefile Privilege"},
+ {SE_CREATE_PERMANENT, "SeCreatePermanentPrivilege", "Create Permanent"},
+ {SE_BACKUP, "SeBackupPrivilege", "Backup Privilege"},
+ {SE_RESTORE, "SeRestorePrivilege", "Restore Privilege"},
+ {SE_SHUTDOWN, "SeShutdownPrivilege", "Shutdown Privilege"},
+ {SE_DEBUG, "SeDebugPrivilege", "Debug Privilege"},
+ {SE_AUDIT, "SeAuditPrivilege", "Audit"},
+ {SE_SYSTEM_ENVIRONMENT, "SeSystemEnvironmentPrivilege", "System Environment Privilege"},
+ {SE_CHANGE_NOTIFY, "SeChangeNotifyPrivilege", "Change Notify"},
+ {SE_REMOTE_SHUTDOWN, "SeRemoteShutdownPrivilege", "Remote Shutdown Privilege"},
+ {SE_UNDOCK, "SeUndockPrivilege", "Undock"},
+ {SE_SYNC_AGENT, "SeSynchronizationAgentPrivilege", "Synchronization Agent"},
+ {SE_ENABLE_DELEGATION, "SeEnableDelegationPrivilege", "Enable Delegation"},
+ {SE_PRINT_OPERATOR, "SePrintOperatorPrivilege", "Printer Operator"},
+ {SE_ADD_USERS, "SeAddUsersPrivilege", "Add Users"},
+ {SE_ALL_PRIVS, "SeAllPrivileges", "All Privileges"}
+ {SE_END, "", ""}
+};
#endif
-/****************************************************************************
- duplicate alloc luid_attr
- ****************************************************************************/
-NTSTATUS dupalloc_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la)
-{
- NTSTATUS ret;
+typedef struct priv_sid_list {
+ uint32 se_priv;
+ SID_LIST sids;
+} PRIV_SID_LIST;
- /* don't crash if the source pointer is NULL (since we don't
- do priviledges now anyways) */
+/***************************************************************************
+ Retrieve the privilege mask (set) for a given SID
+****************************************************************************/
- if ( !old_la )
- return NT_STATUS_OK;
+static uint32 get_privileges( const DOM_SID *sid )
+{
+ TDB_CONTEXT *tdb = get_account_pol_tdb();
+ fstring keystr;
+ uint32 priv_mask;
+
+ if ( !tdb )
+ return 0;
- *new_la = TALLOC_P(mem_ctx, LUID_ATTR);
- ALLOC_CHECK(new_la, ret, done, "dupalloc_luid_attr");
+ fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
- (*new_la)->luid.high = old_la->luid.high;
- (*new_la)->luid.low = old_la->luid.low;
- (*new_la)->attr = old_la->attr;
+ if ( !tdb_fetch_uint32( tdb, keystr, &priv_mask ) ) {
+ DEBUG(3,("get_privileges: No privileges assigned to SID [%s]\n",
+ sid_string_static(sid)));
+ return 0;
+ }
- ret = NT_STATUS_OK;
-
-done:
- return ret;
+ return priv_mask;
}
-/****************************************************************************
- 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_P(mem_ctx, PRIVILEGE_SET);
- ALLOC_CHECK(*priv_set, ret, done, "init_privilege");
+/***************************************************************************
+ Store the privilege mask (set) for a given SID
+****************************************************************************/
- (*priv_set)->mem_ctx = mem_ctx;
+static BOOL set_privileges( const DOM_SID *sid, uint32 mask )
+{
+ TDB_CONTEXT *tdb = get_account_pol_tdb();
+ fstring keystr;
+
+ if ( !tdb )
+ return False;
- ret = NT_STATUS_OK;
+ fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
-done:
- return ret;
+ return tdb_store_uint32( tdb, keystr, mask );
}
-NTSTATUS init_priv_with_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET **priv_set)
+/****************************************************************************
+ check if the privilege is in the privilege list
+****************************************************************************/
+
+static BOOL check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
{
- NTSTATUS ret;
+ int i;
- *priv_set = TALLOC_ZERO_P(mem_ctx, PRIVILEGE_SET);
- ALLOC_CHECK(*priv_set, ret, done, "init_privilege");
+ if ( !priv_set )
+ return False;
- (*priv_set)->mem_ctx = mem_ctx;
- (*priv_set)->ext_ctx = True;
+ for ( i = 0; i < priv_set->count; i++ ) {
+ LUID_ATTR *cur_set;
- ret = NT_STATUS_OK;
+ cur_set = &priv_set->set[i];
-done:
- return ret;
-}
+ /* check only the low and high part. Checking the attr
+ field has no meaning */
-void reset_privilege(PRIVILEGE_SET *priv_set)
-{
- priv_set->count = 0;
- priv_set->control = 0;
- priv_set->set = NULL;
-}
+ if ( (cur_set->luid.low == set.luid.low)
+ && (cur_set->luid.high == set.luid.high) )
+ {
+ return True;
+ }
+ }
-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;
+ return False;
}
/****************************************************************************
add a privilege to a privilege array
****************************************************************************/
-NTSTATUS add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
+
+static 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;
+
+ if ( check_priv_in_privilege(priv_set, set) )
+ return NT_STATUS_OK;
/* we can allocate memory to add the new privilege */
@@ -170,132 +185,222 @@ done:
return ret;
}
-/****************************************************************************
- add all the privileges to a privilege array
- ****************************************************************************/
-NTSTATUS add_all_privilege(PRIVILEGE_SET *priv_set)
+/*********************************************************************
+ Generate the LUID_ATTR structure based on a bitmask
+*********************************************************************/
+
+static LUID_ATTR get_privilege_luid( uint32 mask )
{
- NTSTATUS result = NT_STATUS_OK;
- LUID_ATTR set;
+ LUID_ATTR priv_luid;
+
+ priv_luid.attr = 0;
+ priv_luid.luid.high = 0;
+ priv_luid.luid.low = mask;
+
+ return priv_luid;
+}
- set.attr = 0;
- set.luid.high = 0;
+/*********************************************************************
+ Convert a privilege mask to an LUID_ATTR[] and add the privileges to
+ the PRIVILEGE_SET
+*********************************************************************/
- /* 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");
+static void add_privilege_set( PRIVILEGE_SET *privset, uint32 mask )
+{
+ LUID_ATTR luid;
+ int i;
+
+ for (i=0; privs[i].se_priv != SE_END; i++) {
- set.luid.low = SE_PRIV_ADD_MACHINES;
- result = add_privilege(priv_set, set);
- NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege");
+ /* skip if the privilege is not part of the mask */
- set.luid.low = SE_PRIV_PRINT_OPERATOR;
- result = add_privilege(priv_set, set);
- NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege");
+ if ( !(mask & privs[i].se_priv) )
+ continue;
- return result;
+ /* remove the bit from the mask */
+
+ mask &= ~privs[i].se_priv;
+
+ luid = get_privilege_luid( privs[i].se_priv );
+
+ add_privilege( privset, luid );
+ }
+
+ /* log an error if we have anything left at this point */
+ if ( mask )
+ DEBUG(0,("add_privilege_set: leftover bits! [0x%x]\n", mask ));
}
-/****************************************************************************
- check if the privilege list is empty
- ****************************************************************************/
-NTSTATUS check_empty_privilege(PRIVILEGE_SET *priv_set)
+/*********************************************************************
+ get a list of all privleges for all sids the in list
+*********************************************************************/
+
+void get_privileges_for_sids(PRIVILEGE_SET *privset, DOM_SID *slist, int scount)
{
- if (!priv_set)
- return NT_STATUS_INVALID_PARAMETER;
+ uint32 priv_mask;
+ int i;
+
+ for ( i=0; i<scount; i++ ) {
+ priv_mask = get_privileges( &slist[i] );
- if (priv_set->count == 0)
- return NT_STATUS_OK;
+ /* don't add unless we actually have a privilege assigned */
- return NT_STATUS_UNSUCCESSFUL;
+ if ( priv_mask == 0 )
+ continue;
+
+ DEBUG(5,("get_privileges_for_sids: sid = %s, privilege mask = 0x%x\n",
+ sid_string_static(&slist[i]), priv_mask));
+
+ add_privilege_set( privset, priv_mask );
+ }
}
-/****************************************************************************
- check if the privilege is in the privilege list
- ****************************************************************************/
-NTSTATUS check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
+
+/*********************************************************************
+ travseral functions for privilege_enumerate_accounts
+*********************************************************************/
+
+static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
{
- int i;
+ PRIV_SID_LIST *priv = state;
+ int prefixlen = strlen(PRIVPREFIX);
+ DOM_SID sid;
+ fstring sid_string;
- if (!priv_set)
- return NT_STATUS_INVALID_PARAMETER;
+ /* check we have a PRIV_+SID entry */
- /* 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;
+ if ( strncmp(key.dptr, PRIVPREFIX, prefixlen) != 0)
+ return 0;
+
+ /* check to see if we are looking for a particular privilege */
- for (i = 0; i < priv_set->count; i++) {
- LUID_ATTR *cur_set;
+ if ( priv->se_priv != SE_NONE ) {
+ uint32 mask = SVAL(data.dptr, 0);
+
+ /* if the SID does not have the specified privilege
+ then just return */
+
+ if ( !(mask & priv->se_priv) )
+ return 0;
+ }
+
+ fstrcpy( sid_string, &key.dptr[strlen(PRIVPREFIX)] );
- 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;
- }
+ if ( !string_to_sid(&sid, sid_string) ) {
+ DEBUG(0,("travsersal_fn_enum__acct: Could not convert SID [%s]\n",
+ sid_string));
+ return 0;
}
- return NT_STATUS_UNSUCCESSFUL;
+ add_sid_to_array( &sid, &priv->sids.list, &priv->sids.count );
+
+ return 0;
}
-/****************************************************************************
- remove a privilege from a privilege array
- ****************************************************************************/
-NTSTATUS remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
+/*********************************************************************
+ Retreive list of privileged SIDs (for _lsa_enumerate_accounts()
+*********************************************************************/
+
+NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids)
{
- NTSTATUS ret;
- LUID_ATTR *new_set;
- LUID_ATTR *old_set;
- int i,j;
+ TDB_CONTEXT *tdb = get_account_pol_tdb();
+ PRIV_SID_LIST priv;
+
+ ZERO_STRUCT(priv);
+ priv.se_priv = SE_NONE;
- if (!priv_set)
- return NT_STATUS_INVALID_PARAMETER;
+ tdb_traverse( tdb, priv_traverse_fn, &priv);
- /* check if the privilege is in the list */
- if (!NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set)))
- return NT_STATUS_UNSUCCESSFUL;
+ /* give the memory away; caller will free */
+
+ *sids = priv.sids.list;
+ *num_sids = priv.sids.count;
- /* special case if it's the only privilege in the list */
- if (priv_set->count == 1) {
- reset_privilege(priv_set);
- return NT_STATUS_OK;
- }
+ return NT_STATUS_OK;
+}
+
+/***************************************************************************
+ Retrieve the SIDs assigned to a given privilege
+****************************************************************************/
- /*
- * the privilege is there, create a new list,
- * and copy the other privileges
- */
+NTSTATUS priv_get_sids(const char *privname, DOM_SID **sids, int *num_sids)
+{
+ TDB_CONTEXT *tdb = get_account_pol_tdb();
+ PRIV_SID_LIST priv;
+
+ ZERO_STRUCT(priv);
+ priv.se_priv =
+
- old_set = priv_set->set;
+ tdb_traverse( tdb, priv_traverse_fn, &priv);
- new_set = TALLOC_ARRAY(priv_set->mem_ctx, LUID_ATTR, priv_set->count - 1);
- ALLOC_CHECK(new_set, ret, done, "remove_privilege");
+ /* give the memory away; caller will free */
+
+ *sids = priv.sids.list;
+ *num_sids = priv.sids.count;
- 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;
+ return NT_STATUS_OK;
+}
- j++;
- }
+/***************************************************************************
+ Add privilege to sid
+****************************************************************************/
+
+BOOL grant_privilege(const DOM_SID *sid, uint32 priv_mask)
+{
+ uint32 old_mask, new_mask;
- 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 */
+ old_mask = get_privileges( sid );
- priv_set->count--;
- priv_set->set = new_set;
+ new_mask = old_mask | priv_mask;
+
+ DEBUG(10,("grant_privilege: %s, orig priv set = 0x%x, new privilege set = 0x%x\n",
+ sid_string_static(sid), old_mask, new_mask ));
+ return set_privileges( sid, new_mask );
+}
+
+/***************************************************************************
+ Remove privilege from sid
+****************************************************************************/
+
+BOOL revoke_privilege(const DOM_SID *sid, uint32 priv_mask)
+{
+ uint32 old_mask, new_mask;
+
+ old_mask = get_privileges( sid );
+
+ new_mask = old_mask & ~priv_mask;
+
+ DEBUG(10,("revoke_privilege: %s, orig priv set = 0x%x, new priv set = 0x%x\n",
+ sid_string_static(sid), old_mask, new_mask ));
+
+ return set_privileges( sid, new_mask );
+}
+
+/***************************************************************************
+ Retrieve the SIDs assigned to a given privilege
+****************************************************************************/
+
+NTSTATUS privilege_create_account(const DOM_SID *sid )
+{
+ return ( grant_privilege( sid, SE_NONE ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL);
+}
+
+/****************************************************************************
+ initialise a privilege list and set the talloc context
+ ****************************************************************************/
+NTSTATUS privilege_set_init(PRIVILEGE_SET *priv_set)
+{
+ NTSTATUS ret;
+
+ ZERO_STRUCTP( priv_set );
+
+ TALLOC_CTX *mem_ctx = talloc_init("privilege set");
+ ALLOC_CHECK(mem_ctx, ret, done, "init_privilege");
+
+ priv_set->mem_ctx = mem_ctx;
+
ret = NT_STATUS_OK;
done:
@@ -303,48 +408,154 @@ done:
}
/****************************************************************************
- duplicates a privilege array
- the new privilege set must be passed inited
- (use init_privilege or init_priv_with_ctx)
+ initialise a privilege list and with someone else's talloc context
+****************************************************************************/
+
+NTSTATUS privilege_set_init_by_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET *priv_set)
+{
+ ZERO_STRUCTP( priv_set );
+
+ priv_set->mem_ctx = mem_ctx;
+ priv_set->ext_ctx = True;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Free all memory used by a PRIVILEGE_SET
+****************************************************************************/
+
+void privilege_set_free(PRIVILEGE_SET *priv_set)
+{
+ if ( !priv_set )
+ return;
+
+ if ( !( priv_set->ext_ctx ) )
+ talloc_destroy( priv_set->mem_ctx );
+
+ ZERO_STRUCTP( priv_set );
+}
+
+/****************************************************************************
+ duplicate alloc luid_attr
****************************************************************************/
-NTSTATUS dup_priv_set(PRIVILEGE_SET *new_priv_set, PRIVILEGE_SET *priv_set)
+
+NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la, int count)
{
NTSTATUS ret;
- LUID_ATTR *new_set;
- LUID_ATTR *old_set;
int i;
- if (!new_priv_set || !priv_set)
- return NT_STATUS_INVALID_PARAMETER;
+ /* don't crash if the source pointer is NULL (since we don't
+ do priviledges now anyways) */
- /* special case if there are no privileges in the list */
- if (priv_set->count == 0) {
+ if ( !old_la )
return NT_STATUS_OK;
- }
-
- /*
- * create a new list,
- * and copy the other privileges
- */
- old_set = priv_set->set;
-
- new_set = TALLOC_ARRAY(new_priv_set->mem_ctx, LUID_ATTR, priv_set->count - 1);
- ALLOC_CHECK(new_set, ret, done, "dup_priv_set");
+ *new_la = TALLOC_ARRAY(mem_ctx, LUID_ATTR, count);
+ ALLOC_CHECK(new_la, ret, done, "dupalloc_luid_attr");
- 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;
+ for (i=0; i<count; i++) {
+ (*new_la)[i].luid.high = old_la[i].luid.high;
+ (*new_la)[i].luid.low = old_la[i].luid.low;
+ (*new_la)[i].attr = old_la[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;
}
+
+/****************************************************************************
+ Performa deep copy of a PRIVILEGE_SET structure. Assumes an initialized
+ destination structure.
+*****************************************************************************/
+
+BOOL dup_privilege_set( PRIVILEGE_SET *dest, PRIVILEGE_SET *src )
+{
+ NTSTATUS result;
+
+ if ( !dest || !src )
+ return False;
+
+ result = dup_luid_attr( dest->mem_ctx, &dest->set, src->set, src->count );
+ if ( !NT_STATUS_IS_OK(result) ) {
+ DEBUG(0,("dup_privilege_set: Failed to dup LUID_ATTR array [%s]\n",
+ nt_errstr(result) ));
+ return False;
+ }
+
+ dest->control = src->control;
+ dest->count = src->count;
+
+ return True;
+}
+
+/****************************************************************************
+ Does the user have the specified privilege ? We only deal with one privilege
+ at a time here.
+*****************************************************************************/
+
+BOOL user_has_privilege(NT_USER_TOKEN *token, uint32 privilege)
+{
+ return check_priv_in_privilege( &token->privileges, get_privilege_luid(privilege) );
+}
+
+/****************************************************************************
+ Convert a LUID to a named string
+****************************************************************************/
+
+char* luid_to_privilege_name(const LUID *set)
+{
+ static fstring name;
+ int i = 0;
+
+ if (set->high != 0)
+ return NULL;
+
+ for ( i=0; privs[i].se_priv!=SE_END; i++ ) {
+ if (set->low == privs[i].se_priv) {
+ fstrcpy(name, privs[i].name);
+ return name;
+ }
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+ Convert an LUID to a 32-bit mask
+****************************************************************************/
+
+uint32 luid_to_privilege_mask(const LUID *set)
+{
+ int i = 0;
+
+ if (set->high != 0)
+ return SE_END;
+
+ for ( i=0; privs[i].se_priv != SE_END; i++ ) {
+ if (set->low == privs[i].se_priv)
+ return privs[i].se_priv;
+ }
+
+ return SE_END;
+}
+
+/*******************************************************************
+ return the number of elements in the privlege array
+*******************************************************************/
+
+int count_all_privileges( void )
+{
+ static int count;
+
+ if ( count )
+ return count;
+
+ /* loop over the array and count it */
+ for ( count=0; privs[count].se_priv != SE_END; count++ ) ;
+
+ return count;
+}
+
diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c
index 197157a2f7..0ba774e184 100644
--- a/source3/lib/util_sid.c
+++ b/source3/lib/util_sid.c
@@ -647,3 +647,67 @@ DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src)
return dst;
}
+
+/********************************************************************
+ Add SID to an array SIDs
+********************************************************************/
+
+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;
+}
+
+
+/********************************************************************
+ Add SID to an array SIDs ensuring that it is not already there
+********************************************************************/
+
+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);
+}
+
+/********************************************************************
+ Remove SID from an array
+********************************************************************/
+
+void del_sid_from_array(const DOM_SID *sid, DOM_SID **sids, int *num)
+{
+ DOM_SID *sid_list = *sids;
+ int i;
+
+ for ( i=0; i<*num; i++ ) {
+
+ /* if we find the SID, then decrement the count
+ and break out of the loop */
+
+ if ( sid_equal(sid, &sid_list[i]) ) {
+ *num -= 1;
+ break;
+ }
+ }
+
+ /* This loop will copy the remainder of the array
+ if i < num of sids ni the array */
+
+ for ( ; i<*num; i++ )
+ sid_copy( &sid_list[i], &sid_list[i+1] );
+
+ return;
+}
+
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, &current_count, &current_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(&current_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(&current_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, &current_count, &current_sids);
- if (!NT_STATUS_IS_OK(status)) {
- privilege_unlock_right(right);
- return status;
- }
-
- for (i=0;i<current_count;i++) {
- if (sid_equal(&current_sids[i], sid)) {
- /* found it - so remove it */
- if (current_count-i > 1) {
- memmove(&current_sids[i], &current_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);
-}
diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c
index edff25da7d..b08fa169ef 100644
--- a/source3/rpc_client/cli_lsarpc.c
+++ b/source3/rpc_client/cli_lsarpc.c
@@ -1037,9 +1037,9 @@ NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx,
}
for (i=0; i<r.count; i++) {
- (*set)[i].luid.low = r.set->set[i].luid.low;
- (*set)[i].luid.high = r.set->set[i].luid.high;
- (*set)[i].attr = r.set->set[i].attr;
+ (*set)[i].luid.low = r.set.set[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 e2cb94c8fe..20ccc39ce0 100644
--- a/source3/rpc_parse/parse_lsa.c
+++ b/source3/rpc_parse/parse_lsa.c
@@ -1650,6 +1650,61 @@ BOOL lsa_io_r_unk_get_connuser(const char *desc, LSA_R_UNK_GET_CONNUSER *r_c, pr
return True;
}
+void init_lsa_q_create_account(LSA_Q_CREATEACCOUNT *trn, POLICY_HND *hnd, DOM_SID *sid, uint32 desired_access)
+{
+ memcpy(&trn->pol, hnd, sizeof(trn->pol));
+
+ init_dom_sid2(&trn->sid, sid);
+ trn->access = desired_access;
+}
+
+
+/*******************************************************************
+ Reads or writes an LSA_Q_CREATEACCOUNT structure.
+********************************************************************/
+
+BOOL lsa_io_q_create_account(const char *desc, LSA_Q_CREATEACCOUNT *r_c, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_q_create_account");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("pol", &r_c->pol, ps, depth))
+ return False;
+
+ if(!smb_io_dom_sid2("sid", &r_c->sid, ps, depth)) /* domain SID */
+ return False;
+
+ if(!prs_uint32("access", ps, depth, &r_c->access))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_R_CREATEACCOUNT structure.
+********************************************************************/
+
+BOOL lsa_io_r_create_account(const char *desc, LSA_R_CREATEACCOUNT *r_c, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_r_open_account");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("pol", &r_c->pol, ps, depth))
+ return False;
+
+ if(!prs_ntstatus("status", ps, depth, &r_c->status))
+ return False;
+
+ return True;
+}
+
+
void init_lsa_q_open_account(LSA_Q_OPENACCOUNT *trn, POLICY_HND *hnd, DOM_SID *sid, uint32 desired_access)
{
memcpy(&trn->pol, hnd, sizeof(trn->pol));
@@ -1804,13 +1859,15 @@ NTSTATUS init_lsa_r_enum_privsaccount(TALLOC_CTX *mem_ctx, LSA_R_ENUMPRIVSACCOUN
r_u->ptr = 1;
r_u->count = count;
- if (!NT_STATUS_IS_OK(ret = init_priv_with_ctx(mem_ctx, &(r_u->set))))
+ if ( !NT_STATUS_IS_OK(ret = privilege_set_init_by_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)))
+ r_u->set.count = count;
+
+ if (!NT_STATUS_IS_OK(ret = dup_luid_attr(r_u->set.mem_ctx, &(r_u->set.set), set, count)))
return ret;
- DEBUG(10,("init_lsa_r_enum_privsaccount: %d %d privileges\n", r_u->count, r_u->set->count));
+ DEBUG(10,("init_lsa_r_enum_privsaccount: %d privileges\n", r_u->count));
return ret;
}
@@ -1837,15 +1894,15 @@ 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 (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set))))
+ if (!NT_STATUS_IS_OK(privilege_set_init_by_ctx(ps->mem_ctx, &(r_c->set))))
return False;
- if (!(r_c->set->set = PRS_ALLOC_MEM(ps,LUID_ATTR,r_c->count)))
+ if (!(r_c->set.set = PRS_ALLOC_MEM(ps,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;
}
@@ -2007,14 +2064,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 (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set))))
+ if (!NT_STATUS_IS_OK(privilege_set_init_by_ctx(ps->mem_ctx, &(r_c->set))))
return False;
- if (!(r_c->set->set = PRS_ALLOC_MEM(ps, LUID_ATTR, r_c->count)))
+ if (!(r_c->set.set = PRS_ALLOC_MEM(ps, 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;
@@ -2069,14 +2126,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 (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set))))
+ if (!NT_STATUS_IS_OK(privilege_set_init_by_ctx(ps->mem_ctx, &(r_c->set))))
return False;
- if (!(r_c->set->set = PRS_ALLOC_MEM(ps, LUID_ATTR, r_c->count)))
+ if (!(r_c->set.set = PRS_ALLOC_MEM(ps, 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_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c
index 5d6c1551c9..63e74ec891 100644
--- a/source3/rpc_server/srv_lsa.c
+++ b/source3/rpc_server/srv_lsa.c
@@ -393,6 +393,37 @@ static BOOL api_lsa_unk_get_connuser(pipes_struct *p)
}
/***************************************************************************
+ api_lsa_create_user
+ ***************************************************************************/
+
+static BOOL api_lsa_create_account(pipes_struct *p)
+{
+ LSA_Q_CREATEACCOUNT q_u;
+ LSA_R_CREATEACCOUNT r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!lsa_io_q_create_account("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_create_account: failed to unmarshall LSA_Q_CREATEACCOUNT.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_create_account(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!lsa_io_r_create_account("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_create_account: Failed to marshall LSA_R_CREATEACCOUNT.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
api_lsa_open_user
***************************************************************************/
@@ -659,6 +690,7 @@ static struct api_struct api_lsa_cmds[] =
{ "LSA_PRIV_GET_DISPNAME",LSA_PRIV_GET_DISPNAME,api_lsa_priv_get_dispname},
{ "LSA_ENUM_ACCOUNTS" , LSA_ENUM_ACCOUNTS , api_lsa_enum_accounts },
{ "LSA_UNK_GET_CONNUSER", LSA_UNK_GET_CONNUSER, api_lsa_unk_get_connuser },
+ { "LSA_CREATEACCOUNT" , LSA_CREATEACCOUNT , api_lsa_create_account },
{ "LSA_OPENACCOUNT" , LSA_OPENACCOUNT , api_lsa_open_account },
{ "LSA_ENUMPRIVSACCOUNT", LSA_ENUMPRIVSACCOUNT, api_lsa_enum_privsaccount},
{ "LSA_GETSYSTEMACCOUNT", LSA_GETSYSTEMACCOUNT, api_lsa_getsystemaccount },
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index fcd574971f..89633935a2 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -1,4 +1,4 @@
-/*
+/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
@@ -7,6 +7,7 @@
* Copyright (C) Jeremy Allison 2001,
* Copyright (C) Rafal Szczesniak 2002,
* Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002,
+ * Copyright (C) Simo Sorce 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
@@ -411,9 +412,12 @@ NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL
DEBUG(4,("ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
acc_granted, des_access));
DEBUGADD(4,("but overwritten by euid == 0\n"));
- acc_granted = des_access;
}
+ /* This is needed for lsa_open_account and rpcclient .... :-) */
+
+ if (geteuid() == 0)
+ acc_granted = POLICY_ALL_ACCESS;
/* associate the domain SID with the (unique) handle. */
if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
@@ -758,49 +762,51 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV
{
struct lsa_info *handle;
uint32 i;
+ uint32 enum_context = q_u->enum_context;
+ int num_privs = count_all_privileges();
+ LSA_PRIV_ENTRY *entries = NULL;
- uint32 enum_context=q_u->enum_context;
- LSA_PRIV_ENTRY *entry;
- LSA_PRIV_ENTRY *entries=NULL;
+ /* remember that the enum_context starts at 0 and not 1 */
- if (enum_context >= PRIV_ALL_INDEX)
+ if ( enum_context >= num_privs )
return NT_STATUS_NO_MORE_ENTRIES;
-
- entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, PRIV_ALL_INDEX);
- if (entries==NULL)
+
+ DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n",
+ enum_context, num_privs));
+
+ if ( !(entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, num_privs + 1)))
return NT_STATUS_NO_MEMORY;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
return NT_STATUS_INVALID_HANDLE;
- /* check if the user have enough rights */
+ /* check if the user have enough rights
+ I don't know if it's the right one. not documented. */
- /*
- * I don't know if it's the right one. not documented.
- */
if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
- entry = entries;
-
- DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n", enum_context, PRIV_ALL_INDEX));
-
- for (i = 0; i < PRIV_ALL_INDEX; i++, entry++) {
- if( i<enum_context) {
- init_unistr2(&entry->name, NULL, UNI_FLAGS_NONE);
- init_uni_hdr(&entry->hdr_name, &entry->name);
- entry->luid_low = 0;
- entry->luid_high = 0;
+ if ( !(entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, num_privs )) )
+ return NT_STATUS_NO_MEMORY;
+
+
+ for (i = 0; i < num_privs; i++) {
+ if( i < enum_context) {
+ init_unistr2(&entries[i].name, NULL, UNI_FLAGS_NONE);
+ init_uni_hdr(&entries[i].hdr_name, &entries[i].name);
+ entries[i].luid_low = 0;
+ entries[i].luid_high = 0;
} else {
- init_unistr2(&entry->name, privs[i+1].priv, UNI_FLAGS_NONE);
- init_uni_hdr(&entry->hdr_name, &entry->name);
- entry->luid_low = privs[i+1].se_priv;
- entry->luid_high = 0;
+ init_unistr2(&entries[i].name, privs[i].name, UNI_FLAGS_NONE);
+ init_uni_hdr(&entries[i].hdr_name, &entries[i].name);
+ entries[i].luid_low = privs[i].se_priv;
+ entries[i].luid_high = 0;
}
}
- enum_context = PRIV_ALL_INDEX;
- init_lsa_r_enum_privs(r_u, enum_context, PRIV_ALL_INDEX, entries);
+ enum_context = num_privs;
+
+ init_lsa_r_enum_privs(r_u, enum_context, num_privs, entries);
return NT_STATUS_OK;
}
@@ -813,7 +819,7 @@ NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, L
{
struct lsa_info *handle;
fstring name_asc;
- int i=1;
+ int i = 0;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
return NT_STATUS_INVALID_HANDLE;
@@ -828,22 +834,22 @@ NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, L
unistr2_to_ascii(name_asc, &q_u->name, sizeof(name_asc));
- DEBUG(10,("_lsa_priv_get_dispname: %s", name_asc));
+ DEBUG(10,("_lsa_priv_get_dispname: %s\n", name_asc));
- while (privs[i].se_priv!=SE_PRIV_ALL && strcmp(name_asc, privs[i].priv))
+ while (privs[i].se_priv != SE_END && !strequal(name_asc, privs[i].name))
i++;
- if (privs[i].se_priv!=SE_PRIV_ALL) {
+ if (privs[i].se_priv != SE_END) {
DEBUG(10,(": %s\n", privs[i].description));
init_unistr2(&r_u->desc, privs[i].description, UNI_FLAGS_NONE);
init_uni_hdr(&r_u->hdr_desc, &r_u->desc);
- r_u->ptr_info=0xdeadbeef;
- r_u->lang_id=q_u->lang_id;
+ r_u->ptr_info = 0xdeadbeef;
+ r_u->lang_id = q_u->lang_id;
return NT_STATUS_OK;
} else {
DEBUG(10,("_lsa_priv_get_dispname: doesn't exist\n"));
- r_u->ptr_info=0;
+ r_u->ptr_info = 0;
return NT_STATUS_NO_SUCH_PRIVILEGE;
}
}
@@ -855,32 +861,26 @@ _lsa_enum_accounts.
NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENUM_ACCOUNTS *r_u)
{
struct lsa_info *handle;
- GROUP_MAP *map=NULL;
- int num_entries=0;
+ DOM_SID *sid_list;
+ int i, j, num_entries;
LSA_SID_ENUM *sids=&r_u->sids;
- int i=0,j=0;
- BOOL ret;
+ NTSTATUS ret;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
return NT_STATUS_INVALID_HANDLE;
- /* check if the user have enough rights */
-
- /*
- * I don't know if it's the right one. not documented.
- */
if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
- /* get the list of mapped groups (domain, local, builtin) */
- become_root();
- ret = pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED);
- unbecome_root();
- if( !ret ) {
- DEBUG(3,("_lsa_enum_accounts: enumeration of groups failed!\n"));
- return NT_STATUS_OK;
+ sid_list = NULL;
+ num_entries = 0;
+
+ /* The only way we can currently find out all the SIDs that have been
+ privileged is to scan all privileges */
+
+ if (!NT_STATUS_IS_OK(ret = privilege_enumerate_accounts(&sid_list, &num_entries))) {
+ return ret;
}
-
if (q_u->enum_context >= num_entries)
return NT_STATUS_NO_MORE_ENTRIES;
@@ -889,19 +889,18 @@ NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENU
sids->sid = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_SID2, num_entries-q_u->enum_context);
if (sids->ptr_sid==NULL || sids->sid==NULL) {
- SAFE_FREE(map);
+ SAFE_FREE(sid_list);
return NT_STATUS_NO_MEMORY;
}
- for (i=q_u->enum_context, j=0; i<num_entries; i++) {
- init_dom_sid2( &(*sids).sid[j], &map[i].sid);
- (*sids).ptr_sid[j]=1;
- j++;
+ for (i = q_u->enum_context, j = 0; i < num_entries; i++, j++) {
+ init_dom_sid2(&(*sids).sid[j], &sid_list[i]);
+ (*sids).ptr_sid[j] = 1;
}
- SAFE_FREE(map);
+ SAFE_FREE(sid_list);
- init_lsa_r_enum_accounts(r_u, j);
+ init_lsa_r_enum_accounts(r_u, num_entries);
return NT_STATUS_OK;
}
@@ -934,15 +933,51 @@ NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA
}
/***************************************************************************
-
+ Lsa Create Account
***************************************************************************/
-NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENACCOUNT *r_u)
+NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CREATEACCOUNT *r_u)
{
struct lsa_info *handle;
struct lsa_info *info;
- r_u->status = NT_STATUS_OK;
+ /* find the connection policy handle. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
+ return NT_STATUS_INVALID_HANDLE;
+
+ /* check if the user have enough rights */
+
+ /*
+ * I don't know if it's the right one. not documented.
+ * but guessed with rpcclient.
+ */
+ if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
+ return NT_STATUS_ACCESS_DENIED;
+
+ /* associate the user/group SID with the (unique) handle. */
+ if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ ZERO_STRUCTP(info);
+ info->sid = q_u->sid.sid;
+ info->access = q_u->access;
+
+ /* get a (unique) handle. open a policy on it. */
+ if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ return privilege_create_account( &info->sid );
+}
+
+
+/***************************************************************************
+ Lsa Open Account
+ ***************************************************************************/
+
+NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENACCOUNT *r_u)
+{
+ struct lsa_info *handle;
+ struct lsa_info *info;
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
@@ -957,6 +992,11 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC
if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
+ /* TODO: Fis the parsing routine before reenabling this check! */
+ #if 0
+ if (!lookup_sid(&handle->sid, dom_name, name, &type))
+ return NT_STATUS_ACCESS_DENIED;
+ #endif
/* associate the user/group SID with the (unique) handle. */
if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
return NT_STATUS_NO_MEMORY;
@@ -969,7 +1009,7 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC
if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -979,44 +1019,24 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC
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;
- LUID_ATTR *set=NULL;
-
- r_u->status = NT_STATUS_OK;
+ PRIVILEGE_SET priv;
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!pdb_getgrsid(&map, info->sid))
- return NT_STATUS_NO_SUCH_GROUP;
+ privilege_set_init( &priv );
-#if 0 /* privileges currently not implemented! */
- DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set->count));
- if (map.priv_set->count!=0) {
-
- set=(LUID_ATTR *)talloc(map.priv_set->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR));
- if (set == NULL) {
- destroy_privilege(&map.priv_set);
- return NT_STATUS_NO_MEMORY;
- }
+ get_privileges_for_sids( &priv, &info->sid, 1 );
- for (i = 0; i < map.priv_set.count; i++) {
- set[i].luid.low = map.priv_set->set[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));
- }
- }
+ DEBUG(10,("_lsa_enum_privsaccount: %s has %d privileges\n",
+ sid_string_static(&info->sid), priv.count));
- 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(ps->mem_ctx, r_u, priv.set, priv.count, 0);
- init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, 0, 0);
+ privilege_set_free( &priv );
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -1026,15 +1046,16 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVS
NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u)
{
struct lsa_info *info=NULL;
- GROUP_MAP map;
- r_u->status = NT_STATUS_OK;
+ fstring name, dom_name;
+ enum SID_NAME_USE type;
/* find the connection policy handle. */
+
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!pdb_getgrsid(&map, info->sid))
- return NT_STATUS_NO_SUCH_GROUP;
+ if (!lookup_sid(&info->sid, dom_name, name, &type))
+ return NT_STATUS_ACCESS_DENIED;
/*
0x01 -> Log on locally
@@ -1047,7 +1068,7 @@ NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA
r_u->access = PR_LOG_ON_LOCALLY | PR_ACCESS_FROM_NETWORK;
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -1079,44 +1100,31 @@ 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;
- GROUP_MAP map;
int i = 0;
- LUID_ATTR *luid_attr = NULL;
+ uint32 mask;
PRIVILEGE_SET *set = NULL;
-#endif
-
- r_u->status = NT_STATUS_OK;
-#if 0 /* privileges are not implemented */
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!pdb_getgrsid(&map, info->sid))
- return NT_STATUS_NO_SUCH_GROUP;
-
set = &q_u->set;
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)){
- destroy_privilege(&map.priv_set);
+
+ mask = luid_to_privilege_mask( &(set->set[i].luid) );
+
+ if ( mask != SE_END ) {
+ if ( !grant_privilege( &info->sid, mask ) ) {
+ DEBUG(3,("_lsa_addprivs: grant_privilege( %s, 0x%x) failed!\n",
+ sid_string_static(&info->sid), mask ));
+ return NT_STATUS_NO_SUCH_PRIVILEGE;
+ }
}
-
- add_privilege(map.priv_set, *luid_attr);
}
- if(!pdb_update_group_mapping_entry(&map))
- return NT_STATUS_NO_SUCH_GROUP;
-
- destroy_privilege(&map.priv_set);
-
-#endif
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -1125,57 +1133,30 @@ 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;
- GROUP_MAP map;
- int i=0;
- LUID_ATTR *luid_attr = NULL;
+ int i = 0;
+ uint32 mask;
PRIVILEGE_SET *set = NULL;
-#endif
-
- r_u->status = NT_STATUS_OK;
-#if 0 /* privileges are not implemented */
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!pdb_getgrsid(&map, info->sid))
- return NT_STATUS_NO_SUCH_GROUP;
-
- 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) {
- /* 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;
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)){
- destroy_privilege(&map.priv_set);
- return NT_STATUS_NO_SUCH_PRIVILEGE;
+ mask = luid_to_privilege_mask( &(set->set[i].luid) );
+
+ if ( mask != SE_END ) {
+ if ( !revoke_privilege( &info->sid, mask ) ) {
+ DEBUG(3,("_lsa_removeprivs: revoke_privilege( %s, 0x%x) failed!\n",
+ sid_string_static(&info->sid), mask ));
+ return NT_STATUS_NO_SUCH_PRIVILEGE;
+ }
}
-
- remove_privilege(map.priv_set, *luid_attr);
}
- if(!pdb_update_group_mapping_entry(&map))
- return NT_STATUS_NO_SUCH_GROUP;
-
- destroy_privilege(&map.priv_set);
-#endif
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index da1c386fd2..271553f4b2 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -2215,7 +2215,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
uint32 new_rid = 0;
/* check this, when giving away 'add computer to domain' privs */
uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS;
- BOOL is_domain_admin = False;
+ BOOL can_add_machines = False;
/* Get the domain SID stored in the domain policy */
if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted))
@@ -2242,10 +2242,10 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
/* check to see if we are a domain admin */
- is_domain_admin = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
+ can_add_machines = user_has_privilege( p->pipe_user.nt_user_token, SE_MACHINE_ACCOUNT );
DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n",
- p->pipe_user_name, is_domain_admin ? "" : " not"));
+ p->pipe_user_name, can_add_machines ? "" : " not"));
pdb_init_sam(&sam_pass);
@@ -2280,9 +2280,9 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
pw = Get_Pwnam(account);
- /* ================ BEGIN DOMAIN ADMIN BLOCK ================ */
+ /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
- if ( is_domain_admin )
+ if ( can_add_machines )
become_root();
if ( !pw ) {
@@ -2317,7 +2317,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
/* implicit call to getpwnam() next. we have a valid SID coming out of this call */
if ( !NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pass, account, new_rid)) ) {
- if ( is_domain_admin )
+ if ( can_add_machines )
unbecome_root();
return nt_status;
}
@@ -2326,10 +2326,10 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
ret = pdb_add_sam_account(sam_pass);
- if ( is_domain_admin )
+ if ( can_add_machines )
unbecome_root();
- /* ================ END DOMAIN ADMIN BLOCK ================ */
+ /* ================ END SeMachineAccountPrivilege BLOCK ================ */
if ( !ret ) {
pdb_free_sam(&sam_pass);
@@ -3033,7 +3033,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
SAM_USERINFO_CTR *ctr = q_u->ctr;
uint32 acc_granted;
uint32 acc_required;
- BOOL is_domain_admin;
+ BOOL can_add_machines;
DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__));
@@ -3067,14 +3067,14 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
/* check to see if we are a domain admin */
- is_domain_admin = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
+ can_add_machines = user_has_privilege( p->pipe_user.nt_user_token, SE_MACHINE_ACCOUNT );
DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n",
- p->pipe_user_name, is_domain_admin ? "" : " not"));
+ p->pipe_user_name, can_add_machines ? "" : " not"));
- /* ================ BEGIN DOMAIN ADMIN BLOCK ================ */
+ /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
- if ( is_domain_admin )
+ if ( can_add_machines )
become_root();
/* ok! user info levels (lots: see MSDEV help), off we go... */
@@ -3138,10 +3138,10 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
}
- if ( is_domain_admin )
+ if ( can_add_machines )
unbecome_root();
- /* ================ END DOMAIN ADMIN BLOCK ================ */
+ /* ================ END SeMachineAccountPrivilege BLOCK ================ */
return r_u->status;
}
@@ -3158,7 +3158,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
uint16 switch_value = q_u->switch_value;
uint32 acc_granted;
uint32 acc_required;
- BOOL is_domain_admin;
+ BOOL can_add_machines;
DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__));
@@ -3184,14 +3184,14 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
/* check to see if we are a domain admin */
- is_domain_admin = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
+ can_add_machines = user_has_privilege( p->pipe_user.nt_user_token, SE_MACHINE_ACCOUNT );
DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n",
- p->pipe_user_name, is_domain_admin ? "" : " not"));
+ p->pipe_user_name, can_add_machines ? "" : " not"));
- /* ================ BEGIN DOMAIN ADMIN BLOCK ================ */
+ /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
- if ( is_domain_admin )
+ if ( can_add_machines )
become_root();
/* ok! user info levels (lots: see MSDEV help), off we go... */
@@ -3218,10 +3218,10 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
r_u->status = NT_STATUS_INVALID_INFO_CLASS;
}
- if ( is_domain_admin )
+ if ( can_add_machines )
unbecome_root();
- /* ================ END DOMAIN ADMIN BLOCK ================ */
+ /* ================ END SeMachineAccountPrivilege BLOCK ================ */
return r_u->status;
}