2018-07-23 10:02:16 +12:00
/*
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
2018-07-23 10:02:16 +12:00
2004-03-31 06:45:39 +00:00
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
*/
2018-07-23 10:02:16 +12:00
# include "ldb_kv.h"
2012-10-31 16:06:03 +11:00
# include "ldb_private.h"
2004-03-31 06:45:39 +00:00
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
{
2019-04-05 14:42:09 +13:00
const char * dn_attr = " distinguishedName " ;
char * dn = NULL ;
if ( ldb_msg_find_element ( msg , dn_attr ) ) {
/*
* This should not happen , but this is
* existing behaviour . . .
*/
return LDB_SUCCESS ;
}
2005-10-11 06:21:07 +00:00
2019-04-05 14:42:09 +13:00
dn = ldb_dn_alloc_linearized ( msg , msg - > dn ) ;
if ( dn = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
2018-06-15 11:02:15 +02:00
}
2019-04-05 14:42:09 +13:00
return ldb_msg_add_steal_string ( msg , dn_attr , dn ) ;
2005-10-11 06:21:07 +00:00
}
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
*/
2018-07-20 07:23:10 +12:00
int ldb_kv_search_base ( struct ldb_module * module ,
2018-07-20 07:25:32 +12:00
TALLOC_CTX * mem_ctx ,
struct ldb_dn * dn ,
struct ldb_dn * * ret_dn )
2007-11-15 01:53:44 +01:00
{
2012-08-09 19:58:31 +10:00
int exists ;
2017-08-15 14:39:08 +12:00
int ret ;
struct ldb_message * msg = NULL ;
2007-11-15 01:53:44 +01:00
if ( ldb_dn_is_null ( dn ) ) {
return LDB_ERR_NO_SUCH_OBJECT ;
}
2017-08-15 14:39:08 +12:00
/*
* We can ' t use tdb_exists ( ) directly on a key when the TDB
* key is the GUID one , not the DN based one . So we just do a
* normal search and avoid most of the allocation with the
2019-04-05 11:12:13 +13:00
* LDB_UNPACK_DATA_FLAG_NO_ATTRS flag
2017-08-15 14:39:08 +12:00
*/
msg = ldb_msg_new ( module ) ;
if ( msg = = NULL ) {
2007-11-15 01:53:44 +01:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2018-07-20 07:25:32 +12:00
ret = ldb_kv_search_dn1 ( module , dn , msg , LDB_UNPACK_DATA_FLAG_NO_ATTRS ) ;
2017-08-15 14:39:08 +12:00
if ( ret = = LDB_SUCCESS ) {
2017-08-28 15:37:28 +12:00
const char * dn_linearized
= ldb_dn_get_linearized ( dn ) ;
2019-04-05 16:29:14 +13:00
const char * msg_dn_linearized
2017-08-28 15:37:28 +12:00
= ldb_dn_get_linearized ( msg - > dn ) ;
2019-04-05 16:29:14 +13:00
if ( strcmp ( dn_linearized , msg_dn_linearized ) = = 0 ) {
2017-08-28 15:37:28 +12:00
/*
* Re - use the full incoming DN for
* subtree checks
*/
* ret_dn = dn ;
} else {
/*
* Use the string DN from the unpack , so that
* we have a case - exact match of the base
*/
* ret_dn = talloc_steal ( mem_ctx , msg - > dn ) ;
}
2017-08-15 14:39:08 +12:00
exists = true ;
} else if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
exists = false ;
} else {
2017-08-28 15:37:28 +12:00
talloc_free ( msg ) ;
2017-08-15 14:39:08 +12:00
return ret ;
}
2017-08-28 15:37:28 +12:00
talloc_free ( msg ) ;
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
2018-07-20 13:50:00 +12:00
struct ldb_kv_parse_data_unpack_ctx {
2012-08-09 22:46:48 +10:00
struct ldb_message * msg ;
struct ldb_module * module ;
2019-04-12 11:26:01 +12:00
struct ldb_kv_private * ldb_kv ;
2016-07-27 00:20:27 +12:00
unsigned int unpack_flags ;
2012-08-09 22:46:48 +10:00
} ;
2018-07-20 07:23:10 +12:00
static int ldb_kv_parse_data_unpack ( struct ldb_val key ,
2018-07-20 07:25:32 +12:00
struct ldb_val data ,
void * private_data )
2012-08-09 22:46:48 +10:00
{
2018-07-20 13:50:00 +12:00
struct ldb_kv_parse_data_unpack_ctx * ctx = private_data ;
2016-07-27 00:20:27 +12:00
unsigned int nb_elements_in_db ;
int ret ;
2012-10-30 10:21:42 +11:00
struct ldb_context * ldb = ldb_module_get_ctx ( ctx - > module ) ;
2018-02-19 12:37:20 +13:00
struct ldb_val data_parse = data ;
2016-07-27 00:20:27 +12:00
2019-04-12 11:26:01 +12:00
struct ldb_kv_private * ldb_kv = ctx - > ldb_kv ;
2019-03-07 16:45:46 +13:00
if ( ( ctx - > unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC ) ) {
if ( ( ldb_kv - > kv_ops - > options & LDB_KV_OPTION_STABLE_READ_LOCK ) & &
( ctx - > unpack_flags & LDB_UNPACK_DATA_FLAG_READ_LOCKED ) & &
! ldb_kv - > kv_ops - > transaction_active ( ldb_kv ) ) {
/*
* In the case where no transactions are active and
* we ' re in a read - lock , we can point directly into
* database memory .
*
* The database can ' t be changed underneath us and we
* will duplicate this data in the call to filter .
*
* This is seen in :
* - ldb_kv_index_filter
* - ldb_kv_search_and_return_base
*/
} else {
/*
* In every other case , if we got
* LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC we need at least
* do a memdup on the whole data buffer as that may
* change later and the caller needs a stable result .
*
* During transactions , pointers could change and in
* TDB , there just aren ' t the same guarantees .
*/
data_parse . data = talloc_memdup ( ctx - > msg ,
data . data ,
data . length ) ;
if ( data_parse . data = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Unable to allocate data(%d) for %*.*s \n " ,
( int ) data . length ,
( int ) key . length , ( int ) key . length , key . data ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2016-07-27 00:20:27 +12:00
}
}
ret = ldb_unpack_data_only_attr_list_flags ( ldb , & data_parse ,
ctx - > msg ,
NULL , 0 ,
ctx - > unpack_flags ,
& nb_elements_in_db ) ;
2012-08-09 22:46:48 +10:00
if ( ret = = - 1 ) {
2018-02-19 12:37:20 +13:00
if ( data_parse . data ! = data . data ) {
2016-07-27 00:20:27 +12:00
talloc_free ( data_parse . data ) ;
}
2012-08-09 22:46:48 +10:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " Invalid data for index %*.*s \n " ,
2018-02-19 12:37:20 +13:00
( int ) key . length , ( int ) key . length , key . data ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2012-08-09 22:46:48 +10:00
}
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
*/
2018-07-20 07:25:32 +12:00
int ldb_kv_search_key ( struct ldb_module * module ,
2018-07-20 11:53:21 +12:00
struct ldb_kv_private * ldb_kv ,
2018-07-23 13:20:46 +12:00
const struct ldb_val ldb_key ,
2018-07-20 07:25:32 +12:00
struct ldb_message * msg ,
unsigned int unpack_flags )
2004-03-31 06:45:39 +00:00
{
int ret ;
2018-07-20 13:50:00 +12:00
struct ldb_kv_parse_data_unpack_ctx ctx = {
2012-08-09 22:46:48 +10:00
. msg = msg ,
2016-07-27 00:20:27 +12:00
. module = module ,
2019-04-12 11:26:01 +12:00
. unpack_flags = unpack_flags ,
. ldb_kv = ldb_kv
2012-08-09 22:46:48 +10:00
} ;
2004-05-08 03:44:47 +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 ;
2018-07-20 11:53:21 +12:00
ret = ldb_kv - > kv_ops - > fetch_and_parse (
ldb_kv , ldb_key , ldb_kv_parse_data_unpack , & ctx ) ;
2017-01-10 20:43:38 +13:00
2008-09-24 23:59:59 +02:00
if ( ret = = - 1 ) {
2018-07-20 11:53:21 +12:00
ret = ldb_kv - > kv_ops - > error ( ldb_kv ) ;
2017-08-16 12:46:57 +12:00
if ( ret = = LDB_SUCCESS ) {
/*
* Just to be sure we don ' t turn errors
* into success
*/
return LDB_ERR_OPERATIONS_ERROR ;
2012-08-09 22:46:48 +10:00
}
2017-08-16 12:46:57 +12:00
return ret ;
2012-08-09 22:46:48 +10:00
} else if ( ret ! = LDB_SUCCESS ) {
return ret ;
2004-03-31 06:45:39 +00:00
}
2016-07-27 00:20:27 +12:00
2017-08-10 16:06:08 +12:00
return LDB_SUCCESS ;
}
/*
search the database for a single simple dn , returning all attributes
in a single message
return LDB_ERR_NO_SUCH_OBJECT on record - not - found
and LDB_SUCCESS on success
*/
2018-07-20 07:25:32 +12:00
int ldb_kv_search_dn1 ( struct ldb_module * module ,
struct ldb_dn * dn ,
struct ldb_message * msg ,
unsigned int unpack_flags )
2017-08-10 16:06:08 +12:00
{
void * data = ldb_module_get_private ( module ) ;
2018-07-20 11:54:39 +12:00
struct ldb_kv_private * ldb_kv =
talloc_get_type ( data , struct ldb_kv_private ) ;
2017-08-10 16:06:08 +12:00
int ret ;
2018-07-23 10:08:26 +12:00
uint8_t guid_key [ LDB_KV_GUID_KEY_SIZE ] ;
2018-07-23 13:20:46 +12:00
struct ldb_val key = {
. data = guid_key ,
. length = sizeof ( guid_key )
2017-09-01 20:06:15 +12:00
} ;
TALLOC_CTX * tdb_key_ctx = NULL ;
2017-08-14 15:47:15 +12:00
2018-05-21 15:23:53 +12:00
bool valid_dn = ldb_dn_validate ( dn ) ;
if ( valid_dn = = false ) {
ldb_asprintf_errstring ( ldb_module_get_ctx ( module ) ,
" Invalid Base DN: %s " ,
ldb_dn_get_linearized ( dn ) ) ;
return LDB_ERR_INVALID_DN_SYNTAX ;
}
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > cache - > GUID_index_attribute = = NULL | |
2018-07-20 11:54:39 +12:00
ldb_dn_is_special ( dn ) ) {
2017-09-01 20:06:15 +12:00
tdb_key_ctx = talloc_new ( msg ) ;
if ( ! tdb_key_ctx ) {
return ldb_module_oom ( module ) ;
}
2017-08-10 17:12:30 +12:00
/* form the key */
2018-07-23 13:20:46 +12:00
key = ldb_kv_key_dn ( module , tdb_key_ctx , dn ) ;
if ( ! key . data ) {
2017-08-10 17:12:30 +12:00
TALLOC_FREE ( tdb_key_ctx ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
} else {
2017-09-01 20:06:15 +12:00
/*
* Look in the index to find the key for this DN .
*
* the tdb_key memory is allocated above , msg is just
* used for internal memory .
*
*/
2018-07-23 13:20:46 +12:00
ret = ldb_kv_key_dn_from_idx ( module , ldb_kv , msg , dn , & key ) ;
2017-08-10 17:12:30 +12:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2017-08-10 16:06:08 +12:00
}
2018-07-23 13:20:46 +12:00
ret = ldb_kv_search_key ( module , ldb_kv , key , msg , unpack_flags ) ;
2017-08-14 15:47:15 +12:00
TALLOC_FREE ( tdb_key_ctx ) ;
2017-08-10 16:06:08 +12:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2016-07-27 00:20:27 +12:00
if ( ( unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DN ) = = 0 ) {
if ( ! msg - > dn ) {
msg - > dn = ldb_dn_copy ( msg , dn ) ;
}
if ( ! msg - > dn ) {
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
}
/*
2006-03-03 17:44:03 +00:00
filter the specified list of attributes from a message
2016-08-26 09:58:38 +12:00
removing not requested attrs from the new message constructed .
The reason this makes a new message is that the old one may not be
individually allocated , which is what our callers expect .
2006-03-03 17:44:03 +00:00
*/
2018-07-20 07:23:10 +12:00
int ldb_kv_filter_attrs ( TALLOC_CTX * mem_ctx ,
2018-07-20 07:25:32 +12:00
const struct ldb_message * msg ,
const char * const * attrs ,
struct ldb_message * * filtered_msg )
2006-03-03 17:44:03 +00:00
{
2009-11-06 18:35:17 +01:00
unsigned int i ;
2016-08-26 09:58:38 +12:00
bool keep_all = false ;
bool add_dn = false ;
2010-11-05 18:50:29 +11:00
uint32_t num_elements ;
2016-08-26 09:58:38 +12:00
uint32_t elements_size ;
struct ldb_message * msg2 ;
msg2 = ldb_msg_new ( mem_ctx ) ;
if ( msg2 = = NULL ) {
goto failed ;
}
msg2 - > dn = ldb_dn_copy ( msg2 , msg - > dn ) ;
if ( msg2 - > dn = = NULL ) {
goto failed ;
}
2006-03-03 17:44:03 +00:00
if ( attrs ) {
/* check for special attrs */
for ( i = 0 ; attrs [ i ] ; i + + ) {
2016-08-26 09:58:38 +12:00
int cmp = strcmp ( attrs [ i ] , " * " ) ;
if ( cmp = = 0 ) {
keep_all = true ;
2006-03-03 17:44:03 +00:00
break ;
}
2016-08-26 09:58:38 +12:00
cmp = ldb_attr_cmp ( attrs [ i ] , " distinguishedName " ) ;
if ( cmp = = 0 ) {
add_dn = true ;
2006-03-03 17:44:03 +00:00
}
}
} else {
2016-08-26 09:58:38 +12:00
keep_all = true ;
2006-03-03 17:44:03 +00:00
}
2016-08-26 09:58:38 +12:00
2006-03-03 17:44:03 +00:00
if ( keep_all ) {
2016-08-26 09:58:38 +12:00
add_dn = true ;
elements_size = msg - > num_elements + 1 ;
/* Shortcuts for the simple cases */
} else if ( add_dn & & i = = 1 ) {
if ( msg_add_distinguished_name ( msg2 ) ! = 0 ) {
2018-06-14 12:19:29 +02:00
goto failed ;
2006-03-03 17:44:03 +00:00
}
2016-08-26 09:58:38 +12:00
* filtered_msg = msg2 ;
return 0 ;
} else if ( i = = 0 ) {
* filtered_msg = msg2 ;
2008-09-24 23:59:59 +02:00
return 0 ;
2006-03-03 17:44:03 +00:00
2016-08-26 09:58:38 +12:00
/* Otherwise we are copying at most as many element as we have attributes */
} else {
elements_size = i ;
2010-11-05 18:50:29 +11:00
}
2016-08-26 09:58:38 +12:00
msg2 - > elements = talloc_array ( msg2 , struct ldb_message_element ,
elements_size ) ;
if ( msg2 - > elements = = NULL ) goto failed ;
2010-11-05 18:50:29 +11:00
num_elements = 0 ;
2006-03-03 17:44:03 +00:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
2016-08-26 09:58:38 +12:00
struct ldb_message_element * el = & msg - > elements [ i ] ;
struct ldb_message_element * el2 = & msg2 - > elements [ num_elements ] ;
2010-06-03 18:37:15 +02:00
unsigned int j ;
2016-08-26 09:58:38 +12:00
if ( keep_all = = false ) {
bool found = false ;
for ( j = 0 ; attrs [ j ] ; j + + ) {
int cmp = ldb_attr_cmp ( el - > name , attrs [ j ] ) ;
if ( cmp = = 0 ) {
found = true ;
break ;
}
}
if ( found = = false ) {
continue ;
}
}
* el2 = * el ;
el2 - > name = talloc_strdup ( msg2 - > elements , el - > name ) ;
if ( el2 - > name = = NULL ) {
goto failed ;
}
el2 - > values = talloc_array ( msg2 - > elements , struct ldb_val , el - > num_values ) ;
if ( el2 - > values = = NULL ) {
goto failed ;
}
for ( j = 0 ; j < el - > num_values ; j + + ) {
el2 - > values [ j ] = ldb_val_dup ( el2 - > values , & el - > values [ j ] ) ;
if ( el2 - > values [ j ] . data = = NULL & & el - > values [ j ] . length ! = 0 ) {
goto failed ;
2006-03-03 17:44:03 +00:00
}
}
2016-08-26 09:58:38 +12:00
num_elements + + ;
2004-03-31 06:45:39 +00:00
2016-08-26 09:58:38 +12:00
/* Pidginhole principle: we can't have more elements
* than the number of attributes if they are unique in
* the DB */
if ( num_elements > elements_size ) {
goto failed ;
2006-03-03 17:44:03 +00:00
}
}
2016-08-26 09:58:38 +12:00
msg2 - > num_elements = num_elements ;
2015-11-18 15:25:20 +13:00
2016-08-26 09:58:38 +12:00
if ( add_dn ) {
if ( msg_add_distinguished_name ( msg2 ) ! = 0 ) {
2018-06-14 12:19:29 +02:00
goto failed ;
2016-08-26 09:58:38 +12:00
}
2015-11-18 15:25:20 +13:00
}
2016-08-26 09:58:38 +12:00
if ( msg2 - > num_elements > 0 ) {
msg2 - > elements = talloc_realloc ( msg2 , msg2 - > elements ,
struct ldb_message_element ,
msg2 - > num_elements ) ;
if ( msg2 - > elements = = NULL ) {
2018-06-14 12:19:29 +02:00
goto failed ;
2016-08-26 09:58:38 +12:00
}
} else {
talloc_free ( msg2 - > elements ) ;
msg2 - > elements = NULL ;
2010-11-05 18:50:29 +11:00
}
2015-11-18 15:25:20 +13:00
2016-08-26 09:58:38 +12:00
* filtered_msg = msg2 ;
2010-11-05 18:50:29 +11:00
2008-09-24 23:59:59 +02:00
return 0 ;
2016-08-26 09:58:38 +12:00
failed :
2018-06-14 12:19:29 +02:00
TALLOC_FREE ( msg2 ) ;
2016-08-26 09:58:38 +12:00
return - 1 ;
2006-03-03 17:44:03 +00:00
}
2004-03-31 06:45:39 +00:00
/*
search function for a non - indexed search
*/
2018-07-20 11:54:39 +12:00
static int search_func ( struct ldb_kv_private * ldb_kv ,
struct ldb_val key ,
struct ldb_val val ,
void * state )
2004-03-31 06:45:39 +00:00
{
2009-01-29 18:39:30 -05:00
struct ldb_context * ldb ;
2018-07-20 09:07:47 +12:00
struct ldb_kv_context * ac ;
2016-08-26 09:58:38 +12:00
struct ldb_message * msg , * filtered_msg ;
2004-03-31 06:45:39 +00:00
int ret ;
2010-10-13 20:58:38 +11:00
bool matched ;
2016-08-26 09:58:38 +12:00
unsigned int nb_elements_in_db ;
2004-03-31 06:45:39 +00:00
2018-07-20 09:07:47 +12:00
ac = talloc_get_type ( state , struct ldb_kv_context ) ;
2009-01-29 18:39:30 -05:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2008-09-11 18:34:11 -04:00
2019-04-05 10:46:50 +13:00
/*
* We want to skip @ records early in a search full scan
*
* @ records like @ IDXLIST are only available via a base
* search on the specific name but the method by which they
* were excluded was expensive , after the unpack the DN is
* exploded and ldb_match_msg_error ( ) would reject it for
* failing to match the scope .
*
* ldb_kv_key_is_normal_record ( ) uses the fact that @ records
* have the DN = @ prefix on their TDB / LMDB key to quickly
* exclude them from consideration .
*
* ( any other non - records are also excluded by the same key
* match )
*/
if ( ldb_kv_key_is_normal_record ( key ) = = false ) {
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 ) {
2015-12-03 16:30:59 +13:00
ac - > error = LDB_ERR_OPERATIONS_ERROR ;
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 */
2016-08-26 09:58:38 +12:00
ret = ldb_unpack_data_only_attr_list_flags ( ldb , & val ,
msg ,
NULL , 0 ,
2016-08-23 11:38:26 +12:00
LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC |
LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC ,
2016-08-26 09:58:38 +12:00
& nb_elements_in_db ) ;
2008-09-24 23:59:59 +02:00
if ( ret = = - 1 ) {
2008-09-11 18:34:11 -04:00
talloc_free ( msg ) ;
2015-12-03 16:30:59 +13:00
ac - > error = LDB_ERR_OPERATIONS_ERROR ;
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 ,
2018-02-16 13:06:31 +13:00
( char * ) key . data + 3 ) ;
2008-09-11 18:34:11 -04:00
if ( msg - > dn = = NULL ) {
talloc_free ( msg ) ;
2015-12-03 16:30:59 +13:00
ac - > error = LDB_ERR_OPERATIONS_ERROR ;
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 ) ;
2015-12-03 16:30:59 +13:00
ac - > error = LDB_ERR_OPERATIONS_ERROR ;
2010-10-13 20:58:38 +11:00
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 */
2018-07-20 07:23:10 +12:00
ret = ldb_kv_filter_attrs ( ac , msg , ac - > attrs , & filtered_msg ) ;
2016-08-26 09:58:38 +12:00
talloc_free ( msg ) ;
2004-03-31 06:45:39 +00:00
2008-09-24 23:59:59 +02:00
if ( ret = = - 1 ) {
2015-12-03 16:30:59 +13:00
ac - > error = LDB_ERR_OPERATIONS_ERROR ;
2008-09-24 23:59:59 +02:00
return - 1 ;
2004-03-31 06:45:39 +00:00
}
2016-08-26 09:58:38 +12:00
ret = ldb_module_send_entry ( ac - > req , filtered_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 */
2015-12-03 16:30:59 +13:00
ac - > error = LDB_ERR_OPERATIONS_ERROR ;
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
*/
2018-07-20 09:07:47 +12:00
static int ldb_kv_search_full ( struct ldb_kv_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 ) ;
2018-07-20 11:54:39 +12:00
struct ldb_kv_private * ldb_kv =
talloc_get_type ( data , struct ldb_kv_private ) ;
2005-11-08 00:11:45 +00:00
int ret ;
2005-01-02 07:49:29 +00:00
2015-12-03 16:30:59 +13:00
ctx - > error = LDB_SUCCESS ;
2018-07-20 11:53:21 +12:00
ret = ldb_kv - > kv_ops - > iterate ( ldb_kv , search_func , ctx ) ;
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
2015-12-03 16:30:59 +13:00
return ctx - > error ;
2006-03-03 17:44:03 +00:00
}
2018-07-20 11:53:21 +12:00
static int ldb_kv_search_and_return_base ( struct ldb_kv_private * ldb_kv ,
2018-07-20 09:07:47 +12:00
struct ldb_kv_context * ctx )
2017-08-15 17:21:28 +12:00
{
struct ldb_message * msg , * filtered_msg ;
struct ldb_context * ldb = ldb_module_get_ctx ( ctx - > module ) ;
2017-08-30 13:18:20 +12:00
const char * dn_linearized ;
2019-04-05 16:29:14 +13:00
const char * msg_dn_linearized ;
2017-08-15 17:21:28 +12:00
int ret ;
bool matched ;
msg = ldb_msg_new ( ctx ) ;
if ( ! msg ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2018-07-20 07:25:32 +12:00
ret = ldb_kv_search_dn1 ( ctx - > module ,
ctx - > base ,
msg ,
LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC |
2019-03-07 16:45:46 +13:00
LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC |
LDB_UNPACK_DATA_FLAG_READ_LOCKED ) ;
2017-08-15 17:21:28 +12:00
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > check_base = = false ) {
2017-08-15 17:21:28 +12:00
/*
* In this case , we are done , as no base
* checking is allowed in this DB
*/
talloc_free ( msg ) ;
return LDB_SUCCESS ;
}
ldb_asprintf_errstring ( ldb ,
" No such Base DN: %s " ,
ldb_dn_get_linearized ( ctx - > base ) ) ;
}
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
/*
* We use this , not ldb_match_msg_error ( ) as we know
* we matched on the scope BASE , as we just fetched
* the base DN
*/
ret = ldb_match_message ( ldb , msg ,
ctx - > tree ,
ctx - > scope ,
& matched ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
if ( ! matched ) {
talloc_free ( msg ) ;
return LDB_SUCCESS ;
}
2017-08-30 13:18:20 +12:00
dn_linearized = ldb_dn_get_linearized ( ctx - > base ) ;
2019-04-05 16:29:14 +13:00
msg_dn_linearized = ldb_dn_get_linearized ( msg - > dn ) ;
2017-08-30 13:18:20 +12:00
2019-04-05 16:29:14 +13:00
if ( strcmp ( dn_linearized , msg_dn_linearized ) = = 0 ) {
2017-08-30 13:18:20 +12:00
/*
* If the DN is exactly the same string , then
* re - use the full incoming DN for the
* returned result , as it has already been
* casefolded
*/
msg - > dn = ctx - > base ;
}
/*
* filter the attributes that the user wants .
*
* This copies msg - > dn including the casefolding , so the above
* assignment is safe
*/
2018-07-20 07:23:10 +12:00
ret = ldb_kv_filter_attrs ( ctx , msg , ctx - > attrs , & filtered_msg ) ;
2019-04-04 15:08:18 +13:00
if ( ret = = - 1 ) {
talloc_free ( msg ) ;
filtered_msg = NULL ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2017-08-15 17:21:28 +12:00
2017-08-30 13:18:20 +12:00
/*
* Remove any extended components possibly copied in from
* msg - > dn , we just want the casefold components
*/
ldb_dn_remove_extended_components ( filtered_msg - > dn ) ;
2017-08-15 17:21:28 +12:00
talloc_free ( msg ) ;
ret = ldb_module_send_entry ( ctx - > req , filtered_msg , NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
/* Regardless of success or failure, the msg
* is the callbacks responsiblity , and should
* not be talloc_free ( ) ' ed */
ctx - > request_terminated = true ;
return ret ;
}
return LDB_SUCCESS ;
}
2006-05-29 23:46:43 +00:00
/*
search the database with a LDAP - like expression .
choses a search method
*/
2018-07-20 09:07:47 +12:00
int ldb_kv_search ( struct ldb_kv_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 ) ;
2018-07-20 11:54:39 +12:00
struct ldb_kv_private * ldb_kv =
talloc_get_type ( data , struct ldb_kv_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
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > kv_ops - > 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
}
2018-07-20 07:23:10 +12:00
if ( ldb_kv_cache_load ( module ) ! = 0 ) {
2018-07-20 11:53:21 +12:00
ldb_kv - > kv_ops - > 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 ) {
2018-07-20 11:53:21 +12:00
ldb_kv - > kv_ops - > unlock_read ( module ) ;
2006-03-03 17:44:03 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2017-08-15 17:21:28 +12: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 ( ( 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 :
2018-07-23 10:02:16 +12: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 :
2018-07-23 10:02:16 +12:00
ldb_asprintf_errstring ( ldb ,
2007-11-15 01:53:44 +01:00
" NULL Base DN invalid for a one-level search " ) ;
2018-07-23 10:02:16 +12:00
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 ;
}
2017-08-15 17:21:28 +12:00
} else if ( req - > op . search . scope = = LDB_SCOPE_BASE ) {
/*
* If we are LDB_SCOPE_BASE , do just one search and
* return early . This is critical to ensure we do not
* go into the index code for special DNs , as that
* will try to look up an index record for a special
* record ( which doesn ' t exist ) .
*/
2018-07-20 11:53:21 +12:00
ret = ldb_kv_search_and_return_base ( ldb_kv , ctx ) ;
2017-08-15 17:21:28 +12:00
2018-07-20 11:53:21 +12:00
ldb_kv - > kv_ops - > unlock_read ( module ) ;
2017-08-15 17:21:28 +12:00
return ret ;
2018-07-20 11:53:21 +12:00
} else if ( ldb_kv - > check_base ) {
2017-08-28 15:37:28 +12:00
/*
* This database has been marked as
* ' checkBaseOnSearch ' , so do a spot check of the base
* dn . Also optimise the subsequent filter by filling
* in the ctx - > base to be exactly case correct
*/
2018-07-20 07:25:32 +12:00
ret = ldb_kv_search_base (
module , ctx , req - > op . search . base , & ctx - > base ) ;
2007-11-15 01:53:44 +01:00
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
2018-07-23 10:02:16 +12:00
ldb_asprintf_errstring ( ldb ,
" No such Base DN: %s " ,
2007-11-15 01:53:44 +01:00
ldb_dn_get_linearized ( req - > op . search . base ) ) ;
}
2018-07-23 10:02:16 +12:00
2018-05-21 15:23:53 +12:00
} else if ( ldb_dn_validate ( req - > op . search . base ) = = false ) {
/* We don't want invalid base DNs here */
ldb_asprintf_errstring ( ldb ,
" Invalid Base DN: %s " ,
ldb_dn_get_linearized ( req - > op . search . base ) ) ;
ret = LDB_ERR_INVALID_DN_SYNTAX ;
2007-11-15 01:53:44 +01:00
} else {
/* If we are not checking the base DN life is easy */
ret = LDB_SUCCESS ;
}
if ( ret = = LDB_SUCCESS ) {
2009-09-15 10:00:24 -07:00
uint32_t match_count = 0 ;
2018-07-20 07:23:10 +12:00
ret = ldb_kv_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 ;
2018-07-23 10:02:16 +12:00
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 */
2018-07-23 10:02:16 +12: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 */
2018-07-20 11:54:39 +12:00
if ( ldb_kv - > warn_unindexed | |
ldb_kv - > disable_full_db_scan ) {
2010-11-23 20:19:49 +11:00
/* useful for debugging when slow performance
* is caused by unindexed searches */
char * expression = ldb_filter_from_tree ( ctx , ctx - > tree ) ;
2013-01-06 22:17:26 -08:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb FULL SEARCH: %s SCOPE: %s DN: %s " ,
2010-11-24 00:14:10 +03:00
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 ) ;
}
2018-05-23 17:15:38 +12:00
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
*/
2018-07-20 11:53:21 +12:00
ldb_kv - > kv_ops - > unlock_read ( module ) ;
2009-09-15 10:00:24 -07:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2018-05-23 17:15:38 +12:00
2018-07-20 11:53:21 +12:00
if ( ldb_kv - > disable_full_db_scan ) {
2018-05-23 17:15:38 +12:00
ldb_set_errstring ( ldb ,
" ldb FULL SEARCH disabled " ) ;
2018-07-20 11:53:21 +12:00
ldb_kv - > kv_ops - > unlock_read ( module ) ;
2018-05-23 17:15:38 +12:00
return LDB_ERR_INAPPROPRIATE_MATCHING ;
}
2018-07-20 07:23:10 +12:00
ret = ldb_kv_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
2018-07-20 11:53:21 +12:00
ldb_kv - > kv_ops - > 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
}