2006-01-15 09:12:29 +03:00
/*
ldb database library
2008-09-12 02:35:38 +04:00
Copyright ( C ) Simo Sorce 2005 - 2008
2006-01-15 09:12:29 +03:00
* * 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 .
2006-01-15 09:12:29 +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
2007-07-10 07:42:26 +04:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2006-01-15 09:12:29 +03:00
*/
/*
* Name : ldb
*
* Component : ldb attribute scoped query control module
*
2009-08-26 07:17:40 +04:00
* Description : this module searches all the objects pointed by
* the DNs contained in the references attribute
2006-01-15 09:12:29 +03:00
*
* Author : Simo Sorce
*/
2010-11-01 15:36:42 +03:00
# include "replace.h"
# include "system/filesys.h"
# include "system/time.h"
2009-01-30 02:39:30 +03:00
# include "ldb_module.h"
2006-01-15 09:12:29 +03:00
2006-07-22 20:56:33 +04:00
struct asq_context {
2006-05-28 19:20:53 +04:00
2008-09-12 02:35:38 +04:00
enum { ASQ_SEARCH_BASE , ASQ_SEARCH_MULTI } step ;
2006-05-28 19:20:53 +04:00
2006-03-14 00:05:55 +03:00
struct ldb_module * module ;
2008-09-12 02:35:38 +04:00
struct ldb_request * req ;
2007-01-10 21:18:13 +03:00
struct ldb_asq_control * asq_ctrl ;
2006-03-14 00:05:55 +03:00
const char * const * req_attrs ;
char * req_attribute ;
2006-08-24 12:32:57 +04:00
enum {
ASQ_CTRL_SUCCESS = 0 ,
ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX = 21 ,
ASQ_CTRL_UNWILLING_TO_PERFORM = 53 ,
ASQ_CTRL_AFFECTS_MULTIPLE_DSA = 71
} asq_ret ;
2006-03-14 00:05:55 +03:00
2006-07-22 20:56:33 +04:00
struct ldb_reply * base_res ;
2006-03-14 00:05:55 +03:00
struct ldb_request * * reqs ;
2010-03-08 20:01:32 +03:00
unsigned int num_reqs ;
unsigned int cur_req ;
2006-03-14 00:05:55 +03:00
struct ldb_control * * controls ;
} ;
2008-09-12 02:35:38 +04:00
static struct asq_context * asq_context_init ( struct ldb_module * module , struct ldb_request * req )
2006-03-14 00:05:55 +03:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-07-22 20:56:33 +04:00
struct asq_context * ac ;
2006-03-14 00:05:55 +03:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2008-09-12 02:35:38 +04:00
ac = talloc_zero ( req , struct asq_context ) ;
2006-03-14 00:05:55 +03:00
if ( ac = = NULL ) {
2009-01-30 02:39:30 +03:00
ldb_oom ( ldb ) ;
2006-03-14 00:05:55 +03:00
return NULL ;
}
ac - > module = module ;
2008-09-12 02:35:38 +04:00
ac - > req = req ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
return ac ;
2006-03-14 00:05:55 +03:00
}
2008-09-12 02:35:38 +04:00
static int asq_search_continue ( struct asq_context * ac ) ;
static int asq_search_terminate ( struct asq_context * ac )
2006-03-14 00:05:55 +03:00
{
struct ldb_asq_control * asq ;
2010-03-08 20:01:32 +03:00
unsigned int i ;
2006-03-14 00:05:55 +03:00
if ( ac - > controls ) {
2008-09-12 02:35:38 +04:00
for ( i = 0 ; ac - > controls [ i ] ; i + + ) /* count em */ ;
2006-03-14 00:05:55 +03:00
} else {
i = 0 ;
}
2008-09-12 02:35:38 +04:00
ac - > controls = talloc_realloc ( ac , ac - > controls , struct ldb_control * , i + 2 ) ;
if ( ac - > controls = = NULL ) {
2006-03-14 00:05:55 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2008-09-12 02:35:38 +04:00
}
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
ac - > controls [ i ] = talloc ( ac - > controls , struct ldb_control ) ;
if ( ac - > controls [ i ] = = NULL ) {
2006-03-14 00:05:55 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2008-09-12 02:35:38 +04:00
}
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
ac - > controls [ i ] - > oid = LDB_CONTROL_ASQ_OID ;
ac - > controls [ i ] - > critical = 0 ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
asq = talloc_zero ( ac - > controls [ i ] , struct ldb_asq_control ) ;
2006-03-14 00:05:55 +03:00
if ( asq = = NULL )
return LDB_ERR_OPERATIONS_ERROR ;
asq - > result = ac - > asq_ret ;
2008-09-12 02:35:38 +04:00
ac - > controls [ i ] - > data = asq ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
ac - > controls [ i + 1 ] = NULL ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
return ldb_module_done ( ac - > req , ac - > controls , NULL , LDB_SUCCESS ) ;
2006-03-14 00:05:55 +03:00
}
2008-09-12 02:35:38 +04:00
static int asq_base_callback ( struct ldb_request * req , struct ldb_reply * ares )
2006-03-14 00:05:55 +03:00
{
2006-07-22 20:56:33 +04:00
struct asq_context * ac ;
2008-09-12 02:35:38 +04:00
int ret ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
ac = talloc_get_type ( req - > context , struct asq_context ) ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
if ( ! ares ) {
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
if ( ares - > error ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , ares - > controls ,
ares - > response , ares - > error ) ;
2006-11-25 22:28:09 +03:00
}
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
switch ( ares - > type ) {
case LDB_REPLY_ENTRY :
2006-09-13 06:33:51 +04:00
ac - > base_res = talloc_move ( ac , & ares ) ;
2008-09-12 02:35:38 +04:00
break ;
case LDB_REPLY_REFERRAL :
/* ignore referrals */
2006-03-14 00:05:55 +03:00
talloc_free ( ares ) ;
2008-09-12 02:35:38 +04:00
break ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
case LDB_REPLY_DONE :
talloc_free ( ares ) ;
/* next step */
ret = asq_search_continue ( ac ) ;
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
break ;
}
2006-03-14 00:05:55 +03:00
return LDB_SUCCESS ;
}
2008-09-12 02:35:38 +04:00
static int asq_reqs_callback ( struct ldb_request * req , struct ldb_reply * ares )
2006-03-14 00:05:55 +03:00
{
2006-07-22 20:56:33 +04:00
struct asq_context * ac ;
2008-09-12 02:35:38 +04:00
int ret ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
ac = talloc_get_type ( req - > context , struct asq_context ) ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
if ( ! ares ) {
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
if ( ares - > error ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , ares - > controls ,
ares - > response , ares - > error ) ;
2006-11-25 22:28:09 +03:00
}
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
switch ( ares - > type ) {
case LDB_REPLY_ENTRY :
2006-03-14 00:05:55 +03:00
/* pass the message up to the original callback as we
* do not have to elaborate on it any further */
2008-12-16 10:59:05 +03:00
ret = ldb_module_send_entry ( ac - > req , ares - > message , ares - > controls ) ;
2008-09-12 02:35:38 +04:00
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
talloc_free ( ares ) ;
break ;
case LDB_REPLY_REFERRAL :
/* ignore referrals */
talloc_free ( ares ) ;
break ;
case LDB_REPLY_DONE :
2006-03-14 00:05:55 +03:00
talloc_free ( ares ) ;
2008-09-12 02:35:38 +04:00
ret = asq_search_continue ( ac ) ;
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
break ;
2006-03-14 00:05:55 +03:00
}
return LDB_SUCCESS ;
}
2008-09-12 02:35:38 +04:00
static int asq_build_first_request ( struct asq_context * ac , struct ldb_request * * base_req )
2006-03-14 00:05:55 +03:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:35:38 +04:00
const char * * base_attrs ;
int ret ;
2006-05-29 05:30:02 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2008-09-12 02:35:38 +04:00
ac - > req_attrs = ac - > req - > op . search . attrs ;
ac - > req_attribute = talloc_strdup ( ac , ac - > asq_ctrl - > source_attribute ) ;
if ( ac - > req_attribute = = NULL )
return LDB_ERR_OPERATIONS_ERROR ;
2006-03-14 00:05:55 +03:00
2008-09-12 02:35:38 +04:00
base_attrs = talloc_array ( ac , const char * , 2 ) ;
2007-01-10 21:18:13 +03:00
if ( base_attrs = = NULL ) return LDB_ERR_OPERATIONS_ERROR ;
base_attrs [ 0 ] = talloc_strdup ( base_attrs , ac - > asq_ctrl - > source_attribute ) ;
if ( base_attrs [ 0 ] = = NULL ) return LDB_ERR_OPERATIONS_ERROR ;
2006-03-14 00:05:55 +03:00
base_attrs [ 1 ] = NULL ;
2009-01-30 02:39:30 +03:00
ret = ldb_build_search_req ( base_req , ldb , ac ,
2008-09-12 02:35:38 +04:00
ac - > req - > op . search . base ,
LDB_SCOPE_BASE ,
2008-10-14 20:25:18 +04:00
NULL ,
2008-09-12 02:35:38 +04:00
( const char * const * ) base_attrs ,
NULL ,
ac , asq_base_callback ,
ac - > req ) ;
if ( ret ! = LDB_SUCCESS ) {
2009-10-06 21:27:17 +04:00
return ret ;
2008-09-12 02:35:38 +04:00
}
2006-03-14 00:05:55 +03:00
return LDB_SUCCESS ;
}
2008-09-12 02:35:38 +04:00
static int asq_build_multiple_requests ( struct asq_context * ac , bool * terminated )
2007-01-10 21:18:13 +03:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:35:38 +04:00
struct ldb_control * * saved_controls ;
struct ldb_control * control ;
struct ldb_dn * dn ;
2006-03-14 00:05:55 +03:00
struct ldb_message_element * el ;
2010-03-08 20:01:32 +03:00
unsigned int i ;
int ret ;
2006-03-14 00:05:55 +03:00
2006-09-10 07:11:03 +04:00
if ( ac - > base_res = = NULL ) {
return LDB_ERR_NO_SUCH_OBJECT ;
}
2008-09-12 02:35:38 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2006-03-14 00:05:55 +03:00
el = ldb_msg_find_element ( ac - > base_res - > message , ac - > req_attribute ) ;
/* no values found */
if ( el = = NULL ) {
ac - > asq_ret = ASQ_CTRL_SUCCESS ;
2008-09-12 02:35:38 +04:00
* terminated = true ;
return asq_search_terminate ( ac ) ;
2006-03-14 00:05:55 +03:00
}
ac - > num_reqs = el - > num_values ;
ac - > cur_req = 0 ;
ac - > reqs = talloc_array ( ac , struct ldb_request * , ac - > num_reqs ) ;
if ( ac - > reqs = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
for ( i = 0 ; i < el - > num_values ; i + + ) {
2009-01-30 02:39:30 +03:00
dn = ldb_dn_new ( ac , ldb ,
2008-09-12 02:35:38 +04:00
( const char * ) el - > values [ i ] . data ) ;
if ( ! ldb_dn_validate ( dn ) ) {
2006-03-14 00:05:55 +03:00
ac - > asq_ret = ASQ_CTRL_INVALID_ATTRIBUTE_SYNTAX ;
2008-09-12 02:35:38 +04:00
* terminated = true ;
return asq_search_terminate ( ac ) ;
}
ret = ldb_build_search_req_ex ( & ac - > reqs [ i ] ,
2009-01-30 02:39:30 +03:00
ldb , ac ,
2008-09-12 02:35:38 +04:00
dn , LDB_SCOPE_BASE ,
ac - > req - > op . search . tree ,
ac - > req_attrs ,
ac - > req - > controls ,
ac , asq_reqs_callback ,
ac - > req ) ;
if ( ret ! = LDB_SUCCESS ) {
2009-10-06 21:27:17 +04:00
return ret ;
2006-03-14 00:05:55 +03:00
}
2008-09-12 02:35:38 +04:00
/* remove the ASQ control itself */
control = ldb_request_get_control ( ac - > req , LDB_CONTROL_ASQ_OID ) ;
2010-12-18 01:00:46 +03:00
if ( ! ldb_save_controls ( control , ac - > reqs [ i ] , & saved_controls ) ) {
2008-09-12 02:35:38 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-03-14 00:05:55 +03:00
}
return LDB_SUCCESS ;
}
2008-09-12 02:35:38 +04:00
static int asq_search_continue ( struct asq_context * ac )
2007-01-10 21:18:13 +03:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:35:38 +04:00
bool terminated = false ;
2007-01-10 21:18:13 +03:00
int ret ;
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2007-01-10 21:18:13 +03:00
switch ( ac - > step ) {
case ASQ_SEARCH_BASE :
2008-09-12 02:35:38 +04:00
/* build up the requests call chain */
ret = asq_build_multiple_requests ( ac , & terminated ) ;
if ( ret ! = LDB_SUCCESS | | terminated ) {
return ret ;
2007-01-11 01:22:28 +03:00
}
2008-09-12 02:35:38 +04:00
ac - > step = ASQ_SEARCH_MULTI ;
2007-01-11 01:31:42 +03:00
2009-01-30 02:39:30 +03:00
return ldb_request ( ldb , ac - > reqs [ ac - > cur_req ] ) ;
2007-01-10 21:18:13 +03:00
case ASQ_SEARCH_MULTI :
2008-09-12 02:35:38 +04:00
ac - > cur_req + + ;
2007-01-11 01:22:28 +03:00
2008-09-12 02:35:38 +04:00
if ( ac - > cur_req = = ac - > num_reqs ) {
/* done */
return asq_search_terminate ( ac ) ;
2007-01-11 01:22:28 +03:00
}
2007-01-10 21:18:13 +03:00
2009-01-30 02:39:30 +03:00
return ldb_request ( ldb , ac - > reqs [ ac - > cur_req ] ) ;
2007-01-10 21:18:13 +03:00
}
2008-09-12 02:35:38 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
2007-01-10 21:18:13 +03:00
}
static int asq_search ( struct ldb_module * module , struct ldb_request * req )
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:35:38 +04:00
struct ldb_request * base_req ;
2007-01-10 21:18:13 +03:00
struct ldb_control * control ;
struct asq_context * ac ;
2008-09-12 02:35:38 +04:00
int ret ;
2007-01-10 21:18:13 +03:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2009-05-27 00:22:13 +04:00
/* check if there's an ASQ control */
2007-02-22 04:54:40 +03:00
control = ldb_request_get_control ( req , LDB_CONTROL_ASQ_OID ) ;
2007-01-10 21:18:13 +03:00
if ( control = = NULL ) {
/* not found go on */
return ldb_next_request ( module , req ) ;
}
2008-09-12 02:35:38 +04:00
ac = asq_context_init ( module , req ) ;
if ( ! ac ) {
2007-01-10 21:18:13 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2008-09-12 02:35:38 +04:00
/* check the search is well formed */
if ( req - > op . search . scope ! = LDB_SCOPE_BASE ) {
ac - > asq_ret = ASQ_CTRL_UNWILLING_TO_PERFORM ;
return asq_search_terminate ( ac ) ;
2007-01-10 21:18:13 +03:00
}
ac - > asq_ctrl = talloc_get_type ( control - > data , struct ldb_asq_control ) ;
if ( ! ac - > asq_ctrl ) {
return LDB_ERR_PROTOCOL_ERROR ;
}
2008-09-12 02:35:38 +04:00
ret = asq_build_first_request ( ac , & base_req ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
2006-05-28 19:20:53 +04:00
}
2008-09-12 02:35:38 +04:00
ac - > step = ASQ_SEARCH_BASE ;
2007-12-24 10:38:37 +03:00
2009-01-30 02:39:30 +03:00
return ldb_request ( ldb , base_req ) ;
2006-05-28 19:20:53 +04:00
}
2006-03-02 19:32:53 +03:00
static int asq_init ( struct ldb_module * module )
2006-02-05 23:48:27 +03:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-02-05 23:48:27 +03:00
int ret ;
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2008-09-12 02:35:38 +04:00
ret = ldb_mod_register_control ( module , LDB_CONTROL_ASQ_OID ) ;
2006-02-05 23:48:27 +03:00
if ( ret ! = LDB_SUCCESS ) {
2009-07-11 00:44:27 +04:00
ldb_debug ( ldb , LDB_DEBUG_WARNING , " asq: Unable to register control with rootdse! " ) ;
2006-02-05 23:48:27 +03:00
}
2006-03-02 19:32:53 +03:00
return ldb_next_init ( module ) ;
2006-02-05 23:48:27 +03:00
}
2010-11-01 06:59:28 +03:00
static const struct ldb_module_ops ldb_asq_module_ops = {
2006-01-15 09:12:29 +03:00
. name = " asq " ,
2006-05-29 05:30:02 +04:00
. search = asq_search ,
2006-03-02 19:32:53 +03:00
. init_context = asq_init
2006-01-15 09:12:29 +03:00
} ;
2010-11-01 06:59:28 +03:00
2010-11-01 14:30:23 +03:00
int ldb_asq_init ( const char * version )
2010-11-01 06:59:28 +03:00
{
2010-11-01 14:30:23 +03:00
LDB_MODULE_CHECK_VERSION ( version ) ;
2010-11-01 06:59:28 +03:00
return ldb_register_module ( & ldb_asq_module_ops ) ;
}