2023-01-24 13:03:28 +03:00
/*
2006-12-12 17:52:13 +03:00
Unix SMB / CIFS implementation .
idmap TDB backend
Copyright ( C ) Tim Potter 2000
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2003
Copyright ( C ) Jeremy Allison 2006
Copyright ( C ) Simo Sorce 2003 - 2006
2010-06-17 11:39:11 +04:00
Copyright ( C ) Michael Adam 2009 - 2010
2011-02-26 14:36:19 +03:00
2006-12-12 17:52:13 +03: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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-12-12 17:52:13 +03:00
( at your option ) any later version .
2011-02-26 14:36:19 +03:00
2006-12-12 17:52:13 +03:00
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 .
2011-02-26 14:36:19 +03:00
2006-12-12 17:52:13 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-12-12 17:52:13 +03:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2006-12-12 17:52:13 +03:00
# include "winbindd.h"
2010-08-18 20:13:42 +04:00
# include "idmap.h"
2010-06-23 14:12:37 +04:00
# include "idmap_rw.h"
2012-02-20 15:13:56 +04:00
# include "idmap_tdb_common.h"
2011-07-07 19:42:08 +04:00
# include "dbwrap/dbwrap.h"
2011-07-06 18:40:21 +04:00
# include "dbwrap/dbwrap_open.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2020-08-07 21:17:34 +03:00
# include "lib/util/string_wrappers.h"
2006-12-12 17:52:13 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_IDMAP
2009-01-22 12:24:40 +03:00
/* idmap version determines auto-conversion - this is the database
structure version specifier . */
# define IDMAP_VERSION 2
2006-12-12 17:52:13 +03:00
/* High water mark keys */
# define HWM_GROUP "GROUP HWM"
# define HWM_USER "USER HWM"
2008-12-16 23:14:36 +03:00
struct convert_fn_state {
struct db_context * db ;
bool failed ;
} ;
2006-12-12 17:52:13 +03:00
/*****************************************************************************
For idmap conversion : convert one record to new format
Ancient versions ( eg 2.2 .3 a ) of winbindd_idmap . tdb mapped DOMAINNAME / rid
instead of the SID .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-12-16 23:14:36 +03:00
static int convert_fn ( struct db_record * rec , void * private_data )
2006-12-12 17:52:13 +03:00
{
struct winbindd_domain * domain ;
char * p ;
2008-12-16 23:14:36 +03:00
NTSTATUS status ;
2010-05-21 05:25:01 +04:00
struct dom_sid sid ;
2015-04-24 05:04:23 +03:00
uint32_t rid ;
2018-12-06 21:12:07 +03:00
struct dom_sid_buf keystr ;
2006-12-12 17:52:13 +03:00
fstring dom_name ;
2011-08-17 13:45:31 +04:00
TDB_DATA key ;
2006-12-12 17:52:13 +03:00
TDB_DATA key2 ;
2011-08-17 13:45:31 +04:00
TDB_DATA value ;
2008-12-16 23:14:36 +03:00
struct convert_fn_state * s = ( struct convert_fn_state * ) private_data ;
2006-12-12 17:52:13 +03:00
2011-08-17 13:45:31 +04:00
key = dbwrap_record_get_key ( rec ) ;
2006-12-12 17:52:13 +03:00
2011-08-17 13:45:31 +04:00
DEBUG ( 10 , ( " Converting %s \n " , ( const char * ) key . dptr ) ) ;
p = strchr ( ( const char * ) key . dptr , ' / ' ) ;
2006-12-12 17:52:13 +03:00
if ( ! p )
return 0 ;
* p = 0 ;
2011-08-17 13:45:31 +04:00
fstrcpy ( dom_name , ( const char * ) key . dptr ) ;
2006-12-12 17:52:13 +03:00
* p + + = ' / ' ;
domain = find_domain_from_name ( dom_name ) ;
if ( domain = = NULL ) {
/* We must delete the old record. */
DEBUG ( 0 , ( " Unable to find domain %s \n " , dom_name ) ) ;
2011-08-17 13:45:31 +04:00
DEBUG ( 0 , ( " deleting record %s \n " , ( const char * ) key . dptr ) ) ;
2008-12-16 23:14:36 +03:00
2011-08-17 13:45:31 +04:00
status = dbwrap_record_delete ( rec ) ;
2008-12-16 23:14:36 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Unable to delete record %s:%s \n " ,
2011-08-17 13:45:31 +04:00
( const char * ) key . dptr ,
2008-12-16 23:14:36 +03:00
nt_errstr ( status ) ) ) ;
s - > failed = true ;
2006-12-12 17:52:13 +03:00
return - 1 ;
}
return 0 ;
}
rid = atoi ( p ) ;
2010-01-10 19:39:27 +03:00
sid_compose ( & sid , & domain - > sid , rid ) ;
2006-12-12 17:52:13 +03:00
2018-12-06 21:12:07 +03:00
key2 = string_term_tdb_data ( dom_sid_str_buf ( & sid , & keystr ) ) ;
2006-12-12 17:52:13 +03:00
2011-08-17 13:45:31 +04:00
value = dbwrap_record_get_value ( rec ) ;
status = dbwrap_store ( s - > db , key2 , value , TDB_INSERT ) ;
2008-12-16 23:14:36 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Unable to add record %s:%s \n " ,
( const char * ) key2 . dptr ,
nt_errstr ( status ) ) ) ;
s - > failed = true ;
2006-12-12 17:52:13 +03:00
return - 1 ;
}
2011-08-17 13:45:31 +04:00
status = dbwrap_store ( s - > db , value , key2 , TDB_REPLACE ) ;
2008-12-16 23:14:36 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Unable to update record %s:%s \n " ,
2011-08-17 13:45:31 +04:00
( const char * ) value . dptr ,
2008-12-16 23:14:36 +03:00
nt_errstr ( status ) ) ) ;
s - > failed = true ;
2006-12-12 17:52:13 +03:00
return - 1 ;
}
2011-08-17 13:45:31 +04:00
status = dbwrap_record_delete ( rec ) ;
2008-12-16 23:14:36 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Unable to delete record %s:%s \n " ,
2011-08-17 13:45:31 +04:00
( const char * ) key . dptr ,
2008-12-16 23:14:36 +03:00
nt_errstr ( status ) ) ) ;
s - > failed = true ;
2006-12-12 17:52:13 +03:00
return - 1 ;
}
return 0 ;
}
/*****************************************************************************
Convert the idmap database from an older version .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-17 11:46:08 +04:00
static bool idmap_tdb_upgrade ( struct idmap_domain * dom , struct db_context * db )
2006-12-12 17:52:13 +03:00
{
2015-05-16 00:56:25 +03:00
int32_t vers ;
2008-12-16 23:14:36 +03:00
struct convert_fn_state s ;
2011-08-17 13:45:31 +04:00
NTSTATUS status ;
2006-12-12 17:52:13 +03:00
2012-06-14 22:26:28 +04:00
status = dbwrap_fetch_int32_bystring ( db , " IDMAP_VERSION " , & vers ) ;
2011-10-06 22:34:55 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
vers = - 1 ;
}
2006-12-12 17:52:13 +03:00
2012-06-22 09:37:43 +04:00
if ( IREV ( vers ) = = IDMAP_VERSION ) {
/* Arrggghh ! Bytereversed - make order independent ! */
2006-12-12 17:52:13 +03:00
/*
* high and low records were created on a
* big endian machine and will need byte - reversing .
*/
2015-05-16 00:56:25 +03:00
int32_t wm ;
2006-12-12 17:52:13 +03:00
2012-06-14 22:26:28 +04:00
status = dbwrap_fetch_int32_bystring ( db , HWM_USER , & wm ) ;
2011-10-06 22:34:55 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
wm = - 1 ;
}
2006-12-12 17:52:13 +03:00
if ( wm ! = - 1 ) {
wm = IREV ( wm ) ;
} else {
2010-06-17 11:46:08 +04:00
wm = dom - > low_id ;
2006-12-12 17:52:13 +03:00
}
2012-06-14 22:30:16 +04:00
status = dbwrap_store_int32_bystring ( db , HWM_USER , wm ) ;
2011-10-06 23:24:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Unable to byteswap user hwm in idmap "
" database: %s \n " , nt_errstr ( status ) ) ) ;
2006-12-12 17:52:13 +03:00
return False ;
}
2012-06-14 22:26:28 +04:00
status = dbwrap_fetch_int32_bystring ( db , HWM_GROUP , & wm ) ;
2011-10-06 22:34:55 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
wm = - 1 ;
}
2006-12-12 17:52:13 +03:00
if ( wm ! = - 1 ) {
wm = IREV ( wm ) ;
} else {
2010-06-17 11:46:08 +04:00
wm = dom - > low_id ;
2006-12-12 17:52:13 +03:00
}
2012-06-14 22:30:16 +04:00
status = dbwrap_store_int32_bystring ( db , HWM_GROUP , wm ) ;
2011-10-06 23:24:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Unable to byteswap group hwm in idmap "
" database: %s \n " , nt_errstr ( status ) ) ) ;
2006-12-12 17:52:13 +03:00
return False ;
}
}
2008-12-16 23:14:36 +03:00
s . db = db ;
s . failed = false ;
2006-12-12 17:52:13 +03:00
/* the old format stored as DOMAIN/rid - now we store the SID direct */
2011-08-17 13:45:31 +04:00
status = dbwrap_traverse ( db , convert_fn , & s , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Database traverse failed during conversion \n " ) ) ;
return false ;
}
2006-12-12 17:52:13 +03:00
2008-12-16 23:14:36 +03:00
if ( s . failed ) {
2006-12-12 17:52:13 +03:00
DEBUG ( 0 , ( " Problem during conversion \n " ) ) ;
return False ;
}
2012-06-14 22:30:16 +04:00
status = dbwrap_store_int32_bystring ( db , " IDMAP_VERSION " ,
IDMAP_VERSION ) ;
2011-10-06 23:24:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Unable to store idmap version in database: %s \n " ,
nt_errstr ( status ) ) ) ;
2006-12-12 17:52:13 +03:00
return False ;
}
return True ;
}
2010-06-17 10:11:19 +04:00
static NTSTATUS idmap_tdb_init_hwm ( struct idmap_domain * dom )
{
uint32_t low_uid ;
uint32_t low_gid ;
bool update_uid = false ;
bool update_gid = false ;
2012-02-20 15:13:56 +04:00
struct idmap_tdb_common_context * ctx ;
2011-10-06 23:07:27 +04:00
NTSTATUS status ;
2010-06-17 10:11:19 +04:00
2012-02-20 15:13:56 +04:00
ctx = talloc_get_type ( dom - > private_data ,
struct idmap_tdb_common_context ) ;
2010-06-17 10:11:19 +04:00
2012-06-14 22:39:27 +04:00
status = dbwrap_fetch_uint32_bystring ( ctx - > db , HWM_USER , & low_uid ) ;
2011-10-06 23:07:27 +04:00
if ( ! NT_STATUS_IS_OK ( status ) | | low_uid < dom - > low_id ) {
2010-06-17 10:11:19 +04:00
update_uid = true ;
}
2012-06-14 22:39:27 +04:00
status = dbwrap_fetch_uint32_bystring ( ctx - > db , HWM_GROUP , & low_gid ) ;
2011-10-06 23:07:27 +04:00
if ( ! NT_STATUS_IS_OK ( status ) | | low_gid < dom - > low_id ) {
2010-06-17 10:11:19 +04:00
update_gid = true ;
}
if ( ! update_uid & & ! update_gid ) {
return NT_STATUS_OK ;
}
2011-08-17 13:45:31 +04:00
if ( dbwrap_transaction_start ( ctx - > db ) ! = 0 ) {
2010-06-17 10:11:19 +04:00
DEBUG ( 0 , ( " Unable to start upgrade transaction! \n " ) ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
if ( update_uid ) {
2012-06-15 11:09:57 +04:00
status = dbwrap_store_uint32_bystring ( ctx - > db , HWM_USER ,
dom - > low_id ) ;
2011-10-06 23:29:04 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-08-17 13:45:31 +04:00
dbwrap_transaction_cancel ( ctx - > db ) ;
2010-06-17 10:11:19 +04:00
DEBUG ( 0 , ( " Unable to initialise user hwm in idmap "
2011-10-06 23:29:04 +04:00
" database: %s \n " , nt_errstr ( status ) ) ) ;
2010-06-17 10:11:19 +04:00
return NT_STATUS_INTERNAL_DB_ERROR ;
}
}
if ( update_gid ) {
2012-06-15 11:09:57 +04:00
status = dbwrap_store_uint32_bystring ( ctx - > db , HWM_GROUP ,
dom - > low_id ) ;
2011-10-06 23:29:04 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-08-17 13:45:31 +04:00
dbwrap_transaction_cancel ( ctx - > db ) ;
2010-06-17 10:11:19 +04:00
DEBUG ( 0 , ( " Unable to initialise group hwm in idmap "
2011-10-06 23:29:04 +04:00
" database: %s \n " , nt_errstr ( status ) ) ) ;
2010-06-17 10:11:19 +04:00
return NT_STATUS_INTERNAL_DB_ERROR ;
}
}
2011-08-17 13:45:31 +04:00
if ( dbwrap_transaction_commit ( ctx - > db ) ! = 0 ) {
2010-06-17 10:11:19 +04:00
DEBUG ( 0 , ( " Unable to commit upgrade transaction! \n " ) ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
return NT_STATUS_OK ;
}
2010-06-23 12:53:29 +04:00
static NTSTATUS idmap_tdb_open_db ( struct idmap_domain * dom )
2009-01-26 15:03:28 +03:00
{
NTSTATUS ret ;
2010-06-23 12:53:29 +04:00
TALLOC_CTX * mem_ctx ;
2009-01-26 15:03:28 +03:00
char * tdbfile = NULL ;
struct db_context * db = NULL ;
int32_t version ;
2012-02-20 15:13:56 +04:00
struct idmap_tdb_common_context * ctx ;
2009-01-26 15:03:28 +03:00
2012-02-20 15:13:56 +04:00
ctx = talloc_get_type ( dom - > private_data ,
struct idmap_tdb_common_context ) ;
2006-12-12 17:52:13 +03:00
2010-06-17 11:35:52 +04:00
if ( ctx - > db ) {
/* it is already open */
return NT_STATUS_OK ;
}
2006-12-12 17:52:13 +03:00
/* use our own context here */
2010-06-23 12:53:29 +04:00
mem_ctx = talloc_stackframe ( ) ;
2006-12-12 17:52:13 +03:00
/* use the old database if present */
2018-08-16 11:51:44 +03:00
tdbfile = state_path ( talloc_tos ( ) , " winbindd_idmap.tdb " ) ;
2006-12-12 17:52:13 +03:00
if ( ! tdbfile ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
ret = NT_STATUS_NO_MEMORY ;
goto done ;
}
DEBUG ( 10 , ( " Opening tdbfile %s \n " , tdbfile ) ) ;
/* Open idmap repository */
2012-01-06 20:19:54 +04:00
db = db_open ( mem_ctx , tdbfile , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0644 ,
2014-01-27 17:49:12 +04:00
DBWRAP_LOCK_ORDER_1 , DBWRAP_FLAG_NONE ) ;
2008-12-16 23:14:36 +03:00
if ( ! db ) {
2006-12-12 17:52:13 +03:00
DEBUG ( 0 , ( " Unable to open idmap database \n " ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
/* check against earlier versions */
2012-06-14 22:26:28 +04:00
ret = dbwrap_fetch_int32_bystring ( db , " IDMAP_VERSION " , & version ) ;
2011-10-06 22:34:55 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
version = - 1 ;
}
2006-12-12 17:52:13 +03:00
if ( version ! = IDMAP_VERSION ) {
2011-08-17 13:45:31 +04:00
if ( dbwrap_transaction_start ( db ) ! = 0 ) {
2008-12-16 23:14:36 +03:00
DEBUG ( 0 , ( " Unable to start upgrade transaction! \n " ) ) ;
ret = NT_STATUS_INTERNAL_DB_ERROR ;
goto done ;
}
2006-12-12 17:52:13 +03:00
2010-06-17 11:46:08 +04:00
if ( ! idmap_tdb_upgrade ( dom , db ) ) {
2011-08-17 13:45:31 +04:00
dbwrap_transaction_cancel ( db ) ;
2009-07-29 16:43:14 +04:00
DEBUG ( 0 , ( " Unable to open idmap database, it's in an old format, and upgrade failed! \n " ) ) ;
2006-12-12 17:52:13 +03:00
ret = NT_STATUS_INTERNAL_DB_ERROR ;
goto done ;
}
2011-08-17 13:45:31 +04:00
if ( dbwrap_transaction_commit ( db ) ! = 0 ) {
2008-12-16 23:14:36 +03:00
DEBUG ( 0 , ( " Unable to commit upgrade transaction! \n " ) ) ;
ret = NT_STATUS_INTERNAL_DB_ERROR ;
2006-12-12 17:52:13 +03:00
goto done ;
}
}
2010-06-23 12:53:29 +04:00
ctx - > db = talloc_move ( ctx , & db ) ;
2010-06-17 10:12:43 +04:00
ret = idmap_tdb_init_hwm ( dom ) ;
2006-12-12 17:52:13 +03:00
done :
2010-06-23 12:53:29 +04:00
talloc_free ( mem_ctx ) ;
2006-12-12 17:52:13 +03:00
return ret ;
}
/**********************************************************************
IDMAP MAPPING TDB BACKEND
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*****************************
2023-01-24 13:03:28 +03:00
Initialise idmap database .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-03-03 01:00:58 +03:00
static NTSTATUS idmap_tdb_db_init ( struct idmap_domain * dom )
2006-12-12 17:52:13 +03:00
{
NTSTATUS ret ;
2012-02-20 15:13:56 +04:00
struct idmap_tdb_common_context * ctx ;
2006-12-12 17:52:13 +03:00
2009-05-27 21:14:10 +04:00
DEBUG ( 10 , ( " idmap_tdb_db_init called for domain '%s' \n " , dom - > name ) ) ;
2012-02-20 15:13:56 +04:00
ctx = talloc_zero ( dom , struct idmap_tdb_common_context ) ;
2006-12-12 17:52:13 +03:00
if ( ! ctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-06-17 09:43:14 +04:00
/* load backend specific configuration here: */
#if 0
2009-05-27 21:12:28 +04:00
if ( strequal ( dom - > name , " * " ) ) {
} else {
2006-12-12 17:52:13 +03:00
}
2010-06-17 09:43:14 +04:00
# endif
2009-05-27 21:12:28 +04:00
2010-06-23 14:12:37 +04:00
ctx - > rw_ops = talloc_zero ( ctx , struct idmap_rw_ops ) ;
if ( ctx - > rw_ops = = NULL ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
ret = NT_STATUS_NO_MEMORY ;
goto failed ;
}
2012-02-20 15:13:56 +04:00
ctx - > max_id = dom - > high_id ;
ctx - > hwmkey_uid = HWM_USER ;
ctx - > hwmkey_gid = HWM_GROUP ;
ctx - > rw_ops - > get_new_id = idmap_tdb_common_get_new_id ;
ctx - > rw_ops - > set_mapping = idmap_tdb_common_set_mapping ;
2010-06-23 14:12:37 +04:00
2010-06-23 12:53:29 +04:00
dom - > private_data = ctx ;
ret = idmap_tdb_open_db ( dom ) ;
2009-05-27 21:12:28 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
goto failed ;
}
2006-12-12 17:52:13 +03:00
return NT_STATUS_OK ;
failed :
talloc_free ( ctx ) ;
return ret ;
}
2019-03-21 14:30:37 +03:00
static const struct idmap_methods db_methods = {
2006-12-12 17:52:13 +03:00
. init = idmap_tdb_db_init ,
2012-02-20 15:13:56 +04:00
. unixids_to_sids = idmap_tdb_common_unixids_to_sids ,
. sids_to_unixids = idmap_tdb_common_sids_to_unixids ,
. allocate_id = idmap_tdb_common_get_new_id ,
2006-12-12 17:52:13 +03:00
} ;
2017-04-20 22:24:43 +03:00
NTSTATUS idmap_tdb_init ( TALLOC_CTX * mem_ctx )
2006-12-12 17:52:13 +03:00
{
2008-07-13 14:07:40 +04:00
DEBUG ( 10 , ( " calling idmap_tdb_init \n " ) ) ;
2006-12-12 17:52:13 +03:00
return smb_register_idmap ( SMB_IDMAP_INTERFACE_VERSION , " tdb " , & db_methods ) ;
}