2003-10-06 05:24:48 +04:00
/*
Unix SMB / CIFS implementation .
Privileges handling functions
2005-02-18 01:46:41 +03:00
Copyright ( C ) Jean François Micouleau 1998 - 2001
2003-10-06 05:24:48 +04:00
Copyright ( C ) Simo Sorce 2002 - 2003
2005-01-13 21:20:37 +03:00
Copyright ( C ) Gerald ( Jerry ) Carter 2004
2003-10-06 05:24:48 +04:00
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 0213 9 , USA .
*/
2005-01-13 21:20:37 +03:00
2003-10-06 05:24:48 +04:00
# include "includes.h"
2005-01-13 21:20:37 +03:00
# define PRIVPREFIX "PRIV_"
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
# define GENERATE_LUID_LOW(x) (x)+1;
2005-02-18 01:46:41 +03:00
static const SE_PRIV se_priv_all = SE_ALL_PRIVS ;
static const SE_PRIV se_priv_end = SE_END ;
2005-01-17 18:23:11 +03:00
2005-01-19 19:52:19 +03:00
/* Define variables for all privileges so we can use the
SE_PRIV * in the various se_priv_XXX ( ) functions */
2005-02-03 18:14:54 +03:00
const SE_PRIV se_priv_none = SE_NONE ;
2005-01-19 19:52:19 +03:00
const SE_PRIV se_machine_account = SE_MACHINE_ACCOUNT ;
const SE_PRIV se_print_operator = SE_PRINT_OPERATOR ;
const SE_PRIV se_add_users = SE_ADD_USERS ;
const SE_PRIV se_disk_operators = SE_DISK_OPERATOR ;
const SE_PRIV se_remote_shutdown = SE_REMOTE_SHUTDOWN ;
2005-01-13 21:20:37 +03:00
PRIVS privs [ ] = {
2005-01-17 23:27:29 +03:00
#if 0 /* usrmgr will display these twice if you include them. We don't
use them but we ' ll keep the bitmasks reserved in privileges . h anyways */
{ SE_NETWORK_LOGON , " SeNetworkLogonRight " , " Access this computer from network " } ,
2005-01-13 21:20:37 +03:00
{ 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 " } ,
2005-01-17 23:27:29 +03:00
# endif
2005-01-13 21:20:37 +03:00
{ SE_MACHINE_ACCOUNT , " SeMachineAccountPrivilege " , " Add machines to domain " } ,
2005-01-17 23:27:29 +03:00
{ SE_PRINT_OPERATOR , " SePrintOperatorPrivilege " , " Manage printers " } ,
2005-01-13 21:20:37 +03:00
{ SE_ADD_USERS , " SeAddUsersPrivilege " , " Add users and groups to the domain " } ,
2005-01-17 23:27:29 +03:00
{ SE_REMOTE_SHUTDOWN , " SeRemoteShutdownPrivilege " , " Force shutdown from a remote system " } ,
{ SE_DISK_OPERATOR , " SeDiskOperatorPrivilege " , " Manage disk shares " } ,
2005-01-13 21:20:37 +03:00
{ SE_END , " " , " " }
} ;
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
#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_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_UNDOCK , " SeUndockPrivilege " , " Undock " } ,
{ SE_SYNC_AGENT , " SeSynchronizationAgentPrivilege " , " Synchronization Agent " } ,
{ SE_ENABLE_DELEGATION , " SeEnableDelegationPrivilege " , " Enable Delegation " } ,
{ SE_ALL_PRIVS , " SeAllPrivileges " , " All Privileges " }
{ SE_END , " " , " " }
} ;
2003-10-06 05:24:48 +04:00
# endif
2005-01-13 21:20:37 +03:00
typedef struct priv_sid_list {
2005-01-17 18:23:11 +03:00
SE_PRIV privilege ;
2005-01-13 21:20:37 +03:00
SID_LIST sids ;
} PRIV_SID_LIST ;
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
/***************************************************************************
copy an SE_PRIV structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-19 19:52:19 +03:00
BOOL se_priv_copy ( SE_PRIV * dst , const SE_PRIV * src )
2005-01-17 18:23:11 +03:00
{
if ( ! dst | | ! src )
return False ;
memcpy ( dst , src , sizeof ( SE_PRIV ) ) ;
return True ;
}
/***************************************************************************
combine 2 SE_PRIV structures and store the resulting set in mew_mask
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-26 23:36:44 +03:00
void se_priv_add ( SE_PRIV * mask , const SE_PRIV * addpriv )
2005-01-17 18:23:11 +03:00
{
int i ;
for ( i = 0 ; i < SE_PRIV_MASKSIZE ; i + + ) {
mask - > mask [ i ] | = addpriv - > mask [ i ] ;
}
}
/***************************************************************************
remove one SE_PRIV sytucture from another and store the resulting set
in mew_mask
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-26 23:36:44 +03:00
void se_priv_remove ( SE_PRIV * mask , const SE_PRIV * removepriv )
2005-01-17 18:23:11 +03:00
{
int i ;
for ( i = 0 ; i < SE_PRIV_MASKSIZE ; i + + ) {
mask - > mask [ i ] & = ~ removepriv - > mask [ i ] ;
}
}
/***************************************************************************
invert a given SE_PRIV and store the set in new_mask
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-19 19:52:19 +03:00
static void se_priv_invert ( SE_PRIV * new_mask , const SE_PRIV * mask )
2005-01-17 18:23:11 +03:00
{
SE_PRIV allprivs ;
se_priv_copy ( & allprivs , & se_priv_all ) ;
se_priv_remove ( & allprivs , mask ) ;
se_priv_copy ( new_mask , & allprivs ) ;
}
/***************************************************************************
check if 2 SE_PRIV structure are equal
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-19 19:52:19 +03:00
static BOOL se_priv_equal ( const SE_PRIV * mask1 , const SE_PRIV * mask2 )
2005-01-17 18:23:11 +03:00
{
return ( memcmp ( mask1 , mask2 , sizeof ( SE_PRIV ) ) = = 0 ) ;
}
2005-01-26 23:36:44 +03:00
/***************************************************************************
check if a SE_PRIV has any assigned privileges
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL se_priv_empty ( const SE_PRIV * mask )
{
SE_PRIV p1 ;
int i ;
se_priv_copy ( & p1 , mask ) ;
for ( i = 0 ; i < SE_PRIV_MASKSIZE ; i + + ) {
p1 . mask [ i ] & = se_priv_all . mask [ i ] ;
}
return se_priv_equal ( & p1 , & se_priv_none ) ;
}
2005-01-17 18:23:11 +03:00
/***************************************************************************
dump an SE_PRIV structure to the log files
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-19 19:52:19 +03:00
void dump_se_priv ( int dbg_cl , int dbg_lvl , const SE_PRIV * mask )
2005-01-17 18:23:11 +03:00
{
int i ;
DEBUGADDC ( dbg_cl , dbg_lvl , ( " SE_PRIV " ) ) ;
for ( i = 0 ; i < SE_PRIV_MASKSIZE ; i + + ) {
DEBUGADDC ( dbg_cl , dbg_lvl , ( " 0x%x " , mask - > mask [ i ] ) ) ;
}
DEBUGADDC ( dbg_cl , dbg_lvl , ( " \n " ) ) ;
}
2005-01-13 21:20:37 +03:00
/***************************************************************************
Retrieve the privilege mask ( set ) for a given SID
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-12-04 07:31:29 +03:00
2005-01-17 18:23:11 +03:00
static BOOL get_privileges ( const DOM_SID * sid , SE_PRIV * mask )
2005-01-13 21:20:37 +03:00
{
TDB_CONTEXT * tdb = get_account_pol_tdb ( ) ;
fstring keystr ;
2005-01-17 18:23:11 +03:00
TDB_DATA key , data ;
2005-01-17 23:27:29 +03:00
/* Fail if the admin has not enable privileges */
if ( ! lp_enable_privileges ( ) ) {
return False ;
}
2005-01-13 21:20:37 +03:00
if ( ! tdb )
2005-01-15 05:20:30 +03:00
return False ;
2003-12-04 07:31:29 +03:00
2005-01-17 18:23:11 +03:00
/* PRIV_<SID> (NULL terminated) as the key */
2005-01-13 21:20:37 +03:00
fstr_sprintf ( keystr , " %s%s " , PRIVPREFIX , sid_string_static ( sid ) ) ;
2005-01-17 18:23:11 +03:00
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
data = tdb_fetch ( tdb , key ) ;
if ( ! data . dptr ) {
2005-01-13 21:20:37 +03:00
DEBUG ( 3 , ( " get_privileges: No privileges assigned to SID [%s] \n " ,
sid_string_static ( sid ) ) ) ;
2005-01-15 05:20:30 +03:00
return False ;
2005-01-13 21:20:37 +03:00
}
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
SMB_ASSERT ( data . dsize = = sizeof ( SE_PRIV ) ) ;
se_priv_copy ( mask , ( SE_PRIV * ) data . dptr ) ;
2005-01-17 23:27:29 +03:00
2005-01-15 05:20:30 +03:00
return True ;
2003-10-06 05:24:48 +04:00
}
2005-01-13 21:20:37 +03:00
/***************************************************************************
Store the privilege mask ( set ) for a given SID
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
static BOOL set_privileges ( const DOM_SID * sid , SE_PRIV * mask )
2005-01-13 21:20:37 +03:00
{
TDB_CONTEXT * tdb = get_account_pol_tdb ( ) ;
fstring keystr ;
2005-01-17 18:23:11 +03:00
TDB_DATA key , data ;
2005-01-13 21:20:37 +03:00
2005-01-26 02:32:19 +03:00
if ( ! lp_enable_privileges ( ) )
return False ;
2005-01-13 21:20:37 +03:00
if ( ! tdb )
return False ;
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
/* PRIV_<SID> (NULL terminated) as the key */
2005-01-13 21:20:37 +03:00
fstr_sprintf ( keystr , " %s%s " , PRIVPREFIX , sid_string_static ( sid ) ) ;
2005-01-17 18:23:11 +03:00
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
/* no packing. static size structure, just write it out */
data . dptr = ( char * ) mask ;
data . dsize = sizeof ( SE_PRIV ) ;
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
return ( tdb_store ( tdb , key , data , TDB_REPLACE ) ! = - 1 ) ;
2003-10-06 05:24:48 +04:00
}
2005-01-13 21:20:37 +03:00
/****************************************************************************
check if the privilege is in the privilege list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-26 23:36:44 +03:00
static BOOL is_privilege_assigned ( SE_PRIV * privileges , const SE_PRIV * check )
2003-10-06 05:24:48 +04:00
{
2005-01-17 18:23:11 +03:00
SE_PRIV p1 , p2 ;
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
if ( ! privileges | | ! check )
2005-01-13 21:20:37 +03:00
return False ;
2005-01-17 18:23:11 +03:00
2005-01-26 23:36:44 +03:00
/* everyone has privileges if you aren't checking for any */
if ( se_priv_empty ( check ) ) {
DEBUG ( 1 , ( " is_privilege_assigned: no privileges in check_mask! \n " ) ) ;
return True ;
}
2005-01-17 18:23:11 +03:00
se_priv_copy ( & p1 , check ) ;
/* invert the SE_PRIV we want to check for and remove that from the
original set . If we are left with the SE_PRIV we are checking
for then return True */
se_priv_invert ( & p1 , check ) ;
se_priv_copy ( & p2 , privileges ) ;
se_priv_remove ( & p2 , & p1 ) ;
return se_priv_equal ( & p2 , check ) ;
2003-10-06 05:24:48 +04:00
}
2005-01-26 23:36:44 +03:00
/****************************************************************************
check if the privilege is in the privilege list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL is_any_privilege_assigned ( SE_PRIV * privileges , const SE_PRIV * check )
{
SE_PRIV p1 , p2 ;
if ( ! privileges | | ! check )
return False ;
/* everyone has privileges if you aren't checking for any */
if ( se_priv_empty ( check ) ) {
DEBUG ( 1 , ( " is_any_privilege_assigned: no privileges in check_mask! \n " ) ) ;
return True ;
}
se_priv_copy ( & p1 , check ) ;
/* invert the SE_PRIV we want to check for and remove that from the
original set . If we are left with the SE_PRIV we are checking
for then return True */
se_priv_invert ( & p1 , check ) ;
se_priv_copy ( & p2 , privileges ) ;
se_priv_remove ( & p2 , & p1 ) ;
/* see if we have any bits left */
return ! se_priv_empty ( & p2 ) ;
}
2003-10-06 05:24:48 +04:00
/****************************************************************************
add a privilege to a privilege array
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
static BOOL privilege_set_add ( PRIVILEGE_SET * priv_set , LUID_ATTR set )
2003-10-06 05:24:48 +04:00
{
LUID_ATTR * new_set ;
/* we can allocate memory to add the new privilege */
2004-12-07 21:25:53 +03:00
new_set = TALLOC_REALLOC_ARRAY ( priv_set - > mem_ctx , priv_set - > set , LUID_ATTR , priv_set - > count + 1 ) ;
2005-01-17 18:23:11 +03:00
if ( ! new_set ) {
DEBUG ( 0 , ( " privilege_set_add: failed to allocate memory! \n " ) ) ;
return False ;
}
2003-10-06 05:24:48 +04:00
new_set [ priv_set - > count ] . luid . high = set . luid . high ;
new_set [ priv_set - > count ] . luid . low = set . luid . low ;
new_set [ priv_set - > count ] . attr = set . attr ;
priv_set - > count + + ;
priv_set - > set = new_set ;
2005-01-17 18:23:11 +03:00
return True ;
2003-10-06 05:24:48 +04:00
}
2005-01-13 21:20:37 +03:00
/*********************************************************************
Generate the LUID_ATTR structure based on a bitmask
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-17 18:23:11 +03:00
LUID_ATTR get_privilege_luid ( SE_PRIV * mask )
2003-10-06 05:24:48 +04:00
{
2005-01-13 21:20:37 +03:00
LUID_ATTR priv_luid ;
2005-01-17 18:23:11 +03:00
int i ;
2005-01-13 21:20:37 +03:00
priv_luid . attr = 0 ;
priv_luid . luid . high = 0 ;
2005-01-17 18:23:11 +03:00
for ( i = 0 ; ! se_priv_equal ( & privs [ i ] . se_priv , & se_priv_end ) ; i + + ) {
/* just use the index+1 (so its non-zero) into the
array as the lower portion of the LUID */
if ( se_priv_equal ( & privs [ i ] . se_priv , mask ) ) {
priv_luid . luid . low = GENERATE_LUID_LOW ( i ) ;
}
}
2005-01-13 21:20:37 +03:00
return priv_luid ;
}
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
/*********************************************************************
2005-01-17 18:23:11 +03:00
Generate the LUID_ATTR structure based on a bitmask
2005-01-13 21:20:37 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
const char * get_privilege_dispname ( const char * name )
2005-01-13 21:20:37 +03:00
{
int i ;
2005-01-17 18:23:11 +03:00
for ( i = 0 ; ! se_priv_equal ( & privs [ i ] . se_priv , & se_priv_end ) ; i + + ) {
if ( strequal ( privs [ i ] . name , name ) ) {
return privs [ i ] . description ;
}
2005-01-13 21:20:37 +03:00
}
2005-01-17 18:23:11 +03:00
return NULL ;
2003-10-06 05:24:48 +04:00
}
2005-01-13 21:20:37 +03:00
/*********************************************************************
get a list of all privleges for all sids the in list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-17 18:23:11 +03:00
BOOL get_privileges_for_sids ( SE_PRIV * privileges , DOM_SID * slist , int scount )
2003-10-06 05:24:48 +04:00
{
2005-01-17 18:23:11 +03:00
SE_PRIV mask ;
2005-01-13 21:20:37 +03:00
int i ;
2005-01-17 18:23:11 +03:00
BOOL found = False ;
se_priv_copy ( privileges , & se_priv_none ) ;
2005-01-13 21:20:37 +03:00
for ( i = 0 ; i < scount ; i + + ) {
/* don't add unless we actually have a privilege assigned */
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
if ( ! get_privileges ( & slist [ i ] , & mask ) )
2005-01-13 21:20:37 +03:00
continue ;
2005-01-15 05:20:30 +03:00
2005-01-17 18:23:11 +03:00
DEBUG ( 5 , ( " get_privileges_for_sids: sid = %s \n Privilege set: \n " ,
sid_string_static ( & slist [ i ] ) ) ) ;
dump_se_priv ( DBGC_ALL , 5 , & mask ) ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
se_priv_add ( privileges , & mask ) ;
found = True ;
2005-01-13 21:20:37 +03:00
}
2005-01-17 18:23:11 +03:00
return found ;
2003-10-06 05:24:48 +04:00
}
2005-01-13 21:20:37 +03:00
/*********************************************************************
travseral functions for privilege_enumerate_accounts
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int priv_traverse_fn ( TDB_CONTEXT * t , TDB_DATA key , TDB_DATA data , void * state )
2003-10-06 05:24:48 +04:00
{
2005-01-13 21:20:37 +03:00
PRIV_SID_LIST * priv = state ;
int prefixlen = strlen ( PRIVPREFIX ) ;
DOM_SID sid ;
fstring sid_string ;
2005-01-17 18:23:11 +03:00
/* easy check first */
if ( data . dsize ! = sizeof ( SE_PRIV ) )
return 0 ;
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
/* check we have a PRIV_+SID entry */
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
if ( strncmp ( key . dptr , PRIVPREFIX , prefixlen ) ! = 0 )
return 0 ;
/* check to see if we are looking for a particular privilege */
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
if ( ! se_priv_equal ( & priv - > privilege , & se_priv_none ) ) {
SE_PRIV mask ;
se_priv_copy ( & mask , ( SE_PRIV * ) data . dptr ) ;
2005-01-13 21:20:37 +03:00
/* if the SID does not have the specified privilege
then just return */
2005-01-17 18:23:11 +03:00
if ( ! is_privilege_assigned ( & mask , & priv - > privilege ) )
2005-01-13 21:20:37 +03:00
return 0 ;
}
fstrcpy ( sid_string , & key . dptr [ strlen ( PRIVPREFIX ) ] ) ;
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
if ( ! string_to_sid ( & sid , sid_string ) ) {
DEBUG ( 0 , ( " travsersal_fn_enum__acct: Could not convert SID [%s] \n " ,
sid_string ) ) ;
return 0 ;
2003-10-06 05:24:48 +04:00
}
2005-01-13 21:20:37 +03:00
add_sid_to_array ( & sid , & priv - > sids . list , & priv - > sids . count ) ;
return 0 ;
2003-10-06 05:24:48 +04:00
}
2005-01-13 21:20:37 +03:00
/*********************************************************************
Retreive list of privileged SIDs ( for _lsa_enumerate_accounts ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS privilege_enumerate_accounts ( DOM_SID * * sids , int * num_sids )
2003-10-06 05:24:48 +04:00
{
2005-01-13 21:20:37 +03:00
TDB_CONTEXT * tdb = get_account_pol_tdb ( ) ;
PRIV_SID_LIST priv ;
ZERO_STRUCT ( priv ) ;
2005-01-17 18:23:11 +03:00
se_priv_copy ( & priv . privilege , & se_priv_none ) ;
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
tdb_traverse ( tdb , priv_traverse_fn , & priv ) ;
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
/* give the memory away; caller will free */
* sids = priv . sids . list ;
* num_sids = priv . sids . count ;
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
return NT_STATUS_OK ;
}
/***************************************************************************
Add privilege to sid
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-18 01:46:41 +03:00
BOOL grant_privilege ( const DOM_SID * sid , const SE_PRIV * priv_mask )
2005-01-13 21:20:37 +03:00
{
2005-01-17 18:23:11 +03:00
SE_PRIV old_mask , new_mask ;
2003-10-06 05:24:48 +04:00
2005-01-15 05:20:30 +03:00
if ( get_privileges ( sid , & old_mask ) )
2005-01-17 18:23:11 +03:00
se_priv_copy ( & new_mask , & old_mask ) ;
2005-01-15 05:20:30 +03:00
else
2005-01-17 18:23:11 +03:00
se_priv_copy ( & new_mask , & se_priv_none ) ;
se_priv_add ( & new_mask , priv_mask ) ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
DEBUG ( 10 , ( " grant_privilege: %s \n " , sid_string_static ( sid ) ) ) ;
DEBUGADD ( 10 , ( " original privilege mask: \n " ) ) ;
dump_se_priv ( DBGC_ALL , 10 , & old_mask ) ;
2003-10-06 05:24:48 +04:00
2005-01-17 18:23:11 +03:00
DEBUGADD ( 10 , ( " new privilege mask: \n " ) ) ;
dump_se_priv ( DBGC_ALL , 10 , & new_mask ) ;
return set_privileges ( sid , & new_mask ) ;
2005-01-13 21:20:37 +03:00
}
2005-01-15 05:20:30 +03:00
/*********************************************************************
Add a privilege based on its name
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL grant_privilege_by_name ( DOM_SID * sid , const char * name )
{
int i ;
2005-01-17 18:23:11 +03:00
for ( i = 0 ; ! se_priv_equal ( & privs [ i ] . se_priv , & se_priv_end ) ; i + + ) {
2005-01-15 05:20:30 +03:00
if ( strequal ( privs [ i ] . name , name ) ) {
2005-01-17 18:23:11 +03:00
return grant_privilege ( sid , & privs [ i ] . se_priv ) ;
2005-01-15 05:20:30 +03:00
}
}
DEBUG ( 3 , ( " grant_privilege_by_name: No Such Privilege Found (%s) \n " , name ) ) ;
return False ;
}
2005-01-13 21:20:37 +03:00
/***************************************************************************
Remove privilege from sid
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-18 01:46:41 +03:00
BOOL revoke_privilege ( const DOM_SID * sid , const SE_PRIV * priv_mask )
2005-01-13 21:20:37 +03:00
{
2005-01-17 18:23:11 +03:00
SE_PRIV mask ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
/* if the user has no privileges, then we can't revoke any */
if ( ! get_privileges ( sid , & mask ) )
return True ;
DEBUG ( 10 , ( " revoke_privilege: %s \n " , sid_string_static ( sid ) ) ) ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
DEBUGADD ( 10 , ( " original privilege mask: \n " ) ) ;
dump_se_priv ( DBGC_ALL , 10 , & mask ) ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
se_priv_remove ( & mask , priv_mask ) ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
DEBUGADD ( 10 , ( " new privilege mask: \n " ) ) ;
dump_se_priv ( DBGC_ALL , 10 , & mask ) ;
return set_privileges ( sid , & mask ) ;
}
/*********************************************************************
Revoke all privileges
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL revoke_all_privileges ( DOM_SID * sid )
{
return revoke_privilege ( sid , & se_priv_all ) ;
2005-01-13 21:20:37 +03:00
}
2005-01-15 05:20:30 +03:00
/*********************************************************************
Add a privilege based on its name
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL revoke_privilege_by_name ( DOM_SID * sid , const char * name )
{
int i ;
2005-01-17 18:23:11 +03:00
for ( i = 0 ; ! se_priv_equal ( & privs [ i ] . se_priv , & se_priv_end ) ; i + + ) {
2005-01-15 05:20:30 +03:00
if ( strequal ( privs [ i ] . name , name ) ) {
2005-01-17 18:23:11 +03:00
return revoke_privilege ( sid , & privs [ i ] . se_priv ) ;
2005-01-15 05:20:30 +03:00
}
}
DEBUG ( 3 , ( " revoke_privilege_by_name: No Such Privilege Found (%s) \n " , name ) ) ;
return False ;
}
2005-01-13 21:20:37 +03:00
/***************************************************************************
Retrieve the SIDs assigned to a given privilege
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS privilege_create_account ( const DOM_SID * sid )
{
2005-01-17 18:23:11 +03:00
return ( grant_privilege ( sid , & se_priv_none ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ) ;
2005-01-13 21:20:37 +03:00
}
/****************************************************************************
initialise a privilege list and set the talloc context
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS privilege_set_init ( PRIVILEGE_SET * priv_set )
{
2005-01-14 11:14:22 +03:00
TALLOC_CTX * mem_ctx ;
2005-01-13 21:20:37 +03:00
ZERO_STRUCTP ( priv_set ) ;
2005-01-14 11:14:22 +03:00
mem_ctx = talloc_init ( " privilege set " ) ;
2005-01-17 23:27:29 +03:00
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " privilege_set_init: failed to initialize talloc ctx! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-01-13 21:20:37 +03:00
priv_set - > mem_ctx = mem_ctx ;
2005-01-17 23:27:29 +03:00
return NT_STATUS_OK ;
2003-10-06 05:24:48 +04:00
}
/****************************************************************************
2005-01-13 21:20:37 +03:00
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
2003-10-06 05:24:48 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-13 21:20:37 +03:00
NTSTATUS dup_luid_attr ( TALLOC_CTX * mem_ctx , LUID_ATTR * * new_la , LUID_ATTR * old_la , int count )
2003-10-06 05:24:48 +04:00
{
int i ;
2005-01-13 21:20:37 +03:00
/* don't crash if the source pointer is NULL (since we don't
do priviledges now anyways ) */
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
if ( ! old_la )
2003-10-06 05:24:48 +04:00
return NT_STATUS_OK ;
2005-01-13 21:20:37 +03:00
* new_la = TALLOC_ARRAY ( mem_ctx , LUID_ATTR , count ) ;
2005-01-17 23:27:29 +03:00
if ( ! * new_la ) {
DEBUG ( 0 , ( " dup_luid_attr: failed to alloc new LUID_ATTR array [%d] \n " , count ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2003-10-06 05:24:48 +04:00
2005-01-13 21:20:37 +03:00
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 ;
2003-10-06 05:24:48 +04:00
}
2005-01-17 23:27:29 +03:00
return NT_STATUS_OK ;
2005-01-13 21:20:37 +03:00
}
/****************************************************************************
Does the user have the specified privilege ? We only deal with one privilege
at a time here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-26 23:36:44 +03:00
BOOL user_has_privileges ( NT_USER_TOKEN * token , const SE_PRIV * privilege )
2005-01-13 21:20:37 +03:00
{
2005-01-19 19:52:19 +03:00
if ( ! token )
return False ;
2005-01-17 18:23:11 +03:00
return is_privilege_assigned ( & token - > privileges , privilege ) ;
2005-01-13 21:20:37 +03:00
}
2005-01-26 23:36:44 +03:00
/****************************************************************************
Does the user have any of the specified privileges ? We only deal with one privilege
at a time here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL user_has_any_privilege ( NT_USER_TOKEN * token , const SE_PRIV * privilege )
{
if ( ! token )
return False ;
return is_any_privilege_assigned ( & token - > privileges , privilege ) ;
}
2005-01-13 21:20:37 +03:00
/****************************************************************************
Convert a LUID to a named string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * luid_to_privilege_name ( const LUID * set )
{
static fstring name ;
2005-01-17 18:23:11 +03:00
int max = count_all_privileges ( ) ;
2005-01-13 21:20:37 +03:00
if ( set - > high ! = 0 )
return NULL ;
2005-01-17 18:23:11 +03:00
if ( set - > low > max )
return NULL ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
fstrcpy ( name , privs [ set - > low - 1 ] . name ) ;
return name ;
2005-01-13 21:20:37 +03:00
}
/****************************************************************************
Convert an LUID to a 32 - bit mask
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-17 18:23:11 +03:00
SE_PRIV * luid_to_privilege_mask ( const LUID * set )
2005-01-13 21:20:37 +03:00
{
2005-01-17 18:23:11 +03:00
static SE_PRIV mask ;
int max = count_all_privileges ( ) ;
2005-01-13 21:20:37 +03:00
if ( set - > high ! = 0 )
2005-01-17 18:23:11 +03:00
return NULL ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
if ( set - > low > max )
return NULL ;
se_priv_copy ( & mask , & privs [ set - > low - 1 ] . se_priv ) ;
2005-01-13 21:20:37 +03:00
2005-01-17 18:23:11 +03:00
return & mask ;
2005-01-13 21:20:37 +03:00
}
/*******************************************************************
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 */
2005-01-17 18:23:11 +03:00
for ( count = 0 ; ! se_priv_equal ( & privs [ count ] . se_priv , & se_priv_end ) ; count + + ) ;
2005-01-13 21:20:37 +03:00
return count ;
}
2005-01-17 18:23:11 +03:00
/*******************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL se_priv_to_privilege_set ( PRIVILEGE_SET * set , SE_PRIV * mask )
{
int i ;
uint32 num_privs = count_all_privileges ( ) ;
LUID_ATTR luid ;
luid . attr = 0 ;
luid . luid . high = 0 ;
for ( i = 0 ; i < num_privs ; i + + ) {
if ( ! is_privilege_assigned ( mask , & privs [ i ] . se_priv ) )
continue ;
luid . luid . low = GENERATE_LUID_LOW ( i ) ;
if ( ! privilege_set_add ( set , luid ) )
return False ;
}
return True ;
}
/*******************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL privilege_set_to_se_priv ( SE_PRIV * mask , PRIVILEGE_SET * privset )
{
int i ;
uint32 num_privs = count_all_privileges ( ) ;
ZERO_STRUCTP ( mask ) ;
for ( i = 0 ; i < privset - > count ; i + + ) {
SE_PRIV r ;
/* sanity check for invalid privilege. we really
only care about the low 32 bits */
if ( privset - > set [ i ] . luid . high ! = 0 )
return False ;
/* make sure :LUID.low is in range */
if ( privset - > set [ i ] . luid . low = = 0 | | privset - > set [ i ] . luid . low > num_privs )
return False ;
r = privs [ privset - > set [ i ] . luid . low - 1 ] . se_priv ;
se_priv_add ( mask , & r ) ;
}
return True ;
}
2005-01-15 05:20:30 +03:00
2005-01-18 21:29:28 +03:00
/*******************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL is_privileged_sid ( DOM_SID * sid )
{
SE_PRIV mask ;
return get_privileges ( sid , & mask ) ;
}