mirror of
https://github.com/samba-team/samba.git
synced 2025-01-24 02:04:21 +03:00
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 commit is contained in:
parent
dddd572646
commit
77c10ff9aa
@ -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 \
|
||||
|
@ -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;
|
||||
if ((token = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL)
|
||||
return NULL;
|
||||
|
||||
ZERO_STRUCTP(token);
|
||||
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;
|
||||
}
|
||||
|
||||
if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) {
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
****************************************************************************/
|
||||
|
@ -814,6 +814,8 @@ extern int errno;
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "privileges.h"
|
||||
|
||||
#include "smb.h"
|
||||
|
||||
#include "nameserv.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 */
|
||||
|
@ -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
|
||||
|
@ -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 ***/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
#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"},
|
||||
|
||||
/****************************************************************************
|
||||
Check if a user is a mapped group.
|
||||
{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"},
|
||||
|
||||
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.
|
||||
{SE_END, "", ""}
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
#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)
|
||||
typedef struct priv_sid_list {
|
||||
uint32 se_priv;
|
||||
SID_LIST sids;
|
||||
} PRIV_SID_LIST;
|
||||
|
||||
/***************************************************************************
|
||||
Retrieve the privilege mask (set) for a given SID
|
||||
****************************************************************************/
|
||||
|
||||
static uint32 get_privileges( const DOM_SID *sid )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
|
||||
/* don't crash if the source pointer is NULL (since we don't
|
||||
do priviledges now anyways) */
|
||||
|
||||
if ( !old_la )
|
||||
return NT_STATUS_OK;
|
||||
|
||||
*new_la = TALLOC_P(mem_ctx, 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;
|
||||
TDB_CONTEXT *tdb = get_account_pol_tdb();
|
||||
fstring keystr;
|
||||
uint32 priv_mask;
|
||||
|
||||
ret = NT_STATUS_OK;
|
||||
if ( !tdb )
|
||||
return 0;
|
||||
|
||||
done:
|
||||
return ret;
|
||||
fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return priv_mask;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Store the privilege mask (set) for a given SID
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL set_privileges( const DOM_SID *sid, uint32 mask )
|
||||
{
|
||||
TDB_CONTEXT *tdb = get_account_pol_tdb();
|
||||
fstring keystr;
|
||||
|
||||
if ( !tdb )
|
||||
return False;
|
||||
|
||||
fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
|
||||
|
||||
return tdb_store_uint32( tdb, keystr, mask );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
initialise a privilege list
|
||||
****************************************************************************/
|
||||
NTSTATUS init_privilege(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;
|
||||
TALLOC_CTX *mem_ctx = talloc_init("privilege set");
|
||||
ALLOC_CHECK(mem_ctx, ret, done, "init_privilege");
|
||||
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;
|
||||
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 */
|
||||
|
||||
NTSTATUS init_priv_with_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET **priv_set)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
if ( (cur_set->luid.low == set.luid.low)
|
||||
&& (cur_set->luid.high == set.luid.high) )
|
||||
{
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
*priv_set = TALLOC_ZERO_P(mem_ctx, 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;
|
||||
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,181 +185,377 @@ 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;
|
||||
|
||||
set.attr = 0;
|
||||
set.luid.high = 0;
|
||||
priv_luid.attr = 0;
|
||||
priv_luid.luid.high = 0;
|
||||
priv_luid.luid.low = mask;
|
||||
|
||||
/* 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");
|
||||
|
||||
return result;
|
||||
return priv_luid;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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)
|
||||
/*********************************************************************
|
||||
Convert a privilege mask to an LUID_ATTR[] and add the privileges to
|
||||
the PRIVILEGE_SET
|
||||
*********************************************************************/
|
||||
|
||||
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++) {
|
||||
|
||||
if (!priv_set)
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
/* skip if the privilege is not part of the mask */
|
||||
|
||||
/* 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 ( !(mask & privs[i].se_priv) )
|
||||
continue;
|
||||
|
||||
for (i = 0; i < priv_set->count; i++) {
|
||||
LUID_ATTR *cur_set;
|
||||
/* remove the bit from the mask */
|
||||
|
||||
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;
|
||||
}
|
||||
mask &= ~privs[i].se_priv;
|
||||
|
||||
luid = get_privilege_luid( privs[i].se_priv );
|
||||
|
||||
add_privilege( privset, luid );
|
||||
}
|
||||
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
/* log an error if we have anything left at this point */
|
||||
if ( mask )
|
||||
DEBUG(0,("add_privilege_set: leftover bits! [0x%x]\n", mask ));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
remove a privilege from a privilege array
|
||||
****************************************************************************/
|
||||
NTSTATUS remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR 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)
|
||||
{
|
||||
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 = TALLOC_ARRAY(priv_set->mem_ctx, LUID_ATTR, priv_set->count - 1);
|
||||
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;
|
||||
uint32 priv_mask;
|
||||
int i;
|
||||
|
||||
for ( i=0; i<scount; i++ ) {
|
||||
priv_mask = get_privileges( &slist[i] );
|
||||
|
||||
if (!new_priv_set || !priv_set)
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
/* don't add unless we actually have a privilege assigned */
|
||||
|
||||
/* 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 = TALLOC_ARRAY(new_priv_set->mem_ctx, LUID_ATTR, priv_set->count - 1);
|
||||
ALLOC_CHECK(new_set, ret, done, "dup_priv_set");
|
||||
|
||||
for (i=0; i < priv_set->count; i++) {
|
||||
if ( priv_mask == 0 )
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
DEBUG(5,("get_privileges_for_sids: sid = %s, privilege mask = 0x%x\n",
|
||||
sid_string_static(&slist[i]), priv_mask));
|
||||
|
||||
new_priv_set->count = priv_set->count;
|
||||
new_priv_set->control = priv_set->control;
|
||||
new_priv_set->set = new_set;
|
||||
add_privilege_set( privset, priv_mask );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
travseral functions for privilege_enumerate_accounts
|
||||
*********************************************************************/
|
||||
|
||||
static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
|
||||
{
|
||||
PRIV_SID_LIST *priv = state;
|
||||
int prefixlen = strlen(PRIVPREFIX);
|
||||
DOM_SID sid;
|
||||
fstring sid_string;
|
||||
|
||||
/* check we have a PRIV_+SID entry */
|
||||
|
||||
if ( strncmp(key.dptr, PRIVPREFIX, prefixlen) != 0)
|
||||
return 0;
|
||||
|
||||
/* check to see if we are looking for a particular privilege */
|
||||
|
||||
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)] );
|
||||
|
||||
if ( !string_to_sid(&sid, sid_string) ) {
|
||||
DEBUG(0,("travsersal_fn_enum__acct: Could not convert SID [%s]\n",
|
||||
sid_string));
|
||||
return 0;
|
||||
}
|
||||
|
||||
add_sid_to_array( &sid, &priv->sids.list, &priv->sids.count );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Retreive list of privileged SIDs (for _lsa_enumerate_accounts()
|
||||
*********************************************************************/
|
||||
|
||||
NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids)
|
||||
{
|
||||
TDB_CONTEXT *tdb = get_account_pol_tdb();
|
||||
PRIV_SID_LIST priv;
|
||||
|
||||
ZERO_STRUCT(priv);
|
||||
priv.se_priv = SE_NONE;
|
||||
|
||||
tdb_traverse( tdb, priv_traverse_fn, &priv);
|
||||
|
||||
/* give the memory away; caller will free */
|
||||
|
||||
*sids = priv.sids.list;
|
||||
*num_sids = priv.sids.count;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Retrieve the SIDs assigned to a given privilege
|
||||
****************************************************************************/
|
||||
|
||||
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 =
|
||||
|
||||
|
||||
tdb_traverse( tdb, priv_traverse_fn, &priv);
|
||||
|
||||
/* give the memory away; caller will free */
|
||||
|
||||
*sids = priv.sids.list;
|
||||
*num_sids = priv.sids.count;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Add privilege to sid
|
||||
****************************************************************************/
|
||||
|
||||
BOOL grant_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,("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:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la, int count)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
int i;
|
||||
|
||||
/* don't crash if the source pointer is NULL (since we don't
|
||||
do priviledges now anyways) */
|
||||
|
||||
if ( !old_la )
|
||||
return NT_STATUS_OK;
|
||||
|
||||
*new_la = TALLOC_ARRAY(mem_ctx, LUID_ATTR, count);
|
||||
ALLOC_CHECK(new_la, ret, done, "dupalloc_luid_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -392,6 +392,37 @@ static BOOL api_lsa_unk_get_connuser(pipes_struct *p)
|
||||
return True;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
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 },
|
||||
|
@ -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));
|
||||
if ( !(entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, num_privs )) )
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
|
||||
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;
|
||||
|
||||
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,16 +933,14 @@ 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;
|
||||
@ -969,7 +966,50 @@ 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 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))
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user