2004-03-31 06:45:39 +00:00
/*
ldb database library
Copyright ( C ) Andrew Tridgell 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 02:46:15 +00:00
version 3 of the License , or ( at your option ) any later version .
2004-03-31 06:45:39 +00: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
2007-07-10 03:42:26 +00:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2004-03-31 06:45:39 +00:00
*/
/*
* Name : ldb
*
* Component : ldb search functions
*
* Description : functions to search ldb + tdb databases
*
* Author : Andrew Tridgell
*/
2007-05-05 18:50:56 +00:00
# include "ldb_tdb.h"
2012-06-19 12:43:10 +09:30
# include <tdb.h>
2004-03-31 06:45:39 +00:00
/*
add one element to a message
*/
2006-01-31 11:16:43 +00:00
static int msg_add_element ( struct ldb_message * ret ,
2005-10-11 06:21:07 +00:00
const struct ldb_message_element * el ,
int check_duplicates )
2004-03-31 06:45:39 +00:00
{
2004-07-07 01:02:54 +00:00
unsigned int i ;
2004-04-03 12:29:21 +00:00
struct ldb_message_element * e2 , * elnew ;
2004-03-31 06:45:39 +00:00
2005-10-11 06:21:07 +00:00
if ( check_duplicates & & ldb_msg_find_element ( ret , el - > name ) ) {
/* its already there */
return 0 ;
}
2005-01-12 16:00:01 +00:00
e2 = talloc_realloc ( ret , ret - > elements , struct ldb_message_element , ret - > num_elements + 1 ) ;
2004-03-31 06:45:39 +00:00
if ( ! e2 ) {
return - 1 ;
}
ret - > elements = e2 ;
2004-04-03 12:29:21 +00:00
elnew = & e2 [ ret - > num_elements ] ;
2005-01-02 07:49:29 +00:00
elnew - > name = talloc_strdup ( ret - > elements , el - > name ) ;
2004-04-03 12:29:21 +00:00
if ( ! elnew - > name ) {
2004-03-31 06:45:39 +00:00
return - 1 ;
}
2004-04-03 12:29:21 +00:00
if ( el - > num_values ) {
2005-01-12 16:00:01 +00:00
elnew - > values = talloc_array ( ret - > elements , struct ldb_val , el - > num_values ) ;
2004-04-03 12:29:21 +00:00
if ( ! elnew - > values ) {
return - 1 ;
}
} else {
elnew - > values = NULL ;
2004-03-31 06:45:39 +00:00
}
2004-04-03 12:29:21 +00:00
for ( i = 0 ; i < el - > num_values ; i + + ) {
2005-01-02 07:49:29 +00:00
elnew - > values [ i ] = ldb_val_dup ( elnew - > values , & el - > values [ i ] ) ;
2004-04-03 12:29:21 +00:00
if ( elnew - > values [ i ] . length ! = el - > values [ i ] . length ) {
return - 1 ;
}
}
elnew - > num_values = el - > num_values ;
2010-08-17 20:15:28 +10:00
elnew - > flags = el - > flags ;
2004-04-03 12:29:21 +00:00
2004-03-31 06:45:39 +00:00
ret - > num_elements + + ;
return 0 ;
}
2005-10-11 06:21:07 +00:00
/*
add the special distinguishedName element
*/
2006-01-31 11:16:43 +00:00
static int msg_add_distinguished_name ( struct ldb_message * msg )
2005-10-11 06:21:07 +00:00
{
struct ldb_message_element el ;
struct ldb_val val ;
int ret ;
el . flags = 0 ;
2005-10-12 06:10:23 +00:00
el . name = " distinguishedName " ;
2005-10-11 06:21:07 +00:00
el . num_values = 1 ;
el . values = & val ;
2010-08-17 20:15:28 +10:00
el . flags = 0 ;
2006-11-22 02:05:19 +00:00
val . data = ( uint8_t * ) ldb_dn_alloc_linearized ( msg , msg - > dn ) ;
2005-10-12 06:10:23 +00:00
val . length = strlen ( ( char * ) val . data ) ;
2005-10-11 06:21:07 +00:00
2006-01-31 11:16:43 +00:00
ret = msg_add_element ( msg , & el , 1 ) ;
2005-10-11 06:21:07 +00:00
return ret ;
}
2004-03-31 06:45:39 +00:00
/*
add all elements from one message into another
*/
2004-11-15 11:40:27 +00:00
static int msg_add_all_elements ( struct ldb_module * module , struct ldb_message * ret ,
2004-03-31 06:45:39 +00:00
const struct ldb_message * msg )
{
2009-01-29 18:39:30 -05:00
struct ldb_context * ldb ;
2004-07-07 01:02:54 +00:00
unsigned int i ;
2005-10-11 06:21:07 +00:00
int check_duplicates = ( ret - > num_elements ! = 0 ) ;
2009-01-29 18:39:30 -05:00
ldb = ldb_module_get_ctx ( module ) ;
2006-01-31 11:16:43 +00:00
if ( msg_add_distinguished_name ( ret ) ! = 0 ) {
2005-10-11 06:21:07 +00:00
return - 1 ;
}
2004-11-15 11:40:27 +00:00
2004-03-31 06:45:39 +00:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
2006-12-15 13:08:57 +00:00
const struct ldb_schema_attribute * a ;
a = ldb_schema_attribute_by_name ( ldb , msg - > elements [ i ] . name ) ;
if ( a - > flags & LDB_ATTR_FLAG_HIDDEN ) {
2004-05-09 12:30:30 +00:00
continue ;
}
2006-01-31 11:16:43 +00:00
if ( msg_add_element ( ret , & msg - > elements [ i ] ,
2005-10-11 06:21:07 +00:00
check_duplicates ) ! = 0 ) {
2004-03-31 06:45:39 +00:00
return - 1 ;
}
}
return 0 ;
}
/*
pull the specified list of attributes from a message
*/
2004-11-15 11:40:27 +00:00
static struct ldb_message * ltdb_pull_attrs ( struct ldb_module * module ,
2006-01-31 11:16:43 +00:00
TALLOC_CTX * mem_ctx ,
2004-03-31 06:45:39 +00:00
const struct ldb_message * msg ,
2004-05-07 23:54:41 +00:00
const char * const * attrs )
2004-03-31 06:45:39 +00:00
{
struct ldb_message * ret ;
2009-11-06 18:35:17 +01:00
unsigned int i ;
2004-03-31 06:45:39 +00:00
2006-01-31 11:16:43 +00:00
ret = talloc ( mem_ctx , struct ldb_message ) ;
2004-03-31 06:45:39 +00:00
if ( ! ret ) {
return NULL ;
}
2005-08-18 15:02:01 +00:00
ret - > dn = ldb_dn_copy ( ret , msg - > dn ) ;
2004-03-31 06:45:39 +00:00
if ( ! ret - > dn ) {
2005-01-02 07:49:29 +00:00
talloc_free ( ret ) ;
2004-03-31 06:45:39 +00:00
return NULL ;
}
ret - > num_elements = 0 ;
ret - > elements = NULL ;
if ( ! attrs ) {
2004-11-15 11:40:27 +00:00
if ( msg_add_all_elements ( module , ret , msg ) ! = 0 ) {
2005-01-02 07:49:29 +00:00
talloc_free ( ret ) ;
2004-03-31 06:45:39 +00:00
return NULL ;
}
return ret ;
}
for ( i = 0 ; attrs [ i ] ; i + + ) {
2004-04-10 20:18:22 +00:00
struct ldb_message_element * el ;
2004-03-31 06:45:39 +00:00
if ( strcmp ( attrs [ i ] , " * " ) = = 0 ) {
2004-11-15 11:40:27 +00:00
if ( msg_add_all_elements ( module , ret , msg ) ! = 0 ) {
2005-01-02 07:49:29 +00:00
talloc_free ( ret ) ;
2004-03-31 06:45:39 +00:00
return NULL ;
}
continue ;
}
2004-04-10 20:18:22 +00:00
2005-10-11 06:21:07 +00:00
if ( ldb_attr_cmp ( attrs [ i ] , " distinguishedName " ) = = 0 ) {
2006-01-31 11:16:43 +00:00
if ( msg_add_distinguished_name ( ret ) ! = 0 ) {
2005-10-12 06:10:23 +00:00
return NULL ;
2004-05-20 13:25:06 +00:00
}
continue ;
}
2004-04-10 20:18:22 +00:00
el = ldb_msg_find_element ( msg , attrs [ i ] ) ;
if ( ! el ) {
2004-03-31 06:45:39 +00:00
continue ;
}
2006-01-31 11:16:43 +00:00
if ( msg_add_element ( ret , el , 1 ) ! = 0 ) {
2005-01-02 07:49:29 +00:00
talloc_free ( ret ) ;
2004-04-10 20:18:22 +00:00
return NULL ;
}
2004-03-31 06:45:39 +00:00
}
return ret ;
}
2007-11-15 01:53:44 +01:00
/*
search the database for a single simple dn .
return LDB_ERR_NO_SUCH_OBJECT on record - not - found
and LDB_SUCCESS on success
*/
2008-10-20 18:59:51 +02:00
static int ltdb_search_base ( struct ldb_module * module , struct ldb_dn * dn )
2007-11-15 01:53:44 +01:00
{
2009-01-29 18:39:30 -05:00
void * data = ldb_module_get_private ( module ) ;
struct ltdb_private * ltdb = talloc_get_type ( data , struct ltdb_private ) ;
2012-08-09 19:58:31 +10:00
TDB_DATA tdb_key ;
int exists ;
2007-11-15 01:53:44 +01:00
if ( ldb_dn_is_null ( dn ) ) {
return LDB_ERR_NO_SUCH_OBJECT ;
}
/* form the key */
tdb_key = ltdb_key ( module , dn ) ;
if ( ! tdb_key . dptr ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2012-08-09 19:58:31 +10:00
exists = tdb_exists ( ltdb - > tdb , tdb_key ) ;
2007-11-15 01:53:44 +01:00
talloc_free ( tdb_key . dptr ) ;
2012-08-09 19:58:31 +10:00
if ( exists ) {
return LDB_SUCCESS ;
2007-11-15 01:53:44 +01:00
}
2012-08-09 19:58:31 +10:00
return LDB_ERR_NO_SUCH_OBJECT ;
2007-11-15 01:53:44 +01:00
}
2004-03-31 06:45:39 +00:00
2012-08-09 22:46:48 +10:00
struct ltdb_parse_data_unpack_ctx {
struct ldb_message * msg ;
struct ldb_module * module ;
} ;
static int ltdb_parse_data_unpack ( TDB_DATA key , TDB_DATA data ,
void * private_data )
{
struct ltdb_parse_data_unpack_ctx * ctx = private_data ;
int ret = ltdb_unpack_data ( ctx - > module , & data , ctx - > msg ) ;
if ( ret = = - 1 ) {
struct ldb_context * ldb = ldb_module_get_ctx ( ctx - > module ) ;
ldb_debug ( ldb , LDB_DEBUG_ERROR , " Invalid data for index %*.*s \n " ,
( int ) key . dsize , ( int ) key . dsize , key . dptr ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
return ret ;
}
2004-03-31 06:45:39 +00:00
/*
search the database for a single simple dn , returning all attributes
in a single message
2007-04-23 00:36:49 +00:00
return LDB_ERR_NO_SUCH_OBJECT on record - not - found
and LDB_SUCCESS on success
2004-03-31 06:45:39 +00:00
*/
2006-11-22 00:59:34 +00:00
int ltdb_search_dn1 ( struct ldb_module * module , struct ldb_dn * dn , struct ldb_message * msg )
2004-03-31 06:45:39 +00:00
{
2009-01-29 18:39:30 -05:00
void * data = ldb_module_get_private ( module ) ;
struct ltdb_private * ltdb = talloc_get_type ( data , struct ltdb_private ) ;
2004-03-31 06:45:39 +00:00
int ret ;
2012-08-09 22:46:48 +10:00
TDB_DATA tdb_key ;
struct ltdb_parse_data_unpack_ctx ctx = {
. msg = msg ,
. module = module
} ;
2004-05-08 03:44:47 +00:00
2004-03-31 06:45:39 +00:00
/* form the key */
2004-11-15 11:40:27 +00:00
tdb_key = ltdb_key ( module , dn ) ;
2004-03-31 06:45:39 +00:00
if ( ! tdb_key . dptr ) {
2007-04-23 00:36:49 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
2004-03-31 06:45:39 +00:00
}
2012-08-09 22:46:48 +10:00
memset ( msg , 0 , sizeof ( * msg ) ) ;
2004-03-31 06:45:39 +00:00
msg - > num_elements = 0 ;
msg - > elements = NULL ;
2012-08-09 22:46:48 +10:00
ret = tdb_parse_record ( ltdb - > tdb , tdb_key ,
ltdb_parse_data_unpack , & ctx ) ;
talloc_free ( tdb_key . dptr ) ;
2008-09-24 23:59:59 +02:00
if ( ret = = - 1 ) {
2012-08-09 22:46:48 +10:00
if ( tdb_error ( ltdb - > tdb ) = = TDB_ERR_NOEXIST ) {
return LDB_ERR_NO_SUCH_OBJECT ;
}
return LDB_ERR_OPERATIONS_ERROR ;
} else if ( ret ! = LDB_SUCCESS ) {
return ret ;
2004-03-31 06:45:39 +00:00
}
2012-08-09 22:46:48 +10:00
2004-05-01 09:45:56 +00:00
if ( ! msg - > dn ) {
2006-03-03 17:44:03 +00:00
msg - > dn = ldb_dn_copy ( msg , dn ) ;
2004-05-01 09:45:56 +00:00
}
if ( ! msg - > dn ) {
2007-04-23 00:36:49 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
2004-05-01 09:45:56 +00:00
}
2007-04-23 00:36:49 +00:00
return LDB_SUCCESS ;
2004-03-31 06:45:39 +00:00
}
/*
add a set of attributes from a record to a set of results
return 0 on success , - 1 on failure
*/
2006-01-31 11:16:43 +00:00
int ltdb_add_attr_results ( struct ldb_module * module ,
TALLOC_CTX * mem_ctx ,
struct ldb_message * msg ,
2004-05-07 23:54:41 +00:00
const char * const attrs [ ] ,
2005-11-08 00:11:45 +00:00
unsigned int * count ,
2004-03-31 06:45:39 +00:00
struct ldb_message * * * res )
{
struct ldb_message * msg2 ;
struct ldb_message * * res2 ;
/* pull the attributes that the user wants */
2006-01-31 11:16:43 +00:00
msg2 = ltdb_pull_attrs ( module , mem_ctx , msg , attrs ) ;
2004-03-31 06:45:39 +00:00
if ( ! msg2 ) {
2008-09-24 23:59:59 +02:00
return - 1 ;
2004-03-31 06:45:39 +00:00
}
/* add to the results list */
2006-01-31 11:16:43 +00:00
res2 = talloc_realloc ( mem_ctx , * res , struct ldb_message * , ( * count ) + 2 ) ;
2004-03-31 06:45:39 +00:00
if ( ! res2 ) {
2005-01-02 07:49:29 +00:00
talloc_free ( msg2 ) ;
2008-09-24 23:59:59 +02:00
return - 1 ;
2004-03-31 06:45:39 +00:00
}
( * res ) = res2 ;
2006-09-13 02:33:51 +00:00
( * res ) [ * count ] = talloc_move ( * res , & msg2 ) ;
2004-03-31 06:45:39 +00:00
( * res ) [ ( * count ) + 1 ] = NULL ;
( * count ) + + ;
2008-09-24 23:59:59 +02:00
return 0 ;
2004-03-31 06:45:39 +00:00
}
2006-03-03 17:44:03 +00:00
2004-03-31 06:45:39 +00:00
/*
2006-03-03 17:44:03 +00:00
filter the specified list of attributes from a message
removing not requested attrs .
*/
int ltdb_filter_attrs ( struct ldb_message * msg , const char * const * attrs )
{
2009-11-06 18:35:17 +01:00
unsigned int i ;
int keep_all = 0 ;
2010-11-05 18:50:29 +11:00
struct ldb_message_element * el2 ;
uint32_t num_elements ;
2006-03-03 17:44:03 +00:00
if ( attrs ) {
/* check for special attrs */
for ( i = 0 ; attrs [ i ] ; i + + ) {
if ( strcmp ( attrs [ i ] , " * " ) = = 0 ) {
keep_all = 1 ;
break ;
}
if ( ldb_attr_cmp ( attrs [ i ] , " distinguishedName " ) = = 0 ) {
if ( msg_add_distinguished_name ( msg ) ! = 0 ) {
2008-09-24 23:59:59 +02:00
return - 1 ;
2006-03-03 17:44:03 +00:00
}
}
}
} else {
keep_all = 1 ;
}
if ( keep_all ) {
if ( msg_add_distinguished_name ( msg ) ! = 0 ) {
2008-09-24 23:59:59 +02:00
return - 1 ;
2006-03-03 17:44:03 +00:00
}
2008-09-24 23:59:59 +02:00
return 0 ;
2006-03-03 17:44:03 +00:00
}
2010-11-05 18:50:29 +11:00
el2 = talloc_array ( msg , struct ldb_message_element , msg - > num_elements ) ;
if ( el2 = = NULL ) {
return - 1 ;
}
num_elements = 0 ;
2006-03-03 17:44:03 +00:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
2010-06-03 18:37:15 +02:00
unsigned int j ;
int found = 0 ;
2006-03-03 17:44:03 +00:00
2010-06-03 18:37:15 +02:00
for ( j = 0 ; attrs [ j ] ; j + + ) {
2006-03-03 17:44:03 +00:00
if ( ldb_attr_cmp ( msg - > elements [ i ] . name , attrs [ j ] ) = = 0 ) {
found = 1 ;
break ;
}
}
2004-03-31 06:45:39 +00:00
2010-11-05 18:50:29 +11:00
if ( found ) {
el2 [ num_elements ] = msg - > elements [ i ] ;
talloc_steal ( el2 , el2 [ num_elements ] . name ) ;
talloc_steal ( el2 , el2 [ num_elements ] . values ) ;
num_elements + + ;
2006-03-03 17:44:03 +00:00
}
}
2010-11-05 18:50:29 +11:00
talloc_free ( msg - > elements ) ;
msg - > elements = talloc_realloc ( msg , el2 , struct ldb_message_element , msg - > num_elements ) ;
if ( msg - > elements = = NULL ) {
return - 1 ;
}
msg - > num_elements = num_elements ;
2008-09-24 23:59:59 +02:00
return 0 ;
2006-03-03 17:44:03 +00:00
}
2004-03-31 06:45:39 +00:00
/*
search function for a non - indexed search
*/
static int search_func ( struct tdb_context * tdb , TDB_DATA key , TDB_DATA data , void * state )
{
2009-01-29 18:39:30 -05:00
struct ldb_context * ldb ;
2008-09-11 18:34:11 -04:00
struct ltdb_context * ac ;
struct ldb_message * msg ;
2004-03-31 06:45:39 +00:00
int ret ;
2010-10-13 20:58:38 +11:00
bool matched ;
2004-03-31 06:45:39 +00:00
2008-09-11 18:34:11 -04:00
ac = talloc_get_type ( state , struct ltdb_context ) ;
2009-01-29 18:39:30 -05:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2008-09-11 18:34:11 -04:00
2004-03-31 06:45:39 +00:00
if ( key . dsize < 4 | |
2005-10-12 06:10:23 +00:00
strncmp ( ( char * ) key . dptr , " DN= " , 3 ) ! = 0 ) {
2008-09-24 23:59:59 +02:00
return 0 ;
2004-03-31 06:45:39 +00:00
}
2008-09-11 18:34:11 -04:00
msg = ldb_msg_new ( ac ) ;
if ( ! msg ) {
2008-09-24 23:59:59 +02:00
return - 1 ;
2005-01-02 07:49:29 +00:00
}
2004-03-31 06:45:39 +00:00
/* unpack the record */
2008-09-11 18:34:11 -04:00
ret = ltdb_unpack_data ( ac - > module , & data , msg ) ;
2008-09-24 23:59:59 +02:00
if ( ret = = - 1 ) {
2008-09-11 18:34:11 -04:00
talloc_free ( msg ) ;
2008-09-24 23:59:59 +02:00
return - 1 ;
2004-03-31 06:45:39 +00:00
}
2008-09-11 18:34:11 -04:00
if ( ! msg - > dn ) {
2009-01-29 18:39:30 -05:00
msg - > dn = ldb_dn_new ( msg , ldb ,
2008-09-11 18:34:11 -04:00
( char * ) key . dptr + 3 ) ;
if ( msg - > dn = = NULL ) {
talloc_free ( msg ) ;
2008-09-24 23:59:59 +02:00
return - 1 ;
2005-08-18 15:02:01 +00:00
}
2004-05-01 09:45:56 +00:00
}
2004-03-31 06:45:39 +00:00
/* see if it matches the given expression */
2010-10-13 20:58:38 +11:00
ret = ldb_match_msg_error ( ldb , msg ,
ac - > tree , ac - > base , ac - > scope , & matched ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return - 1 ;
}
if ( ! matched ) {
2008-09-11 18:34:11 -04:00
talloc_free ( msg ) ;
2008-09-24 23:59:59 +02:00
return 0 ;
2004-03-31 06:45:39 +00:00
}
2006-03-03 17:44:03 +00:00
/* filter the attributes that the user wants */
2008-09-11 18:34:11 -04:00
ret = ltdb_filter_attrs ( msg , ac - > attrs ) ;
2004-03-31 06:45:39 +00:00
2008-09-24 23:59:59 +02:00
if ( ret = = - 1 ) {
2008-09-11 18:34:11 -04:00
talloc_free ( msg ) ;
2008-09-24 23:59:59 +02:00
return - 1 ;
2004-03-31 06:45:39 +00:00
}
2008-12-16 08:59:05 +01:00
ret = ldb_module_send_entry ( ac - > req , msg , NULL ) ;
2008-09-11 18:34:11 -04:00
if ( ret ! = LDB_SUCCESS ) {
2009-03-09 18:04:38 -04:00
ac - > request_terminated = true ;
2008-09-11 18:34:11 -04:00
/* the callback failed, abort the operation */
2008-09-24 23:59:59 +02:00
return - 1 ;
2009-03-09 18:04:38 -04:00
}
2006-03-03 17:44:03 +00:00
2008-09-24 23:59:59 +02:00
return 0 ;
2004-03-31 06:45:39 +00:00
}
/*
search the database with a LDAP - like expression .
2004-06-27 11:06:10 +00:00
this is the " full search " non - indexed variant
2004-03-31 06:45:39 +00:00
*/
2008-09-11 18:34:11 -04:00
static int ltdb_search_full ( struct ltdb_context * ctx )
2004-03-31 06:45:39 +00:00
{
2009-01-29 18:39:30 -05:00
void * data = ldb_module_get_private ( ctx - > module ) ;
struct ltdb_private * ltdb = talloc_get_type ( data , struct ltdb_private ) ;
2005-11-08 00:11:45 +00:00
int ret ;
2005-01-02 07:49:29 +00:00
2007-10-18 02:03:21 +02:00
if ( ltdb - > in_transaction ! = 0 ) {
2008-09-11 18:34:11 -04:00
ret = tdb_traverse ( ltdb - > tdb , search_func , ctx ) ;
2007-10-18 02:03:21 +02:00
} else {
2008-09-11 18:34:11 -04:00
ret = tdb_traverse_read ( ltdb - > tdb , search_func , ctx ) ;
2007-10-18 02:03:21 +02:00
}
2005-11-08 00:11:45 +00:00
2011-06-20 18:40:31 +09:30
if ( ret < 0 ) {
2008-09-11 18:34:11 -04:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-01-02 07:49:29 +00:00
}
2004-03-31 06:45:39 +00:00
2006-05-28 02:10:44 +00:00
return LDB_SUCCESS ;
2006-03-03 17:44:03 +00:00
}
2006-05-29 23:46:43 +00:00
/*
search the database with a LDAP - like expression .
choses a search method
*/
2008-09-11 18:34:11 -04:00
int ltdb_search ( struct ltdb_context * ctx )
2004-03-31 06:45:39 +00:00
{
2009-01-29 18:39:30 -05:00
struct ldb_context * ldb ;
2008-09-11 18:34:11 -04:00
struct ldb_module * module = ctx - > module ;
struct ldb_request * req = ctx - > req ;
2009-01-29 18:39:30 -05:00
void * data = ldb_module_get_private ( module ) ;
struct ltdb_private * ltdb = talloc_get_type ( data , struct ltdb_private ) ;
2004-03-31 06:45:39 +00:00
int ret ;
2009-01-29 18:39:30 -05:00
ldb = ldb_module_get_ctx ( module ) ;
ldb_request_set_state ( req , LDB_ASYNC_PENDING ) ;
2008-09-11 18:34:11 -04:00
2005-05-01 12:34:12 +00:00
if ( ltdb_lock_read ( module ) ! = 0 ) {
2006-03-03 17:44:03 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-05-01 12:34:12 +00:00
}
2004-11-15 11:40:27 +00:00
if ( ltdb_cache_load ( module ) ! = 0 ) {
2005-05-01 12:34:12 +00:00
ltdb_unlock_read ( module ) ;
2006-03-03 17:44:03 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
2004-05-01 09:45:56 +00:00
}
2006-05-29 01:30:02 +00:00
if ( req - > op . search . tree = = NULL ) {
2006-03-03 17:44:03 +00:00
ltdb_unlock_read ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2007-11-15 01:53:44 +01:00
if ( ( req - > op . search . base = = NULL ) | | ( ldb_dn_is_null ( req - > op . search . base ) = = true ) ) {
/* Check what we should do with a NULL dn */
switch ( req - > op . search . scope ) {
case LDB_SCOPE_BASE :
2009-01-29 18:39:30 -05:00
ldb_asprintf_errstring ( ldb ,
2007-11-15 01:53:44 +01:00
" NULL Base DN invalid for a base search " ) ;
ret = LDB_ERR_INVALID_DN_SYNTAX ;
2007-11-26 06:12:01 +01:00
break ;
2007-11-15 01:53:44 +01:00
case LDB_SCOPE_ONELEVEL :
2009-01-29 18:39:30 -05:00
ldb_asprintf_errstring ( ldb ,
2007-11-15 01:53:44 +01:00
" NULL Base DN invalid for a one-level search " ) ;
ret = LDB_ERR_INVALID_DN_SYNTAX ;
2007-11-26 06:12:01 +01:00
break ;
2007-11-15 01:53:44 +01:00
case LDB_SCOPE_SUBTREE :
default :
/* We accept subtree searches from a NULL base DN, ie over the whole DB */
ret = LDB_SUCCESS ;
}
} else if ( ldb_dn_is_valid ( req - > op . search . base ) = = false ) {
/* We don't want invalid base DNs here */
2009-01-29 18:39:30 -05:00
ldb_asprintf_errstring ( ldb ,
2007-11-15 01:53:44 +01:00
" Invalid Base DN: %s " ,
ldb_dn_get_linearized ( req - > op . search . base ) ) ;
ret = LDB_ERR_INVALID_DN_SYNTAX ;
} else if ( ltdb - > check_base ) {
/* This database has been marked as 'checkBaseOnSearch', so do a spot check of the base dn */
ret = ltdb_search_base ( module , req - > op . search . base ) ;
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
2009-01-29 18:39:30 -05:00
ldb_asprintf_errstring ( ldb ,
2007-11-15 01:53:44 +01:00
" No such Base DN: %s " ,
ldb_dn_get_linearized ( req - > op . search . base ) ) ;
}
} else {
/* If we are not checking the base DN life is easy */
ret = LDB_SUCCESS ;
}
2008-09-11 18:34:11 -04:00
ctx - > tree = req - > op . search . tree ;
ctx - > scope = req - > op . search . scope ;
ctx - > base = req - > op . search . base ;
ctx - > attrs = req - > op . search . attrs ;
2007-11-15 01:53:44 +01:00
if ( ret = = LDB_SUCCESS ) {
2009-09-15 10:00:24 -07:00
uint32_t match_count = 0 ;
ret = ltdb_search_indexed ( ctx , & match_count ) ;
2007-11-15 01:53:44 +01:00
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
/* Not in the index, therefore OK! */
ret = LDB_SUCCESS ;
2008-09-11 18:34:11 -04:00
}
/* Check if we got just a normal error.
* In that case proceed to a full search unless we got a
* callback error */
2009-03-09 18:04:38 -04:00
if ( ! ctx - > request_terminated & & ret ! = LDB_SUCCESS ) {
2007-11-15 01:53:44 +01:00
/* Not indexed, so we need to do a full scan */
2010-11-23 20:19:49 +11:00
if ( ltdb - > warn_unindexed ) {
/* useful for debugging when slow performance
* is caused by unindexed searches */
char * expression = ldb_filter_from_tree ( ctx , ctx - > tree ) ;
2010-11-24 00:14:10 +03:00
ldb_debug ( ldb , LDB_DEBUG_WARNING , " ldb FULL SEARCH: %s SCOPE: %s DN: %s \n " ,
expression ,
req - > op . search . scope = = LDB_SCOPE_BASE ? " base " :
req - > op . search . scope = = LDB_SCOPE_ONELEVEL ? " one " :
req - > op . search . scope = = LDB_SCOPE_SUBTREE ? " sub " : " UNKNOWN " ,
ldb_dn_get_linearized ( req - > op . search . base ) ) ;
2010-11-23 20:19:49 +11:00
talloc_free ( expression ) ;
}
2009-09-15 10:00:24 -07:00
if ( match_count ! = 0 ) {
/* the indexing code gave an error
* after having returned at least one
* entry . This means the indexes are
* corrupt or a database record is
* corrupt . We cannot continue with a
* full search or we may return
* duplicate entries
*/
2009-12-09 14:36:50 +11:00
ltdb_unlock_read ( module ) ;
2009-09-15 10:00:24 -07:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2008-09-11 18:34:11 -04:00
ret = ltdb_search_full ( ctx ) ;
2007-11-15 01:53:44 +01:00
if ( ret ! = LDB_SUCCESS ) {
2009-01-29 18:39:30 -05:00
ldb_set_errstring ( ldb , " Indexed and full searches both failed! \n " ) ;
2007-11-15 01:53:44 +01:00
}
}
2006-03-03 17:44:03 +00:00
}
2007-11-15 01:53:44 +01:00
2005-05-01 12:34:12 +00:00
ltdb_unlock_read ( module ) ;
2004-03-31 06:45:39 +00:00
2008-09-11 18:34:11 -04:00
return ret ;
2004-03-31 06:45:39 +00:00
}