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
2007-07-10 06:46:15 +04:00
version 3 of the License , or ( at your option ) any later version .
2004-03-31 10:45:39 +04:00
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
2007-07-10 07:42:26 +04:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2004-03-31 10:45:39 +04:00
*/
/*
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 :
*
2010-02-21 09:22:45 +03:00
* - description : make the module use asynchronous calls
2006-02-28 07:38:53 +03:00
* date : Feb 2006
* author : Simo Sorce
2004-03-31 10:45:39 +04:00
*/
2009-02-24 01:35:49 +03:00
# include "ldb_includes.h"
2009-01-30 02:39:30 +03:00
# include "ldb_module.h"
2010-07-06 09:36:21 +04:00
# include "ldb_private.h"
2006-01-10 19:48:32 +03:00
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 ;
} ;
2004-10-20 23:28:02 +04:00
2006-07-22 20:56:33 +04:00
struct lldb_context {
2008-09-12 02:34:56 +04:00
struct ldb_module * module ;
struct ldb_request * req ;
2006-12-12 21:45:12 +03:00
struct lldb_private * lldb ;
2008-09-12 02:34:56 +04:00
struct ldb_control * * controls ;
2006-02-28 07:38:53 +03:00
int msgid ;
} ;
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
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 ) {
2008-09-25 01:59:59 +04:00
return - 1 ;
2004-03-31 10:45:39 +04:00
}
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 ;
2008-09-25 01:59:59 +04:00
return - 1 ;
2004-03-31 10:45:39 +04:00
}
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 ;
2008-09-25 01:59:59 +04:00
return - 1 ;
2004-04-03 16:29:21 +04:00
}
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 ;
2008-09-25 01:59:59 +04:00
return - 1 ;
2004-04-03 16:29:21 +04:00
}
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 ;
2008-09-25 01:59:59 +04:00
return - 1 ;
2004-03-31 10:45:39 +04:00
}
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 + + ;
2008-09-25 01:59:59 +04:00
return 0 ;
2004-03-31 10:45:39 +04:00
}
/*
search for matching records
*/
2008-09-12 02:34:56 +04:00
static int lldb_search ( struct lldb_context * lldb_ac )
2004-03-31 10:45:39 +04:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:34:56 +04:00
struct lldb_private * lldb = lldb_ac - > lldb ;
struct ldb_module * module = lldb_ac - > module ;
struct ldb_request * req = lldb_ac - > req ;
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 ;
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( module ) ;
2006-07-22 21:21:59 +04:00
if ( ! req - > callback | | ! req - > context ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( 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 ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( 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 ) {
2009-07-11 00:44:27 +04:00
ldb_debug ( ldb , LDB_DEBUG_WARNING , " Controls are not yet supported by ldb_ldap backend! " ) ;
2006-02-28 07:38:53 +03:00
}
2009-01-30 02:39:30 +03:00
ldb_request_set_state ( req , LDB_ASYNC_PENDING ) ;
2004-03-31 10:45:39 +04: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 ,
2009-10-18 00:27:42 +04:00
expression ,
discard_const_p ( char * , req - > op . search . attrs ) ,
0 ,
NULL ,
NULL ,
& tv ,
LDAP_NO_LIMIT ,
& lldb_ac - > msgid ) ;
2006-02-28 07:38:53 +03:00
if ( ret ! = LDAP_SUCCESS ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( 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
*/
2008-09-12 02:34:56 +04:00
static int lldb_add ( struct lldb_context * lldb_ac )
2004-03-31 10:45:39 +04:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:34:56 +04:00
struct lldb_private * lldb = lldb_ac - > lldb ;
struct ldb_module * module = lldb_ac - > module ;
struct ldb_request * req = lldb_ac - > req ;
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
2010-07-02 05:39:28 +04:00
ldb = ldb_module_get_ctx ( module ) ;
2009-01-30 02:39:30 +03:00
ldb_request_set_state ( req , LDB_ASYNC_PENDING ) ;
2004-03-31 10:45:39 +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 ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( 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
*/
2008-09-12 02:34:56 +04:00
static int lldb_modify ( struct lldb_context * lldb_ac )
2004-03-31 10:45:39 +04:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:34:56 +04:00
struct lldb_private * lldb = lldb_ac - > lldb ;
struct ldb_module * module = lldb_ac - > module ;
struct ldb_request * req = lldb_ac - > req ;
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
2010-07-02 05:39:28 +04:00
ldb = ldb_module_get_ctx ( module ) ;
2009-01-30 02:39:30 +03:00
ldb_request_set_state ( req , LDB_ASYNC_PENDING ) ;
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 ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( 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
*/
2008-09-12 02:34:56 +04:00
static int lldb_delete ( struct lldb_context * lldb_ac )
2006-02-28 07:38:53 +03:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:34:56 +04:00
struct lldb_private * lldb = lldb_ac - > lldb ;
struct ldb_module * module = lldb_ac - > module ;
struct ldb_request * req = lldb_ac - > req ;
2006-02-28 07:38:53 +03:00
char * dnstr ;
int ret ;
2010-07-02 05:39:28 +04:00
ldb = ldb_module_get_ctx ( module ) ;
2009-01-30 02:39:30 +03:00
ldb_request_set_state ( req , LDB_ASYNC_PENDING ) ;
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 ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( 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
*/
2008-09-12 02:34:56 +04:00
static int lldb_rename ( struct lldb_context * lldb_ac )
2004-03-31 10:45:39 +04:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:34:56 +04:00
struct lldb_private * lldb = lldb_ac - > lldb ;
struct ldb_module * module = lldb_ac - > module ;
struct ldb_request * req = lldb_ac - > req ;
2006-02-28 07:38:53 +03:00
char * old_dn ;
2010-03-08 11:58:28 +03:00
char * newrdn ;
2006-02-28 07:38:53 +03:00
char * parentdn ;
int ret ;
2010-07-02 05:39:28 +04:00
ldb = ldb_module_get_ctx ( module ) ;
2009-01-30 02:39:30 +03:00
ldb_request_set_state ( req , LDB_ASYNC_PENDING ) ;
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 ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( ldb , ldap_err2string ( ret ) ) ;
2006-02-28 07:38:53 +03:00
}
return lldb_ldap_to_ldb ( ret ) ;
}
2008-09-12 02:34:56 +04:00
static int lldb_start_trans ( struct ldb_module * module )
{
/* TODO implement a local transaction mechanism here */
return LDB_SUCCESS ;
}
static int lldb_end_trans ( struct ldb_module * module )
{
/* TODO implement a local transaction mechanism here */
return LDB_SUCCESS ;
}
static int lldb_del_trans ( struct ldb_module * module )
{
/* TODO implement a local transaction mechanism here */
return LDB_SUCCESS ;
}
2009-01-30 02:39:30 +03:00
void lldb_request_done ( struct lldb_context * ac ,
2008-09-12 02:34:56 +04:00
struct ldb_control * * ctrls , int error )
{
2009-01-30 02:39:30 +03:00
struct ldb_request * req ;
2008-09-12 02:34:56 +04:00
struct ldb_reply * ares ;
2009-01-30 02:39:30 +03:00
req = ac - > req ;
2008-09-12 02:34:56 +04:00
ares = talloc_zero ( req , struct ldb_reply ) ;
if ( ! ares ) {
2009-01-30 02:39:30 +03:00
ldb_oom ( ldb_module_get_ctx ( ac - > module ) ) ;
2008-09-12 02:34:56 +04:00
req - > callback ( req , NULL ) ;
return ;
}
ares - > type = LDB_REPLY_DONE ;
ares - > controls = talloc_steal ( ares , ctrls ) ;
ares - > error = error ;
req - > callback ( req , ares ) ;
}
/* return false if the request is still in progress
* return true if the request is completed
*/
static bool lldb_parse_result ( struct lldb_context * ac , LDAPMessage * result )
2006-02-28 07:38:53 +03:00
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2006-12-12 21:45:12 +03:00
struct lldb_private * lldb = ac - > lldb ;
2008-09-12 02:34:56 +04:00
LDAPControl * * serverctrlsp = NULL ;
char * * referralsp = NULL ;
2006-02-28 07:38:53 +03:00
char * matcheddnp = NULL ;
char * errmsgp = NULL ;
2008-09-12 02:34:56 +04:00
LDAPMessage * msg ;
int type ;
struct ldb_message * ldbmsg ;
char * referral ;
bool callback_failed ;
bool request_done ;
bool lret ;
2009-11-06 20:35:17 +03:00
unsigned int i ;
2008-09-12 02:34:56 +04:00
int ret ;
2006-02-28 07:38:53 +03:00
2009-01-30 02:39:30 +03:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2008-09-12 02:34:56 +04:00
type = ldap_msgtype ( result ) ;
callback_failed = false ;
request_done = false ;
2006-10-14 08:43:51 +04:00
2006-02-28 07:38:53 +03:00
switch ( type ) {
case LDAP_RES_SEARCH_ENTRY :
2008-09-12 02:34:56 +04:00
2006-02-28 07:38:53 +03:00
msg = ldap_first_entry ( lldb - > ldap , result ) ;
if ( msg ! = NULL ) {
BerElement * berptr = NULL ;
char * attr , * dn ;
2008-09-12 02:34:56 +04:00
ldbmsg = ldb_msg_new ( ac ) ;
if ( ! ldbmsg ) {
2010-07-02 05:39:28 +04:00
ldb_oom ( ldb ) ;
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2008-09-12 02:34:56 +04:00
break ;
2006-02-28 07:38:53 +03:00
}
dn = ldap_get_dn ( lldb - > ldap , msg ) ;
if ( ! dn ) {
2010-07-02 05:39:28 +04:00
ldb_oom ( ldb ) ;
2008-09-12 02:34:56 +04:00
talloc_free ( ldbmsg ) ;
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2008-09-12 02:34:56 +04:00
break ;
2006-02-28 07:38:53 +03:00
}
2009-01-30 02:39:30 +03:00
ldbmsg - > dn = ldb_dn_new ( ldbmsg , ldb , dn ) ;
2008-09-12 02:34:56 +04:00
if ( ! ldb_dn_validate ( ldbmsg - > dn ) ) {
2010-07-02 05:39:28 +04:00
ldb_asprintf_errstring ( ldb , " Invalid DN '%s' in reply " , dn ) ;
2008-09-12 02:34:56 +04:00
talloc_free ( ldbmsg ) ;
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2010-07-02 05:39:28 +04:00
ldap_memfree ( dn ) ;
2008-09-12 02:34:56 +04:00
break ;
2006-02-28 07:38:53 +03:00
}
ldap_memfree ( dn ) ;
2008-09-12 02:34:56 +04:00
ldbmsg - > num_elements = 0 ;
ldbmsg - > elements = NULL ;
2006-02-28 07:38:53 +03:00
/* 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 ) {
2009-01-30 02:39:30 +03:00
lldb_add_msg_attr ( ldb , ldbmsg , attr , bval ) ;
2006-02-28 07:38:53 +03:00
ldap_value_free_len ( bval ) ;
2008-09-12 02:34:56 +04:00
}
2006-02-28 07:38:53 +03:00
}
if ( berptr ) ber_free ( berptr , 0 ) ;
2008-12-16 10:59:05 +03:00
ret = ldb_module_send_entry ( ac - > req , ldbmsg , NULL /* controls not yet supported */ ) ;
2008-09-12 02:34:56 +04:00
if ( ret ! = LDB_SUCCESS ) {
2010-07-02 05:39:28 +04:00
ldb_asprintf_errstring ( ldb , " entry send failed: %s " ,
ldb_errstring ( ldb ) ) ;
2008-09-12 02:34:56 +04:00
callback_failed = true ;
}
2006-03-07 23:43:40 +03:00
} else {
2008-09-12 02:34:56 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
}
break ;
case LDAP_RES_SEARCH_REFERENCE :
2008-09-12 02:34:56 +04:00
2010-07-02 05:37:50 +04:00
ret = ldap_parse_reference ( lldb - > ldap , result ,
& referralsp , & serverctrlsp , 0 ) ;
if ( ret ! = LDAP_SUCCESS ) {
ldb_asprintf_errstring ( ldb , " ldap reference parse error: %s : %s " ,
ldap_err2string ( ret ) , errmsgp ) ;
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2008-09-12 02:34:56 +04:00
break ;
2006-02-28 07:38:53 +03:00
}
2008-09-12 02:34:56 +04:00
if ( referralsp = = NULL ) {
2010-07-02 05:37:50 +04:00
ldb_asprintf_errstring ( ldb , " empty ldap referrals list " ) ;
2008-09-12 02:34:56 +04:00
ret = LDB_ERR_PROTOCOL_ERROR ;
break ;
2006-02-28 07:38:53 +03:00
}
2008-09-12 02:34:56 +04:00
for ( i = 0 ; referralsp [ i ] ; i + + ) {
referral = talloc_strdup ( ac , referralsp [ i ] ) ;
2006-02-28 07:38:53 +03:00
2008-09-12 02:34:56 +04:00
ret = ldb_module_send_referral ( ac - > req , referral ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-07-02 05:39:28 +04:00
ldb_asprintf_errstring ( ldb , " referral send failed: %s " ,
ldb_errstring ( ldb ) ) ;
2008-09-12 02:34:56 +04:00
callback_failed = true ;
break ;
}
}
2006-02-28 07:38:53 +03:00
break ;
case LDAP_RES_SEARCH_RESULT :
2008-09-12 02:34:56 +04:00
case LDAP_RES_MODIFY :
case LDAP_RES_ADD :
case LDAP_RES_DELETE :
case LDAP_RES_MODDN :
if ( ldap_parse_result ( lldb - > ldap , result , & ret ,
2006-02-28 07:38:53 +03:00
& 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 ;
2008-09-12 02:34:56 +04:00
}
if ( ret ! = LDB_SUCCESS ) {
2010-07-02 05:39:28 +04:00
ldb_asprintf_errstring ( ldb , " ldap parse error for type %d: %s : %s " ,
type , ldap_err2string ( ret ) , errmsgp ) ;
2008-09-12 02:34:56 +04:00
break ;
2006-02-28 07:38:53 +03:00
}
if ( serverctrlsp ! = NULL ) {
/* FIXME: transform the LDAPControl list into an ldb_control one */
2008-09-12 02:34:56 +04:00
ac - > controls = NULL ;
2006-02-28 07:38:53 +03:00
}
2008-09-12 02:34:56 +04:00
request_done = true ;
2006-02-28 07:38:53 +03:00
break ;
default :
2010-07-02 05:39:28 +04:00
ldb_asprintf_errstring ( ldb , " unknown ldap return type: %d " , type ) ;
2006-05-28 06:10:44 +04:00
ret = LDB_ERR_PROTOCOL_ERROR ;
2008-09-12 02:34:56 +04:00
break ;
2005-08-18 19:02:01 +04:00
}
2008-09-12 02:34:56 +04:00
if ( ret ! = LDB_SUCCESS ) {
/* if the callback failed the caller will have freed the
* request . Just return and don ' t try to use it */
if ( callback_failed ) {
/* tell lldb_wait to remove the request from the
* queue */
lret = true ;
goto free_and_return ;
}
request_done = true ;
}
if ( request_done ) {
2009-01-30 02:39:30 +03:00
lldb_request_done ( ac , ac - > controls , ret ) ;
2008-09-12 02:34:56 +04:00
lret = true ;
goto free_and_return ;
}
lret = false ;
free_and_return :
2006-02-28 07:38:53 +03:00
if ( matcheddnp ) ldap_memfree ( matcheddnp ) ;
2006-10-14 08:43:51 +04:00
if ( errmsgp & & * errmsgp ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( ldb , errmsgp ) ;
2006-10-14 08:43:51 +04:00
}
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-02-28 07:38:53 +03:00
2008-09-12 02:34:56 +04:00
return lret ;
2006-02-28 07:38:53 +03:00
}
2004-03-31 10:45:39 +04:00
2008-12-29 22:24:57 +03:00
static void lldb_timeout ( struct tevent_context * ev ,
struct tevent_timer * te ,
2008-09-12 02:34:56 +04:00
struct timeval t ,
void * private_data )
2006-02-28 07:38:53 +03:00
{
2008-09-12 02:34:56 +04:00
struct lldb_context * ac ;
ac = talloc_get_type ( private_data , struct lldb_context ) ;
2009-01-30 02:39:30 +03:00
lldb_request_done ( ac , NULL , LDB_ERR_TIME_LIMIT_EXCEEDED ) ;
2008-09-12 02:34:56 +04:00
}
2008-12-29 22:24:57 +03:00
static void lldb_callback ( struct tevent_context * ev ,
struct tevent_timer * te ,
2008-09-12 02:34:56 +04:00
struct timeval t ,
void * private_data )
{
struct lldb_context * ac ;
2008-12-29 22:24:57 +03:00
struct tevent_timer * lte ;
2008-09-12 02:34:56 +04:00
struct timeval tv ;
2006-02-28 07:38:53 +03:00
LDAPMessage * result ;
2008-09-12 02:34:56 +04:00
int lret ;
ac = talloc_get_type ( private_data , struct lldb_context ) ;
2006-02-28 07:38:53 +03:00
2008-09-12 02:34:56 +04:00
if ( ! ac - > msgid ) {
2009-01-30 02:39:30 +03:00
lldb_request_done ( ac , NULL , LDB_ERR_OPERATIONS_ERROR ) ;
2008-09-12 02:34:56 +04:00
return ;
2006-03-10 18:27:16 +03:00
}
2008-09-12 02:34:56 +04:00
tv . tv_sec = 0 ;
tv . tv_usec = 0 ;
lret = ldap_result ( ac - > lldb - > ldap , ac - > msgid , 0 , & tv , & result ) ;
if ( lret = = 0 ) {
goto respin ;
}
if ( lret = = - 1 ) {
2009-01-30 02:39:30 +03:00
lldb_request_done ( ac , NULL , LDB_ERR_OPERATIONS_ERROR ) ;
2008-09-12 02:34:56 +04:00
return ;
2004-03-31 10:45:39 +04:00
}
2008-09-12 02:34:56 +04:00
if ( ! lldb_parse_result ( ac , result ) ) {
goto respin ;
}
2006-02-28 07:38:53 +03:00
2008-09-12 02:34:56 +04:00
return ;
2006-06-04 09:28:13 +04:00
2008-09-12 02:34:56 +04:00
respin :
tv . tv_sec = 0 ;
tv . tv_usec = 100 ;
2009-01-30 02:39:30 +03:00
lte = tevent_add_timer ( ev , ac , tv , lldb_callback , ac ) ;
2008-09-12 02:34:56 +04:00
if ( NULL = = lte ) {
2009-01-30 02:39:30 +03:00
lldb_request_done ( ac , NULL , LDB_ERR_OPERATIONS_ERROR ) ;
2008-09-12 02:34:56 +04:00
}
}
2006-06-04 09:28:13 +04:00
2008-09-12 02:34:56 +04:00
static bool lldb_dn_is_special ( struct ldb_request * req )
{
struct ldb_dn * dn = NULL ;
2006-05-28 06:10:44 +04:00
2008-09-12 02:34:56 +04:00
switch ( req - > operation ) {
case LDB_ADD :
dn = req - > op . add . message - > dn ;
break ;
case LDB_MODIFY :
dn = req - > op . mod . message - > dn ;
break ;
case LDB_DELETE :
dn = req - > op . del . dn ;
break ;
case LDB_RENAME :
dn = req - > op . rename . olddn ;
break ;
default :
break ;
}
2006-05-28 06:10:44 +04:00
2008-09-12 02:34:56 +04:00
if ( dn & & ldb_dn_is_special ( dn ) ) {
return true ;
}
return false ;
}
2006-05-28 06:10:44 +04:00
2008-12-29 22:24:57 +03:00
static void lldb_auto_done_callback ( struct tevent_context * ev ,
struct tevent_timer * te ,
2008-09-12 02:34:56 +04:00
struct timeval t ,
void * private_data )
{
struct lldb_context * ac ;
2006-05-28 06:10:44 +04:00
2008-09-12 02:34:56 +04:00
ac = talloc_get_type ( private_data , struct lldb_context ) ;
2009-01-30 02:39:30 +03:00
lldb_request_done ( ac , NULL , LDB_SUCCESS ) ;
2008-09-12 02:34:56 +04:00
}
2006-05-28 06:10:44 +04:00
2008-09-12 02:34:56 +04:00
static int lldb_handle_request ( struct ldb_module * module , struct ldb_request * req )
{
2009-01-30 02:39:30 +03:00
struct ldb_context * ldb ;
2008-09-12 02:34:56 +04:00
struct lldb_private * lldb ;
struct lldb_context * ac ;
2008-12-29 22:24:57 +03:00
struct tevent_context * ev ;
struct tevent_timer * te ;
2008-09-12 02:34:56 +04:00
struct timeval tv ;
int ret ;
2006-05-28 06:10:44 +04:00
2009-01-30 02:39:30 +03:00
lldb = talloc_get_type ( ldb_module_get_private ( module ) , struct lldb_private ) ;
ldb = ldb_module_get_ctx ( module ) ;
2008-09-12 02:34:56 +04:00
if ( req - > starttime = = 0 | | req - > timeout = = 0 ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( ldb , " Invalid timeout settings " ) ;
2008-09-12 02:34:56 +04:00
return LDB_ERR_TIME_LIMIT_EXCEEDED ;
}
2009-01-30 02:39:30 +03:00
ev = ldb_get_event_context ( ldb ) ;
2008-09-12 02:34:56 +04:00
if ( NULL = = ev ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2009-01-30 02:39:30 +03:00
ac = talloc_zero ( ldb , struct lldb_context ) ;
2008-09-12 02:34:56 +04:00
if ( ac = = NULL ) {
2009-01-30 02:39:30 +03:00
ldb_set_errstring ( ldb , " Out of Memory " ) ;
2008-09-12 02:34:56 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
ac - > module = module ;
ac - > req = req ;
ac - > lldb = lldb ;
ac - > msgid = 0 ;
if ( lldb_dn_is_special ( req ) ) {
tv . tv_sec = 0 ;
tv . tv_usec = 0 ;
2009-01-30 02:39:30 +03:00
te = tevent_add_timer ( ev , ac , tv ,
2008-09-12 02:34:56 +04:00
lldb_auto_done_callback , ac ) ;
if ( NULL = = te ) {
return LDB_ERR_OPERATIONS_ERROR ;
2006-02-28 07:38:53 +03:00
}
2006-05-28 06:10:44 +04:00
2008-09-12 02:34:56 +04:00
return LDB_SUCCESS ;
}
switch ( ac - > req - > operation ) {
case LDB_SEARCH :
ret = lldb_search ( ac ) ;
break ;
case LDB_ADD :
ret = lldb_add ( ac ) ;
break ;
case LDB_MODIFY :
ret = lldb_modify ( ac ) ;
break ;
case LDB_DELETE :
ret = lldb_delete ( ac ) ;
break ;
case LDB_RENAME :
ret = lldb_rename ( ac ) ;
2006-02-28 07:38:53 +03:00
break ;
2006-05-28 06:10:44 +04:00
default :
2008-09-12 02:34:56 +04:00
/* no other op supported */
2010-10-18 23:21:45 +04:00
ret = LDB_ERR_PROTOCOL_ERROR ;
2008-09-12 02:34:56 +04:00
break ;
2006-02-28 07:38:53 +03:00
}
2004-03-31 10:45:39 +04:00
2008-09-12 02:34:56 +04:00
if ( ret ! = LDB_SUCCESS ) {
2009-01-30 02:39:30 +03:00
lldb_request_done ( ac , NULL , ret ) ;
2008-09-12 02:34:56 +04:00
return ret ;
}
2004-11-21 18:51:54 +03:00
2008-09-12 02:34:56 +04:00
tv . tv_sec = 0 ;
tv . tv_usec = 0 ;
2009-01-30 02:39:30 +03:00
te = tevent_add_timer ( ev , ac , tv , lldb_callback , ac ) ;
2008-09-12 02:34:56 +04:00
if ( NULL = = te ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2004-11-21 18:51:54 +03:00
2005-09-24 19:42:15 +04:00
2008-09-12 02:34:56 +04:00
tv . tv_sec = req - > starttime + req - > timeout ;
tv . tv_usec = 0 ;
2009-01-30 02:39:30 +03:00
te = tevent_add_timer ( ev , ac , tv , lldb_timeout , ac ) ;
2008-09-12 02:34:56 +04:00
if ( NULL = = te ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2005-09-24 19:42:15 +04:00
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
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 " ,
2008-09-12 02:34:56 +04:00
. search = lldb_handle_request ,
. add = lldb_handle_request ,
. modify = lldb_handle_request ,
. del = lldb_handle_request ,
. rename = lldb_handle_request ,
. request = lldb_handle_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 ,
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 ;
}
2010-07-06 09:36:21 +04:00
/*
optionally perform a bind
*/
static int lldb_bind ( struct ldb_module * module ,
const char * options [ ] )
{
const char * bind_mechanism ;
struct lldb_private * lldb ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
int ret ;
bind_mechanism = ldb_options_find ( ldb , options , " bindMech " ) ;
if ( bind_mechanism = = NULL ) {
/* no bind wanted */
return LDB_SUCCESS ;
}
lldb = talloc_get_type ( ldb_module_get_private ( module ) , struct lldb_private ) ;
if ( strcmp ( bind_mechanism , " simple " ) = = 0 ) {
const char * bind_id , * bind_secret ;
bind_id = ldb_options_find ( ldb , options , " bindID " ) ;
bind_secret = ldb_options_find ( ldb , options , " bindSecret " ) ;
if ( bind_id = = NULL | | bind_secret = = NULL ) {
ldb_asprintf_errstring ( ldb , " simple bind requires bindID and bindSecret " ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
ret = ldap_simple_bind_s ( lldb - > ldap , bind_id , bind_secret ) ;
if ( ret ! = LDAP_SUCCESS ) {
ldb_asprintf_errstring ( ldb , " bind failed: %s " , ldap_err2string ( ret ) ) ;
return ret ;
}
return LDB_SUCCESS ;
}
ldb_asprintf_errstring ( ldb , " bind failed: unknown mechanism %s " , bind_mechanism ) ;
return LDB_ERR_INAPPROPRIATE_AUTHENTICATION ;
}
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 ,
2008-09-12 02:34:56 +04:00
const char * url ,
unsigned int flags ,
2006-06-08 01:03:38 +04:00
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
2009-01-30 02:39:30 +03:00
module = ldb_module_new ( ldb , ldb , " ldb_ldap backend " , & lldb_ops ) ;
2009-10-23 19:23:44 +04:00
if ( ! module ) return LDB_ERR_OPERATIONS_ERROR ;
2006-12-12 21:25:19 +03:00
2009-01-30 02:39:30 +03:00
lldb = talloc_zero ( 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 ;
}
2009-01-30 02:39:30 +03:00
ldb_module_set_private ( module , lldb ) ;
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 ) {
2009-07-11 00:44:27 +04:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " ldap_initialize failed for URL '%s' - %s " ,
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 ) {
2009-07-11 00:44:27 +04:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " ldap_set_option failed - %s " ,
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 ;
2010-07-06 09:36:21 +04:00
ret = lldb_bind ( module , options ) ;
if ( ret ! = LDB_SUCCESS ) {
goto failed ;
}
2009-10-23 19:23:44 +04:00
return LDB_SUCCESS ;
2004-03-31 10:45:39 +04:00
failed :
2006-12-12 21:25:19 +03:00
talloc_free ( module ) ;
2009-10-23 19:23:44 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
2004-03-31 10:45:39 +04:00
}
2004-04-11 00:18:22 +04:00
2010-11-01 04:37:35 +03:00
/*
initialise the module
*/
int ldb_ldap_init ( const char * ldb_version )
{
int ret , i ;
const char * names [ ] = { " ldap " , " ldaps " , " ldapi " , NULL } ;
for ( i = 0 ; names [ i ] ; i + + ) {
ret = ldb_register_backend ( names [ i ] , lldb_connect ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
}
return LDB_SUCCESS ;
}