2004-11-15 14:42:17 +03:00
/*
ldb database library
Copyright ( C ) Simo Sorce 2004
* * NOTE ! The following LGPL license applies to the ldb
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
2007-07-10 06:46:15 +04:00
version 3 of the License , or ( at your option ) any later version .
2004-11-15 14:42:17 +03:00
This library 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/*
* Name : ldb
*
* Component : ldb modules core
*
* Description : core modules routines
*
* Author : Simo Sorce
*/
2007-05-05 22:50:56 +04:00
# include "ldb_includes.h"
2005-02-27 14:35:47 +03:00
2006-09-23 03:22:39 +04:00
# if (_SAMBA_BUILD_ >= 4)
2007-05-05 22:50:56 +04:00
# include "includes.h"
2006-03-08 00:02:11 +03:00
# include "build.h"
2006-03-21 11:32:50 +03:00
# include "dynconfig.h"
2006-03-08 00:02:11 +03:00
# endif
2005-03-06 18:33:40 +03:00
# define LDB_MODULE_PREFIX "modules:"
# define LDB_MODULE_PREFIX_LEN 8
2006-10-09 13:56:13 +04:00
static char * ldb_modules_strdup_no_spaces ( TALLOC_CTX * mem_ctx , const char * string )
2005-03-06 18:33:40 +03:00
{
int i , len ;
char * trimmed ;
2006-10-09 13:56:13 +04:00
trimmed = talloc_strdup ( mem_ctx , string ) ;
2005-03-06 18:33:40 +03:00
if ( ! trimmed ) {
return NULL ;
}
len = strlen ( trimmed ) ;
for ( i = 0 ; trimmed [ i ] ! = ' \0 ' ; i + + ) {
switch ( trimmed [ i ] ) {
case ' ' :
case ' \t ' :
case ' \n ' :
memmove ( & trimmed [ i ] , & trimmed [ i + 1 ] , len - i - 1 ) ;
break ;
}
}
return trimmed ;
}
/* modules are called in inverse order on the stack.
Lets place them as an admin would think the right order is .
2006-03-02 19:32:53 +03:00
Modules order is important */
2006-08-10 05:51:27 +04:00
const char * * ldb_modules_list_from_string ( struct ldb_context * ldb , TALLOC_CTX * mem_ctx , const char * string )
2005-03-06 18:33:40 +03:00
{
char * * modules = NULL ;
2006-08-04 14:27:14 +04:00
const char * * m ;
2005-03-06 18:33:40 +03:00
char * modstr , * p ;
int i ;
/* spaces not admitted */
2006-10-09 13:56:13 +04:00
modstr = ldb_modules_strdup_no_spaces ( mem_ctx , string ) ;
2005-03-06 18:33:40 +03:00
if ( ! modstr ) {
2006-10-09 13:56:13 +04:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " Out of Memory in ldb_modules_strdup_no_spaces() \n " ) ;
2005-03-06 18:33:40 +03:00
return NULL ;
}
2006-08-04 14:27:14 +04:00
modules = talloc_realloc ( mem_ctx , modules , char * , 2 ) ;
2005-03-06 18:33:40 +03:00
if ( ! modules ) {
ldb_debug ( ldb , LDB_DEBUG_FATAL , " Out of Memory in ldb_modules_list_from_string() \n " ) ;
talloc_free ( modstr ) ;
return NULL ;
}
talloc_steal ( modules , modstr ) ;
i = 0 ;
2006-08-10 05:51:27 +04:00
/* The str*r*chr walks backwards: This is how we get the inverse order mentioned above */
2005-03-06 18:33:40 +03:00
while ( ( p = strrchr ( modstr , ' , ' ) ) ! = NULL ) {
* p = ' \0 ' ;
p + + ;
modules [ i ] = p ;
i + + ;
2006-08-04 14:27:14 +04:00
modules = talloc_realloc ( mem_ctx , modules , char * , i + 2 ) ;
2005-03-06 18:33:40 +03:00
if ( ! modules ) {
ldb_debug ( ldb , LDB_DEBUG_FATAL , " Out of Memory in ldb_modules_list_from_string() \n " ) ;
return NULL ;
}
}
modules [ i ] = modstr ;
modules [ i + 1 ] = NULL ;
2006-08-04 14:27:14 +04:00
m = ( const char * * ) modules ;
return m ;
2005-03-06 18:33:40 +03:00
}
2004-11-15 14:42:17 +03:00
2006-03-02 19:32:53 +03:00
static struct ops_list_entry {
const struct ldb_module_ops * ops ;
struct ops_list_entry * next ;
} * registered_modules = NULL ;
static const struct ldb_module_ops * ldb_find_module_ops ( const char * name )
{
struct ops_list_entry * e ;
for ( e = registered_modules ; e ; e = e - > next ) {
if ( strcmp ( e - > ops - > name , name ) = = 0 )
return e - > ops ;
}
return NULL ;
}
2007-05-11 13:24:41 +04:00
# ifndef STATIC_LIBLDB_MODULES
2006-08-24 13:41:10 +04:00
2006-09-25 20:59:00 +04:00
# ifdef HAVE_LDB_LDAP
2006-03-05 19:05:26 +03:00
# define LDAP_INIT ldb_ldap_init,
# else
# define LDAP_INIT
# endif
2006-09-25 20:59:00 +04:00
# ifdef HAVE_LDB_SQLITE3
2006-03-05 19:05:26 +03:00
# define SQLITE3_INIT ldb_sqlite3_init,
# else
# define SQLITE3_INIT
# endif
2007-05-11 13:24:41 +04:00
# define STATIC_LIBLDB_MODULES \
2006-03-02 19:32:53 +03:00
{ \
2006-03-05 19:05:26 +03:00
LDAP_INIT \
SQLITE3_INIT \
ldb_tdb_init , \
2006-03-02 19:32:53 +03:00
ldb_operational_init , \
ldb_rdn_name_init , \
ldb_objectclass_init , \
ldb_paged_results_init , \
ldb_sort_init , \
2006-10-23 01:16:46 +04:00
ldb_asq_init , \
2006-03-02 19:32:53 +03:00
NULL \
}
# endif
int ldb_global_init ( void )
{
2007-05-11 13:24:41 +04:00
static int ( * static_init_fns [ ] ) ( void ) = STATIC_LIBLDB_MODULES ;
2006-03-02 19:32:53 +03:00
static int initialized = 0 ;
int ret = 0 , i ;
if ( initialized )
return 0 ;
initialized = 1 ;
for ( i = 0 ; static_init_fns [ i ] ; i + + ) {
if ( static_init_fns [ i ] ( ) = = - 1 )
ret = - 1 ;
}
return ret ;
}
int ldb_register_module ( const struct ldb_module_ops * ops )
{
struct ops_list_entry * entry = talloc ( talloc_autofree_context ( ) , struct ops_list_entry ) ;
if ( ldb_find_module_ops ( ops - > name ) ! = NULL )
return - 1 ;
if ( entry = = NULL )
return - 1 ;
entry - > ops = ops ;
entry - > next = registered_modules ;
registered_modules = entry ;
return 0 ;
}
2006-03-21 00:44:59 +03:00
int ldb_try_load_dso ( struct ldb_context * ldb , const char * name )
{
char * path ;
void * handle ;
int ( * init_fn ) ( void ) ;
2006-10-29 20:40:19 +03:00
char * modulesdir ;
2006-03-21 00:44:59 +03:00
2006-10-29 20:40:19 +03:00
if ( getenv ( " LD_LDB_MODULE_PATH " ) ! = NULL ) {
modulesdir = talloc_strdup ( ldb , getenv ( " LD_LDB_MODULE_PATH " ) ) ;
} else {
2006-03-21 11:32:50 +03:00
# ifdef _SAMBA_BUILD_
2006-10-29 20:40:19 +03:00
modulesdir = talloc_asprintf ( ldb , " %s/ldb " , dyn_MODULESDIR ) ;
2006-03-21 11:32:50 +03:00
# else
2006-10-29 20:40:19 +03:00
modulesdir = talloc_strdup ( ldb , MODULESDIR ) ;
2006-03-21 11:32:50 +03:00
# endif
2006-10-29 20:40:19 +03:00
}
path = talloc_asprintf ( ldb , " %s/%s.%s " , modulesdir , name , SHLIBEXT ) ;
talloc_free ( modulesdir ) ;
2006-03-21 00:44:59 +03:00
ldb_debug ( ldb , LDB_DEBUG_TRACE , " trying to load %s from %s \n " , name , path ) ;
2006-10-29 20:40:19 +03:00
handle = dlopen ( path , RTLD_NOW ) ;
2006-03-21 00:44:59 +03:00
if ( handle = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_WARNING , " unable to load %s from %s: %s \n " , name , path , dlerror ( ) ) ;
return - 1 ;
}
2006-08-23 04:46:40 +04:00
init_fn = ( int ( * ) ( void ) ) dlsym ( handle , " init_module " ) ;
2006-03-21 00:44:59 +03:00
if ( init_fn = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR , " no symbol `init_module' found in %s: %s \n " , path , dlerror ( ) ) ;
return - 1 ;
}
talloc_free ( path ) ;
return init_fn ( ) ;
}
2006-08-10 05:51:27 +04:00
int ldb_load_modules_list ( struct ldb_context * ldb , const char * * module_list , struct ldb_module * backend , struct ldb_module * * out )
2006-08-10 04:52:56 +04:00
{
struct ldb_module * module ;
2006-08-10 05:51:27 +04:00
int i ;
2006-08-10 04:52:56 +04:00
module = backend ;
for ( i = 0 ; module_list [ i ] ! = NULL ; i + + ) {
struct ldb_module * current ;
const struct ldb_module_ops * ops ;
ops = ldb_find_module_ops ( module_list [ i ] ) ;
if ( ops = = NULL ) {
if ( ldb_try_load_dso ( ldb , module_list [ i ] ) = = 0 ) {
ops = ldb_find_module_ops ( module_list [ i ] ) ;
}
}
if ( ops = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_WARNING , " WARNING: Module [%s] not found \n " ,
module_list [ i ] ) ;
continue ;
}
current = talloc_zero ( ldb , struct ldb_module ) ;
if ( current = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-10-17 05:21:02 +04:00
talloc_set_name ( current , " ldb_module: %s " , module_list [ i ] ) ;
2006-08-10 04:52:56 +04:00
current - > ldb = ldb ;
current - > ops = ops ;
DLIST_ADD ( module , current ) ;
}
* out = module ;
return LDB_SUCCESS ;
}
2006-08-10 05:51:27 +04:00
int ldb_init_module_chain ( struct ldb_context * ldb , struct ldb_module * module )
2006-08-10 04:52:56 +04:00
{
while ( module & & module - > ops - > init_context = = NULL )
module = module - > next ;
if ( module & & module - > ops - > init_context & &
module - > ops - > init_context ( module ) ! = LDB_SUCCESS ) {
ldb_debug ( ldb , LDB_DEBUG_FATAL , " module initialization failed \n " ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
return LDB_SUCCESS ;
}
2004-11-15 14:42:17 +03:00
int ldb_load_modules ( struct ldb_context * ldb , const char * options [ ] )
{
2006-08-04 14:27:14 +04:00
const char * * modules = NULL ;
2005-03-06 18:33:40 +03:00
int i ;
2006-08-10 04:52:56 +04:00
int ret ;
2006-08-04 14:27:14 +04:00
TALLOC_CTX * mem_ctx = talloc_new ( ldb ) ;
if ( ! mem_ctx ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2004-11-15 14:42:17 +03:00
/* find out which modules we are requested to activate */
2005-03-06 18:33:40 +03:00
/* check if we have a custom module list passd as ldb option */
2004-11-15 14:42:17 +03:00
if ( options ) {
for ( i = 0 ; options [ i ] ! = NULL ; i + + ) {
2005-03-06 18:33:40 +03:00
if ( strncmp ( options [ i ] , LDB_MODULE_PREFIX , LDB_MODULE_PREFIX_LEN ) = = 0 ) {
2006-08-04 14:27:14 +04:00
modules = ldb_modules_list_from_string ( ldb , mem_ctx , & options [ i ] [ LDB_MODULE_PREFIX_LEN ] ) ;
2004-11-15 14:42:17 +03:00
}
}
}
2006-03-02 19:32:53 +03:00
/* if not overloaded by options and the backend is not ldap try to load the modules list from ldb */
2005-03-06 18:33:40 +03:00
if ( ( modules = = NULL ) & & ( strcmp ( " ldap " , ldb - > modules - > ops - > name ) ! = 0 ) ) {
2005-02-27 14:35:47 +03:00
const char * const attrs [ ] = { " @LIST " , NULL } ;
2006-08-04 16:05:46 +04:00
struct ldb_result * res = NULL ;
struct ldb_dn * mods_dn ;
2004-11-15 14:42:17 +03:00
2006-11-22 03:59:34 +03:00
mods_dn = ldb_dn_new ( mem_ctx , ldb , " @MODULES " ) ;
2006-08-04 16:05:46 +04:00
if ( mods_dn = = NULL ) {
2006-08-04 14:27:14 +04:00
talloc_free ( mem_ctx ) ;
2005-08-18 19:02:01 +04:00
return - 1 ;
}
2006-08-04 16:05:46 +04:00
ret = ldb_search ( ldb , mods_dn , LDB_SCOPE_BASE , " " , attrs , & res ) ;
2006-10-06 10:38:26 +04:00
talloc_steal ( mods_dn , res ) ;
2005-11-08 03:11:45 +03:00
if ( ret = = LDB_SUCCESS & & ( res - > count = = 0 | | res - > msgs [ 0 ] - > num_elements = = 0 ) ) {
2004-11-15 14:42:17 +03:00
ldb_debug ( ldb , LDB_DEBUG_TRACE , " no modules required by the db \n " ) ;
} else {
2005-11-08 03:11:45 +03:00
if ( ret ! = LDB_SUCCESS ) {
2004-11-15 14:42:17 +03:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " ldb error (%s) occurred searching for modules, bailing out \n " , ldb_errstring ( ldb ) ) ;
2006-08-04 14:27:14 +04:00
talloc_free ( mem_ctx ) ;
2004-11-15 14:42:17 +03:00
return - 1 ;
}
2005-11-08 03:11:45 +03:00
if ( res - > count > 1 ) {
ldb_debug ( ldb , LDB_DEBUG_FATAL , " Too many records found (%d), bailing out \n " , res - > count ) ;
2006-08-04 14:27:14 +04:00
talloc_free ( mem_ctx ) ;
2004-11-15 14:42:17 +03:00
return - 1 ;
}
2006-08-04 14:27:14 +04:00
modules = ldb_modules_list_from_string ( ldb , mem_ctx ,
2005-11-08 03:11:45 +03:00
( const char * ) res - > msgs [ 0 ] - > elements [ 0 ] . values [ 0 ] . data ) ;
2005-02-27 14:35:47 +03:00
2004-11-15 14:42:17 +03:00
}
2006-08-04 16:05:46 +04:00
talloc_free ( mods_dn ) ;
2004-11-15 14:42:17 +03:00
}
2006-03-07 00:58:07 +03:00
if ( modules ! = NULL ) {
2006-08-10 04:52:56 +04:00
ret = ldb_load_modules_list ( ldb , modules , ldb - > modules , & ldb - > modules ) ;
2006-03-07 00:58:07 +03:00
talloc_free ( modules ) ;
2006-08-10 04:52:56 +04:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2006-03-07 00:58:07 +03:00
} else {
ldb_debug ( ldb , LDB_DEBUG_TRACE , " No modules specified for this database \n " ) ;
2004-11-15 14:42:17 +03:00
}
2006-08-10 04:52:56 +04:00
return ldb_init_module_chain ( ldb , ldb - > modules ) ;
2004-11-15 14:42:17 +03:00
}
2005-10-06 10:57:09 +04:00
/*
by using this we allow ldb modules to only implement the functions they care about ,
which makes writing a module simpler , and makes it more likely to keep working
when ldb is extended
*/
# define FIND_OP(module, op) do { \
2006-07-10 12:31:47 +04:00
struct ldb_context * ldb = module - > ldb ; \
2005-10-06 10:57:09 +04:00
module = module - > next ; \
while ( module & & module - > ops - > op = = NULL ) module = module - > next ; \
2006-07-10 12:31:47 +04:00
if ( module = = NULL ) { \
2006-08-13 11:33:57 +04:00
ldb_asprintf_errstring ( ldb , " Unable to find backend operation for " # op ) ; \
2006-07-10 12:31:47 +04:00
return LDB_ERR_OPERATIONS_ERROR ; \
} \
2005-10-06 10:57:09 +04:00
} while ( 0 )
2004-11-15 14:42:17 +03:00
/*
helper functions to call the next module in chain
*/
2006-05-29 05:30:02 +04:00
2005-11-08 03:11:45 +03:00
int ldb_next_request ( struct ldb_module * module , struct ldb_request * request )
2005-10-06 09:24:46 +04:00
{
2007-03-08 06:32:28 +03:00
int ret ;
2006-05-29 05:30:02 +04:00
switch ( request - > operation ) {
2006-05-30 04:33:52 +04:00
case LDB_SEARCH :
2006-05-29 05:30:02 +04:00
FIND_OP ( module , search ) ;
2007-03-08 06:32:28 +03:00
ret = module - > ops - > search ( module , request ) ;
break ;
2006-05-30 04:33:52 +04:00
case LDB_ADD :
2006-05-29 05:30:02 +04:00
FIND_OP ( module , add ) ;
2007-03-08 06:32:28 +03:00
ret = module - > ops - > add ( module , request ) ;
break ;
2006-05-30 04:33:52 +04:00
case LDB_MODIFY :
2006-05-29 05:30:02 +04:00
FIND_OP ( module , modify ) ;
2007-03-08 06:32:28 +03:00
ret = module - > ops - > modify ( module , request ) ;
break ;
2006-05-30 04:33:52 +04:00
case LDB_DELETE :
2006-05-29 05:30:02 +04:00
FIND_OP ( module , del ) ;
2007-03-08 06:32:28 +03:00
ret = module - > ops - > del ( module , request ) ;
break ;
2006-05-30 04:33:52 +04:00
case LDB_RENAME :
2006-05-29 05:30:02 +04:00
FIND_OP ( module , rename ) ;
2007-03-08 06:32:28 +03:00
ret = module - > ops - > rename ( module , request ) ;
break ;
2007-01-06 13:21:32 +03:00
case LDB_EXTENDED :
FIND_OP ( module , extended ) ;
2007-03-08 06:32:28 +03:00
ret = module - > ops - > extended ( module , request ) ;
break ;
2006-06-08 01:03:38 +04:00
case LDB_SEQUENCE_NUMBER :
FIND_OP ( module , sequence_number ) ;
2007-03-08 06:32:28 +03:00
ret = module - > ops - > sequence_number ( module , request ) ;
break ;
2006-05-29 05:30:02 +04:00
default :
FIND_OP ( module , request ) ;
2007-03-08 06:32:28 +03:00
ret = module - > ops - > request ( module , request ) ;
break ;
}
if ( ret = = LDB_SUCCESS ) {
return ret ;
2006-05-29 05:30:02 +04:00
}
2007-03-08 06:32:28 +03:00
if ( ! ldb_errstring ( module - > ldb ) ) {
/* Set a default error string, to place the blame somewhere */
2007-03-08 09:23:39 +03:00
ldb_asprintf_errstring ( module - > ldb , " error in module %s: %s (%d) " , module - > ops - > name , ldb_strerror ( ret ) , ret ) ;
2007-03-08 06:32:28 +03:00
}
return ret ;
2004-11-15 14:42:17 +03:00
}
2006-03-02 19:32:53 +03:00
int ldb_next_init ( struct ldb_module * module )
2006-01-06 19:12:45 +03:00
{
2006-03-02 19:32:53 +03:00
/* init is different in that it is not an error if modules
* do not require initialization */
module = module - > next ;
while ( module & & module - > ops - > init_context = = NULL )
module = module - > next ;
if ( module = = NULL )
return LDB_SUCCESS ;
return module - > ops - > init_context ( module ) ;
2006-01-06 19:12:45 +03:00
}
2005-09-17 23:25:50 +04:00
int ldb_next_start_trans ( struct ldb_module * module )
2004-11-21 18:51:54 +03:00
{
2005-10-06 10:57:09 +04:00
FIND_OP ( module , start_transaction ) ;
return module - > ops - > start_transaction ( module ) ;
2004-11-21 18:51:54 +03:00
}
2005-09-24 19:42:15 +04:00
int ldb_next_end_trans ( struct ldb_module * module )
2004-11-21 18:51:54 +03:00
{
2005-10-06 10:57:09 +04:00
FIND_OP ( module , end_transaction ) ;
return module - > ops - > end_transaction ( module ) ;
2005-09-24 19:42:15 +04:00
}
int ldb_next_del_trans ( struct ldb_module * module )
{
2005-10-06 10:57:09 +04:00
FIND_OP ( module , del_transaction ) ;
return module - > ops - > del_transaction ( module ) ;
2004-11-21 18:51:54 +03:00
}