2006-08-14 03:58:04 +04:00
/*
ldb database mapping module
2005-08-25 02:06:26 +04:00
Copyright ( C ) Jelmer Vernooij 2005
2006-08-14 03:58:04 +04:00
Copyright ( C ) Martin Kuehl < mkhl @ samba . org > 2006
2008-09-12 02:35:38 +04:00
Copyright ( C ) Simo Sorce 2008
2005-08-25 02:06:26 +04:00
2007-05-09 01:17:58 +04: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-14 03:58:04 +04:00
2007-05-09 01:17:58 +04: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 06:46:15 +04:00
version 3 of the License , or ( at your option ) any later version .
2007-05-09 01:17:58 +04:00
This library is distributed in the hope that it will be useful ,
2005-08-25 02:06:26 +04:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2007-05-09 01:17:58 +04: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 07:42:26 +04:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2007-05-09 01:17:58 +04:00
2005-08-25 02:06:26 +04:00
*/
2006-08-14 03:58:04 +04:00
/*
* Name : ldb
*
* Component : ldb ldb_map module
*
* Description : Map portions of data into a different format on a
* remote partition .
*
* Author : Jelmer Vernooij , Martin Kuehl
*/
2010-11-01 15:36:42 +03:00
# include "replace.h"
# include "system/filesys.h"
# include "system/time.h"
2007-05-05 22:50:56 +04:00
# include "ldb_map.h"
# include "ldb_map_private.h"
# ifndef _PUBLIC_
# define _PUBLIC_
# endif
2005-08-25 02:06:26 +04:00
2006-08-14 03:58:04 +04:00
/* Description of the provided ldb requests:
2005-08-29 19:54:10 +04:00
- special attribute ' isMapped '
2006-08-14 03:58:04 +04:00
- search :
- if parse tree can be split
- search remote records w / remote attrs and parse tree
- otherwise
- enumerate all remote records
- for each remote result
- map remote result to local message
- search local result
- is present
- merge local into remote result
- run callback on merged result
- otherwise
- run callback on remote result
- add :
- split message into local and remote part
- if local message is not empty
- add isMapped to local message
- add local message
- add remote message
- modify :
- split message into local and remote part
- if local message is not empty
- add isMapped to local message
- search for local record
- if present
- modify local record
- otherwise
- add local message
- modify remote record
- delete :
- search for local record
- if present
- delete local record
- delete remote record
- rename :
- search for local record
- if present
- rename local record
- modify local isMapped
- rename remote record
*/
2005-08-28 03:47:17 +04:00
2005-09-01 19:33:31 +04:00
2006-08-14 03:58:04 +04:00
/* Private data structures
* = = = = = = = = = = = = = = = = = = = = = = = */
2005-08-25 02:06:26 +04:00
2006-08-14 03:58:04 +04:00
/* Global private data */
/* Extract mappings from private data. */
const struct ldb_map_context * map_get_context ( struct ldb_module * module )
2005-08-29 19:54:10 +04:00
{
2009-01-30 02:39:30 +03:00
const struct map_private * data = talloc_get_type ( ldb_module_get_private ( module ) , struct map_private ) ;
2006-08-22 10:01:47 +04:00
return data - > context ;
2005-08-29 19:54:10 +04:00
}
2006-08-14 03:58:04 +04:00
/* Create a generic request context. */
2008-09-12 02:35:38 +04:00
struct map_context * map_init_context ( struct ldb_module * module ,
struct ldb_request * req )
2005-08-29 19:54:10 +04:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct map_context * ac ;
2005-08-29 21:31:19 +04: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 map_context ) ;
2006-08-14 03:58:04 +04:00
if ( ac = = NULL ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( ldb , " Out of Memory " ) ;
2006-08-14 03:58:04 +04:00
return NULL ;
2005-08-29 21:31:19 +04:00
}
2008-09-12 02:35:38 +04:00
ac - > module = module ;
ac - > req = req ;
2005-09-01 19:33:31 +04:00
2006-08-14 03:58:04 +04:00
return ac ;
}
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
/* Dealing with DNs for different partitions
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2005-09-01 19:33:31 +04:00
2006-08-14 03:58:04 +04:00
/* Check whether any data should be stored in the local partition. */
2007-05-05 22:50:56 +04:00
bool map_check_local_db ( struct ldb_module * module )
2005-08-25 02:06:26 +04:00
{
2006-08-14 03:58:04 +04:00
const struct ldb_map_context * data = map_get_context ( module ) ;
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
if ( ! data - > remote_base_dn | | ! data - > local_base_dn ) {
2007-05-05 22:50:56 +04:00
return false ;
2006-08-14 03:58:04 +04:00
}
2005-08-28 03:47:17 +04:00
2007-05-05 22:50:56 +04:00
return true ;
2006-08-14 03:58:04 +04:00
}
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
/* Copy a DN with the base DN of the local partition. */
2006-11-22 03:59:34 +03:00
static struct ldb_dn * ldb_dn_rebase_local ( void * mem_ctx , const struct ldb_map_context * data , struct ldb_dn * dn )
2006-08-14 03:58:04 +04:00
{
2006-11-22 03:59:34 +03:00
struct ldb_dn * new_dn ;
new_dn = ldb_dn_copy ( mem_ctx , dn ) ;
if ( ! ldb_dn_validate ( new_dn ) ) {
talloc_free ( new_dn ) ;
return NULL ;
}
/* may be we don't need to rebase at all */
if ( ! data - > remote_base_dn | | ! data - > local_base_dn ) {
return new_dn ;
}
if ( ! ldb_dn_remove_base_components ( new_dn , ldb_dn_get_comp_num ( data - > remote_base_dn ) ) ) {
talloc_free ( new_dn ) ;
return NULL ;
}
if ( ! ldb_dn_add_base ( new_dn , data - > local_base_dn ) ) {
talloc_free ( new_dn ) ;
return NULL ;
}
return new_dn ;
2006-08-14 03:58:04 +04:00
}
/* Copy a DN with the base DN of the remote partition. */
2006-11-22 03:59:34 +03:00
static struct ldb_dn * ldb_dn_rebase_remote ( void * mem_ctx , const struct ldb_map_context * data , struct ldb_dn * dn )
2006-08-14 03:58:04 +04:00
{
2006-11-22 03:59:34 +03:00
struct ldb_dn * new_dn ;
new_dn = ldb_dn_copy ( mem_ctx , dn ) ;
if ( ! ldb_dn_validate ( new_dn ) ) {
talloc_free ( new_dn ) ;
return NULL ;
}
/* may be we don't need to rebase at all */
if ( ! data - > remote_base_dn | | ! data - > local_base_dn ) {
return new_dn ;
}
if ( ! ldb_dn_remove_base_components ( new_dn , ldb_dn_get_comp_num ( data - > local_base_dn ) ) ) {
talloc_free ( new_dn ) ;
return NULL ;
}
if ( ! ldb_dn_add_base ( new_dn , data - > remote_base_dn ) ) {
talloc_free ( new_dn ) ;
return NULL ;
}
return new_dn ;
2006-08-14 03:58:04 +04:00
}
/* Run a request and make sure it targets the remote partition. */
/* TODO: free old DNs and messages? */
int ldb_next_remote_request ( struct ldb_module * module , struct ldb_request * request )
{
const struct ldb_map_context * data = map_get_context ( module ) ;
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_message * msg ;
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2006-08-14 03:58:04 +04:00
switch ( request - > operation ) {
case LDB_SEARCH :
if ( request - > op . search . base ) {
request - > op . search . base = ldb_dn_rebase_remote ( request , data , request - > op . search . base ) ;
} else {
request - > op . search . base = data - > remote_base_dn ;
/* TODO: adjust scope? */
2005-08-29 19:54:10 +04:00
}
2006-08-14 03:58:04 +04:00
break ;
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
case LDB_ADD :
msg = ldb_msg_copy_shallow ( request , request - > op . add . message ) ;
2013-08-18 23:54:31 +04:00
if ( msg = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-14 03:58:04 +04:00
msg - > dn = ldb_dn_rebase_remote ( msg , data , msg - > dn ) ;
request - > op . add . message = msg ;
break ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
case LDB_MODIFY :
msg = ldb_msg_copy_shallow ( request , request - > op . mod . message ) ;
2013-08-18 23:54:31 +04:00
if ( msg = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-14 03:58:04 +04:00
msg - > dn = ldb_dn_rebase_remote ( msg , data , msg - > dn ) ;
request - > op . mod . message = msg ;
break ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
case LDB_DELETE :
request - > op . del . dn = ldb_dn_rebase_remote ( request , data , request - > op . del . dn ) ;
break ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
case LDB_RENAME :
request - > op . rename . olddn = ldb_dn_rebase_remote ( request , data , request - > op . rename . olddn ) ;
request - > op . rename . newdn = ldb_dn_rebase_remote ( request , data , request - > op . rename . newdn ) ;
break ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
default :
2009-01-30 02:39:30 +03:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb_map: "
2009-07-11 00:44:27 +04:00
" Invalid remote request! " ) ;
2006-08-14 03:58:04 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-08-28 03:47:17 +04:00
}
2006-08-14 03:58:04 +04:00
return ldb_next_request ( module , request ) ;
}
2005-08-28 03:47:17 +04:00
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
/* Finding mappings for attributes and objectClasses
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2005-08-27 22:30:00 +04:00
2006-08-14 03:58:04 +04:00
/* Find an objectClass mapping by the local name. */
static const struct ldb_map_objectclass * map_objectclass_find_local ( const struct ldb_map_context * data , const char * name )
{
2009-11-06 20:35:17 +03:00
unsigned int i ;
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
for ( i = 0 ; data - > objectclass_maps & & data - > objectclass_maps [ i ] . local_name ; i + + ) {
if ( ldb_attr_cmp ( data - > objectclass_maps [ i ] . local_name , name ) = = 0 ) {
return & data - > objectclass_maps [ i ] ;
}
2005-08-28 03:47:17 +04:00
}
2006-08-14 03:58:04 +04:00
return NULL ;
}
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
/* Find an objectClass mapping by the remote name. */
static const struct ldb_map_objectclass * map_objectclass_find_remote ( const struct ldb_map_context * data , const char * name )
{
2009-11-06 20:35:17 +03:00
unsigned int i ;
2006-08-14 03:58:04 +04:00
for ( i = 0 ; data - > objectclass_maps & & data - > objectclass_maps [ i ] . remote_name ; i + + ) {
if ( ldb_attr_cmp ( data - > objectclass_maps [ i ] . remote_name , name ) = = 0 ) {
return & data - > objectclass_maps [ i ] ;
}
2005-08-25 19:25:22 +04:00
}
2006-08-14 03:58:04 +04:00
return NULL ;
2005-08-25 19:25:22 +04:00
}
2006-08-14 03:58:04 +04:00
/* Find an attribute mapping by the local name. */
const struct ldb_map_attribute * map_attr_find_local ( const struct ldb_map_context * data , const char * name )
2005-08-25 19:25:22 +04:00
{
2009-11-06 20:35:17 +03:00
unsigned int i ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
for ( i = 0 ; data - > attribute_maps [ i ] . local_name ; i + + ) {
if ( ldb_attr_cmp ( data - > attribute_maps [ i ] . local_name , name ) = = 0 ) {
return & data - > attribute_maps [ i ] ;
}
}
for ( i = 0 ; data - > attribute_maps [ i ] . local_name ; i + + ) {
if ( ldb_attr_cmp ( data - > attribute_maps [ i ] . local_name , " * " ) = = 0 ) {
return & data - > attribute_maps [ i ] ;
}
}
2005-08-27 19:13:15 +04:00
2006-08-14 03:58:04 +04:00
return NULL ;
}
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
/* Find an attribute mapping by the remote name. */
const struct ldb_map_attribute * map_attr_find_remote ( const struct ldb_map_context * data , const char * name )
{
2006-08-22 10:01:47 +04:00
const struct ldb_map_attribute * map ;
2006-08-14 03:58:04 +04:00
const struct ldb_map_attribute * wildcard = NULL ;
2009-11-06 20:35:17 +03:00
unsigned int i , j ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
for ( i = 0 ; data - > attribute_maps [ i ] . local_name ; i + + ) {
2006-08-22 10:01:47 +04:00
map = & data - > attribute_maps [ i ] ;
if ( ldb_attr_cmp ( map - > local_name , " * " ) = = 0 ) {
2006-08-14 03:58:04 +04:00
wildcard = & data - > attribute_maps [ i ] ;
}
2005-08-25 19:25:22 +04:00
2006-08-22 10:01:47 +04:00
switch ( map - > type ) {
2009-10-20 20:33:25 +04:00
case LDB_MAP_IGNORE :
2006-08-14 03:58:04 +04:00
break ;
2005-08-27 22:30:00 +04:00
2009-10-20 20:33:25 +04:00
case LDB_MAP_KEEP :
2006-08-22 10:01:47 +04:00
if ( ldb_attr_cmp ( map - > local_name , name ) = = 0 ) {
return map ;
2006-08-14 03:58:04 +04:00
}
2005-08-28 03:47:17 +04:00
break ;
2006-08-14 03:58:04 +04:00
2009-10-20 20:33:25 +04:00
case LDB_MAP_RENAME :
2013-09-19 03:50:34 +04:00
case LDB_MAP_RENDROP :
2009-10-20 20:33:25 +04:00
case LDB_MAP_CONVERT :
2006-08-22 10:01:47 +04:00
if ( ldb_attr_cmp ( map - > u . rename . remote_name , name ) = = 0 ) {
return map ;
2006-08-14 03:58:04 +04:00
}
2005-08-28 03:47:17 +04:00
break ;
2006-08-14 03:58:04 +04:00
2009-10-20 20:33:25 +04:00
case LDB_MAP_GENERATE :
2013-11-10 00:29:24 +04:00
for ( j = 0 ; map - > u . generate . remote_names [ j ] ; j + + ) {
2006-08-22 10:01:47 +04:00
if ( ldb_attr_cmp ( map - > u . generate . remote_names [ j ] , name ) = = 0 ) {
return map ;
2006-08-14 03:58:04 +04:00
}
}
2005-08-28 03:47:17 +04:00
break ;
2005-08-25 19:25:22 +04:00
}
}
2005-08-27 19:13:15 +04:00
2006-08-14 03:58:04 +04:00
/* We didn't find it, so return the wildcard record if one was configured */
return wildcard ;
}
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
/* Mapping attributes
* = = = = = = = = = = = = = = = = = = */
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
/* Check whether an attribute will be mapped into the remote partition. */
2007-05-05 22:50:56 +04:00
bool map_attr_check_remote ( const struct ldb_map_context * data , const char * attr )
2006-08-14 03:58:04 +04:00
{
const struct ldb_map_attribute * map = map_attr_find_local ( data , attr ) ;
2005-08-27 22:30:00 +04:00
2006-08-14 03:58:04 +04:00
if ( map = = NULL ) {
2007-05-05 22:50:56 +04:00
return false ;
2006-08-14 03:58:04 +04:00
}
2009-10-20 20:33:25 +04:00
if ( map - > type = = LDB_MAP_IGNORE ) {
2007-05-05 22:50:56 +04:00
return false ;
2005-08-25 19:25:22 +04:00
}
2007-05-05 22:50:56 +04:00
return true ;
2005-08-25 19:25:22 +04:00
}
2006-08-14 03:58:04 +04:00
/* Map an attribute name into the remote partition. */
const char * map_attr_map_local ( void * mem_ctx , const struct ldb_map_attribute * map , const char * attr )
2005-08-25 02:06:26 +04:00
{
2006-08-14 03:58:04 +04:00
if ( map = = NULL ) {
return talloc_strdup ( mem_ctx , attr ) ;
}
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
switch ( map - > type ) {
2009-10-20 20:33:25 +04:00
case LDB_MAP_KEEP :
2006-08-14 03:58:04 +04:00
return talloc_strdup ( mem_ctx , attr ) ;
2005-08-27 19:13:15 +04:00
2009-10-20 20:33:25 +04:00
case LDB_MAP_RENAME :
2013-09-19 03:50:34 +04:00
case LDB_MAP_RENDROP :
2009-10-20 20:33:25 +04:00
case LDB_MAP_CONVERT :
2006-08-14 03:58:04 +04:00
return talloc_strdup ( mem_ctx , map - > u . rename . remote_name ) ;
default :
return NULL ;
2005-08-25 19:25:22 +04:00
}
2006-08-14 03:58:04 +04:00
}
/* Map an attribute name back into the local partition. */
const char * map_attr_map_remote ( void * mem_ctx , const struct ldb_map_attribute * map , const char * attr )
{
if ( map = = NULL ) {
return talloc_strdup ( mem_ctx , attr ) ;
2005-08-28 03:47:17 +04:00
}
2005-08-25 19:25:22 +04:00
2009-10-20 20:33:25 +04:00
if ( map - > type = = LDB_MAP_KEEP ) {
2006-08-14 03:58:04 +04:00
return talloc_strdup ( mem_ctx , attr ) ;
}
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
return talloc_strdup ( mem_ctx , map - > local_name ) ;
2005-08-25 02:06:26 +04:00
}
2006-09-14 07:15:30 +04:00
/* Merge two lists of attributes into a single one. */
2006-11-16 12:16:17 +03:00
int map_attrs_merge ( struct ldb_module * module , void * mem_ctx ,
const char * * * attrs , const char * const * more_attrs )
2006-09-14 07:15:30 +04:00
{
2009-11-06 20:35:17 +03:00
unsigned int i , j , k ;
2006-09-14 07:15:30 +04:00
for ( i = 0 ; * attrs & & ( * attrs ) [ i ] ; i + + ) /* noop */ ;
for ( j = 0 ; more_attrs & & more_attrs [ j ] ; j + + ) /* noop */ ;
2006-11-16 12:16:17 +03:00
2006-09-14 07:15:30 +04:00
* attrs = talloc_realloc ( mem_ctx , * attrs , const char * , i + j + 1 ) ;
if ( * attrs = = NULL ) {
map_oom ( module ) ;
return - 1 ;
}
for ( k = 0 ; k < j ; k + + ) {
2006-11-16 12:16:17 +03:00
( * attrs ) [ i + k ] = more_attrs [ k ] ;
2006-09-14 07:15:30 +04:00
}
( * attrs ) [ i + k ] = NULL ;
return 0 ;
}
2006-08-14 03:58:04 +04:00
/* Mapping ldb values
* = = = = = = = = = = = = = = = = = = */
2005-08-27 20:33:42 +04:00
2006-08-14 03:58:04 +04:00
/* Map an ldb value into the remote partition. */
2006-11-16 12:16:17 +03:00
struct ldb_val ldb_val_map_local ( struct ldb_module * module , void * mem_ctx ,
const struct ldb_map_attribute * map , const struct ldb_val * val )
2006-08-14 03:58:04 +04:00
{
2009-10-20 20:33:25 +04:00
if ( map & & ( map - > type = = LDB_MAP_CONVERT ) & & ( map - > u . convert . convert_local ) ) {
2006-11-02 02:31:26 +03:00
return map - > u . convert . convert_local ( module , mem_ctx , val ) ;
2006-08-14 03:58:04 +04:00
}
2005-08-27 20:33:42 +04:00
2006-11-02 02:31:26 +03:00
return ldb_val_dup ( mem_ctx , val ) ;
2006-08-14 03:58:04 +04:00
}
2005-08-27 20:33:42 +04:00
2006-08-14 03:58:04 +04:00
/* Map an ldb value back into the local partition. */
2006-11-16 12:16:17 +03:00
struct ldb_val ldb_val_map_remote ( struct ldb_module * module , void * mem_ctx ,
const struct ldb_map_attribute * map , const struct ldb_val * val )
2006-08-14 03:58:04 +04:00
{
2009-10-20 20:33:25 +04:00
if ( map & & ( map - > type = = LDB_MAP_CONVERT ) & & ( map - > u . convert . convert_remote ) ) {
2006-11-02 02:31:26 +03:00
return map - > u . convert . convert_remote ( module , mem_ctx , val ) ;
2005-08-27 20:33:42 +04:00
}
2006-11-02 02:31:26 +03:00
return ldb_val_dup ( mem_ctx , val ) ;
2005-08-27 20:33:42 +04:00
}
2006-08-14 03:58:04 +04:00
/* Mapping DNs
* = = = = = = = = = = = */
/* Check whether a DN is below the local baseDN. */
2007-05-05 22:50:56 +04:00
bool ldb_dn_check_local ( struct ldb_module * module , struct ldb_dn * dn )
2005-08-25 02:06:26 +04:00
{
2006-08-14 03:58:04 +04:00
const struct ldb_map_context * data = map_get_context ( module ) ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
if ( ! data - > local_base_dn ) {
2007-05-05 22:50:56 +04:00
return true ;
2006-08-14 03:58:04 +04:00
}
2006-11-22 03:59:34 +03:00
return ldb_dn_compare_base ( data - > local_base_dn , dn ) = = 0 ;
2006-08-14 03:58:04 +04:00
}
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
/* Map a DN into the remote partition. */
2006-11-22 03:59:34 +03:00
struct ldb_dn * ldb_dn_map_local ( struct ldb_module * module , void * mem_ctx , struct ldb_dn * dn )
2006-08-14 03:58:04 +04:00
{
const struct ldb_map_context * data = map_get_context ( module ) ;
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_dn * newdn ;
const struct ldb_map_attribute * map ;
enum ldb_map_attr_type map_type ;
2006-11-02 02:31:26 +03:00
const char * name ;
struct ldb_val value ;
int i , ret ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
if ( dn = = NULL ) {
return NULL ;
}
2005-08-27 20:33:42 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2006-08-14 03:58:04 +04:00
newdn = ldb_dn_copy ( mem_ctx , dn ) ;
if ( newdn = = NULL ) {
map_oom ( module ) ;
return NULL ;
2005-08-27 20:33:42 +04:00
}
2006-08-14 03:58:04 +04:00
/* For each RDN, map the component name and possibly the value */
2006-11-02 02:31:26 +03:00
for ( i = 0 ; i < ldb_dn_get_comp_num ( newdn ) ; i + + ) {
map = map_attr_find_local ( data , ldb_dn_get_component_name ( dn , i ) ) ;
2005-08-25 19:25:22 +04:00
2006-08-14 03:58:04 +04:00
/* Unknown attribute - leave this RDN as is and hope the best... */
if ( map = = NULL ) {
2009-10-20 20:33:25 +04:00
map_type = LDB_MAP_KEEP ;
2006-08-14 03:58:04 +04:00
} else {
map_type = map - > type ;
}
2005-08-25 19:25:22 +04:00
2005-08-28 03:47:17 +04:00
switch ( map_type ) {
2009-10-20 20:33:25 +04:00
case LDB_MAP_IGNORE :
case LDB_MAP_GENERATE :
2009-01-30 02:39:30 +03:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb_map: "
2009-10-20 20:33:25 +04:00
" LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' "
2009-07-11 00:44:27 +04:00
" used in DN! " , ldb_dn_get_component_name ( dn , i ) ) ;
2006-08-14 03:58:04 +04:00
goto failed ;
2009-10-20 20:33:25 +04:00
case LDB_MAP_CONVERT :
2006-08-14 03:58:04 +04:00
if ( map - > u . convert . convert_local = = NULL ) {
2009-01-30 02:39:30 +03:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb_map: "
2006-08-14 03:58:04 +04:00
" 'convert_local' not set for attribute '%s' "
2009-07-11 00:44:27 +04:00
" used in DN! " , ldb_dn_get_component_name ( dn , i ) ) ;
2006-08-14 03:58:04 +04:00
goto failed ;
}
2017-07-27 16:19:23 +03:00
FALL_THROUGH ;
2009-10-20 20:33:25 +04:00
case LDB_MAP_KEEP :
case LDB_MAP_RENAME :
2013-09-19 03:50:34 +04:00
case LDB_MAP_RENDROP :
2006-11-02 02:31:26 +03:00
name = map_attr_map_local ( newdn , map , ldb_dn_get_component_name ( dn , i ) ) ;
if ( name = = NULL ) goto failed ;
value = ldb_val_map_local ( module , newdn , map , ldb_dn_get_component_val ( dn , i ) ) ;
if ( value . data = = NULL ) goto failed ;
ret = ldb_dn_set_component ( newdn , i , name , value ) ;
if ( ret ! = LDB_SUCCESS ) {
goto failed ;
}
2006-08-14 03:58:04 +04:00
break ;
2005-08-25 19:25:22 +04:00
}
}
2006-08-14 03:58:04 +04:00
return newdn ;
2005-08-27 20:33:42 +04:00
2006-08-14 03:58:04 +04:00
failed :
talloc_free ( newdn ) ;
return NULL ;
2005-08-25 02:06:26 +04:00
}
2006-08-14 03:58:04 +04:00
/* Map a DN into the local partition. */
2006-11-22 03:59:34 +03:00
struct ldb_dn * ldb_dn_map_remote ( struct ldb_module * module , void * mem_ctx , struct ldb_dn * dn )
2005-08-25 02:06:26 +04:00
{
2006-08-14 03:58:04 +04:00
const struct ldb_map_context * data = map_get_context ( module ) ;
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_dn * newdn ;
const struct ldb_map_attribute * map ;
enum ldb_map_attr_type map_type ;
2006-11-02 02:31:26 +03:00
const char * name ;
struct ldb_val value ;
int i , ret ;
2005-09-01 19:33:31 +04:00
2006-08-14 03:58:04 +04:00
if ( dn = = NULL ) {
return NULL ;
}
2005-08-25 02:06:26 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2006-08-14 03:58:04 +04:00
newdn = ldb_dn_copy ( mem_ctx , dn ) ;
if ( newdn = = NULL ) {
map_oom ( module ) ;
return NULL ;
2005-09-01 05:11:15 +04:00
}
2006-08-14 03:58:04 +04:00
/* For each RDN, map the component name and possibly the value */
2006-11-02 02:31:26 +03:00
for ( i = 0 ; i < ldb_dn_get_comp_num ( newdn ) ; i + + ) {
map = map_attr_find_remote ( data , ldb_dn_get_component_name ( dn , i ) ) ;
2005-08-25 02:06:26 +04:00
2006-08-14 03:58:04 +04:00
/* Unknown attribute - leave this RDN as is and hope the best... */
if ( map = = NULL ) {
2009-10-20 20:33:25 +04:00
map_type = LDB_MAP_KEEP ;
2006-08-14 03:58:04 +04:00
} else {
map_type = map - > type ;
}
2005-09-01 19:33:31 +04:00
2006-08-14 03:58:04 +04:00
switch ( map_type ) {
2009-10-20 20:33:25 +04:00
case LDB_MAP_IGNORE :
case LDB_MAP_GENERATE :
2009-01-30 02:39:30 +03:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb_map: "
2009-10-20 20:33:25 +04:00
" LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' "
2009-07-11 00:44:27 +04:00
" used in DN! " , ldb_dn_get_component_name ( dn , i ) ) ;
2006-08-14 03:58:04 +04:00
goto failed ;
2005-08-25 02:06:26 +04:00
2009-10-20 20:33:25 +04:00
case LDB_MAP_CONVERT :
2006-08-14 03:58:04 +04:00
if ( map - > u . convert . convert_remote = = NULL ) {
2009-01-30 02:39:30 +03:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb_map: "
2006-08-14 03:58:04 +04:00
" 'convert_remote' not set for attribute '%s' "
2009-07-11 00:44:27 +04:00
" used in DN! " , ldb_dn_get_component_name ( dn , i ) ) ;
2006-08-14 03:58:04 +04:00
goto failed ;
}
2017-07-27 16:19:23 +03:00
FALL_THROUGH ;
2009-10-20 20:33:25 +04:00
case LDB_MAP_KEEP :
case LDB_MAP_RENAME :
2013-09-19 03:50:34 +04:00
case LDB_MAP_RENDROP :
2006-11-02 02:31:26 +03:00
name = map_attr_map_remote ( newdn , map , ldb_dn_get_component_name ( dn , i ) ) ;
if ( name = = NULL ) goto failed ;
value = ldb_val_map_remote ( module , newdn , map , ldb_dn_get_component_val ( dn , i ) ) ;
if ( value . data = = NULL ) goto failed ;
ret = ldb_dn_set_component ( newdn , i , name , value ) ;
if ( ret ! = LDB_SUCCESS ) {
goto failed ;
}
2006-08-14 03:58:04 +04:00
break ;
2005-09-01 22:04:23 +04:00
}
2005-09-01 05:11:15 +04:00
}
2006-08-14 03:58:04 +04:00
return newdn ;
2005-08-25 02:06:26 +04:00
2006-08-14 03:58:04 +04:00
failed :
2005-08-25 02:06:26 +04:00
talloc_free ( newdn ) ;
2006-08-14 03:58:04 +04:00
return NULL ;
2005-08-25 02:06:26 +04:00
}
2006-08-14 03:58:04 +04:00
/* Map a DN and its base into the local partition. */
/* TODO: This should not be required with GUIDs. */
2006-11-22 03:59:34 +03:00
struct ldb_dn * ldb_dn_map_rebase_remote ( struct ldb_module * module , void * mem_ctx , struct ldb_dn * dn )
2005-08-25 02:06:26 +04:00
{
2006-08-14 03:58:04 +04:00
const struct ldb_map_context * data = map_get_context ( module ) ;
struct ldb_dn * dn1 , * dn2 ;
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
dn1 = ldb_dn_rebase_local ( mem_ctx , data , dn ) ;
dn2 = ldb_dn_map_remote ( module , mem_ctx , dn1 ) ;
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
talloc_free ( dn1 ) ;
return dn2 ;
}
2005-08-29 19:54:10 +04:00
2005-11-08 03:11:45 +03:00
2006-08-14 03:58:04 +04:00
/* Converting DNs and objectClasses (as ldb values)
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
/* Map a DN contained in an ldb value into the remote partition. */
static struct ldb_val ldb_dn_convert_local ( struct ldb_module * module , void * mem_ctx , const struct ldb_val * val )
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_dn * dn , * newdn ;
struct ldb_val newval ;
2005-08-29 19:54:10 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
dn = ldb_dn_from_ldb_val ( mem_ctx , ldb , val ) ;
2006-11-22 03:59:34 +03:00
if ( ! ldb_dn_validate ( dn ) ) {
newval . length = 0 ;
newval . data = NULL ;
talloc_free ( dn ) ;
return newval ;
}
2006-08-14 03:58:04 +04:00
newdn = ldb_dn_map_local ( module , mem_ctx , dn ) ;
talloc_free ( dn ) ;
newval . length = 0 ;
2006-11-22 05:05:19 +03:00
newval . data = ( uint8_t * ) ldb_dn_alloc_linearized ( mem_ctx , newdn ) ;
2006-08-14 03:58:04 +04:00
if ( newval . data ) {
newval . length = strlen ( ( char * ) newval . data ) ;
}
talloc_free ( newdn ) ;
return newval ;
2005-08-29 19:54:10 +04:00
}
2006-08-14 03:58:04 +04:00
/* Map a DN contained in an ldb value into the local partition. */
static struct ldb_val ldb_dn_convert_remote ( struct ldb_module * module , void * mem_ctx , const struct ldb_val * val )
2005-08-29 19:54:10 +04:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_dn * dn , * newdn ;
struct ldb_val newval ;
2005-08-25 02:06:26 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
dn = ldb_dn_from_ldb_val ( mem_ctx , ldb , val ) ;
2006-11-22 03:59:34 +03:00
if ( ! ldb_dn_validate ( dn ) ) {
newval . length = 0 ;
newval . data = NULL ;
talloc_free ( dn ) ;
return newval ;
}
2006-08-14 03:58:04 +04:00
newdn = ldb_dn_map_remote ( module , mem_ctx , dn ) ;
talloc_free ( dn ) ;
2005-08-25 02:06:26 +04:00
2006-08-14 03:58:04 +04:00
newval . length = 0 ;
2006-11-22 05:05:19 +03:00
newval . data = ( uint8_t * ) ldb_dn_alloc_linearized ( mem_ctx , newdn ) ;
2006-08-14 03:58:04 +04:00
if ( newval . data ) {
newval . length = strlen ( ( char * ) newval . data ) ;
}
talloc_free ( newdn ) ;
2005-08-29 21:31:19 +04:00
2006-08-14 03:58:04 +04:00
return newval ;
2005-08-25 02:06:26 +04:00
}
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
/* Map an objectClass into the remote partition. */
static struct ldb_val map_objectclass_convert_local ( struct ldb_module * module , void * mem_ctx , const struct ldb_val * val )
2005-08-29 19:54:10 +04:00
{
2006-08-14 03:58:04 +04:00
const struct ldb_map_context * data = map_get_context ( module ) ;
const char * name = ( char * ) val - > data ;
const struct ldb_map_objectclass * map = map_objectclass_find_local ( data , name ) ;
struct ldb_val newval ;
if ( map ) {
newval . data = ( uint8_t * ) talloc_strdup ( mem_ctx , map - > remote_name ) ;
newval . length = strlen ( ( char * ) newval . data ) ;
return newval ;
}
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
return ldb_val_dup ( mem_ctx , val ) ;
}
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
/* Generate a remote message with a mapped objectClass. */
static void map_objectclass_generate_remote ( struct ldb_module * module , const char * local_attr , const struct ldb_message * old , struct ldb_message * remote , struct ldb_message * local )
{
2008-01-16 01:45:29 +03:00
const struct ldb_map_context * data = map_get_context ( module ) ;
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_message_element * el , * oc ;
struct ldb_val val ;
2007-05-05 22:50:56 +04:00
bool found_extensibleObject = false ;
2009-11-06 20:35:17 +03:00
unsigned int i ;
2016-06-28 15:41:19 +03:00
int ret ;
2006-08-14 03:58:04 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2006-08-14 03:58:04 +04:00
/* Find old local objectClass */
2006-11-16 12:16:17 +03:00
oc = ldb_msg_find_element ( old , " objectClass " ) ;
2006-08-14 03:58:04 +04:00
if ( oc = = NULL ) {
return ;
2005-09-01 01:04:17 +04:00
}
2006-08-14 03:58:04 +04:00
/* Prepare new element */
el = talloc_zero ( remote , struct ldb_message_element ) ;
if ( el = = NULL ) {
2009-01-30 02:39:30 +03:00
ldb_oom ( ldb ) ;
2006-08-14 03:58:04 +04:00
return ; /* TODO: fail? */
}
2005-11-29 15:34:03 +03:00
2006-08-14 03:58:04 +04:00
/* Copy local objectClass element, reverse space for an extra value */
el - > num_values = oc - > num_values + 1 ;
el - > values = talloc_array ( el , struct ldb_val , el - > num_values ) ;
if ( el - > values = = NULL ) {
talloc_free ( el ) ;
2009-01-30 02:39:30 +03:00
ldb_oom ( ldb ) ;
2006-08-14 03:58:04 +04:00
return ; /* TODO: fail? */
2005-08-30 04:41:02 +04:00
}
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
/* Copy local element name "objectClass" */
el - > name = talloc_strdup ( el , local_attr ) ;
2005-11-29 15:34:03 +03:00
2006-08-14 03:58:04 +04:00
/* Convert all local objectClasses */
for ( i = 0 ; i < el - > num_values - 1 ; i + + ) {
el - > values [ i ] = map_objectclass_convert_local ( module , el - > values , & oc - > values [ i ] ) ;
2008-01-16 01:45:29 +03:00
if ( ldb_attr_cmp ( ( char * ) el - > values [ i ] . data , data - > add_objectclass ) = = 0 ) {
2007-05-05 22:50:56 +04:00
found_extensibleObject = true ;
2006-08-14 03:58:04 +04:00
}
}
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
if ( ! found_extensibleObject ) {
2008-01-16 01:45:29 +03:00
val . data = ( uint8_t * ) talloc_strdup ( el - > values , data - > add_objectclass ) ;
2006-08-14 03:58:04 +04:00
val . length = strlen ( ( char * ) val . data ) ;
2005-09-01 01:04:17 +04:00
2008-01-16 01:45:29 +03:00
/* Append additional objectClass data->add_objectclass */
2006-08-14 03:58:04 +04:00
el - > values [ i ] = val ;
} else {
el - > num_values - - ;
2005-11-29 15:34:03 +03:00
}
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
/* Add new objectClass to remote message */
2016-06-28 15:41:19 +03:00
ret = ldb_msg_add ( remote , el , 0 ) ;
if ( ret ! = LDB_SUCCESS ) {
ldb_oom ( ldb ) ;
return ;
}
2005-08-29 19:54:10 +04:00
}
2005-08-25 02:06:26 +04:00
2006-08-14 03:58:04 +04:00
/* Map an objectClass into the local partition. */
static struct ldb_val map_objectclass_convert_remote ( struct ldb_module * module , void * mem_ctx , const struct ldb_val * val )
2005-09-01 19:33:31 +04:00
{
2006-08-14 03:58:04 +04:00
const struct ldb_map_context * data = map_get_context ( module ) ;
const char * name = ( char * ) val - > data ;
const struct ldb_map_objectclass * map = map_objectclass_find_remote ( data , name ) ;
struct ldb_val newval ;
if ( map ) {
newval . data = ( uint8_t * ) talloc_strdup ( mem_ctx , map - > local_name ) ;
newval . length = strlen ( ( char * ) newval . data ) ;
return newval ;
2005-09-01 19:33:31 +04:00
}
2006-08-14 03:58:04 +04:00
return ldb_val_dup ( mem_ctx , val ) ;
2005-09-01 19:33:31 +04:00
}
2006-08-14 03:58:04 +04:00
/* Generate a local message with a mapped objectClass. */
2006-11-16 12:16:17 +03:00
static struct ldb_message_element * map_objectclass_generate_local ( struct ldb_module * module , void * mem_ctx , const char * local_attr , const struct ldb_message * remote )
2005-08-25 02:06:26 +04:00
{
2008-07-21 05:18:21 +04:00
const struct ldb_map_context * data = map_get_context ( module ) ;
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_message_element * el , * oc ;
struct ldb_val val ;
2009-11-06 20:35:17 +03:00
unsigned int i ;
2005-08-25 02:06:26 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2006-08-14 03:58:04 +04:00
/* Find old remote objectClass */
2006-11-16 12:16:17 +03:00
oc = ldb_msg_find_element ( remote , " objectClass " ) ;
2006-08-14 03:58:04 +04:00
if ( oc = = NULL ) {
return NULL ;
}
2005-09-01 01:04:17 +04:00
2006-08-14 03:58:04 +04:00
/* Prepare new element */
el = talloc_zero ( mem_ctx , struct ldb_message_element ) ;
if ( el = = NULL ) {
2009-01-30 02:39:30 +03:00
ldb_oom ( ldb ) ;
2006-08-14 03:58:04 +04:00
return NULL ;
}
2005-09-01 19:33:31 +04:00
2006-08-14 03:58:04 +04:00
/* Copy remote objectClass element */
el - > num_values = oc - > num_values ;
el - > values = talloc_array ( el , struct ldb_val , el - > num_values ) ;
if ( el - > values = = NULL ) {
talloc_free ( el ) ;
2009-01-30 02:39:30 +03:00
ldb_oom ( ldb ) ;
2006-08-14 03:58:04 +04:00
return NULL ;
}
/* Copy remote element name "objectClass" */
2006-11-16 12:16:17 +03:00
el - > name = talloc_strdup ( el , local_attr ) ;
2006-08-14 03:58:04 +04:00
/* Convert all remote objectClasses */
for ( i = 0 ; i < el - > num_values ; i + + ) {
el - > values [ i ] = map_objectclass_convert_remote ( module , el - > values , & oc - > values [ i ] ) ;
}
2008-07-21 05:18:21 +04:00
val . data = ( uint8_t * ) talloc_strdup ( el - > values , data - > add_objectclass ) ;
2006-08-14 03:58:04 +04:00
val . length = strlen ( ( char * ) val . data ) ;
2005-09-01 19:33:31 +04:00
2008-07-21 05:18:21 +04:00
/* Remove last value if it was the string in data->add_objectclass (eg samba4top, extensibleObject) */
2006-08-14 03:58:04 +04:00
if ( ldb_val_equal_exact ( & val , & el - > values [ i - 1 ] ) ) {
el - > num_values - - ;
el - > values = talloc_realloc ( el , el - > values , struct ldb_val , el - > num_values ) ;
if ( el - > values = = NULL ) {
talloc_free ( el ) ;
2009-01-30 02:39:30 +03:00
ldb_oom ( ldb ) ;
2006-08-14 03:58:04 +04:00
return NULL ;
2005-09-01 19:33:31 +04:00
}
}
2006-08-14 03:58:04 +04:00
return el ;
}
2005-09-01 19:33:31 +04:00
2008-01-16 01:45:29 +03:00
static const struct ldb_map_attribute objectclass_convert_map = {
. local_name = " objectClass " ,
2009-10-20 20:33:25 +04:00
. type = LDB_MAP_CONVERT ,
2008-01-16 01:45:29 +03:00
. u = {
. convert = {
. remote_name = " objectClass " ,
. convert_local = map_objectclass_convert_local ,
. convert_remote = map_objectclass_convert_remote ,
} ,
} ,
} ;
2006-08-15 03:25:04 +04:00
/* Mappings for searches on objectClass= assuming a one-to-one
* mapping . Needed because this is a generate operator for the
* add / modify code */
static int map_objectclass_convert_operator ( struct ldb_module * module , void * mem_ctx ,
struct ldb_parse_tree * * new , const struct ldb_parse_tree * tree )
{
2008-01-16 01:45:29 +03:00
return map_subtree_collect_remote_simple ( module , mem_ctx , new , tree , & objectclass_convert_map ) ;
2006-08-15 03:25:04 +04:00
}
2005-09-02 00:28:03 +04:00
2006-08-14 03:58:04 +04:00
/* Auxiliary request construction
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2005-09-02 00:28:03 +04:00
2006-08-14 03:58:04 +04:00
/* Build a request to search a record by its DN. */
2013-08-16 16:56:04 +04:00
struct ldb_request * map_search_base_req ( struct map_context * ac , struct ldb_dn * dn , const char * const * attrs , struct ldb_parse_tree * tree , void * context , ldb_map_callback_t callback )
2006-08-14 03:58:04 +04:00
{
2013-08-16 16:56:04 +04:00
struct ldb_parse_tree * search_tree ;
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_request * req ;
2008-09-12 02:35:38 +04:00
int ret ;
2006-08-14 03:58:04 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2006-08-14 03:58:04 +04:00
if ( tree ) {
2008-09-12 02:35:38 +04:00
search_tree = tree ;
2006-08-14 03:58:04 +04:00
} else {
2008-09-12 02:35:38 +04:00
search_tree = ldb_parse_tree ( ac , NULL ) ;
if ( search_tree = = NULL ) {
2006-08-14 03:58:04 +04:00
return NULL ;
}
2005-09-01 19:33:31 +04:00
}
2009-01-30 02:39:30 +03:00
ret = ldb_build_search_req_ex ( & req , ldb , ac ,
2008-09-12 02:35:38 +04:00
dn , LDB_SCOPE_BASE ,
search_tree , attrs ,
NULL ,
context , callback ,
ac - > req ) ;
2010-10-18 15:13:20 +04:00
LDB_REQ_SET_LOCATION ( req ) ;
2008-09-12 02:35:38 +04:00
if ( ret ! = LDB_SUCCESS ) {
2006-08-14 03:58:04 +04:00
return NULL ;
2005-09-01 19:33:31 +04:00
}
2008-09-12 02:35:38 +04:00
return req ;
2005-08-25 02:06:26 +04:00
}
2006-08-14 03:58:04 +04:00
/* Build a request to update the 'IS_MAPPED' attribute */
2008-09-12 02:35:38 +04:00
struct ldb_request * map_build_fixup_req ( struct map_context * ac ,
struct ldb_dn * olddn ,
struct ldb_dn * newdn ,
void * context ,
ldb_map_callback_t callback )
2005-08-25 02:06:26 +04:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_request * req ;
struct ldb_message * msg ;
const char * dn ;
2008-09-12 02:35:38 +04:00
int ret ;
2005-09-01 22:55:51 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2006-08-14 03:58:04 +04:00
/* Prepare message */
2008-09-12 02:35:38 +04:00
msg = ldb_msg_new ( ac ) ;
2006-08-14 03:58:04 +04:00
if ( msg = = NULL ) {
map_oom ( ac - > module ) ;
2008-09-12 02:35:38 +04:00
return NULL ;
2006-08-14 03:58:04 +04:00
}
2005-08-29 19:54:10 +04:00
2006-08-14 03:58:04 +04:00
/* Update local 'IS_MAPPED' to the new remote DN */
2006-11-22 05:05:19 +03:00
msg - > dn = ldb_dn_copy ( msg , olddn ) ;
dn = ldb_dn_alloc_linearized ( msg , newdn ) ;
if ( ! dn | | ! ldb_dn_validate ( msg - > dn ) ) {
2006-08-14 03:58:04 +04:00
goto failed ;
}
2006-10-25 05:42:59 +04:00
if ( ldb_msg_add_empty ( msg , IS_MAPPED , LDB_FLAG_MOD_REPLACE , NULL ) ! = 0 ) {
2006-08-14 03:58:04 +04:00
goto failed ;
}
if ( ldb_msg_add_string ( msg , IS_MAPPED , dn ) ! = 0 ) {
goto failed ;
2005-09-01 19:33:31 +04:00
}
2008-09-12 02:35:38 +04:00
/* Prepare request */
2009-01-30 02:39:30 +03:00
ret = ldb_build_mod_req ( & req , ldb ,
2008-09-12 02:35:38 +04:00
ac , msg , NULL ,
context , callback ,
ac - > req ) ;
2010-10-18 15:13:20 +04:00
LDB_REQ_SET_LOCATION ( req ) ;
2008-09-12 02:35:38 +04:00
if ( ret ! = LDB_SUCCESS ) {
goto failed ;
}
talloc_steal ( req , msg ) ;
2005-08-25 02:06:26 +04:00
2006-08-14 03:58:04 +04:00
return req ;
failed :
2008-09-12 02:35:38 +04:00
talloc_free ( msg ) ;
2006-08-14 03:58:04 +04:00
return NULL ;
2005-08-25 02:06:26 +04:00
}
2006-08-14 03:58:04 +04:00
/* Module initialization
* = = = = = = = = = = = = = = = = = = = = = */
2005-08-25 02:06:26 +04:00
2006-08-14 03:58:04 +04:00
/* Builtin mappings for DNs and objectClasses */
static const struct ldb_map_attribute builtin_attribute_maps [ ] = {
{
. local_name = " dn " ,
2009-10-20 20:33:25 +04:00
. type = LDB_MAP_CONVERT ,
2006-08-14 03:58:04 +04:00
. u = {
. convert = {
. remote_name = " dn " ,
. convert_local = ldb_dn_convert_local ,
. convert_remote = ldb_dn_convert_remote ,
} ,
} ,
} ,
{
. local_name = NULL ,
}
} ;
2005-08-28 03:47:17 +04:00
2008-01-16 01:45:29 +03:00
static const struct ldb_map_attribute objectclass_attribute_map = {
. local_name = " objectClass " ,
2009-10-20 20:33:25 +04:00
. type = LDB_MAP_GENERATE ,
2008-01-16 01:45:29 +03:00
. convert_operator = map_objectclass_convert_operator ,
. u = {
. generate = {
. remote_names = { " objectClass " , NULL } ,
. generate_local = map_objectclass_generate_local ,
. generate_remote = map_objectclass_generate_remote ,
} ,
} ,
} ;
2006-08-14 03:58:04 +04:00
/* Find the special 'MAP_DN_NAME' record and store local and remote
* base DNs in private data . */
static int map_init_dns ( struct ldb_module * module , struct ldb_map_context * data , const char * name )
2005-08-28 03:47:17 +04:00
{
2007-12-20 02:02:15 +03:00
static const char * const attrs [ ] = { MAP_DN_FROM , MAP_DN_TO , NULL } ;
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-08-14 03:58:04 +04:00
struct ldb_dn * dn ;
struct ldb_message * msg ;
struct ldb_result * res ;
int ret ;
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
if ( ! name ) {
data - > local_base_dn = NULL ;
data - > remote_base_dn = NULL ;
return LDB_SUCCESS ;
}
2005-08-28 03:47:17 +04:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
dn = ldb_dn_new_fmt ( data , ldb , " %s=%s " , MAP_DN_NAME , name ) ;
2006-11-22 03:59:34 +03:00
if ( ! ldb_dn_validate ( dn ) ) {
2009-01-30 02:39:30 +03:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb_map: "
2009-07-11 00:44:27 +04:00
" Failed to construct '%s' DN! " , MAP_DN_NAME ) ;
2006-08-14 03:58:04 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2005-08-28 03:47:17 +04:00
2012-08-06 12:46:41 +04:00
ret = ldb_search ( ldb , data , & res , dn , LDB_SCOPE_BASE , attrs , NULL ) ;
2005-08-28 03:47:17 +04:00
talloc_free ( dn ) ;
2006-08-14 03:58:04 +04:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
if ( res - > count = = 0 ) {
2009-01-30 02:39:30 +03:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb_map: "
2009-07-11 00:44:27 +04:00
" No results for '%s=%s'! " , MAP_DN_NAME , name ) ;
2006-10-16 03:14:19 +04:00
talloc_free ( res ) ;
2006-08-14 03:58:04 +04:00
return LDB_ERR_CONSTRAINT_VIOLATION ;
}
if ( res - > count > 1 ) {
2009-01-30 02:39:30 +03:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " ldb_map: "
2009-07-11 00:44:27 +04:00
" Too many results for '%s=%s'! " , MAP_DN_NAME , name ) ;
2006-10-16 03:14:19 +04:00
talloc_free ( res ) ;
2006-08-14 03:58:04 +04:00
return LDB_ERR_CONSTRAINT_VIOLATION ;
2005-09-01 22:55:51 +04:00
}
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
msg = res - > msgs [ 0 ] ;
2009-01-30 02:39:30 +03:00
data - > local_base_dn = ldb_msg_find_attr_as_dn ( ldb , data , msg , MAP_DN_FROM ) ;
data - > remote_base_dn = ldb_msg_find_attr_as_dn ( ldb , data , msg , MAP_DN_TO ) ;
2006-08-14 03:58:04 +04:00
talloc_free ( res ) ;
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
return LDB_SUCCESS ;
2005-08-28 03:47:17 +04:00
}
2006-08-14 03:58:04 +04:00
/* Store attribute maps and objectClass maps in private data. */
2006-09-14 07:15:30 +04:00
static int map_init_maps ( struct ldb_module * module , struct ldb_map_context * data ,
const struct ldb_map_attribute * attrs ,
const struct ldb_map_objectclass * ocls ,
const char * const * wildcard_attributes )
2005-08-28 03:47:17 +04:00
{
2009-11-06 20:35:17 +03:00
unsigned int i , j , last ;
2006-08-14 03:58:04 +04:00
last = 0 ;
/* Count specified attribute maps */
for ( i = 0 ; attrs [ i ] . local_name ; i + + ) /* noop */ ;
/* Count built-in attribute maps */
for ( j = 0 ; builtin_attribute_maps [ j ] . local_name ; j + + ) /* noop */ ;
/* Store list of attribute maps */
2008-01-16 01:45:29 +03:00
data - > attribute_maps = talloc_array ( data , struct ldb_map_attribute , i + j + 2 ) ;
2006-08-14 03:58:04 +04:00
if ( data - > attribute_maps = = NULL ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
/* Specified ones go first */
for ( i = 0 ; attrs [ i ] . local_name ; i + + ) {
data - > attribute_maps [ last ] = attrs [ i ] ;
last + + ;
}
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
/* Built-in ones go last */
for ( i = 0 ; builtin_attribute_maps [ i ] . local_name ; i + + ) {
data - > attribute_maps [ last ] = builtin_attribute_maps [ i ] ;
last + + ;
2005-09-02 00:28:03 +04:00
}
2005-08-28 03:47:17 +04:00
2008-01-16 01:45:29 +03:00
if ( data - > add_objectclass ) {
/* ObjectClass one is very last, if required */
data - > attribute_maps [ last ] = objectclass_attribute_map ;
last + + ;
} else if ( ocls ) {
data - > attribute_maps [ last ] = objectclass_convert_map ;
last + + ;
}
2006-08-14 03:58:04 +04:00
/* Ensure 'local_name == NULL' for the last entry */
memset ( & data - > attribute_maps [ last ] , 0 , sizeof ( struct ldb_map_attribute ) ) ;
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
/* Store list of objectClass maps */
data - > objectclass_maps = ocls ;
2006-09-14 07:15:30 +04:00
data - > wildcard_attributes = wildcard_attributes ;
2006-08-14 03:58:04 +04:00
return LDB_SUCCESS ;
2005-08-28 03:47:17 +04:00
}
2006-08-14 03:58:04 +04:00
/* Initialize global private data. */
2006-10-29 20:40:19 +03:00
_PUBLIC_ int ldb_map_init ( struct ldb_module * module , const struct ldb_map_attribute * attrs ,
2008-01-16 01:45:29 +03:00
const struct ldb_map_objectclass * ocls ,
const char * const * wildcard_attributes ,
const char * add_objectclass ,
const char * name )
2006-08-14 03:58:04 +04:00
{
struct map_private * data ;
int ret ;
2005-08-28 03:47:17 +04:00
2006-08-14 03:58:04 +04:00
/* Prepare private data */
data = talloc_zero ( module , struct map_private ) ;
if ( data = = NULL ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2005-08-28 03:47:17 +04:00
}
2009-01-30 02:39:30 +03:00
ldb_module_set_private ( module , data ) ;
2005-08-28 03:47:17 +04:00
2006-08-22 10:01:47 +04:00
data - > context = talloc_zero ( data , struct ldb_map_context ) ;
if ( ! data - > context ) {
map_oom ( module ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-08-14 03:58:04 +04:00
/* Store local and remote baseDNs */
2006-08-22 10:01:47 +04:00
ret = map_init_dns ( module , data - > context , name ) ;
2006-08-14 03:58:04 +04:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( data ) ;
return ret ;
}
2005-08-28 03:47:17 +04:00
2008-01-16 01:45:29 +03:00
data - > context - > add_objectclass = add_objectclass ;
2006-08-14 03:58:04 +04:00
/* Store list of attribute and objectClass maps */
2006-09-14 07:15:30 +04:00
ret = map_init_maps ( module , data - > context , attrs , ocls , wildcard_attributes ) ;
2006-08-14 03:58:04 +04:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( data ) ;
return ret ;
2005-08-28 03:47:17 +04:00
}
2006-08-14 03:58:04 +04:00
return LDB_SUCCESS ;
2005-08-28 03:47:17 +04:00
}