2006-09-24 06:52:25 +04:00
/*
* Unix SMB / CIFS implementation .
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 2006 ,
* Copyright ( C ) Jean Fran <EFBFBD> ois Micouleau 1998 - 2001.
* Copyright ( C ) Volker Lendecke 2006.
* Copyright ( C ) Gerald Carter 2006.
*
* 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
2007-07-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2006-09-24 06:52:25 +04:00
* ( 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
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2006-09-24 06:52:25 +04:00
*/
# include "includes.h"
# include "groupdb/mapping.h"
2008-03-11 16:15:52 +03:00
static struct db_context * db ; /* used for driver files */
2006-09-24 06:52:25 +04:00
2007-10-19 04:40:25 +04:00
static bool enum_group_mapping ( const DOM_SID * domsid , enum lsa_SidType sid_name_use , GROUP_MAP * * pp_rmap ,
size_t * p_num_entries , bool unix_only ) ;
static bool group_map_remove ( const DOM_SID * sid ) ;
2007-06-04 05:51:18 +04:00
2006-09-24 06:52:25 +04:00
/****************************************************************************
Open the group mapping tdb .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool init_group_mapping ( void )
2006-09-24 06:52:25 +04:00
{
2008-03-11 16:15:52 +03:00
if ( db ! = NULL ) {
return true ;
2006-09-24 06:52:25 +04:00
}
2008-08-07 10:20:05 +04:00
db = db_open ( NULL , state_path ( " group_mapping.tdb " ) , 0 ,
2008-03-27 19:39:58 +03:00
TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
2008-03-11 16:15:52 +03:00
if ( db = = NULL ) {
DEBUG ( 0 , ( " Failed to open group mapping database: %s \n " ,
strerror ( errno ) ) ) ;
return false ;
2006-09-24 06:52:25 +04:00
}
2008-03-11 16:15:52 +03:00
#if 0
/*
* This code was designed to handle a group mapping version
* upgrade . mapping_tdb is not active by default anymore , so ignore
* this here .
*/
{
const char * vstring = " INFO/version " ;
int32 vers_id ;
GROUP_MAP * map_table = NULL ;
size_t num_entries = 0 ;
/* handle a Samba upgrade */
tdb_lock_bystring ( tdb , vstring ) ;
/* Cope with byte-reversed older versions of the db. */
vers_id = tdb_fetch_int32 ( tdb , vstring ) ;
if ( ( vers_id = = DATABASE_VERSION_V1 )
| | ( IREV ( vers_id ) = = DATABASE_VERSION_V1 ) ) {
/*
* Written on a bigendian machine with old fetch_int
* code . Save as le .
*/
tdb_store_int32 ( tdb , vstring , DATABASE_VERSION_V2 ) ;
vers_id = DATABASE_VERSION_V2 ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
/* if its an unknown version we remove everthing in the db */
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( vers_id ! = DATABASE_VERSION_V2 ) {
2008-03-26 13:13:47 +03:00
tdb_wipe_all ( tdb ) ;
2008-03-11 16:15:52 +03:00
tdb_store_int32 ( tdb , vstring , DATABASE_VERSION_V2 ) ;
}
tdb_unlock_bystring ( tdb , vstring ) ;
/* cleanup any map entries with a gid == -1 */
if ( enum_group_mapping ( NULL , SID_NAME_UNKNOWN , & map_table ,
& num_entries , False ) ) {
int i ;
for ( i = 0 ; i < num_entries ; i + + ) {
if ( map_table [ i ] . gid = = - 1 ) {
group_map_remove ( & map_table [ i ] . sid ) ;
}
2006-09-24 06:52:25 +04:00
}
2008-03-11 16:15:52 +03:00
SAFE_FREE ( map_table ) ;
2006-09-24 06:52:25 +04:00
}
2008-03-11 16:15:52 +03:00
}
# endif
return true ;
}
static char * group_mapping_key ( TALLOC_CTX * mem_ctx , const DOM_SID * sid )
{
char * sidstr , * result ;
sidstr = sid_string_talloc ( talloc_tos ( ) , sid ) ;
if ( sidstr = = NULL ) {
return NULL ;
2006-09-24 06:52:25 +04:00
}
2008-04-04 17:27:51 +04:00
result = talloc_asprintf ( mem_ctx , " %s%s " , GROUP_PREFIX , sidstr ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
TALLOC_FREE ( sidstr ) ;
return result ;
2006-09-24 06:52:25 +04:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool add_mapping_entry ( GROUP_MAP * map , int flag )
2006-09-24 06:52:25 +04:00
{
2008-03-11 16:15:52 +03:00
char * key , * buf ;
2006-09-24 06:52:25 +04:00
int len ;
2008-03-28 13:53:00 +03:00
NTSTATUS status ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
key = group_mapping_key ( talloc_tos ( ) , & map - > sid ) ;
if ( key = = NULL ) {
2008-07-03 13:09:32 +04:00
return false ;
2008-03-11 14:53:50 +03:00
}
2006-09-24 06:52:25 +04:00
2008-03-28 12:34:37 +03:00
len = tdb_pack ( NULL , 0 , " ddff " ,
2007-11-14 02:00:48 +03:00
map - > gid , map - > sid_name_use , map - > nt_name , map - > comment ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
buf = TALLOC_ARRAY ( key , char , len ) ;
if ( ! buf ) {
TALLOC_FREE ( key ) ;
2007-11-14 02:00:48 +03:00
return false ;
}
2008-03-11 16:15:52 +03:00
len = tdb_pack ( ( uint8 * ) buf , len , " ddff " , map - > gid ,
map - > sid_name_use , map - > nt_name , map - > comment ) ;
2006-09-24 06:52:25 +04:00
2008-03-28 13:53:00 +03:00
status = dbwrap_trans_store (
2008-03-27 19:10:31 +03:00
db , string_term_tdb_data ( key ) ,
2008-03-31 13:24:10 +04:00
make_tdb_data ( ( uint8_t * ) buf , len ) , TDB_REPLACE ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
TALLOC_FREE ( key ) ;
2007-11-14 02:00:48 +03:00
2008-03-28 13:53:00 +03:00
return NT_STATUS_IS_OK ( status ) ;
2006-09-24 06:52:25 +04:00
}
/****************************************************************************
Return the sid and the type of the unix group .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool get_group_map_from_sid ( DOM_SID sid , GROUP_MAP * map )
2006-09-24 06:52:25 +04:00
{
2007-03-27 13:17:31 +04:00
TDB_DATA dbuf ;
2008-03-11 16:15:52 +03:00
char * key ;
2006-09-24 06:52:25 +04:00
int ret = 0 ;
2007-11-14 02:00:48 +03:00
2006-09-24 06:52:25 +04:00
/* the key is the SID, retrieving is direct */
2008-03-28 14:20:06 +03:00
key = group_mapping_key ( talloc_tos ( ) , & sid ) ;
2008-03-11 16:15:52 +03:00
if ( key = = NULL ) {
2007-11-14 02:00:48 +03:00
return false ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
dbuf = dbwrap_fetch_bystring ( db , key , key ) ;
if ( dbuf . dptr = = NULL ) {
TALLOC_FREE ( key ) ;
2007-11-14 02:00:48 +03:00
return false ;
}
2006-09-24 06:52:25 +04:00
ret = tdb_unpack ( dbuf . dptr , dbuf . dsize , " ddff " ,
2007-11-14 02:00:48 +03:00
& map - > gid , & map - > sid_name_use ,
& map - > nt_name , & map - > comment ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
TALLOC_FREE ( key ) ;
2007-11-14 02:00:48 +03:00
2006-09-24 06:52:25 +04:00
if ( ret = = - 1 ) {
DEBUG ( 3 , ( " get_group_map_from_sid: tdb_unpack failure \n " ) ) ;
2008-03-11 16:15:52 +03:00
return false ;
2006-09-24 06:52:25 +04:00
}
sid_copy ( & map - > sid , & sid ) ;
2007-11-14 02:00:48 +03:00
2008-03-11 16:15:52 +03:00
return true ;
2006-09-24 06:52:25 +04:00
}
2008-03-11 16:15:52 +03:00
static bool dbrec2map ( const struct db_record * rec , GROUP_MAP * map )
2006-09-24 06:52:25 +04:00
{
2008-03-11 16:15:52 +03:00
if ( ( rec - > key . dsize < strlen ( GROUP_PREFIX ) )
| | ( strncmp ( ( char * ) rec - > key . dptr , GROUP_PREFIX ,
GROUP_PREFIX_LEN ) ! = 0 ) ) {
return False ;
}
2007-11-14 02:00:48 +03:00
2008-03-11 16:15:52 +03:00
if ( ! string_to_sid ( & map - > sid , ( const char * ) rec - > key . dptr
+ GROUP_PREFIX_LEN ) ) {
return False ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
return tdb_unpack ( rec - > value . dptr , rec - > value . dsize , " ddff " ,
& map - > gid , & map - > sid_name_use , & map - > nt_name ,
& map - > comment ) ! = - 1 ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
struct find_map_state {
bool found ;
const char * name ; /* If != NULL, look for name */
gid_t gid ; /* valid iff name == NULL */
GROUP_MAP * map ;
} ;
2007-11-14 02:00:48 +03:00
2008-03-11 16:15:52 +03:00
static int find_map ( struct db_record * rec , void * private_data )
{
struct find_map_state * state = ( struct find_map_state * ) private_data ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( ! dbrec2map ( rec , state - > map ) ) {
DEBUG ( 10 , ( " failed to unpack map \n " ) ) ;
return 0 ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( state - > name ! = NULL ) {
if ( strequal ( state - > name , state - > map - > nt_name ) ) {
state - > found = true ;
return 1 ;
2006-09-24 06:52:25 +04:00
}
2008-03-11 16:15:52 +03:00
}
else {
if ( state - > map - > gid = = state - > gid ) {
state - > found = true ;
return 1 ;
2006-09-24 06:52:25 +04:00
}
}
2008-03-11 16:15:52 +03:00
return 0 ;
2006-09-24 06:52:25 +04:00
}
/****************************************************************************
Return the sid and the type of the unix group .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-11 16:15:52 +03:00
static bool get_group_map_from_gid ( gid_t gid , GROUP_MAP * map )
2006-09-24 06:52:25 +04:00
{
2008-03-11 16:15:52 +03:00
struct find_map_state state ;
2007-11-14 02:00:48 +03:00
2008-03-11 16:15:52 +03:00
state . found = false ;
state . name = NULL ; /* Indicate we're looking for gid */
state . gid = gid ;
state . map = map ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
db - > traverse_read ( db , find_map , ( void * ) & state ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
return state . found ;
}
2007-11-14 02:00:48 +03:00
2008-03-11 16:15:52 +03:00
/****************************************************************************
Return the sid and the type of the unix group .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
static bool get_group_map_from_ntname ( const char * name , GROUP_MAP * map )
{
struct find_map_state state ;
2007-11-14 02:00:48 +03:00
2008-03-11 16:15:52 +03:00
state . found = false ;
state . name = name ;
state . map = map ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
db - > traverse_read ( db , find_map , ( void * ) & state ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
return state . found ;
2006-09-24 06:52:25 +04:00
}
/****************************************************************************
Remove a group mapping entry .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool group_map_remove ( const DOM_SID * sid )
2006-09-24 06:52:25 +04:00
{
2008-03-11 16:15:52 +03:00
char * key ;
2008-03-28 13:57:54 +03:00
NTSTATUS status ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
key = group_mapping_key ( talloc_tos ( ) , sid ) ;
if ( key = = NULL ) {
2007-11-14 02:00:48 +03:00
return false ;
}
2006-09-24 06:52:25 +04:00
2008-03-28 13:57:54 +03:00
status = dbwrap_trans_delete ( db , string_term_tdb_data ( key ) ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
TALLOC_FREE ( key ) ;
2008-03-28 13:57:54 +03:00
return NT_STATUS_IS_OK ( status ) ;
2006-09-24 06:52:25 +04:00
}
/****************************************************************************
Enumerate the group mapping .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-11 16:15:52 +03:00
struct enum_map_state {
const DOM_SID * domsid ;
enum lsa_SidType sid_name_use ;
bool unix_only ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
size_t num_maps ;
GROUP_MAP * maps ;
} ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
static int collect_map ( struct db_record * rec , void * private_data )
{
struct enum_map_state * state = ( struct enum_map_state * ) private_data ;
GROUP_MAP map ;
GROUP_MAP * tmp ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( ! dbrec2map ( rec , & map ) ) {
return 0 ;
}
/* list only the type or everything if UNKNOWN */
if ( state - > sid_name_use ! = SID_NAME_UNKNOWN
& & state - > sid_name_use ! = map . sid_name_use ) {
DEBUG ( 11 , ( " enum_group_mapping: group %s is not of the "
" requested type \n " , map . nt_name ) ) ;
return 0 ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( ( state - > unix_only = = ENUM_ONLY_MAPPED ) & & ( map . gid = = - 1 ) ) {
DEBUG ( 11 , ( " enum_group_mapping: group %s is non mapped \n " ,
map . nt_name ) ) ;
return 0 ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( ( state - > domsid ! = NULL ) & &
( sid_compare_domain ( state - > domsid , & map . sid ) ! = 0 ) ) {
DEBUG ( 11 , ( " enum_group_mapping: group %s is not in domain \n " ,
sid_string_dbg ( & map . sid ) ) ) ;
return 0 ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( ! ( tmp = SMB_REALLOC_ARRAY ( state - > maps , GROUP_MAP ,
state - > num_maps + 1 ) ) ) {
DEBUG ( 0 , ( " enum_group_mapping: Unable to enlarge group "
" map! \n " ) ) ;
return 1 ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
state - > maps = tmp ;
state - > maps [ state - > num_maps ] = map ;
state - > num_maps + + ;
return 0 ;
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
static bool enum_group_mapping ( const DOM_SID * domsid ,
enum lsa_SidType sid_name_use ,
GROUP_MAP * * pp_rmap ,
size_t * p_num_entries , bool unix_only )
{
struct enum_map_state state ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
state . domsid = domsid ;
state . sid_name_use = sid_name_use ;
state . unix_only = unix_only ;
state . num_maps = 0 ;
state . maps = NULL ;
2006-09-24 06:52:25 +04:00
2008-04-04 18:56:02 +04:00
if ( db - > traverse_read ( db , collect_map , ( void * ) & state ) < 0 ) {
2008-03-11 16:15:52 +03:00
return false ;
2006-09-24 06:52:25 +04:00
}
2008-03-11 16:15:52 +03:00
* pp_rmap = state . maps ;
* p_num_entries = state . num_maps ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
return true ;
2006-09-24 06:52:25 +04:00
}
/* This operation happens on session setup, so it should better be fast. We
* store a list of aliases a SID is member of hanging off MEMBEROF / SID . */
2007-06-04 05:51:18 +04:00
static NTSTATUS one_alias_membership ( const DOM_SID * member ,
2006-09-24 06:52:25 +04:00
DOM_SID * * sids , size_t * num )
{
2007-12-16 00:00:39 +03:00
fstring tmp ;
2007-12-08 04:32:32 +03:00
fstring key ;
char * string_sid ;
2007-03-27 13:17:31 +04:00
TDB_DATA dbuf ;
2006-09-24 06:52:25 +04:00
const char * p ;
2008-01-16 02:09:13 +03:00
NTSTATUS status = NT_STATUS_OK ;
2008-03-11 16:15:52 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2006-09-24 06:52:25 +04:00
2007-12-15 13:38:28 +03:00
slprintf ( key , sizeof ( key ) , " %s%s " , MEMBEROF_PREFIX ,
2007-12-16 00:47:30 +03:00
sid_to_fstring ( tmp , member ) ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
dbuf = dbwrap_fetch_bystring ( db , frame , key ) ;
2006-09-24 06:52:25 +04:00
if ( dbuf . dptr = = NULL ) {
2008-03-11 16:15:52 +03:00
TALLOC_FREE ( frame ) ;
2006-09-24 06:52:25 +04:00
return NT_STATUS_OK ;
}
2007-03-29 13:35:51 +04:00
p = ( const char * ) dbuf . dptr ;
2008-03-11 16:15:52 +03:00
2007-12-08 04:32:32 +03:00
while ( next_token_talloc ( frame , & p , & string_sid , " " ) ) {
2006-09-24 06:52:25 +04:00
DOM_SID alias ;
if ( ! string_to_sid ( & alias , string_sid ) )
continue ;
2008-01-09 02:11:31 +03:00
status = add_sid_to_array_unique ( NULL , & alias , sids , num ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-08 23:51:07 +03:00
goto done ;
2006-12-09 05:58:18 +03:00
}
2006-09-24 06:52:25 +04:00
}
2008-01-08 23:51:07 +03:00
done :
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2008-01-08 23:51:07 +03:00
return status ;
2006-09-24 06:52:25 +04:00
}
static NTSTATUS alias_memberships ( const DOM_SID * members , size_t num_members ,
DOM_SID * * sids , size_t * num )
{
size_t i ;
* num = 0 ;
* sids = NULL ;
for ( i = 0 ; i < num_members ; i + + ) {
NTSTATUS status = one_alias_membership ( & members [ i ] , sids , num ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
return status ;
}
return NT_STATUS_OK ;
}
2007-10-19 04:40:25 +04:00
static bool is_aliasmem ( const DOM_SID * alias , const DOM_SID * member )
2006-09-24 06:52:25 +04:00
{
DOM_SID * sids ;
size_t i , num ;
/* This feels the wrong way round, but the on-disk data structure
* dictates it this way . */
if ( ! NT_STATUS_IS_OK ( alias_memberships ( member , 1 , & sids , & num ) ) )
return False ;
for ( i = 0 ; i < num ; i + + ) {
if ( sid_compare ( alias , & sids [ i ] ) = = 0 ) {
2007-04-25 13:32:03 +04:00
TALLOC_FREE ( sids ) ;
2006-09-24 06:52:25 +04:00
return True ;
}
}
2007-04-25 13:32:03 +04:00
TALLOC_FREE ( sids ) ;
2006-09-24 06:52:25 +04:00
return False ;
}
2007-06-04 05:51:18 +04:00
static NTSTATUS add_aliasmem ( const DOM_SID * alias , const DOM_SID * member )
2006-09-24 06:52:25 +04:00
{
GROUP_MAP map ;
2008-03-11 16:15:52 +03:00
char * key ;
2006-09-24 06:52:25 +04:00
fstring string_sid ;
char * new_memberstring ;
2008-03-11 16:15:52 +03:00
struct db_record * rec ;
NTSTATUS status ;
2006-09-24 06:52:25 +04:00
if ( ! get_group_map_from_sid ( * alias , & map ) )
return NT_STATUS_NO_SUCH_ALIAS ;
if ( ( map . sid_name_use ! = SID_NAME_ALIAS ) & &
( map . sid_name_use ! = SID_NAME_WKN_GRP ) )
return NT_STATUS_NO_SUCH_ALIAS ;
if ( is_aliasmem ( alias , member ) )
return NT_STATUS_MEMBER_IN_ALIAS ;
2007-12-16 00:47:30 +03:00
sid_to_fstring ( string_sid , member ) ;
2008-03-11 16:15:52 +03:00
key = talloc_asprintf ( talloc_tos ( ) , " %s%s " , MEMBEROF_PREFIX ,
string_sid ) ;
if ( key = = NULL ) {
2007-11-14 02:00:48 +03:00
return NT_STATUS_NO_MEMORY ;
}
2006-09-24 06:52:25 +04:00
2008-03-27 19:10:31 +03:00
if ( db - > transaction_start ( db ) ! = 0 ) {
DEBUG ( 0 , ( " transaction_start failed \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2008-03-11 16:15:52 +03:00
rec = db - > fetch_locked ( db , key , string_term_tdb_data ( key ) ) ;
if ( rec = = NULL ) {
DEBUG ( 10 , ( " fetch_lock failed \n " ) ) ;
TALLOC_FREE ( key ) ;
2008-03-27 19:10:31 +03:00
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
goto cancel ;
2008-03-11 16:15:52 +03:00
}
2006-09-24 06:52:25 +04:00
2007-12-16 00:47:30 +03:00
sid_to_fstring ( string_sid , alias ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( rec - > value . dptr ! = NULL ) {
new_memberstring = talloc_asprintf (
key , " %s %s " , ( char * ) ( rec - > value . dptr ) , string_sid ) ;
2006-09-24 06:52:25 +04:00
} else {
2008-03-11 16:15:52 +03:00
new_memberstring = talloc_strdup ( key , string_sid ) ;
2006-09-24 06:52:25 +04:00
}
2007-11-14 02:00:48 +03:00
if ( new_memberstring = = NULL ) {
2008-03-11 16:15:52 +03:00
TALLOC_FREE ( key ) ;
2008-03-27 19:10:31 +03:00
status = NT_STATUS_NO_MEMORY ;
goto cancel ;
2007-11-14 02:00:48 +03:00
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
status = rec - > store ( rec , string_term_tdb_data ( new_memberstring ) , 0 ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
TALLOC_FREE ( key ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " Could not store record: %s \n " , nt_errstr ( status ) ) ) ;
2008-03-27 19:10:31 +03:00
goto cancel ;
}
if ( db - > transaction_commit ( db ) ! = 0 ) {
DEBUG ( 0 , ( " transaction_commit failed \n " ) ) ;
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
2008-08-08 05:42:06 +04:00
return status ;
2008-03-27 19:10:31 +03:00
}
return NT_STATUS_OK ;
cancel :
if ( db - > transaction_cancel ( db ) ! = 0 ) {
smb_panic ( " transaction_cancel failed " ) ;
2008-03-11 16:15:52 +03:00
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
return status ;
2006-09-24 06:52:25 +04:00
}
2008-03-11 16:15:52 +03:00
struct aliasmem_state {
2006-09-24 06:52:25 +04:00
const DOM_SID * alias ;
DOM_SID * * sids ;
size_t * num ;
} ;
2008-03-11 16:15:52 +03:00
static int collect_aliasmem ( struct db_record * rec , void * priv )
2006-09-24 06:52:25 +04:00
{
2008-03-11 16:15:52 +03:00
struct aliasmem_state * state = ( struct aliasmem_state * ) priv ;
2006-09-24 06:52:25 +04:00
const char * p ;
2007-12-08 04:32:32 +03:00
char * alias_string ;
TALLOC_CTX * frame ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
if ( strncmp ( ( const char * ) rec - > key . dptr , MEMBEROF_PREFIX ,
MEMBEROF_PREFIX_LEN ) ! = 0 )
2006-09-24 06:52:25 +04:00
return 0 ;
2008-03-11 16:15:52 +03:00
p = ( const char * ) rec - > value . dptr ;
2006-09-24 06:52:25 +04:00
2007-12-08 04:32:32 +03:00
frame = talloc_stackframe ( ) ;
2008-03-11 16:15:52 +03:00
2007-12-08 04:32:32 +03:00
while ( next_token_talloc ( frame , & p , & alias_string , " " ) ) {
2006-09-24 06:52:25 +04:00
DOM_SID alias , member ;
const char * member_string ;
if ( ! string_to_sid ( & alias , alias_string ) )
continue ;
2008-03-11 16:15:52 +03:00
if ( sid_compare ( state - > alias , & alias ) ! = 0 )
2006-09-24 06:52:25 +04:00
continue ;
/* Ok, we found the alias we're looking for in the membership
* list currently scanned . The key represents the alias
* member . Add that . */
2008-03-11 16:15:52 +03:00
member_string = strchr ( ( const char * ) rec - > key . dptr , ' / ' ) ;
2006-09-24 06:52:25 +04:00
/* Above we tested for MEMBEROF_PREFIX which includes the
* slash . */
SMB_ASSERT ( member_string ! = NULL ) ;
member_string + = 1 ;
if ( ! string_to_sid ( & member , member_string ) )
continue ;
2007-12-08 04:32:32 +03:00
2008-01-09 02:11:31 +03:00
if ( ! NT_STATUS_IS_OK ( add_sid_to_array ( NULL , & member ,
2008-03-11 16:15:52 +03:00
state - > sids ,
state - > num ) ) )
2008-01-09 02:11:31 +03:00
{
2006-12-09 05:58:18 +03:00
/* talloc fail. */
break ;
}
2006-09-24 06:52:25 +04:00
}
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2006-09-24 06:52:25 +04:00
return 0 ;
}
2007-06-04 05:51:18 +04:00
static NTSTATUS enum_aliasmem ( const DOM_SID * alias , DOM_SID * * sids , size_t * num )
2006-09-24 06:52:25 +04:00
{
GROUP_MAP map ;
2008-03-11 16:15:52 +03:00
struct aliasmem_state state ;
2006-09-24 06:52:25 +04:00
if ( ! get_group_map_from_sid ( * alias , & map ) )
return NT_STATUS_NO_SUCH_ALIAS ;
if ( ( map . sid_name_use ! = SID_NAME_ALIAS ) & &
( map . sid_name_use ! = SID_NAME_WKN_GRP ) )
return NT_STATUS_NO_SUCH_ALIAS ;
* sids = NULL ;
* num = 0 ;
2008-03-11 16:15:52 +03:00
state . alias = alias ;
state . sids = sids ;
state . num = num ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
db - > traverse_read ( db , collect_aliasmem , & state ) ;
2006-09-24 06:52:25 +04:00
return NT_STATUS_OK ;
}
2007-06-04 05:51:18 +04:00
static NTSTATUS del_aliasmem ( const DOM_SID * alias , const DOM_SID * member )
2006-09-24 06:52:25 +04:00
{
2008-03-11 16:15:52 +03:00
NTSTATUS status ;
2006-09-24 06:52:25 +04:00
DOM_SID * sids ;
size_t i , num ;
2007-10-19 04:40:25 +04:00
bool found = False ;
2006-09-24 06:52:25 +04:00
char * member_string ;
2008-03-11 16:15:52 +03:00
char * key ;
2006-09-24 06:52:25 +04:00
fstring sid_string ;
2008-03-27 19:10:31 +03:00
if ( db - > transaction_start ( db ) ! = 0 ) {
DEBUG ( 0 , ( " transaction_start failed \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2008-03-11 16:15:52 +03:00
status = alias_memberships ( member , 1 , & sids , & num ) ;
2006-09-24 06:52:25 +04:00
2008-03-27 19:10:31 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto cancel ;
}
2006-09-24 06:52:25 +04:00
for ( i = 0 ; i < num ; i + + ) {
if ( sid_compare ( & sids [ i ] , alias ) = = 0 ) {
found = True ;
break ;
}
}
if ( ! found ) {
2007-04-25 13:32:03 +04:00
TALLOC_FREE ( sids ) ;
2008-03-27 19:10:31 +03:00
status = NT_STATUS_MEMBER_NOT_IN_ALIAS ;
goto cancel ;
2006-09-24 06:52:25 +04:00
}
if ( i < num )
sids [ i ] = sids [ num - 1 ] ;
num - = 1 ;
2007-12-16 00:47:30 +03:00
sid_to_fstring ( sid_string , member ) ;
2008-03-11 16:15:52 +03:00
key = talloc_asprintf ( sids , " %s%s " , MEMBEROF_PREFIX , sid_string ) ;
if ( key = = NULL ) {
2007-11-14 02:00:48 +03:00
TALLOC_FREE ( sids ) ;
2008-03-27 19:10:31 +03:00
status = NT_STATUS_NO_MEMORY ;
goto cancel ;
2007-11-14 02:00:48 +03:00
}
2006-09-24 06:52:25 +04:00
2007-11-14 02:00:48 +03:00
if ( num = = 0 ) {
2008-03-11 16:15:52 +03:00
status = dbwrap_delete_bystring ( db , key ) ;
2008-09-18 07:01:47 +04:00
goto commit ;
2007-11-14 02:00:48 +03:00
}
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
member_string = talloc_strdup ( sids , " " ) ;
2006-09-24 06:52:25 +04:00
if ( member_string = = NULL ) {
2007-04-25 13:32:03 +04:00
TALLOC_FREE ( sids ) ;
2008-03-27 19:10:31 +03:00
status = NT_STATUS_NO_MEMORY ;
goto cancel ;
2006-09-24 06:52:25 +04:00
}
for ( i = 0 ; i < num ; i + + ) {
2007-12-16 00:47:30 +03:00
sid_to_fstring ( sid_string , & sids [ i ] ) ;
2006-09-24 06:52:25 +04:00
2008-03-11 16:15:52 +03:00
member_string = talloc_asprintf_append_buffer (
member_string , " %s " , sid_string ) ;
2006-09-24 06:52:25 +04:00
if ( member_string = = NULL ) {
2007-04-25 13:32:03 +04:00
TALLOC_FREE ( sids ) ;
2008-03-27 19:10:31 +03:00
status = NT_STATUS_NO_MEMORY ;
goto cancel ;
2006-09-24 06:52:25 +04:00
}
}
2008-03-11 16:15:52 +03:00
status = dbwrap_store_bystring (
db , key , string_term_tdb_data ( member_string ) , 0 ) ;
2008-09-18 07:01:47 +04:00
commit :
2007-04-25 13:32:03 +04:00
TALLOC_FREE ( sids ) ;
2006-09-24 06:52:25 +04:00
2008-03-27 19:10:31 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " dbwrap_store_bystring failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto cancel ;
}
if ( db - > transaction_commit ( db ) ! = 0 ) {
DEBUG ( 0 , ( " transaction_commit failed \n " ) ) ;
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
2008-08-08 05:42:06 +04:00
return status ;
2008-03-27 19:10:31 +03:00
}
return NT_STATUS_OK ;
cancel :
if ( db - > transaction_cancel ( db ) ! = 0 ) {
smb_panic ( " transaction_cancel failed " ) ;
}
2008-03-11 16:15:52 +03:00
return status ;
2006-09-24 06:52:25 +04:00
}
2007-06-04 05:51:18 +04:00
static const struct mapping_backend tdb_backend = {
. add_mapping_entry = add_mapping_entry ,
. get_group_map_from_sid = get_group_map_from_sid ,
. get_group_map_from_gid = get_group_map_from_gid ,
. get_group_map_from_ntname = get_group_map_from_ntname ,
. group_map_remove = group_map_remove ,
. enum_group_mapping = enum_group_mapping ,
. one_alias_membership = one_alias_membership ,
. add_aliasmem = add_aliasmem ,
. del_aliasmem = del_aliasmem ,
. enum_aliasmem = enum_aliasmem
} ;
/*
initialise the tdb mapping backend
*/
const struct mapping_backend * groupdb_tdb_init ( void )
{
if ( ! init_group_mapping ( ) ) {
DEBUG ( 0 , ( " Failed to initialise tdb mapping backend \n " ) ) ;
return NULL ;
}
return & tdb_backend ;
}