1
0
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:
Gerald Carter 2005-01-13 18:20:37 +00:00 committed by Gerald (Jerry) Carter
parent dddd572646
commit 77c10ff9aa
18 changed files with 971 additions and 859 deletions

View File

@ -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 \

View File

@ -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;
}

View File

@ -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
****************************************************************************/

View File

@ -814,6 +814,8 @@ extern int errno;
#include "version.h"
#include "privileges.h"
#include "smb.h"
#include "nameserv.h"

View File

@ -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 */

View File

@ -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

View File

@ -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 ***/

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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 },

View File

@ -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;
}
/***************************************************************************

View File

@ -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;
}