2006-08-13 23:58:04 +00:00
/*
ldb database mapping module
Copyright ( C ) Jelmer Vernooij 2005
Copyright ( C ) Martin Kuehl < mkhl @ samba . org > 2006
2008-09-11 18:35:38 -04:00
Copyright ( C ) Simo Sorce < idra @ samba . org > 2008
2006-08-13 23:58:04 +00:00
2007-05-08 21:17:58 +00:00
* * NOTE ! The following LGPL license applies to the ldb
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
2006-08-13 23:58:04 +00:00
2007-05-08 21:17:58 +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 .
2007-05-08 21:17:58 +00:00
This library is distributed in the hope that it will be useful ,
2006-08-13 23:58:04 +00:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2007-05-08 21:17:58 +00:00
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/>.
2007-05-08 21:17:58 +00:00
2006-08-13 23:58:04 +00:00
*/
2007-05-05 18:50:56 +00:00
# include "ldb_includes.h"
2006-08-13 23:58:04 +00:00
2007-05-05 18:50:56 +00:00
# include "ldb_map.h"
# include "ldb_map_private.h"
2006-08-13 23:58:04 +00:00
/* Mapping message elements
* = = = = = = = = = = = = = = = = = = = = = = = = */
/* Map a message element into the remote partition. */
static struct ldb_message_element * ldb_msg_el_map_local ( struct ldb_module * module , void * mem_ctx , const struct ldb_map_attribute * map , const struct ldb_message_element * old )
{
struct ldb_message_element * el ;
int i ;
el = talloc_zero ( mem_ctx , struct ldb_message_element ) ;
if ( el = = NULL ) {
map_oom ( module ) ;
return NULL ;
}
el - > num_values = old - > num_values ;
el - > values = talloc_array ( el , struct ldb_val , el - > num_values ) ;
if ( el - > values = = NULL ) {
talloc_free ( el ) ;
map_oom ( module ) ;
return NULL ;
}
el - > name = map_attr_map_local ( el , map , old - > name ) ;
for ( i = 0 ; i < el - > num_values ; i + + ) {
2006-11-01 23:31:26 +00:00
el - > values [ i ] = ldb_val_map_local ( module , el - > values , map , & old - > values [ i ] ) ;
2006-08-13 23:58:04 +00:00
}
return el ;
}
/* Add a message element either to a local or to a remote message,
* depending on whether it goes into the local or remote partition . */
static int ldb_msg_el_partition ( struct ldb_module * module , struct ldb_message * local , struct ldb_message * remote , const struct ldb_message * msg , const char * attr_name , /* const char * const names[], */ const struct ldb_message_element * old )
{
const struct ldb_map_context * data = map_get_context ( module ) ;
const struct ldb_map_attribute * map = map_attr_find_local ( data , attr_name ) ;
2006-09-10 10:00:42 +00:00
struct ldb_message_element * el = NULL ;
2006-08-13 23:58:04 +00:00
/* Unknown attribute: ignore */
if ( map = = NULL ) {
ldb_debug ( module - > ldb , LDB_DEBUG_WARNING , " ldb_map: "
" Not mapping attribute '%s': no mapping found \n " ,
old - > name ) ;
goto local ;
}
switch ( map - > type ) {
case MAP_IGNORE :
goto local ;
case MAP_CONVERT :
if ( map - > u . convert . convert_local = = NULL ) {
ldb_debug ( module - > ldb , LDB_DEBUG_WARNING , " ldb_map: "
" Not mapping attribute '%s': "
" 'convert_local' not set \n " ,
map - > local_name ) ;
goto local ;
}
/* fall through */
case MAP_KEEP :
case MAP_RENAME :
el = ldb_msg_el_map_local ( module , remote , map , old ) ;
break ;
case MAP_GENERATE :
if ( map - > u . generate . generate_remote = = NULL ) {
ldb_debug ( module - > ldb , LDB_DEBUG_WARNING , " ldb_map: "
" Not mapping attribute '%s': "
" 'generate_remote' not set \n " ,
map - > local_name ) ;
goto local ;
}
/* TODO: if this attr requires context:
* make sure all context attrs are mappable ( in ' names ' )
* make sure all context attrs have already been mapped ?
* maybe postpone generation until they have been mapped ?
*/
map - > u . generate . generate_remote ( module , map - > local_name , msg , remote , local ) ;
return 0 ;
}
if ( el = = NULL ) {
return - 1 ;
}
return ldb_msg_add ( remote , el , old - > flags ) ;
local :
el = talloc ( local , struct ldb_message_element ) ;
if ( el = = NULL ) {
map_oom ( module ) ;
return - 1 ;
}
* el = * old ; /* copy the old element */
return ldb_msg_add ( local , el , old - > flags ) ;
}
/* Mapping messages
* = = = = = = = = = = = = = = = = */
/* Check whether a message will be (partially) mapped into the remote partition. */
2007-05-05 18:50:56 +00:00
static bool ldb_msg_check_remote ( struct ldb_module * module , const struct ldb_message * msg )
2006-08-13 23:58:04 +00:00
{
const struct ldb_map_context * data = map_get_context ( module ) ;
2007-05-05 18:50:56 +00:00
bool ret ;
2006-08-13 23:58:04 +00:00
int i ;
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
ret = map_attr_check_remote ( data , msg - > elements [ i ] . name ) ;
if ( ret ) {
return ret ;
}
}
2007-05-05 18:50:56 +00:00
return false ;
2006-08-13 23:58:04 +00:00
}
/* Split message elements that stay in the local partition from those
* that are mapped into the remote partition . */
static int ldb_msg_partition ( struct ldb_module * module , struct ldb_message * local , struct ldb_message * remote , const struct ldb_message * msg )
{
/* const char * const names[]; */
int i , ret ;
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
/* Skip 'IS_MAPPED' */
if ( ldb_attr_cmp ( msg - > elements [ i ] . name , IS_MAPPED ) = = 0 ) {
ldb_debug ( module - > ldb , LDB_DEBUG_WARNING , " ldb_map: "
" Skipping attribute '%s' \n " ,
msg - > elements [ i ] . name ) ;
continue ;
}
ret = ldb_msg_el_partition ( module , local , remote , msg , msg - > elements [ i ] . name , & msg - > elements [ i ] ) ;
if ( ret ) {
return ret ;
}
}
return 0 ;
}
2008-09-11 18:35:38 -04:00
static int map_add_do_local ( struct map_context * ac ) ;
static int map_modify_do_local ( struct map_context * ac ) ;
static int map_delete_do_local ( struct map_context * ac ) ;
static int map_rename_do_local ( struct map_context * ac ) ;
static int map_rename_do_fixup ( struct map_context * ac ) ;
static int map_rename_local_callback ( struct ldb_request * req ,
struct ldb_reply * ares ) ;
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/*****************************************************************************
* COMMON INBOUND functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Store the DN of a single search result in context. */
static int map_search_self_callback ( struct ldb_request * req , struct ldb_reply * ares )
2006-08-13 23:58:04 +00:00
{
struct map_context * ac ;
2008-09-11 18:35:38 -04:00
int ret ;
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
ac = talloc_get_type ( req - > context , struct map_context ) ;
2006-08-13 23:58:04 +00:00
2008-09-11 18: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-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/* We are interested only in the single reply */
switch ( ares - > type ) {
case LDB_REPLY_ENTRY :
/* We have already found a remote DN */
if ( ac - > local_dn ) {
ldb_set_errstring ( ac - > module - > ldb ,
" Too many results! " ) ;
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/* Store local DN */
ac - > local_dn = talloc_steal ( ac , ares - > message - > dn ) ;
break ;
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
case LDB_REPLY_DONE :
switch ( ac - > req - > operation ) {
case LDB_MODIFY :
ret = map_modify_do_local ( ac ) ;
break ;
case LDB_DELETE :
ret = map_delete_do_local ( ac ) ;
break ;
case LDB_RENAME :
ret = map_rename_do_local ( ac ) ;
break ;
default :
/* if we get here we have definitely a problem */
ret = LDB_ERR_OPERATIONS_ERROR ;
}
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
default :
/* ignore referrals */
break ;
}
talloc_free ( ares ) ;
return LDB_SUCCESS ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/* Build a request to search the local record by its DN. */
static int map_search_self_req ( struct ldb_request * * req ,
struct map_context * ac ,
struct ldb_dn * dn )
{
/* attrs[] is returned from this function in
* ac - > search_req - > op . search . attrs , so it must be static , as
* otherwise the compiler can put it on the stack */
static const char * const attrs [ ] = { IS_MAPPED , NULL } ;
struct ldb_parse_tree * tree ;
/* Limit search to records with 'IS_MAPPED' present */
tree = ldb_parse_tree ( ac , " ( " IS_MAPPED " =*) " ) ;
if ( tree = = NULL ) {
map_oom ( ac - > module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
* req = map_search_base_req ( ac , dn , attrs , tree ,
ac , map_search_self_callback ) ;
if ( * req = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
return LDB_SUCCESS ;
}
static int map_op_local_callback ( struct ldb_request * req ,
struct ldb_reply * ares )
2006-08-13 23:58:04 +00:00
{
struct map_context * ac ;
2008-09-11 18:35:38 -04:00
int ret ;
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
ac = talloc_get_type ( req - > context , struct map_context ) ;
2006-08-13 23:58:04 +00:00
2008-09-11 18: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-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
if ( ares - > type ! = LDB_REPLY_DONE ) {
ldb_set_errstring ( req - > handle - > ldb , " Invalid reply type! " ) ;
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/* Do the remote request. */
ret = ldb_next_remote_request ( ac - > module , ac - > remote_req ) ;
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
return LDB_SUCCESS ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
static int map_op_remote_callback ( struct ldb_request * req ,
struct ldb_reply * ares )
{
struct map_context * ac ;
ac = talloc_get_type ( req - > context , struct map_context ) ;
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 ) ;
}
if ( ares - > type ! = LDB_REPLY_DONE ) {
ldb_set_errstring ( req - > handle - > ldb , " Invalid reply type! " ) ;
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
return ldb_module_done ( ac - > req , ares - > controls ,
ares - > response , ares - > error ) ;
}
/*****************************************************************************
* ADD operations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-08-13 23:58:04 +00:00
/* Add a record. */
int map_add ( struct ldb_module * module , struct ldb_request * req )
{
const struct ldb_message * msg = req - > op . add . message ;
struct map_context * ac ;
2008-09-11 18:35:38 -04:00
struct ldb_message * remote_msg ;
2006-08-13 23:58:04 +00:00
const char * dn ;
2008-09-11 18:35:38 -04:00
int ret ;
2006-08-13 23:58:04 +00:00
/* Do not manipulate our control entries */
if ( ldb_dn_is_special ( msg - > dn ) ) {
return ldb_next_request ( module , req ) ;
}
/* No mapping requested (perhaps no DN mapping specified), skip to next module */
if ( ! ldb_dn_check_local ( module , msg - > dn ) ) {
return ldb_next_request ( module , req ) ;
}
/* No mapping needed, fail */
if ( ! ldb_msg_check_remote ( module , msg ) ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
/* Prepare context and handle */
2008-09-11 18:35:38 -04:00
ac = map_init_context ( module , req ) ;
if ( ac = = NULL ) {
2006-08-13 23:58:04 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
}
/* Prepare the local message */
2008-09-11 18:35:38 -04:00
ac - > local_msg = ldb_msg_new ( ac ) ;
if ( ac - > local_msg = = NULL ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
ac - > local_msg - > dn = msg - > dn ;
2006-08-13 23:58:04 +00:00
/* Prepare the remote message */
2008-09-11 18:35:38 -04:00
remote_msg = ldb_msg_new ( ac ) ;
if ( remote_msg = = NULL ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
remote_msg - > dn = ldb_dn_map_local ( ac - > module , remote_msg , msg - > dn ) ;
2006-08-13 23:58:04 +00:00
/* Split local from remote message */
2008-09-11 18:35:38 -04:00
ldb_msg_partition ( module , ac - > local_msg , remote_msg , msg ) ;
/* Prepare the remote operation */
ret = ldb_build_add_req ( & ac - > remote_req , module - > ldb ,
ac , remote_msg ,
req - > controls ,
ac , map_op_remote_callback ,
req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
if ( ( ac - > local_msg - > num_elements = = 0 ) | |
( ! map_check_local_db ( ac - > module ) ) ) {
2006-08-13 23:58:04 +00:00
/* No local data or db, just run the remote request */
2008-09-11 18:35:38 -04:00
return ldb_next_remote_request ( ac - > module , ac - > remote_req ) ;
2006-08-13 23:58:04 +00:00
}
/* Store remote DN in 'IS_MAPPED' */
/* TODO: use GUIDs here instead */
2008-09-11 18:35:38 -04:00
dn = ldb_dn_alloc_linearized ( ac - > local_msg , remote_msg - > dn ) ;
if ( ldb_msg_add_string ( ac - > local_msg , IS_MAPPED , dn ) ! = 0 ) {
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
return map_add_do_local ( ac ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/* Add the local record. */
static int map_add_do_local ( struct map_context * ac )
2006-08-13 23:58:04 +00:00
{
2008-09-11 18:35:38 -04:00
struct ldb_request * local_req ;
int ret ;
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/* Prepare the local operation */
ret = ldb_build_add_req ( & local_req , ac - > module - > ldb , ac ,
ac - > local_msg ,
ac - > req - > controls ,
ac ,
map_op_local_callback ,
ac - > req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
return ldb_next_request ( ac - > module , local_req ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/*****************************************************************************
* MODIFY operations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-08-13 23:58:04 +00:00
/* Modify a record. */
int map_modify ( struct ldb_module * module , struct ldb_request * req )
{
const struct ldb_message * msg = req - > op . mod . message ;
2008-09-11 18:35:38 -04:00
struct ldb_request * search_req ;
struct ldb_message * remote_msg ;
2006-08-13 23:58:04 +00:00
struct map_context * ac ;
2008-09-11 18:35:38 -04:00
int ret ;
2006-08-13 23:58:04 +00:00
/* Do not manipulate our control entries */
if ( ldb_dn_is_special ( msg - > dn ) ) {
return ldb_next_request ( module , req ) ;
}
/* No mapping requested (perhaps no DN mapping specified), skip to next module */
if ( ! ldb_dn_check_local ( module , msg - > dn ) ) {
return ldb_next_request ( module , req ) ;
}
/* No mapping needed, skip to next module */
/* TODO: What if the remote part exists, the local doesn't,
* and this request wants to modify local data and thus
* add the local record ? */
if ( ! ldb_msg_check_remote ( module , msg ) ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
/* Prepare context and handle */
2008-09-11 18:35:38 -04:00
ac = map_init_context ( module , req ) ;
if ( ac = = NULL ) {
2006-08-13 23:58:04 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
}
/* Prepare the local message */
2008-09-11 18:35:38 -04:00
ac - > local_msg = ldb_msg_new ( ac ) ;
if ( ac - > local_msg = = NULL ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
ac - > local_msg - > dn = msg - > dn ;
2006-08-13 23:58:04 +00:00
/* Prepare the remote message */
2008-09-11 18:35:38 -04:00
remote_msg = ldb_msg_new ( ac - > remote_req ) ;
if ( remote_msg = = NULL ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
remote_msg - > dn = ldb_dn_map_local ( ac - > module , remote_msg , msg - > dn ) ;
2006-08-13 23:58:04 +00:00
/* Split local from remote message */
2008-09-11 18:35:38 -04:00
ldb_msg_partition ( module , ac - > local_msg , remote_msg , msg ) ;
/* Prepare the remote operation */
ret = ldb_build_mod_req ( & ac - > remote_req , module - > ldb ,
ac , remote_msg ,
req - > controls ,
ac , map_op_remote_callback ,
req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
if ( ( ac - > local_msg - > num_elements = = 0 ) | |
( ! map_check_local_db ( ac - > module ) ) ) {
2006-08-13 23:58:04 +00:00
/* No local data or db, just run the remote request */
2008-09-11 18:35:38 -04:00
return ldb_next_remote_request ( ac - > module , ac - > remote_req ) ;
2006-08-13 23:58:04 +00:00
}
/* prepare the search operation */
2008-09-11 18:35:38 -04:00
ret = map_search_self_req ( & search_req , ac , msg - > dn ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
return ldb_next_request ( module , search_req ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/* Modify the local record. */
static int map_modify_do_local ( struct map_context * ac )
2006-08-13 23:58:04 +00:00
{
2008-09-11 18:35:38 -04:00
struct ldb_request * local_req ;
char * dn ;
int ret ;
2006-08-13 23:58:04 +00:00
if ( ac - > local_dn = = NULL ) {
2008-09-11 18:35:38 -04:00
/* No local record present, add it instead */
/* Add local 'IS_MAPPED' */
/* TODO: use GUIDs here instead */
if ( ldb_msg_add_empty ( ac - > local_msg , IS_MAPPED ,
LDB_FLAG_MOD_ADD , NULL ) ! = 0 ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
dn = ldb_dn_alloc_linearized ( ac - > local_msg ,
ac - > remote_req - > op . mod . message - > dn ) ;
if ( ldb_msg_add_string ( ac - > local_msg , IS_MAPPED , dn ) ! = 0 ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/* Prepare the local operation */
ret = ldb_build_add_req ( & local_req , ac - > module - > ldb , ac ,
ac - > local_msg ,
ac - > req - > controls ,
ac ,
map_op_local_callback ,
ac - > req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
} else {
/* Prepare the local operation */
ret = ldb_build_mod_req ( & local_req , ac - > module - > ldb , ac ,
ac - > local_msg ,
ac - > req - > controls ,
ac ,
map_op_local_callback ,
ac - > req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
return ldb_next_request ( ac - > module , local_req ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/*****************************************************************************
* DELETE operations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-08-13 23:58:04 +00:00
/* Delete a record. */
int map_delete ( struct ldb_module * module , struct ldb_request * req )
{
2008-09-11 18:35:38 -04:00
struct ldb_request * search_req ;
2006-08-13 23:58:04 +00:00
struct map_context * ac ;
2008-09-11 18:35:38 -04:00
int ret ;
2006-08-13 23:58:04 +00:00
/* Do not manipulate our control entries */
if ( ldb_dn_is_special ( req - > op . del . dn ) ) {
return ldb_next_request ( module , req ) ;
}
2008-09-11 18:35:38 -04:00
/* No mapping requested (perhaps no DN mapping specified).
* Skip to next module */
2006-08-13 23:58:04 +00:00
if ( ! ldb_dn_check_local ( module , req - > op . del . dn ) ) {
return ldb_next_request ( module , req ) ;
}
/* Prepare context and handle */
2008-09-11 18:35:38 -04:00
ac = map_init_context ( module , req ) ;
if ( ac = = NULL ) {
2006-08-13 23:58:04 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
}
/* Prepare the remote operation */
2008-09-11 18:35:38 -04:00
ret = ldb_build_del_req ( & ac - > remote_req , module - > ldb , ac ,
ldb_dn_map_local ( module , ac , req - > op . del . dn ) ,
req - > controls ,
ac ,
map_op_remote_callback ,
req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
/* No local db, just run the remote request */
if ( ! map_check_local_db ( ac - > module ) ) {
2008-09-11 18:35:38 -04:00
/* Do the remote request. */
return ldb_next_remote_request ( ac - > module , ac - > remote_req ) ;
2006-08-13 23:58:04 +00:00
}
/* Prepare the search operation */
2008-09-11 18:35:38 -04:00
ret = map_search_self_req ( & search_req , ac , req - > op . del . dn ) ;
if ( ret ! = LDB_SUCCESS ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
return ldb_next_request ( module , search_req ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/* Delete the local record. */
static int map_delete_do_local ( struct map_context * ac )
2006-08-13 23:58:04 +00:00
{
2008-09-11 18:35:38 -04:00
struct ldb_request * local_req ;
int ret ;
2006-08-13 23:58:04 +00:00
/* No local record, continue remotely */
if ( ac - > local_dn = = NULL ) {
2008-09-11 18:35:38 -04:00
/* Do the remote request. */
return ldb_next_remote_request ( ac - > module , ac - > remote_req ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/* Prepare the local operation */
ret = ldb_build_del_req ( & local_req , ac - > module - > ldb , ac ,
ac - > req - > op . del . dn ,
ac - > req - > controls ,
ac ,
map_op_local_callback ,
ac - > req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
return ldb_next_request ( ac - > module , local_req ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/*****************************************************************************
* RENAME operations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-08-13 23:58:04 +00:00
/* Rename a record. */
int map_rename ( struct ldb_module * module , struct ldb_request * req )
{
2008-09-11 18:35:38 -04:00
struct ldb_request * search_req ;
2006-08-13 23:58:04 +00:00
struct map_context * ac ;
2008-09-11 18:35:38 -04:00
int ret ;
2006-08-13 23:58:04 +00:00
/* Do not manipulate our control entries */
if ( ldb_dn_is_special ( req - > op . rename . olddn ) ) {
return ldb_next_request ( module , req ) ;
}
2008-09-11 18:35:38 -04:00
/* No mapping requested (perhaps no DN mapping specified).
* Skip to next module */
2006-08-13 23:58:04 +00:00
if ( ( ! ldb_dn_check_local ( module , req - > op . rename . olddn ) ) & &
( ! ldb_dn_check_local ( module , req - > op . rename . newdn ) ) ) {
return ldb_next_request ( module , req ) ;
}
/* Rename into/out of the mapped partition requested, bail out */
if ( ! ldb_dn_check_local ( module , req - > op . rename . olddn ) | |
! ldb_dn_check_local ( module , req - > op . rename . newdn ) ) {
return LDB_ERR_AFFECTS_MULTIPLE_DSAS ;
}
/* Prepare context and handle */
2008-09-11 18:35:38 -04:00
ac = map_init_context ( module , req ) ;
if ( ac = = NULL ) {
2006-08-13 23:58:04 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2008-09-11 18:35:38 -04:00
/* Prepare the remote operation */
ret = ldb_build_rename_req ( & ac - > remote_req , module - > ldb , ac ,
ldb_dn_map_local ( module , ac , req - > op . rename . olddn ) ,
ldb_dn_map_local ( module , ac , req - > op . rename . newdn ) ,
req - > controls ,
ac , map_op_remote_callback ,
req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/* No local db, just run the remote request */
if ( ! map_check_local_db ( ac - > module ) ) {
/* Do the remote request. */
return ldb_next_remote_request ( ac - > module , ac - > remote_req ) ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/* Prepare the search operation */
ret = map_search_self_req ( & search_req , ac , req - > op . rename . olddn ) ;
if ( ret ! = LDB_SUCCESS ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
return ldb_next_request ( module , search_req ) ;
}
/* Rename the local record. */
static int map_rename_do_local ( struct map_context * ac )
{
struct ldb_request * local_req ;
int ret ;
/* No local record, continue remotely */
if ( ac - > local_dn = = NULL ) {
/* Do the remote request. */
return ldb_next_remote_request ( ac - > module , ac - > remote_req ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/* Prepare the local operation */
ret = ldb_build_rename_req ( & local_req , ac - > module - > ldb , ac ,
ac - > req - > op . rename . olddn ,
ac - > req - > op . rename . newdn ,
ac - > req - > controls ,
ac ,
map_rename_local_callback ,
ac - > req ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
return ldb_next_request ( ac - > module , local_req ) ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
static int map_rename_local_callback ( struct ldb_request * req ,
struct ldb_reply * ares )
{
struct map_context * ac ;
int ret ;
ac = talloc_get_type ( req - > context , struct map_context ) ;
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-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
if ( ares - > type ! = LDB_REPLY_DONE ) {
ldb_set_errstring ( req - > handle - > ldb , " Invalid reply type! " ) ;
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
/* proceed with next step */
ret = map_rename_do_fixup ( ac ) ;
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
2006-08-13 23:58:04 +00:00
}
2008-09-11 18:35:38 -04:00
return LDB_SUCCESS ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/* Update the local 'IS_MAPPED' attribute. */
static int map_rename_do_fixup ( struct map_context * ac )
{
struct ldb_request * local_req ;
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
/* Prepare the fixup operation */
/* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
local_req = map_build_fixup_req ( ac ,
ac - > req - > op . rename . newdn ,
ac - > remote_req - > op . rename . newdn ,
ac ,
map_op_local_callback ) ;
if ( local_req = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-13 23:58:04 +00:00
2008-09-11 18:35:38 -04:00
return ldb_next_request ( ac - > module , local_req ) ;
2006-08-13 23:58:04 +00:00
}