2004-03-31 10:45:39 +04:00
/*
ldb database library
Copyright ( C ) Andrew Tridgell 2004
2006-02-28 07:38:53 +03:00
Copyright ( C ) Simo Sorce 2006
2004-03-31 10:45:39 +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
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
version 2 of the License , or ( at your option ) any later version .
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
License along with this library ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/*
2006-02-28 07:38:53 +03:00
* Name : ldb_ldap
2004-03-31 10:45:39 +04:00
*
* Component : ldb ldap backend
*
* Description : core files for LDAP backend
*
* Author : Andrew Tridgell
2006-02-28 07:38:53 +03:00
*
* Modifications :
*
* - description : make the module use asyncronous calls
* date : Feb 2006
* author : Simo Sorce
2004-03-31 10:45:39 +04:00
*/
# include "includes.h"
2006-01-10 19:48:32 +03:00
# include "ldb/include/includes.h"
2006-07-18 16:11:02 +04:00
# define LDAP_DEPRECATED 1
2006-02-28 07:38:53 +03:00
# include <ldap.h>
2004-03-31 10:45:39 +04:00
2006-02-28 07:38:53 +03:00
struct lldb_private {
LDAP * ldap ;
2006-12-12 21:25:19 +03:00
struct ldb_module * module ;
2006-02-28 07:38:53 +03:00
} ;
2004-10-20 23:28:02 +04:00
2006-07-22 20:56:33 +04:00
struct lldb_context {
2006-02-28 07:38:53 +03:00
struct ldb_module * module ;
int msgid ;
2006-03-03 20:44:03 +03:00
int timeout ;
2006-06-04 09:28:13 +04:00
time_t starttime ;
2006-02-28 07:38:53 +03:00
void * context ;
2006-07-22 20:56:33 +04:00
int ( * callback ) ( struct ldb_context * , void * , struct ldb_reply * ) ;
2006-02-28 07:38:53 +03:00
} ;
2004-10-20 23:28:02 +04:00
2006-02-28 07:38:53 +03:00
static int lldb_ldap_to_ldb ( int err ) {
/* Ldap errors and ldb errors are defined to the same values */
return err ;
}
2004-10-20 23:28:02 +04:00
2006-07-22 20:56:33 +04:00
static struct ldb_handle * init_handle ( struct lldb_private * lldb , struct ldb_module * module ,
2006-02-28 07:38:53 +03:00
void * context ,
2006-07-22 20:56:33 +04:00
int ( * callback ) ( struct ldb_context * , void * , struct ldb_reply * ) ,
2006-06-04 09:28:13 +04:00
int timeout , time_t starttime )
2006-02-28 07:38:53 +03:00
{
2006-07-22 20:56:33 +04:00
struct lldb_context * ac ;
struct ldb_handle * h ;
2005-08-18 19:02:01 +04:00
2006-07-22 20:56:33 +04:00
h = talloc_zero ( lldb , struct ldb_handle ) ;
2006-02-28 07:38:53 +03:00
if ( h = = NULL ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , " Out of Memory " ) ;
2006-02-28 07:38:53 +03:00
return NULL ;
2005-08-18 19:02:01 +04:00
}
2006-03-08 00:08:09 +03:00
h - > module = module ;
2006-07-22 20:56:33 +04:00
ac = talloc ( h , struct lldb_context ) ;
2006-02-28 07:38:53 +03:00
if ( ac = = NULL ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , " Out of Memory " ) ;
2006-02-28 07:38:53 +03:00
talloc_free ( h ) ;
return NULL ;
2004-10-20 23:28:02 +04:00
}
2006-02-28 07:38:53 +03:00
h - > private_data = ( void * ) ac ;
2004-10-20 23:28:02 +04:00
2006-03-10 18:27:16 +03:00
h - > state = LDB_ASYNC_INIT ;
h - > status = LDB_SUCCESS ;
2006-02-28 07:38:53 +03:00
ac - > module = module ;
ac - > context = context ;
ac - > callback = callback ;
ac - > timeout = timeout ;
2006-06-04 09:28:13 +04:00
ac - > starttime = starttime ;
2006-02-28 07:38:53 +03:00
ac - > msgid = 0 ;
2005-08-18 19:02:01 +04:00
2006-02-28 07:38:53 +03:00
return h ;
2004-10-20 23:28:02 +04:00
}
2004-03-31 10:45:39 +04:00
/*
2006-02-28 07:38:53 +03:00
convert a ldb_message structure to a list of LDAPMod structures
ready for ldap_add ( ) or ldap_modify ( )
2004-03-31 10:45:39 +04:00
*/
2006-02-28 07:38:53 +03:00
static LDAPMod * * lldb_msg_to_mods ( void * mem_ctx , const struct ldb_message * msg , int use_flags )
2004-03-31 10:45:39 +04:00
{
2006-02-28 07:38:53 +03:00
LDAPMod * * mods ;
unsigned int i , j ;
int num_mods = 0 ;
2004-05-01 13:45:56 +04:00
2006-02-28 07:38:53 +03:00
/* allocate maximum number of elements needed */
mods = talloc_array ( mem_ctx , LDAPMod * , msg - > num_elements + 1 ) ;
if ( ! mods ) {
errno = ENOMEM ;
return NULL ;
2004-05-01 13:45:56 +04:00
}
2006-02-28 07:38:53 +03:00
mods [ 0 ] = NULL ;
2005-08-18 19:02:01 +04:00
2006-02-28 07:38:53 +03:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
const struct ldb_message_element * el = & msg - > elements [ i ] ;
2005-08-18 19:02:01 +04:00
2006-02-28 07:38:53 +03:00
mods [ num_mods ] = talloc ( mods , LDAPMod ) ;
if ( ! mods [ num_mods ] ) {
goto failed ;
}
mods [ num_mods + 1 ] = NULL ;
mods [ num_mods ] - > mod_op = LDAP_MOD_BVALUES ;
if ( use_flags ) {
switch ( el - > flags & LDB_FLAG_MOD_MASK ) {
case LDB_FLAG_MOD_ADD :
mods [ num_mods ] - > mod_op | = LDAP_MOD_ADD ;
break ;
case LDB_FLAG_MOD_DELETE :
mods [ num_mods ] - > mod_op | = LDAP_MOD_DELETE ;
break ;
case LDB_FLAG_MOD_REPLACE :
mods [ num_mods ] - > mod_op | = LDAP_MOD_REPLACE ;
break ;
}
}
mods [ num_mods ] - > mod_type = discard_const_p ( char , el - > name ) ;
mods [ num_mods ] - > mod_vals . modv_bvals = talloc_array ( mods [ num_mods ] ,
struct berval * ,
1 + el - > num_values ) ;
if ( ! mods [ num_mods ] - > mod_vals . modv_bvals ) {
goto failed ;
}
for ( j = 0 ; j < el - > num_values ; j + + ) {
mods [ num_mods ] - > mod_vals . modv_bvals [ j ] = talloc ( mods [ num_mods ] - > mod_vals . modv_bvals ,
struct berval ) ;
if ( ! mods [ num_mods ] - > mod_vals . modv_bvals [ j ] ) {
goto failed ;
}
mods [ num_mods ] - > mod_vals . modv_bvals [ j ] - > bv_val = el - > values [ j ] . data ;
mods [ num_mods ] - > mod_vals . modv_bvals [ j ] - > bv_len = el - > values [ j ] . length ;
}
mods [ num_mods ] - > mod_vals . modv_bvals [ j ] = NULL ;
num_mods + + ;
2004-03-31 10:45:39 +04:00
}
2006-02-28 07:38:53 +03:00
return mods ;
failed :
talloc_free ( mods ) ;
return NULL ;
2004-03-31 10:45:39 +04:00
}
/*
add a single set of ldap message values to a ldb_message
*/
2004-05-06 08:40:15 +04:00
static int lldb_add_msg_attr ( struct ldb_context * ldb ,
struct ldb_message * msg ,
2004-03-31 10:45:39 +04:00
const char * attr , struct berval * * bval )
{
int count , i ;
struct ldb_message_element * el ;
count = ldap_count_values_len ( bval ) ;
if ( count < = 0 ) {
return - 1 ;
}
2005-01-12 19:00:01 +03:00
el = talloc_realloc ( msg , msg - > elements , struct ldb_message_element ,
2005-01-02 10:49:29 +03:00
msg - > num_elements + 1 ) ;
2004-03-31 10:45:39 +04:00
if ( ! el ) {
errno = ENOMEM ;
return - 1 ;
}
msg - > elements = el ;
2004-04-03 16:29:21 +04:00
el = & msg - > elements [ msg - > num_elements ] ;
2005-01-02 10:49:29 +03:00
el - > name = talloc_strdup ( msg - > elements , attr ) ;
2004-04-03 16:29:21 +04:00
if ( ! el - > name ) {
errno = ENOMEM ;
return - 1 ;
}
el - > flags = 0 ;
el - > num_values = 0 ;
2005-01-12 19:00:01 +03:00
el - > values = talloc_array ( msg - > elements , struct ldb_val , count ) ;
2004-04-03 16:29:21 +04:00
if ( ! el - > values ) {
errno = ENOMEM ;
return - 1 ;
}
2004-03-31 10:45:39 +04:00
for ( i = 0 ; i < count ; i + + ) {
2006-09-30 11:54:20 +04:00
/* we have to ensure this is null terminated so that
ldb_msg_find_attr_as_string ( ) can work */
el - > values [ i ] . data = talloc_size ( el - > values , bval [ i ] - > bv_len + 1 ) ;
2004-04-03 16:29:21 +04:00
if ( ! el - > values [ i ] . data ) {
2006-09-30 11:54:20 +04:00
errno = ENOMEM ;
2004-03-31 10:45:39 +04:00
return - 1 ;
}
2006-09-30 11:54:20 +04:00
memcpy ( el - > values [ i ] . data , bval [ i ] - > bv_val , bval [ i ] - > bv_len ) ;
el - > values [ i ] . data [ bval [ i ] - > bv_len ] = 0 ;
2004-04-03 16:29:21 +04:00
el - > values [ i ] . length = bval [ i ] - > bv_len ;
el - > num_values + + ;
2004-03-31 10:45:39 +04:00
}
2004-04-03 16:29:21 +04:00
msg - > num_elements + + ;
2004-03-31 10:45:39 +04:00
return 0 ;
}
/*
search for matching records
*/
2006-05-30 03:46:43 +04:00
static int lldb_search ( struct ldb_module * module , struct ldb_request * req )
2004-03-31 10:45:39 +04:00
{
2006-02-28 07:38:53 +03:00
struct lldb_private * lldb = talloc_get_type ( module - > private_data , struct lldb_private ) ;
2006-07-22 20:56:33 +04:00
struct lldb_context * lldb_ac ;
2006-02-28 07:38:53 +03:00
struct timeval tv ;
int ldap_scope ;
2005-08-18 19:02:01 +04:00
char * search_base ;
2005-10-06 09:24:46 +04:00
char * expression ;
2006-02-28 07:38:53 +03:00
int ret ;
2006-07-22 21:21:59 +04:00
if ( ! req - > callback | | ! req - > context ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , " Async interface called with NULL callback function or NULL context " ) ;
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-05-29 05:30:02 +04:00
if ( req - > op . search . tree = = NULL ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , " Invalid expression parse tree " ) ;
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-05-29 05:30:02 +04:00
if ( req - > controls ! = NULL ) {
2006-02-28 07:38:53 +03:00
ldb_debug ( module - > ldb , LDB_DEBUG_WARNING , " Controls are not yet supported by ldb_ldap backend! \n " ) ;
}
2006-07-22 21:21:59 +04:00
req - > handle = init_handle ( lldb , module , req - > context , req - > callback , req - > timeout , req - > starttime ) ;
if ( req - > handle = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2004-03-31 10:45:39 +04:00
2006-07-22 21:21:59 +04:00
lldb_ac = talloc_get_type ( req - > handle - > private_data , struct lldb_context ) ;
2006-02-28 07:38:53 +03:00
2006-11-22 05:05:19 +03:00
search_base = ldb_dn_alloc_linearized ( lldb_ac , req - > op . search . base ) ;
2006-05-29 05:30:02 +04:00
if ( req - > op . search . base = = NULL ) {
2006-02-28 07:38:53 +03:00
search_base = talloc_strdup ( lldb_ac , " " ) ;
2005-08-18 19:02:01 +04:00
}
if ( search_base = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2004-11-15 15:30:28 +03:00
}
2006-05-29 05:30:02 +04:00
expression = ldb_filter_from_tree ( lldb_ac , req - > op . search . tree ) ;
2005-10-06 09:24:46 +04:00
if ( expression = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-10-06 09:24:46 +04:00
}
2006-05-29 05:30:02 +04:00
switch ( req - > op . search . scope ) {
2005-10-06 09:24:46 +04:00
case LDB_SCOPE_BASE :
ldap_scope = LDAP_SCOPE_BASE ;
break ;
case LDB_SCOPE_ONELEVEL :
ldap_scope = LDAP_SCOPE_ONELEVEL ;
break ;
default :
ldap_scope = LDAP_SCOPE_SUBTREE ;
break ;
2005-06-14 23:15:17 +04:00
}
2006-07-22 21:21:59 +04:00
tv . tv_sec = req - > timeout ;
2006-02-28 07:38:53 +03:00
tv . tv_usec = 0 ;
ret = ldap_search_ext ( lldb - > ldap , search_base , ldap_scope ,
expression ,
2006-05-29 05:30:02 +04:00
discard_const_p ( char * , req - > op . search . attrs ) ,
2006-02-28 07:38:53 +03:00
0 ,
NULL ,
NULL ,
& tv ,
LDAP_NO_LIMIT ,
& lldb_ac - > msgid ) ;
if ( ret ! = LDAP_SUCCESS ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , ldap_err2string ( ret ) ) ;
2005-11-08 03:11:45 +03:00
}
2006-02-28 07:38:53 +03:00
return lldb_ldap_to_ldb ( ret ) ;
}
2004-03-31 10:45:39 +04:00
/*
2006-02-28 07:38:53 +03:00
add a record
2004-03-31 10:45:39 +04:00
*/
2006-05-30 03:46:43 +04:00
static int lldb_add ( struct ldb_module * module , struct ldb_request * req )
2004-03-31 10:45:39 +04:00
{
2006-02-28 07:38:53 +03:00
struct lldb_private * lldb = talloc_get_type ( module - > private_data , struct lldb_private ) ;
2006-07-22 20:56:33 +04:00
struct lldb_context * lldb_ac ;
2004-03-31 10:45:39 +04:00
LDAPMod * * mods ;
2006-02-28 07:38:53 +03:00
char * dn ;
int ret ;
2004-03-31 10:45:39 +04:00
2006-02-28 07:38:53 +03:00
/* ltdb specials should not reach this point */
2006-05-29 05:30:02 +04:00
if ( ldb_dn_is_special ( req - > op . add . message - > dn ) ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_INVALID_DN_SYNTAX ;
2004-03-31 10:45:39 +04:00
}
2006-07-22 21:21:59 +04:00
req - > handle = init_handle ( lldb , module , req - > context , req - > callback , req - > timeout , req - > starttime ) ;
if ( req - > handle = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2004-03-31 10:45:39 +04:00
2006-07-22 21:21:59 +04:00
lldb_ac = talloc_get_type ( req - > handle - > private_data , struct lldb_context ) ;
2004-04-03 16:29:21 +04:00
2006-05-29 05:30:02 +04:00
mods = lldb_msg_to_mods ( lldb_ac , req - > op . add . message , 0 ) ;
2006-02-28 07:38:53 +03:00
if ( mods = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
2004-03-31 10:45:39 +04:00
}
2006-11-22 05:05:19 +03:00
dn = ldb_dn_alloc_linearized ( lldb_ac , req - > op . add . message - > dn ) ;
2006-02-28 07:38:53 +03:00
if ( dn = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2004-03-31 10:45:39 +04:00
2006-02-28 07:38:53 +03:00
ret = ldap_add_ext ( lldb - > ldap , dn , mods ,
NULL ,
NULL ,
& lldb_ac - > msgid ) ;
if ( ret ! = LDAP_SUCCESS ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , ldap_err2string ( ret ) ) ;
2006-02-28 07:38:53 +03:00
}
return lldb_ldap_to_ldb ( ret ) ;
}
2004-03-31 10:45:39 +04:00
/*
2006-02-28 07:38:53 +03:00
modify a record
2004-03-31 10:45:39 +04:00
*/
2006-05-30 03:46:43 +04:00
static int lldb_modify ( struct ldb_module * module , struct ldb_request * req )
2004-03-31 10:45:39 +04:00
{
2006-02-28 07:38:53 +03:00
struct lldb_private * lldb = talloc_get_type ( module - > private_data , struct lldb_private ) ;
2006-07-22 20:56:33 +04:00
struct lldb_context * lldb_ac ;
2004-03-31 10:45:39 +04:00
LDAPMod * * mods ;
2005-08-18 19:02:01 +04:00
char * dn ;
2006-02-28 07:38:53 +03:00
int ret ;
2004-03-31 10:45:39 +04:00
2006-02-28 07:38:53 +03:00
/* ltdb specials should not reach this point */
2006-05-29 05:30:02 +04:00
if ( ldb_dn_is_special ( req - > op . mod . message - > dn ) ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_INVALID_DN_SYNTAX ;
2004-05-01 13:45:56 +04:00
}
2006-07-22 21:21:59 +04:00
req - > handle = init_handle ( lldb , module , req - > context , req - > callback , req - > timeout , req - > starttime ) ;
if ( req - > handle = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-07-22 21:21:59 +04:00
lldb_ac = talloc_get_type ( req - > handle - > private_data , struct lldb_context ) ;
2006-02-28 07:38:53 +03:00
2006-05-29 05:30:02 +04:00
mods = lldb_msg_to_mods ( lldb_ac , req - > op . mod . message , 1 ) ;
2005-08-18 19:02:01 +04:00
if ( mods = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-08-18 19:02:01 +04:00
}
2006-11-22 05:05:19 +03:00
dn = ldb_dn_alloc_linearized ( lldb_ac , req - > op . mod . message - > dn ) ;
2005-08-18 19:02:01 +04:00
if ( dn = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-08-18 19:02:01 +04:00
}
2004-03-31 10:45:39 +04:00
2006-02-28 07:38:53 +03:00
ret = ldap_modify_ext ( lldb - > ldap , dn , mods ,
NULL ,
NULL ,
& lldb_ac - > msgid ) ;
if ( ret ! = LDAP_SUCCESS ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , ldap_err2string ( ret ) ) ;
2004-03-31 10:45:39 +04:00
}
2006-02-28 07:38:53 +03:00
return lldb_ldap_to_ldb ( ret ) ;
}
2004-03-31 10:45:39 +04:00
2006-02-28 07:38:53 +03:00
/*
delete a record
*/
2006-05-30 03:46:43 +04:00
static int lldb_delete ( struct ldb_module * module , struct ldb_request * req )
2006-02-28 07:38:53 +03:00
{
struct lldb_private * lldb = talloc_get_type ( module - > private_data , struct lldb_private ) ;
2006-07-22 20:56:33 +04:00
struct lldb_context * lldb_ac ;
2006-02-28 07:38:53 +03:00
char * dnstr ;
int ret ;
/* ltdb specials should not reach this point */
2006-05-29 05:30:02 +04:00
if ( ldb_dn_is_special ( req - > op . del . dn ) ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_INVALID_DN_SYNTAX ;
}
2006-07-22 21:21:59 +04:00
req - > handle = init_handle ( lldb , module , req - > context , req - > callback , req - > timeout , req - > starttime ) ;
if ( req - > handle = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-07-22 21:21:59 +04:00
lldb_ac = talloc_get_type ( req - > handle - > private_data , struct lldb_context ) ;
2006-02-28 07:38:53 +03:00
2006-11-22 05:05:19 +03:00
dnstr = ldb_dn_alloc_linearized ( lldb_ac , req - > op . del . dn ) ;
2006-02-28 07:38:53 +03:00
ret = ldap_delete_ext ( lldb - > ldap , dnstr ,
NULL ,
NULL ,
& lldb_ac - > msgid ) ;
if ( ret ! = LDAP_SUCCESS ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , ldap_err2string ( ret ) ) ;
2006-02-28 07:38:53 +03:00
}
return lldb_ldap_to_ldb ( ret ) ;
}
2004-03-31 10:45:39 +04:00
/*
2006-02-28 07:38:53 +03:00
rename a record
2004-03-31 10:45:39 +04:00
*/
2006-05-30 03:46:43 +04:00
static int lldb_rename ( struct ldb_module * module , struct ldb_request * req )
2004-03-31 10:45:39 +04:00
{
2006-02-28 07:38:53 +03:00
struct lldb_private * lldb = talloc_get_type ( module - > private_data , struct lldb_private ) ;
2006-07-22 20:56:33 +04:00
struct lldb_context * lldb_ac ;
2006-02-28 07:38:53 +03:00
char * old_dn ;
char * newrdn ;
char * parentdn ;
int ret ;
/* ltdb specials should not reach this point */
2006-05-29 05:30:02 +04:00
if ( ldb_dn_is_special ( req - > op . rename . olddn ) | | ldb_dn_is_special ( req - > op . rename . newdn ) ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_INVALID_DN_SYNTAX ;
}
2006-07-22 21:21:59 +04:00
req - > handle = init_handle ( lldb , module , req - > context , req - > callback , req - > timeout , req - > starttime ) ;
if ( req - > handle = = NULL ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-07-22 21:21:59 +04:00
lldb_ac = talloc_get_type ( req - > handle - > private_data , struct lldb_context ) ;
2006-02-28 07:38:53 +03:00
2006-11-22 05:05:19 +03:00
old_dn = ldb_dn_alloc_linearized ( lldb_ac , req - > op . rename . olddn ) ;
2006-02-28 07:38:53 +03:00
if ( old_dn = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
newrdn = talloc_asprintf ( lldb_ac , " %s=%s " ,
2006-11-02 03:32:42 +03:00
ldb_dn_get_rdn_name ( req - > op . rename . newdn ) ,
ldb_dn_escape_value ( lldb , * ( ldb_dn_get_rdn_val ( req - > op . rename . newdn ) ) ) ) ;
2006-02-28 07:38:53 +03:00
if ( ! newrdn ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-11-22 05:05:19 +03:00
parentdn = ldb_dn_alloc_linearized ( lldb_ac , ldb_dn_get_parent ( lldb_ac , req - > op . rename . newdn ) ) ;
2006-02-28 07:38:53 +03:00
if ( ! parentdn ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
ret = ldap_rename ( lldb - > ldap , old_dn , newrdn , parentdn ,
1 , NULL , NULL ,
& lldb_ac - > msgid ) ;
if ( ret ! = LDAP_SUCCESS ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , ldap_err2string ( ret ) ) ;
2006-02-28 07:38:53 +03:00
}
return lldb_ldap_to_ldb ( ret ) ;
}
2006-07-22 20:56:33 +04:00
static int lldb_parse_result ( struct ldb_handle * handle , LDAPMessage * result )
2006-02-28 07:38:53 +03:00
{
2006-07-22 20:56:33 +04:00
struct lldb_context * ac = talloc_get_type ( handle - > private_data , struct lldb_context ) ;
2006-02-28 07:38:53 +03:00
struct lldb_private * lldb = talloc_get_type ( ac - > module - > private_data , struct lldb_private ) ;
2006-07-22 20:56:33 +04:00
struct ldb_reply * ares = NULL ;
2006-02-28 07:38:53 +03:00
LDAPMessage * msg ;
int type ;
char * matcheddnp = NULL ;
char * errmsgp = NULL ;
char * * referralsp = NULL ;
LDAPControl * * serverctrlsp = NULL ;
2006-05-28 06:10:44 +04:00
int ret = LDB_SUCCESS ;
2006-10-14 08:43:51 +04:00
2006-02-28 07:38:53 +03:00
type = ldap_msgtype ( result ) ;
2006-10-14 08:43:51 +04:00
handle - > status = 0 ;
2006-02-28 07:38:53 +03:00
switch ( type ) {
case LDAP_RES_SEARCH_ENTRY :
msg = ldap_first_entry ( lldb - > ldap , result ) ;
if ( msg ! = NULL ) {
BerElement * berptr = NULL ;
char * attr , * dn ;
2006-07-22 20:56:33 +04:00
ares = talloc_zero ( ac , struct ldb_reply ) ;
2006-02-28 07:38:53 +03:00
if ( ! ares ) {
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
goto error ;
}
ares - > message = ldb_msg_new ( ares ) ;
if ( ! ares - > message ) {
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
goto error ;
}
dn = ldap_get_dn ( lldb - > ldap , msg ) ;
if ( ! dn ) {
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
goto error ;
}
2006-11-22 03:59:34 +03:00
ares - > message - > dn = ldb_dn_new ( ares - > message , ac - > module - > ldb , dn ) ;
if ( ! ldb_dn_validate ( ares - > message - > dn ) ) {
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
goto error ;
}
ldap_memfree ( dn ) ;
ares - > message - > num_elements = 0 ;
ares - > message - > elements = NULL ;
ares - > message - > private_data = NULL ;
/* loop over all attributes */
for ( attr = ldap_first_attribute ( lldb - > ldap , msg , & berptr ) ;
attr ;
attr = ldap_next_attribute ( lldb - > ldap , msg , berptr ) ) {
struct berval * * bval ;
bval = ldap_get_values_len ( lldb - > ldap , msg , attr ) ;
if ( bval ) {
lldb_add_msg_attr ( ac - > module - > ldb , ares - > message , attr , bval ) ;
ldap_value_free_len ( bval ) ;
}
}
if ( berptr ) ber_free ( berptr , 0 ) ;
ares - > type = LDB_REPLY_ENTRY ;
2006-03-07 23:43:40 +03:00
ret = ac - > callback ( ac - > module - > ldb , ac - > context , ares ) ;
} else {
handle - > status = LDB_ERR_PROTOCOL_ERROR ;
handle - > state = LDB_ASYNC_DONE ;
2006-02-28 07:38:53 +03:00
}
break ;
case LDAP_RES_SEARCH_REFERENCE :
if ( ldap_parse_result ( lldb - > ldap , result , & handle - > status ,
& matcheddnp , & errmsgp ,
2006-08-22 05:13:45 +04:00
& referralsp , & serverctrlsp , 0 ) ! = LDAP_SUCCESS ) {
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
goto error ;
}
if ( referralsp = = NULL ) {
handle - > status = LDB_ERR_PROTOCOL_ERROR ;
goto error ;
}
2006-07-22 20:56:33 +04:00
ares = talloc_zero ( ac , struct ldb_reply ) ;
2006-02-28 07:38:53 +03:00
if ( ! ares ) {
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
goto error ;
}
ares - > referral = talloc_strdup ( ares , * referralsp ) ;
ares - > type = LDB_REPLY_REFERRAL ;
2006-03-07 23:43:40 +03:00
ret = ac - > callback ( ac - > module - > ldb , ac - > context , ares ) ;
2006-02-28 07:38:53 +03:00
break ;
case LDAP_RES_SEARCH_RESULT :
if ( ldap_parse_result ( lldb - > ldap , result , & handle - > status ,
& matcheddnp , & errmsgp ,
2006-08-22 05:13:45 +04:00
& referralsp , & serverctrlsp , 0 ) ! = LDAP_SUCCESS ) {
2006-02-28 07:38:53 +03:00
handle - > status = LDB_ERR_OPERATIONS_ERROR ;
goto error ;
}
2006-07-22 20:56:33 +04:00
ares = talloc_zero ( ac , struct ldb_reply ) ;
2006-02-28 07:38:53 +03:00
if ( ! ares ) {
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
goto error ;
}
if ( serverctrlsp ! = NULL ) {
/* FIXME: transform the LDAPControl list into an ldb_control one */
ares - > controls = NULL ;
}
ares - > type = LDB_REPLY_DONE ;
handle - > state = LDB_ASYNC_DONE ;
2006-03-07 23:43:40 +03:00
ret = ac - > callback ( ac - > module - > ldb , ac - > context , ares ) ;
2006-02-28 07:38:53 +03:00
break ;
case LDAP_RES_MODIFY :
case LDAP_RES_ADD :
case LDAP_RES_DELETE :
case LDAP_RES_MODDN :
if ( ldap_parse_result ( lldb - > ldap , result , & handle - > status ,
& matcheddnp , & errmsgp ,
2006-08-22 05:13:45 +04:00
& referralsp , & serverctrlsp , 0 ) ! = LDAP_SUCCESS ) {
2006-02-28 07:38:53 +03:00
handle - > status = LDB_ERR_OPERATIONS_ERROR ;
goto error ;
}
if ( ac - > callback & & handle - > status = = LDB_SUCCESS ) {
ares = NULL ; /* FIXME: build a corresponding ares to pass on */
2006-05-28 06:10:44 +04:00
ret = ac - > callback ( ac - > module - > ldb , ac - > context , ares ) ;
2006-02-28 07:38:53 +03:00
}
handle - > state = LDB_ASYNC_DONE ;
break ;
default :
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_PROTOCOL_ERROR ;
2006-03-07 23:43:40 +03:00
goto error ;
2005-08-18 19:02:01 +04:00
}
2006-02-28 07:38:53 +03:00
if ( matcheddnp ) ldap_memfree ( matcheddnp ) ;
2006-10-14 08:43:51 +04:00
if ( errmsgp & & * errmsgp ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( ac - > module - > ldb , errmsgp ) ;
2006-10-14 08:43:51 +04:00
} else if ( handle - > status ) {
ldb_set_errstring ( ac - > module - > ldb , ldap_err2string ( handle - > status ) ) ;
}
if ( errmsgp ) {
2006-02-28 07:38:53 +03:00
ldap_memfree ( errmsgp ) ;
2005-08-18 19:02:01 +04:00
}
2006-02-28 07:38:53 +03:00
if ( referralsp ) ldap_value_free ( referralsp ) ;
if ( serverctrlsp ) ldap_controls_free ( serverctrlsp ) ;
2006-03-07 23:43:40 +03:00
ldap_msgfree ( result ) ;
2006-10-14 08:43:51 +04:00
return lldb_ldap_to_ldb ( handle - > status ) ;
2006-02-28 07:38:53 +03:00
error :
handle - > state = LDB_ASYNC_DONE ;
2006-03-07 23:43:40 +03:00
ldap_msgfree ( result ) ;
2006-05-28 06:10:44 +04:00
return ret ;
2006-02-28 07:38:53 +03:00
}
2004-03-31 10:45:39 +04:00
2006-07-22 20:56:33 +04:00
static int lldb_wait ( struct ldb_handle * handle , enum ldb_wait_type type )
2006-02-28 07:38:53 +03:00
{
2006-07-22 20:56:33 +04:00
struct lldb_context * ac = talloc_get_type ( handle - > private_data , struct lldb_context ) ;
2006-03-08 00:08:09 +03:00
struct lldb_private * lldb = talloc_get_type ( handle - > module - > private_data , struct lldb_private ) ;
2006-02-28 07:38:53 +03:00
struct timeval timeout ;
LDAPMessage * result ;
2006-05-28 06:10:44 +04:00
int ret , lret ;
2006-02-28 07:38:53 +03:00
2006-03-10 18:27:16 +03:00
if ( handle - > state = = LDB_ASYNC_DONE ) {
return handle - > status ;
}
if ( ! ac | | ! ac - > msgid ) {
2006-02-28 07:38:53 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2004-03-31 10:45:39 +04:00
}
2006-05-28 06:10:44 +04:00
handle - > state = LDB_ASYNC_PENDING ;
2006-02-28 07:38:53 +03:00
handle - > status = LDB_SUCCESS ;
switch ( type ) {
case LDB_WAIT_NONE :
2006-06-04 09:28:13 +04:00
if ( ( ac - > timeout ! = - 1 ) & &
2006-07-18 16:11:02 +04:00
( ( ac - > starttime + ac - > timeout ) > time ( NULL ) ) ) {
2006-06-04 09:28:13 +04:00
return LDB_ERR_TIME_LIMIT_EXCEEDED ;
}
2006-02-28 07:38:53 +03:00
timeout . tv_sec = 0 ;
timeout . tv_usec = 0 ;
2006-05-28 06:10:44 +04:00
lret = ldap_result ( lldb - > ldap , ac - > msgid , 0 , & timeout , & result ) ;
if ( lret = = - 1 ) {
return LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
}
2006-05-28 06:10:44 +04:00
if ( lret = = 0 ) {
ret = LDB_SUCCESS ;
goto done ;
2006-02-28 07:38:53 +03:00
}
2006-05-28 06:10:44 +04:00
return lldb_parse_result ( handle , result ) ;
2006-02-28 07:38:53 +03:00
case LDB_WAIT_ALL :
timeout . tv_usec = 0 ;
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
while ( handle - > status = = LDB_SUCCESS & & handle - > state ! = LDB_ASYNC_DONE ) {
2006-05-28 06:10:44 +04:00
2006-06-04 09:28:13 +04:00
if ( ac - > timeout = = - 1 ) {
lret = ldap_result ( lldb - > ldap , ac - > msgid , 0 , NULL , & result ) ;
} else {
timeout . tv_sec = ac - > timeout - ( time ( NULL ) - ac - > starttime ) ;
if ( timeout . tv_sec < = 0 )
return LDB_ERR_TIME_LIMIT_EXCEEDED ;
lret = ldap_result ( lldb - > ldap , ac - > msgid , 0 , & timeout , & result ) ;
}
2006-05-28 06:10:44 +04:00
if ( lret = = - 1 ) {
return LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
}
2006-05-28 06:10:44 +04:00
if ( lret = = 0 ) {
return LDB_ERR_TIME_LIMIT_EXCEEDED ;
}
2006-02-28 07:38:53 +03:00
ret = lldb_parse_result ( handle , result ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
}
2006-05-28 06:10:44 +04:00
2006-02-28 07:38:53 +03:00
break ;
2006-05-28 06:10:44 +04:00
default :
handle - > state = LDB_ASYNC_DONE ;
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
}
2004-03-31 10:45:39 +04:00
2006-05-28 06:10:44 +04:00
done :
2004-03-31 10:45:39 +04:00
return ret ;
}
2005-09-17 23:25:50 +04:00
static int lldb_start_trans ( struct ldb_module * module )
2004-11-21 18:51:54 +03:00
{
2005-09-17 23:25:50 +04:00
/* TODO implement a local transaction mechanism here */
2004-11-21 18:51:54 +03:00
2006-05-30 03:46:43 +04:00
return LDB_SUCCESS ;
2004-11-21 18:51:54 +03:00
}
2005-09-24 19:42:15 +04:00
static int lldb_end_trans ( struct ldb_module * module )
2004-11-21 18:51:54 +03:00
{
2005-09-17 23:25:50 +04:00
/* TODO implement a local transaction mechanism here */
2004-11-21 18:51:54 +03:00
2006-05-30 03:46:43 +04:00
return LDB_SUCCESS ;
2005-09-24 19:42:15 +04:00
}
static int lldb_del_trans ( struct ldb_module * module )
{
/* TODO implement a local transaction mechanism here */
2006-05-30 03:46:43 +04:00
return LDB_SUCCESS ;
2004-11-21 18:51:54 +03:00
}
2004-03-31 10:45:39 +04:00
2005-11-08 03:11:45 +03:00
static int lldb_request ( struct ldb_module * module , struct ldb_request * req )
{
2006-05-30 03:46:43 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-11-08 03:11:45 +03:00
}
2004-11-15 14:40:27 +03:00
static const struct ldb_module_ops lldb_ops = {
2005-09-17 23:25:50 +04:00
. name = " ldap " ,
2006-05-30 03:46:43 +04:00
. search = lldb_search ,
. add = lldb_add ,
. modify = lldb_modify ,
. del = lldb_delete ,
. rename = lldb_rename ,
2005-11-08 03:11:45 +03:00
. request = lldb_request ,
2005-09-17 23:25:50 +04:00
. start_transaction = lldb_start_trans ,
2005-09-24 19:42:15 +04:00
. end_transaction = lldb_end_trans ,
2006-01-06 19:12:45 +03:00
. del_transaction = lldb_del_trans ,
2006-07-22 20:56:33 +04:00
. wait = lldb_wait
2004-03-31 10:45:39 +04:00
} ;
2006-05-24 11:34:11 +04:00
static int lldb_destructor ( struct lldb_private * lldb )
2005-01-02 10:49:29 +03:00
{
ldap_unbind ( lldb - > ldap ) ;
return 0 ;
}
2004-03-31 10:45:39 +04:00
/*
connect to the database
*/
2006-03-05 19:05:26 +03:00
static int lldb_connect ( struct ldb_context * ldb ,
2006-06-08 01:03:38 +04:00
const char * url ,
unsigned int flags ,
const char * options [ ] ,
2006-12-12 21:25:19 +03:00
struct ldb_module * * _module )
2004-03-31 10:45:39 +04:00
{
2006-12-12 21:25:19 +03:00
struct ldb_module * module ;
struct lldb_private * lldb ;
2005-06-18 11:42:21 +04:00
int version = 3 ;
2006-02-28 07:38:53 +03:00
int ret ;
2005-06-13 10:02:55 +04:00
2006-12-12 21:25:19 +03:00
module = talloc ( ldb , struct ldb_module ) ;
if ( module = = NULL ) {
ldb_oom ( ldb ) ;
talloc_free ( lldb ) ;
return - 1 ;
}
talloc_set_name_const ( module , " ldb_ldap backend " ) ;
module - > ldb = ldb ;
module - > prev = module - > next = NULL ;
module - > private_data = NULL ;
module - > ops = & lldb_ops ;
lldb = talloc ( module , struct lldb_private ) ;
2004-03-31 10:45:39 +04:00
if ( ! lldb ) {
2005-06-18 11:42:21 +04:00
ldb_oom ( ldb ) ;
2004-03-31 10:45:39 +04:00
goto failed ;
}
2006-12-12 21:25:19 +03:00
module - > private_data = lldb ;
lldb - > module = module ;
lldb - > ldap = NULL ;
2004-03-31 10:45:39 +04:00
2006-02-28 07:38:53 +03:00
ret = ldap_initialize ( & lldb - > ldap , url ) ;
if ( ret ! = LDAP_SUCCESS ) {
2005-06-18 11:42:21 +04:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " ldap_initialize failed for URL '%s' - %s \n " ,
2006-02-28 07:38:53 +03:00
url , ldap_err2string ( ret ) ) ;
2004-03-31 10:45:39 +04:00
goto failed ;
}
2005-01-02 10:49:29 +03:00
talloc_set_destructor ( lldb , lldb_destructor ) ;
2006-02-28 07:38:53 +03:00
ret = ldap_set_option ( lldb - > ldap , LDAP_OPT_PROTOCOL_VERSION , & version ) ;
if ( ret ! = LDAP_SUCCESS ) {
2005-06-18 11:42:21 +04:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " ldap_set_option failed - %s \n " ,
2006-02-28 07:38:53 +03:00
ldap_err2string ( ret ) ) ;
goto failed ;
2004-10-20 23:28:02 +04:00
}
2006-12-12 21:25:19 +03:00
* _module = module ;
2005-06-18 11:42:21 +04:00
return 0 ;
2004-03-31 10:45:39 +04:00
failed :
2006-12-12 21:25:19 +03:00
talloc_free ( module ) ;
2005-06-18 11:42:21 +04:00
return - 1 ;
2004-03-31 10:45:39 +04:00
}
2004-04-11 00:18:22 +04:00
2006-03-05 19:05:26 +03:00
int ldb_ldap_init ( void )
{
2006-03-21 00:44:59 +03:00
return ldb_register_backend ( " ldap " , lldb_connect ) +
ldb_register_backend ( " ldapi " , lldb_connect ) +
ldb_register_backend ( " ldaps " , lldb_connect ) ;
2006-03-05 19:05:26 +03:00
}