2003-03-08 00:49:18 +00:00
/*
Unix SMB / CIFS implementation .
idmap TDB backend
Copyright ( C ) Tim Potter 2000
2003-08-01 15:30:44 +00:00
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2003
2003-03-08 00:49:18 +00:00
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
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 .
*/
# include "includes.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_IDMAP
/* High water mark keys */
# define HWM_GROUP "GROUP HWM"
# define HWM_USER "USER HWM"
/* Globals */
static TDB_CONTEXT * idmap_tdb ;
2003-04-02 10:36:02 +00:00
static struct idmap_state {
2003-03-08 17:29:40 +00:00
/* User and group id pool */
uid_t uid_low , uid_high ; /* Range of uids to allocate */
gid_t gid_low , gid_high ; /* Range of gids to allocate */
} idmap_state ;
2003-07-11 05:33:40 +00:00
/**********************************************************************
Allocate either a user or group id from the pool
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-04-02 10:36:02 +00:00
static NTSTATUS db_allocate_id ( unid_t * id , int id_type )
2003-03-08 00:49:18 +00:00
{
2003-06-11 18:14:34 +00:00
BOOL ret ;
2003-03-08 00:49:18 +00:00
int hwm ;
2003-06-25 00:02:17 +00:00
if ( ! id )
return NT_STATUS_INVALID_PARAMETER ;
2003-03-08 00:49:18 +00:00
/* Get current high water mark */
2003-03-08 17:29:40 +00:00
switch ( id_type & ID_TYPEMASK ) {
2003-03-08 00:49:18 +00:00
case ID_USERID :
2003-06-25 00:02:17 +00:00
2003-03-08 00:49:18 +00:00
if ( ( hwm = tdb_fetch_int32 ( idmap_tdb , HWM_USER ) ) = = - 1 ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2003-06-11 18:14:34 +00:00
/* check it is in the range */
2003-03-08 17:29:40 +00:00
if ( hwm > idmap_state . uid_high ) {
2003-07-22 04:31:20 +00:00
DEBUG ( 0 , ( " idmap Fatal Error: UID range full!! (max: %lu) \n " ,
( unsigned long ) idmap_state . uid_high ) ) ;
2003-03-08 00:49:18 +00:00
return NT_STATUS_UNSUCCESSFUL ;
}
2003-06-11 18:14:34 +00:00
/* fetch a new id and increment it */
2003-08-15 04:42:05 +00:00
ret = tdb_change_uint32_atomic ( idmap_tdb , HWM_USER , ( unsigned int * ) & hwm , 1 ) ;
2003-06-11 18:14:34 +00:00
if ( ! ret ) {
DEBUG ( 0 , ( " idmap_tdb: Fatal error while fetching a new id \n ! " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
/* recheck it is in the range */
if ( hwm > idmap_state . uid_high ) {
2003-07-22 04:31:20 +00:00
DEBUG ( 0 , ( " idmap Fatal Error: UID range full!! (max: %lu) \n " ,
( unsigned long ) idmap_state . uid_high ) ) ;
2003-06-11 18:14:34 +00:00
return NT_STATUS_UNSUCCESSFUL ;
}
( * id ) . uid = hwm ;
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " db_allocate_id: ID_USERID (*id).uid = %d \n " , ( unsigned int ) hwm ) ) ;
2003-03-08 00:49:18 +00:00
break ;
case ID_GROUPID :
if ( ( hwm = tdb_fetch_int32 ( idmap_tdb , HWM_GROUP ) ) = = - 1 ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2003-06-11 18:14:34 +00:00
/* check it is in the range */
2003-03-08 17:29:40 +00:00
if ( hwm > idmap_state . gid_high ) {
2003-07-22 04:31:20 +00:00
DEBUG ( 0 , ( " idmap Fatal Error: GID range full!! (max: %lu) \n " ,
( unsigned long ) idmap_state . gid_high ) ) ;
2003-03-08 00:49:18 +00:00
return NT_STATUS_UNSUCCESSFUL ;
}
2003-06-11 18:14:34 +00:00
/* fetch a new id and increment it */
2003-08-15 04:42:05 +00:00
ret = tdb_change_uint32_atomic ( idmap_tdb , HWM_GROUP , ( unsigned int * ) & hwm , 1 ) ;
2003-06-11 18:14:34 +00:00
if ( ! ret ) {
DEBUG ( 0 , ( " idmap_tdb: Fatal error while fetching a new id \n ! " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
/* recheck it is in the range */
2003-06-11 20:06:11 +00:00
if ( hwm > idmap_state . gid_high ) {
2003-07-22 04:31:20 +00:00
DEBUG ( 0 , ( " idmap Fatal Error: GID range full!! (max: %lu) \n " ,
( unsigned long ) idmap_state . gid_high ) ) ;
2003-06-11 18:14:34 +00:00
return NT_STATUS_UNSUCCESSFUL ;
}
( * id ) . gid = hwm ;
2003-07-09 16:44:47 +00:00
DEBUG ( 10 , ( " db_allocate_id: ID_GROUPID (*id).gid = %d \n " , ( unsigned int ) hwm ) ) ;
2003-03-08 00:49:18 +00:00
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
return NT_STATUS_OK ;
}
/* Get a sid from an id */
2003-06-21 08:31:18 +00:00
static NTSTATUS internal_get_sid_from_id ( DOM_SID * sid , unid_t id , int id_type )
2003-03-08 00:49:18 +00:00
{
TDB_DATA key , data ;
fstring keystr ;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
2003-06-26 00:19:57 +00:00
if ( ! sid )
return NT_STATUS_INVALID_PARAMETER ;
2003-03-08 00:49:18 +00:00
2003-03-08 17:29:40 +00:00
switch ( id_type & ID_TYPEMASK ) {
2003-03-08 00:49:18 +00:00
case ID_USERID :
2003-07-22 04:31:20 +00:00
slprintf ( keystr , sizeof ( keystr ) , " UID %lu " , ( unsigned long ) id . uid ) ;
2003-04-02 10:36:02 +00:00
break ;
2003-03-08 00:49:18 +00:00
case ID_GROUPID :
2003-07-22 04:31:20 +00:00
slprintf ( keystr , sizeof ( keystr ) , " GID %lu " , ( unsigned long ) id . gid ) ;
2003-04-02 10:36:02 +00:00
break ;
2003-03-08 00:49:18 +00:00
default :
2003-04-02 10:36:02 +00:00
return NT_STATUS_UNSUCCESSFUL ;
2003-03-08 00:49:18 +00:00
}
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " internal_get_sid_from_id: fetching record %s \n " , keystr ) ) ;
2003-03-08 00:49:18 +00:00
data = tdb_fetch ( idmap_tdb , key ) ;
if ( data . dptr ) {
if ( string_to_sid ( sid , data . dptr ) ) {
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " internal_get_sid_from_id: fetching record %s -> %s \n " , keystr , data . dptr ) ) ;
2003-03-08 00:49:18 +00:00
ret = NT_STATUS_OK ;
}
SAFE_FREE ( data . dptr ) ;
}
return ret ;
}
2003-06-26 00:19:57 +00:00
/* Error codes for get_id_from_sid */
enum getidfromsiderr { GET_ID_FROM_SID_OK = 0 , GET_ID_FROM_SID_NOTFOUND , GET_ID_FROM_SID_WRONG_TYPE , GET_ID_FROM_SID_ERR } ;
2003-06-21 08:31:18 +00:00
2003-06-26 00:19:57 +00:00
static enum getidfromsiderr internal_get_id_from_sid ( unid_t * id , int * id_type , const DOM_SID * sid )
2003-03-08 00:49:18 +00:00
{
2003-06-26 00:19:57 +00:00
enum getidfromsiderr ret = GET_ID_FROM_SID_ERR ;
2003-06-21 08:31:18 +00:00
fstring keystr ;
TDB_DATA key , data ;
int type = * id_type & ID_TYPEMASK ;
2003-03-08 00:49:18 +00:00
/* Check if sid is present in database */
sid_to_string ( keystr , sid ) ;
key . dptr = keystr ;
key . dsize = strlen ( keystr ) + 1 ;
2003-06-25 19:01:17 +00:00
DEBUG ( 10 , ( " internal_get_id_from_sid: fetching record %s of type 0x%x \n " , keystr , type ) ) ;
2003-06-25 00:02:17 +00:00
2003-03-08 00:49:18 +00:00
data = tdb_fetch ( idmap_tdb , key ) ;
2003-06-25 19:01:17 +00:00
if ( ! data . dptr ) {
DEBUG ( 10 , ( " internal_get_id_from_sid: record %s not found \n " , keystr ) ) ;
2003-06-26 00:19:57 +00:00
return GET_ID_FROM_SID_NOTFOUND ;
2003-06-25 19:01:17 +00:00
} else {
DEBUG ( 10 , ( " internal_get_id_from_sid: record %s -> %s \n " , keystr , data . dptr ) ) ;
}
2003-03-08 00:49:18 +00:00
2003-06-21 08:31:18 +00:00
if ( type = = ID_EMPTY | | type = = ID_USERID ) {
fstring scanstr ;
/* Parse and return existing uid */
fstrcpy ( scanstr , " UID %d " ) ;
if ( sscanf ( data . dptr , scanstr , & ( ( * id ) . uid ) ) = = 1 ) {
/* uid ok? */
if ( type = = ID_EMPTY ) {
* id_type = ID_USERID ;
}
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " internal_get_id_from_sid: %s fetching record %s -> %s \n " ,
( type = = ID_EMPTY ) ? " ID_EMPTY " : " ID_USERID " ,
keystr , data . dptr ) ) ;
2003-06-26 00:19:57 +00:00
ret = GET_ID_FROM_SID_OK ;
} else {
ret = GET_ID_FROM_SID_WRONG_TYPE ;
2003-06-21 08:31:18 +00:00
}
}
2003-06-26 00:19:57 +00:00
if ( ( ret ! = GET_ID_FROM_SID_OK ) & & ( type = = ID_EMPTY | | type = = ID_GROUPID ) ) {
2003-03-08 00:49:18 +00:00
fstring scanstr ;
2003-06-21 08:31:18 +00:00
/* Parse and return existing gid */
fstrcpy ( scanstr , " GID %d " ) ;
if ( sscanf ( data . dptr , scanstr , & ( ( * id ) . gid ) ) = = 1 ) {
/* gid ok? */
if ( type = = ID_EMPTY ) {
* id_type = ID_GROUPID ;
}
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " internal_get_id_from_sid: %s fetching record %s -> %s \n " ,
( type = = ID_EMPTY ) ? " ID_EMPTY " : " ID_GROUPID " ,
keystr , data . dptr ) ) ;
2003-06-26 00:19:57 +00:00
ret = GET_ID_FROM_SID_OK ;
} else {
ret = GET_ID_FROM_SID_WRONG_TYPE ;
2003-06-21 08:31:18 +00:00
}
}
SAFE_FREE ( data . dptr ) ;
return ret ;
}
2003-03-08 00:49:18 +00:00
2003-06-21 08:31:18 +00:00
/* Get a sid from an id */
static NTSTATUS db_get_sid_from_id ( DOM_SID * sid , unid_t id , int id_type_in )
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
2003-06-26 00:19:57 +00:00
enum getidfromsiderr iderr ;
2003-06-21 08:31:18 +00:00
int id_type = id_type_in & ID_TYPEMASK ;
unid_t id_tmp = id ;
int id_type_tmp = id_type ;
2003-03-08 00:49:18 +00:00
2003-06-25 00:11:38 +00:00
DEBUG ( 10 , ( " db_get_sid_from_id: id_type_in = 0x%x \n " , id_type_in ) ) ;
2003-06-21 08:31:18 +00:00
ret = internal_get_sid_from_id ( sid , id , id_type ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
return ret ;
}
2003-06-26 00:19:57 +00:00
iderr = internal_get_id_from_sid ( & id_tmp , & id_type_tmp , sid ) ;
if ( iderr ! = GET_ID_FROM_SID_OK ) {
return NT_STATUS_UNSUCCESSFUL ;
2003-06-21 08:31:18 +00:00
}
if ( id_type_tmp ! = id_type ) {
return NT_STATUS_UNSUCCESSFUL ;
} else if ( id_type = = ID_USERID ) {
if ( id_tmp . uid ! = id . uid ) {
return NT_STATUS_UNSUCCESSFUL ;
2003-03-08 00:49:18 +00:00
}
2003-06-21 08:31:18 +00:00
} else if ( id_type = = ID_GROUPID ) {
if ( id_tmp . gid ! = id . gid ) {
return NT_STATUS_UNSUCCESSFUL ;
}
} else {
return NT_STATUS_UNSUCCESSFUL ;
}
return ret ;
}
/* Get an id from a sid */
static NTSTATUS db_get_id_from_sid ( unid_t * id , int * id_type , const DOM_SID * sid )
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
2003-06-26 00:19:57 +00:00
enum getidfromsiderr iderr ;
2003-03-08 00:49:18 +00:00
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " db_get_id_from_sid \n " ) ) ;
if ( ! sid | | ! id | | ! id_type )
return NT_STATUS_INVALID_PARAMETER ;
2003-03-08 00:49:18 +00:00
2003-06-26 00:19:57 +00:00
iderr = internal_get_id_from_sid ( id , id_type , sid ) ;
if ( iderr = = GET_ID_FROM_SID_OK ) {
2003-06-21 08:31:18 +00:00
DOM_SID sid_tmp ;
ret = internal_get_sid_from_id ( & sid_tmp , * id , * id_type ) ;
if ( NT_STATUS_IS_OK ( ret ) ) {
if ( ! sid_equal ( & sid_tmp , sid ) ) {
2003-06-26 00:19:57 +00:00
return NT_STATUS_UNSUCCESSFUL ;
2003-03-08 00:49:18 +00:00
}
}
2003-06-26 00:19:57 +00:00
} else if ( iderr = = GET_ID_FROM_SID_WRONG_TYPE ) {
/* We found a record but not the type we wanted.
* This is an error , not an opportunity to overwrite . . .
* JRA .
*/
return NT_STATUS_UNSUCCESSFUL ;
2003-06-21 08:31:18 +00:00
}
2003-03-08 00:49:18 +00:00
2003-06-26 23:48:46 +00:00
if ( ! ( * id_type & ID_QUERY_ONLY ) & & ( iderr ! = GET_ID_FROM_SID_OK ) & &
2003-03-08 17:29:40 +00:00
( ( ( * id_type & ID_TYPEMASK ) = = ID_USERID )
| | ( * id_type & ID_TYPEMASK ) = = ID_GROUPID ) ) {
2003-06-21 08:31:18 +00:00
TDB_DATA sid_data ;
TDB_DATA ugid_data ;
fstring sid_string ;
sid_to_string ( sid_string , sid ) ;
sid_data . dptr = sid_string ;
sid_data . dsize = strlen ( sid_string ) + 1 ;
2003-06-26 23:48:46 +00:00
/* Lock the record for this SID. */
if ( tdb_chainlock ( idmap_tdb , sid_data ) ! = 0 ) {
DEBUG ( 10 , ( " db_get_id_from_sid: failed to lock record %s. Error %s \n " ,
sid_string , tdb_errorstr ( idmap_tdb ) ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2003-06-21 08:31:18 +00:00
do {
fstring ugid_str ;
2003-06-26 00:19:57 +00:00
2003-06-21 08:31:18 +00:00
/* Allocate a new id for this sid */
ret = db_allocate_id ( id , * id_type ) ;
if ( ! NT_STATUS_IS_OK ( ret ) )
break ;
2003-06-26 00:19:57 +00:00
/* Store the UID side */
2003-03-08 00:49:18 +00:00
/* Store new id */
2003-03-08 17:29:40 +00:00
if ( * id_type & ID_USERID ) {
2003-07-22 04:31:20 +00:00
slprintf ( ugid_str , sizeof ( ugid_str ) , " UID %lu " ,
( unsigned long ) ( ( * id ) . uid ) ) ;
2003-03-08 17:29:40 +00:00
} else {
2003-07-22 04:31:20 +00:00
slprintf ( ugid_str , sizeof ( ugid_str ) , " GID %lu " ,
( unsigned long ) ( ( * id ) . gid ) ) ;
2003-03-08 17:29:40 +00:00
}
2003-06-21 08:31:18 +00:00
ugid_data . dptr = ugid_str ;
ugid_data . dsize = strlen ( ugid_str ) + 1 ;
2003-03-08 00:49:18 +00:00
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " db_get_id_from_sid: storing %s -> %s \n " ,
ugid_data . dptr , sid_data . dptr ) ) ;
2003-06-21 08:31:18 +00:00
if ( tdb_store ( idmap_tdb , ugid_data , sid_data , TDB_INSERT ) ! = - 1 ) {
ret = NT_STATUS_OK ;
break ;
2003-03-08 17:29:40 +00:00
}
2003-06-25 00:28:46 +00:00
if ( tdb_error ( idmap_tdb ) ! = TDB_ERR_EXISTS )
DEBUG ( 10 , ( " db_get_id_from_sid: error %s \n " , tdb_errorstr ( idmap_tdb ) ) ) ;
2003-06-21 08:31:18 +00:00
ret = NT_STATUS_UNSUCCESSFUL ;
2003-06-25 00:28:46 +00:00
} while ( tdb_error ( idmap_tdb ) = = TDB_ERR_EXISTS ) ;
2003-06-21 08:31:18 +00:00
if ( NT_STATUS_IS_OK ( ret ) ) {
2003-06-25 00:28:46 +00:00
DEBUG ( 10 , ( " db_get_id_from_sid: storing %s -> %s \n " ,
sid_data . dptr , ugid_data . dptr ) ) ;
2003-06-21 08:31:18 +00:00
if ( tdb_store ( idmap_tdb , sid_data , ugid_data , TDB_REPLACE ) = = - 1 ) {
2003-06-25 00:28:46 +00:00
DEBUG ( 10 , ( " db_get_id_from_sid: error %s \n " , tdb_errorstr ( idmap_tdb ) ) ) ;
2003-03-08 17:29:40 +00:00
/* TODO: print tdb error !! */
2003-06-26 23:48:46 +00:00
tdb_chainunlock ( idmap_tdb , sid_data ) ;
2003-03-08 00:49:18 +00:00
return NT_STATUS_UNSUCCESSFUL ;
2003-03-08 17:29:40 +00:00
}
2003-03-08 00:49:18 +00:00
}
2003-06-26 23:48:46 +00:00
tdb_chainunlock ( idmap_tdb , sid_data ) ;
2003-03-08 00:49:18 +00:00
}
2003-04-02 10:36:02 +00:00
2003-03-08 00:49:18 +00:00
return ret ;
}
2003-04-26 15:48:48 +00:00
static NTSTATUS db_set_mapping ( const DOM_SID * sid , unid_t id , int id_type )
2003-03-08 17:29:40 +00:00
{
2003-05-01 11:47:48 +00:00
TDB_DATA ksid , kid , data ;
2003-03-08 17:29:40 +00:00
fstring ksidstr ;
fstring kidstr ;
2003-06-25 00:11:38 +00:00
DEBUG ( 10 , ( " db_set_mapping: id_type = 0x%x \n " , id_type ) ) ;
2003-06-25 00:02:17 +00:00
if ( ! sid )
return NT_STATUS_INVALID_PARAMETER ;
2003-03-08 17:29:40 +00:00
sid_to_string ( ksidstr , sid ) ;
ksid . dptr = ksidstr ;
ksid . dsize = strlen ( ksidstr ) + 1 ;
if ( id_type & ID_USERID ) {
2003-07-22 04:31:20 +00:00
slprintf ( kidstr , sizeof ( kidstr ) , " UID %lu " , ( unsigned long ) id . uid ) ;
2003-03-08 17:29:40 +00:00
} else if ( id_type & ID_GROUPID ) {
2003-07-22 04:31:20 +00:00
slprintf ( kidstr , sizeof ( kidstr ) , " GID %lu " , ( unsigned long ) id . gid ) ;
2003-03-08 17:29:40 +00:00
} else {
return NT_STATUS_INVALID_PARAMETER ;
}
kid . dptr = kidstr ;
kid . dsize = strlen ( kidstr ) + 1 ;
2003-05-01 11:47:48 +00:00
/* *DELETE* prevoius mappings if any.
* This is done both SID and [ U | G ] ID passed in */
2003-06-26 23:48:46 +00:00
/* Lock the record for this SID. */
if ( tdb_chainlock ( idmap_tdb , ksid ) ! = 0 ) {
2003-06-27 20:55:48 +00:00
DEBUG ( 10 , ( " db_set_mapping: failed to lock record %s. Error %s \n " ,
2003-06-26 23:48:46 +00:00
ksidstr , tdb_errorstr ( idmap_tdb ) ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2003-06-25 00:11:38 +00:00
DEBUG ( 10 , ( " db_set_mapping: fetching %s \n " , ksid . dptr ) ) ;
2003-05-01 11:47:48 +00:00
data = tdb_fetch ( idmap_tdb , ksid ) ;
if ( data . dptr ) {
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " db_set_mapping: deleting %s and %s \n " , data . dptr , ksid . dptr ) ) ;
2003-05-01 11:47:48 +00:00
tdb_delete ( idmap_tdb , data ) ;
tdb_delete ( idmap_tdb , ksid ) ;
2003-06-17 10:16:20 +00:00
SAFE_FREE ( data . dptr ) ;
2003-05-01 11:47:48 +00:00
}
data = tdb_fetch ( idmap_tdb , kid ) ;
if ( data . dptr ) {
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " db_set_mapping: deleting %s and %s \n " , data . dptr , kid . dptr ) ) ;
2003-05-01 11:47:48 +00:00
tdb_delete ( idmap_tdb , data ) ;
tdb_delete ( idmap_tdb , kid ) ;
2003-06-17 10:16:20 +00:00
SAFE_FREE ( data . dptr ) ;
2003-05-01 11:47:48 +00:00
}
2003-03-08 17:29:40 +00:00
if ( tdb_store ( idmap_tdb , ksid , kid , TDB_INSERT ) = = - 1 ) {
2003-04-17 14:25:52 +00:00
DEBUG ( 0 , ( " idb_set_mapping: tdb_store 1 error: %s \n " , tdb_errorstr ( idmap_tdb ) ) ) ;
2003-06-26 23:48:46 +00:00
tdb_chainunlock ( idmap_tdb , ksid ) ;
2003-03-08 17:29:40 +00:00
return NT_STATUS_UNSUCCESSFUL ;
}
if ( tdb_store ( idmap_tdb , kid , ksid , TDB_INSERT ) = = - 1 ) {
2003-04-17 14:25:52 +00:00
DEBUG ( 0 , ( " idb_set_mapping: tdb_store 2 error: %s \n " , tdb_errorstr ( idmap_tdb ) ) ) ;
2003-06-26 23:48:46 +00:00
tdb_chainunlock ( idmap_tdb , ksid ) ;
2003-03-08 17:29:40 +00:00
return NT_STATUS_UNSUCCESSFUL ;
}
2003-06-25 00:02:17 +00:00
2003-06-26 23:48:46 +00:00
tdb_chainunlock ( idmap_tdb , ksid ) ;
2003-06-25 00:02:17 +00:00
DEBUG ( 10 , ( " db_set_mapping: stored %s -> %s and %s -> %s \n " , ksid . dptr , kid . dptr , kid . dptr , ksid . dptr ) ) ;
2003-06-21 08:31:18 +00:00
return NT_STATUS_OK ;
2003-03-08 17:29:40 +00:00
}
2003-03-08 00:49:18 +00:00
/*****************************************************************************
Initialise idmap database .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-06-25 00:02:17 +00:00
2003-06-06 13:48:39 +00:00
static NTSTATUS db_idmap_init ( char * params )
2003-03-08 00:49:18 +00:00
{
2003-04-06 09:35:16 +00:00
SMB_STRUCT_STAT stbuf ;
2003-04-29 22:06:16 +00:00
char * tdbfile = NULL ;
2003-04-26 15:48:48 +00:00
int32 version ;
2003-04-29 22:06:16 +00:00
BOOL tdb_is_new = False ;
2003-04-06 09:35:16 +00:00
2003-04-26 15:48:48 +00:00
/* use the old database if present */
2004-12-07 18:25:53 +00:00
tdbfile = SMB_STRDUP ( lock_path ( " winbindd_idmap.tdb " ) ) ;
2003-04-29 22:06:16 +00:00
if ( ! tdbfile ) {
2003-06-25 08:15:51 +00:00
DEBUG ( 0 , ( " idmap_init: out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
2003-04-06 09:35:16 +00:00
}
2003-06-25 08:15:51 +00:00
if ( ! file_exist ( tdbfile , & stbuf ) ) {
tdb_is_new = True ;
}
2003-06-25 10:18:22 +00:00
DEBUG ( 10 , ( " db_idmap_init: Opening tdbfile %s \n " , tdbfile ) ) ;
2003-06-25 00:02:17 +00:00
2003-06-25 08:15:51 +00:00
/* Open idmap repository */
2003-04-26 15:48:48 +00:00
if ( ! ( idmap_tdb = tdb_open_log ( tdbfile , 0 ,
2003-03-08 00:49:18 +00:00
TDB_DEFAULT , O_RDWR | O_CREAT ,
2003-06-18 13:28:37 +00:00
0644 ) ) ) {
2003-03-08 00:49:18 +00:00
DEBUG ( 0 , ( " idmap_init: Unable to open idmap database \n " ) ) ;
2003-04-26 15:48:48 +00:00
SAFE_FREE ( tdbfile ) ;
2003-03-08 00:49:18 +00:00
return NT_STATUS_UNSUCCESSFUL ;
}
2003-04-26 15:48:48 +00:00
SAFE_FREE ( tdbfile ) ;
2003-06-25 10:18:22 +00:00
if ( tdb_is_new ) {
/* the file didn't existed before opening it, let's
* store idmap version as nobody else yet opened and
* stored it . I do not like this method but didn ' t
* found a way to understand if an opened tdb have
* been just created or not - - - SSS */
tdb_store_int32 ( idmap_tdb , " IDMAP_VERSION " , IDMAP_VERSION ) ;
}
2003-04-26 15:48:48 +00:00
/* check against earlier versions */
2003-06-25 08:15:51 +00:00
version = tdb_fetch_int32 ( idmap_tdb , " IDMAP_VERSION " ) ;
if ( version ! = IDMAP_VERSION ) {
2003-06-25 10:18:22 +00:00
DEBUG ( 0 , ( " idmap_init: Unable to open idmap database, it's in an old format! \n " ) ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
2003-04-26 15:48:48 +00:00
}
2003-03-08 00:49:18 +00:00
/* Create high water marks for group and user id */
2003-04-19 15:29:39 +00:00
if ( ! lp_idmap_uid ( & idmap_state . uid_low , & idmap_state . uid_high ) ) {
2003-05-14 03:32:20 +00:00
DEBUG ( 1 , ( " idmap uid range missing or invalid \n " ) ) ;
DEBUGADD ( 1 , ( " idmap will be unable to map foreign SIDs \n " ) ) ;
2003-04-30 16:35:17 +00:00
} else {
if ( tdb_fetch_int32 ( idmap_tdb , HWM_USER ) = = - 1 ) {
if ( tdb_store_int32 ( idmap_tdb , HWM_USER , idmap_state . uid_low ) = = - 1 ) {
DEBUG ( 0 , ( " idmap_init: Unable to initialise user hwm in idmap database \n " ) ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
}
2003-04-19 15:29:39 +00:00
}
2003-04-30 16:35:17 +00:00
2003-04-19 15:29:39 +00:00
if ( ! lp_idmap_gid ( & idmap_state . gid_low , & idmap_state . gid_high ) ) {
2003-05-14 03:32:20 +00:00
DEBUG ( 1 , ( " idmap gid range missing or invalid \n " ) ) ;
DEBUGADD ( 1 , ( " idmap will be unable to map foreign SIDs \n " ) ) ;
2003-04-30 16:35:17 +00:00
} else {
if ( tdb_fetch_int32 ( idmap_tdb , HWM_GROUP ) = = - 1 ) {
if ( tdb_store_int32 ( idmap_tdb , HWM_GROUP , idmap_state . gid_low ) = = - 1 ) {
DEBUG ( 0 , ( " idmap_init: Unable to initialise group hwm in idmap database \n " ) ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
}
2003-04-19 15:29:39 +00:00
}
2003-04-30 16:35:17 +00:00
2003-03-08 00:49:18 +00:00
return NT_STATUS_OK ;
}
/* Close the tdb */
2003-04-02 10:36:02 +00:00
static NTSTATUS db_idmap_close ( void )
2003-03-08 00:49:18 +00:00
{
2003-03-08 17:29:40 +00:00
if ( idmap_tdb ) {
if ( tdb_close ( idmap_tdb ) = = 0 ) {
2003-03-08 00:49:18 +00:00
return NT_STATUS_OK ;
2003-03-08 17:29:40 +00:00
} else {
return NT_STATUS_UNSUCCESSFUL ;
}
}
2003-03-08 00:49:18 +00:00
return NT_STATUS_OK ;
}
/* Dump status information to log file. Display different stuff based on
the debug level :
Debug Level Information Displayed
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
0 Percentage of [ ug ] id range allocated
0 High water marks ( next allocated ids )
*/
# define DUMP_INFO 0
2003-04-02 10:36:02 +00:00
static void db_idmap_status ( void )
2003-03-08 00:49:18 +00:00
{
int user_hwm , group_hwm ;
DEBUG ( 0 , ( " winbindd idmap status: \n " ) ) ;
/* Get current high water marks */
if ( ( user_hwm = tdb_fetch_int32 ( idmap_tdb , HWM_USER ) ) = = - 1 ) {
DEBUG ( DUMP_INFO ,
( " \t Could not get userid high water mark! \n " ) ) ;
}
if ( ( group_hwm = tdb_fetch_int32 ( idmap_tdb , HWM_GROUP ) ) = = - 1 ) {
DEBUG ( DUMP_INFO ,
( " \t Could not get groupid high water mark! \n " ) ) ;
}
/* Display next ids to allocate */
if ( user_hwm ! = - 1 ) {
DEBUG ( DUMP_INFO ,
( " \t Next userid to allocate is %d \n " , user_hwm ) ) ;
}
if ( group_hwm ! = - 1 ) {
DEBUG ( DUMP_INFO ,
( " \t Next groupid to allocate is %d \n " , group_hwm ) ) ;
}
/* Display percentage of id range already allocated. */
if ( user_hwm ! = - 1 ) {
2003-03-08 17:29:40 +00:00
int num_users = user_hwm - idmap_state . uid_low ;
2003-03-08 00:49:18 +00:00
int total_users =
2003-03-08 17:29:40 +00:00
idmap_state . uid_high - idmap_state . uid_low ;
2003-03-08 00:49:18 +00:00
DEBUG ( DUMP_INFO ,
( " \t User id range is %d%% full (%d of %d) \n " ,
num_users * 100 / total_users , num_users ,
total_users ) ) ;
}
if ( group_hwm ! = - 1 ) {
2003-03-08 17:29:40 +00:00
int num_groups = group_hwm - idmap_state . gid_low ;
2003-03-08 00:49:18 +00:00
int total_groups =
2003-03-08 17:29:40 +00:00
idmap_state . gid_high - idmap_state . gid_low ;
2003-03-08 00:49:18 +00:00
DEBUG ( DUMP_INFO ,
( " \t Group id range is %d%% full (%d of %d) \n " ,
num_groups * 100 / total_groups , num_groups ,
total_groups ) ) ;
}
/* Display complete mapping of users and groups to rids */
}
2003-08-06 18:01:39 +00:00
/**********************************************************************
Return the TDB_CONTEXT * for winbindd_idmap . I * * really * * feel
dirty doing this , but not so dirty that I want to create another
tdb
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
TDB_CONTEXT * idmap_tdb_handle ( void )
{
if ( idmap_tdb )
return idmap_tdb ;
/* go ahead an open it; db_idmap_init() doesn't use any params
right now */
db_idmap_init ( NULL ) ;
if ( idmap_tdb )
return idmap_tdb ;
return NULL ;
}
2003-05-29 19:08:40 +00:00
static struct idmap_methods db_methods = {
2003-03-08 00:49:18 +00:00
2003-04-02 10:36:02 +00:00
db_idmap_init ,
2003-07-09 16:44:47 +00:00
db_allocate_id ,
2003-04-02 10:36:02 +00:00
db_get_sid_from_id ,
db_get_id_from_sid ,
db_set_mapping ,
db_idmap_close ,
db_idmap_status
2003-03-08 00:49:18 +00:00
} ;
2003-05-29 21:30:48 +00:00
NTSTATUS idmap_tdb_init ( void )
2003-03-08 00:49:18 +00:00
{
2003-05-29 19:08:40 +00:00
return smb_register_idmap ( SMB_IDMAP_INTERFACE_VERSION , " tdb " , & db_methods ) ;
2003-03-08 00:49:18 +00:00
}