2005-06-17 06:47:26 +04:00
/*
ldb database library - ildap backend
Copyright ( C ) Andrew Tridgell 2005
2006-02-22 04:31:35 +03:00
Copyright ( C ) Simo Sorce 2006
2005-06-17 06:47:26 +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 .
2005-06-17 06:47:26 +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/>.
2005-06-17 06:47:26 +04:00
*/
/*
2006-02-28 07:37:47 +03:00
* Name : ldb_ildap
*
* Component : ldb ildap backend
*
* Description : This is a ldb backend for the internal ldap
* client library in Samba4 . By using this backend we are
* independent of a system ldap library
*
* Author : Andrew Tridgell
*
* Modifications :
*
* - description : make the module use asyncronous calls
* date : Feb 2006
* author : Simo Sorce
*/
2005-06-17 06:47:26 +04:00
# include "includes.h"
2007-05-05 22:50:56 +04:00
# include "ldb_includes.h"
2006-01-10 19:48:32 +03:00
2006-02-22 04:31:35 +03:00
# include "lib/events/events.h"
2005-06-17 06:47:26 +04:00
# include "libcli/ldap/ldap.h"
# include "libcli/ldap/ldap_client.h"
2005-11-05 14:13:22 +03:00
# include "auth/auth.h"
2006-11-07 03:48:36 +03:00
# include "auth/credentials/credentials.h"
2007-12-09 01:32:43 +03:00
# include "param/param.h"
2005-06-17 06:47:26 +04:00
struct ildb_private {
struct ldap_connection * ldap ;
2006-12-12 19:56:53 +03:00
struct ldb_module * module ;
2005-06-17 06:47:26 +04:00
} ;
2006-07-22 20:56:33 +04:00
struct ildb_context {
2006-12-12 20:37:41 +03:00
struct ildb_private * ildb ;
struct ldb_handle * handle ;
2006-02-22 04:31:35 +03:00
struct ldap_request * req ;
void * context ;
2006-07-22 20:56:33 +04:00
int ( * callback ) ( struct ldb_context * , void * , struct ldb_reply * ) ;
2006-02-22 04:31:35 +03:00
} ;
/*
convert a ldb_message structure to a list of ldap_mod structures
ready for ildap_add ( ) or ildap_modify ( )
*/
static struct ldap_mod * * ildb_msg_to_mods ( void * mem_ctx , int * num_mods ,
const struct ldb_message * msg , int use_flags )
{
struct ldap_mod * * mods ;
unsigned int i ;
int n = 0 ;
/* allocate maximum number of elements needed */
mods = talloc_array ( mem_ctx , struct ldap_mod * , msg - > num_elements + 1 ) ;
if ( ! mods ) {
errno = ENOMEM ;
return NULL ;
}
mods [ 0 ] = NULL ;
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
const struct ldb_message_element * el = & msg - > elements [ i ] ;
mods [ n ] = talloc ( mods , struct ldap_mod ) ;
if ( ! mods [ n ] ) {
goto failed ;
}
mods [ n + 1 ] = NULL ;
mods [ n ] - > type = 0 ;
mods [ n ] - > attrib = * el ;
if ( use_flags ) {
switch ( el - > flags & LDB_FLAG_MOD_MASK ) {
case LDB_FLAG_MOD_ADD :
mods [ n ] - > type = LDAP_MODIFY_ADD ;
break ;
case LDB_FLAG_MOD_DELETE :
mods [ n ] - > type = LDAP_MODIFY_DELETE ;
break ;
case LDB_FLAG_MOD_REPLACE :
mods [ n ] - > type = LDAP_MODIFY_REPLACE ;
break ;
}
}
n + + ;
}
* num_mods = n ;
return mods ;
failed :
talloc_free ( mods ) ;
return NULL ;
}
2005-10-31 05:13:02 +03:00
/*
map an ildap NTSTATUS to a ldb error code
*/
static int ildb_map_error ( struct ildb_private * ildb , NTSTATUS status )
{
2007-03-08 09:23:39 +03:00
TALLOC_CTX * mem_ctx = talloc_new ( ildb ) ;
2005-10-31 05:13:02 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
return LDB_SUCCESS ;
}
2007-03-08 09:23:39 +03:00
if ( ! mem_ctx ) {
ldb_oom ( ildb - > module - > ldb ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
ldb_set_errstring ( ildb - > module - > ldb , ldap_errstr ( ildb - > ldap , mem_ctx , status ) ) ;
talloc_free ( mem_ctx ) ;
2005-10-31 05:13:02 +03:00
if ( NT_STATUS_IS_LDAP ( status ) ) {
return NT_STATUS_LDAP_CODE ( status ) ;
}
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-02-22 04:31:35 +03:00
static void ildb_request_timeout ( struct event_context * ev , struct timed_event * te ,
struct timeval t , void * private_data )
2005-06-17 06:47:26 +04:00
{
2006-12-12 21:52:25 +03:00
struct ildb_context * ac = talloc_get_type ( private_data , struct ildb_context ) ;
struct ldb_handle * handle = ac - > handle ;
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
if ( ac - > req - > state = = LDAP_REQUEST_PENDING ) {
DLIST_REMOVE ( ac - > req - > conn - > pending , ac - > req ) ;
2005-06-17 06:47:26 +04:00
}
2006-06-04 09:28:13 +04:00
handle - > status = LDB_ERR_TIME_LIMIT_EXCEEDED ;
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
return ;
}
2005-08-18 19:02:01 +04:00
2006-05-30 03:46:43 +04:00
static void ildb_callback ( struct ldap_request * req )
2006-02-22 04:31:35 +03:00
{
2006-12-12 21:52:25 +03:00
struct ildb_context * ac = talloc_get_type ( req - > async . private_data , struct ildb_context ) ;
struct ldb_handle * handle = ac - > handle ;
struct ildb_private * ildb = ac - > ildb ;
2006-02-22 04:31:35 +03:00
NTSTATUS status ;
int i ;
2005-08-18 19:02:01 +04:00
2006-02-22 04:31:35 +03:00
handle - > status = LDB_SUCCESS ;
if ( ! NT_STATUS_IS_OK ( req - > status ) ) {
handle - > status = ildb_map_error ( ildb , req - > status ) ;
return ;
2005-06-17 06:47:26 +04:00
}
2006-02-22 04:31:35 +03:00
if ( req - > num_replies < 1 ) {
handle - > status = LDB_ERR_OPERATIONS_ERROR ;
return ;
}
switch ( req - > type ) {
2005-08-18 19:02:01 +04:00
2006-02-22 04:31:35 +03:00
case LDAP_TAG_ModifyRequest :
if ( req - > replies [ 0 ] - > type ! = LDAP_TAG_ModifyResponse ) {
handle - > status = LDB_ERR_PROTOCOL_ERROR ;
return ;
}
status = ldap_check_response ( req - > conn , & req - > replies [ 0 ] - > r . GeneralResult ) ;
handle - > status = ildb_map_error ( ildb , status ) ;
2006-02-28 07:37:47 +03:00
if ( ac - > callback & & handle - > status = = LDB_SUCCESS ) {
/* FIXME: build a corresponding ares to pass on */
2006-12-12 21:58:21 +03:00
handle - > status = ac - > callback ( ac - > ildb - > module - > ldb , ac - > context , NULL ) ;
2006-02-28 07:37:47 +03:00
}
2006-02-22 04:31:35 +03:00
handle - > state = LDB_ASYNC_DONE ;
break ;
case LDAP_TAG_AddRequest :
if ( req - > replies [ 0 ] - > type ! = LDAP_TAG_AddResponse ) {
handle - > status = LDB_ERR_PROTOCOL_ERROR ;
return ;
}
status = ldap_check_response ( req - > conn , & req - > replies [ 0 ] - > r . GeneralResult ) ;
handle - > status = ildb_map_error ( ildb , status ) ;
2006-02-28 07:37:47 +03:00
if ( ac - > callback & & handle - > status = = LDB_SUCCESS ) {
/* FIXME: build a corresponding ares to pass on */
2006-12-12 21:58:21 +03:00
handle - > status = ac - > callback ( ac - > ildb - > module - > ldb , ac - > context , NULL ) ;
2006-02-28 07:37:47 +03:00
}
2006-02-22 04:31:35 +03:00
handle - > state = LDB_ASYNC_DONE ;
break ;
case LDAP_TAG_DelRequest :
if ( req - > replies [ 0 ] - > type ! = LDAP_TAG_DelResponse ) {
handle - > status = LDB_ERR_PROTOCOL_ERROR ;
return ;
}
status = ldap_check_response ( req - > conn , & req - > replies [ 0 ] - > r . GeneralResult ) ;
handle - > status = ildb_map_error ( ildb , status ) ;
2006-02-28 07:37:47 +03:00
if ( ac - > callback & & handle - > status = = LDB_SUCCESS ) {
/* FIXME: build a corresponding ares to pass on */
2006-12-12 21:58:21 +03:00
handle - > status = ac - > callback ( ac - > ildb - > module - > ldb , ac - > context , NULL ) ;
2006-02-28 07:37:47 +03:00
}
2006-02-22 04:31:35 +03:00
handle - > state = LDB_ASYNC_DONE ;
break ;
case LDAP_TAG_ModifyDNRequest :
if ( req - > replies [ 0 ] - > type ! = LDAP_TAG_ModifyDNResponse ) {
handle - > status = LDB_ERR_PROTOCOL_ERROR ;
return ;
}
status = ldap_check_response ( req - > conn , & req - > replies [ 0 ] - > r . GeneralResult ) ;
handle - > status = ildb_map_error ( ildb , status ) ;
2006-02-28 07:37:47 +03:00
if ( ac - > callback & & handle - > status = = LDB_SUCCESS ) {
/* FIXME: build a corresponding ares to pass on */
2006-12-12 21:58:21 +03:00
handle - > status = ac - > callback ( ac - > ildb - > module - > ldb , ac - > context , NULL ) ;
2006-02-28 07:37:47 +03:00
}
2006-02-22 04:31:35 +03:00
handle - > state = LDB_ASYNC_DONE ;
break ;
case LDAP_TAG_SearchRequest :
/* loop over all messages */
for ( i = 0 ; i < req - > num_replies ; i + + ) {
struct ldap_SearchResEntry * search ;
2006-07-22 20:56:33 +04:00
struct ldb_reply * ares = NULL ;
2006-02-22 04:31:35 +03:00
struct ldap_message * msg ;
int ret ;
2006-07-22 20:56:33 +04:00
ares = talloc_zero ( ac , struct ldb_reply ) ;
2006-02-22 04:31:35 +03:00
if ( ! ares ) {
handle - > status = LDB_ERR_OPERATIONS_ERROR ;
return ;
}
msg = req - > replies [ i ] ;
switch ( msg - > type ) {
case LDAP_TAG_SearchResultDone :
status = ldap_check_response ( req - > conn , & msg - > r . GeneralResult ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
handle - > status = ildb_map_error ( ildb , status ) ;
return ;
}
2006-09-13 06:33:51 +04:00
ares - > controls = talloc_move ( ares , & msg - > controls ) ;
2006-02-22 04:31:35 +03:00
if ( msg - > r . SearchResultDone . resultcode ) {
if ( msg - > r . SearchResultDone . errormessage ) {
2006-12-12 21:58:21 +03:00
ldb_set_errstring ( ac - > ildb - > module - > ldb , msg - > r . SearchResultDone . errormessage ) ;
2006-02-22 04:31:35 +03:00
}
}
handle - > status = msg - > r . SearchResultDone . resultcode ;
handle - > state = LDB_ASYNC_DONE ;
ares - > type = LDB_REPLY_DONE ;
break ;
case LDAP_TAG_SearchResultEntry :
ares - > message = ldb_msg_new ( ares ) ;
if ( ! ares - > message ) {
2006-05-30 23:09:34 +04:00
handle - > status = LDB_ERR_OPERATIONS_ERROR ;
2006-02-22 04:31:35 +03:00
return ;
}
search = & ( msg - > r . SearchResultEntry ) ;
2006-12-12 21:58:21 +03:00
ares - > message - > dn = ldb_dn_new ( ares - > message , ac - > ildb - > module - > ldb , search - > dn ) ;
2006-11-22 03:59:34 +03:00
if ( ! ldb_dn_validate ( ares - > message - > dn ) ) {
2006-02-22 04:31:35 +03:00
handle - > status = LDB_ERR_OPERATIONS_ERROR ;
return ;
}
ares - > message - > num_elements = search - > num_attributes ;
2006-09-13 06:33:51 +04:00
ares - > message - > elements = talloc_move ( ares - > message ,
& search - > attributes ) ;
2006-02-22 04:31:35 +03:00
handle - > status = LDB_SUCCESS ;
handle - > state = LDB_ASYNC_PENDING ;
ares - > type = LDB_REPLY_ENTRY ;
break ;
case LDAP_TAG_SearchResultReference :
ares - > referral = talloc_strdup ( ares , msg - > r . SearchResultReference . referral ) ;
handle - > status = LDB_SUCCESS ;
handle - > state = LDB_ASYNC_PENDING ;
ares - > type = LDB_REPLY_REFERRAL ;
break ;
default :
/* TAG not handled, fail ! */
handle - > status = LDB_ERR_PROTOCOL_ERROR ;
return ;
}
2006-12-12 21:58:21 +03:00
ret = ac - > callback ( ac - > ildb - > module - > ldb , ac - > context , ares ) ;
2006-02-22 04:31:35 +03:00
if ( ret ) {
handle - > status = ret ;
}
}
talloc_free ( req - > replies ) ;
req - > replies = NULL ;
req - > num_replies = 0 ;
break ;
default :
handle - > status = LDB_ERR_PROTOCOL_ERROR ;
return ;
}
2005-06-17 06:47:26 +04:00
}
2006-12-12 20:37:41 +03:00
static struct ildb_context * init_ildb_handle ( struct ildb_private * ildb ,
struct ldb_request * req )
2005-06-17 06:47:26 +04:00
{
2006-07-22 20:56:33 +04:00
struct ildb_context * ildb_ac ;
struct ldb_handle * h ;
2005-06-17 06:47:26 +04:00
2006-12-12 21:14:31 +03:00
h = talloc_zero ( req , struct ldb_handle ) ;
2006-02-22 04:31:35 +03:00
if ( h = = NULL ) {
2006-12-12 20:37:41 +03:00
ldb_set_errstring ( ildb - > module - > ldb , " Out of Memory " ) ;
2006-08-01 06:25:05 +04:00
return NULL ;
2005-06-17 06:47:26 +04:00
}
2006-02-22 04:31:35 +03:00
2006-12-12 20:37:41 +03:00
h - > module = ildb - > module ;
2006-03-08 00:08:09 +03:00
2006-07-22 20:56:33 +04:00
ildb_ac = talloc ( h , struct ildb_context ) ;
2006-02-22 04:31:35 +03:00
if ( ildb_ac = = NULL ) {
2006-12-12 20:37:41 +03:00
ldb_set_errstring ( ildb - > module - > ldb , " Out of Memory " ) ;
2006-02-22 04:31:35 +03:00
talloc_free ( h ) ;
2006-08-01 06:25:05 +04:00
return NULL ;
2005-06-17 06:47:26 +04:00
}
2006-12-12 20:37:41 +03:00
h - > private_data = ildb_ac ;
2005-10-31 05:13:02 +03:00
2006-03-10 18:27:16 +03:00
h - > state = LDB_ASYNC_INIT ;
h - > status = LDB_SUCCESS ;
2006-12-12 20:37:41 +03:00
ildb_ac - > ildb = ildb ;
ildb_ac - > handle = h ;
ildb_ac - > context = req - > context ;
ildb_ac - > callback = req - > callback ;
2006-08-01 06:25:05 +04:00
2006-12-12 20:37:41 +03:00
req - > handle = h ;
return ildb_ac ;
2006-08-01 06:25:05 +04:00
}
2006-12-12 20:14:58 +03:00
static int ildb_request_send ( struct ildb_private * ildb , struct ldap_message * msg , struct ldb_request * r )
2006-08-01 06:25:05 +04:00
{
2006-12-12 20:37:41 +03:00
struct ildb_context * ildb_ac = init_ildb_handle ( ildb , r ) ;
2006-08-01 06:25:05 +04:00
struct ldap_request * req ;
2006-12-12 20:37:41 +03:00
if ( ! ildb_ac ) {
2006-08-01 06:25:05 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-02-22 04:31:35 +03:00
req = ldap_request_send ( ildb - > ldap , msg ) ;
if ( req = = NULL ) {
2006-12-12 20:14:58 +03:00
ldb_set_errstring ( ildb - > module - > ldb , " async send request failed " ) ;
2006-02-22 04:31:35 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-12-12 21:14:31 +03:00
ildb_ac - > req = talloc_steal ( ildb_ac , req ) ;
2005-08-18 19:02:01 +04:00
2006-07-29 05:22:22 +04:00
if ( ! req - > conn ) {
2006-12-12 20:14:58 +03:00
ldb_set_errstring ( ildb - > module - > ldb , " connection to remote LDAP server dropped? " ) ;
2006-07-29 05:22:22 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-02-22 04:31:35 +03:00
talloc_free ( req - > time_event ) ;
req - > time_event = NULL ;
2006-12-12 20:14:58 +03:00
if ( r - > timeout ) {
2006-12-12 21:52:25 +03:00
req - > time_event = event_add_timed ( req - > conn - > event . event_ctx , ildb_ac ,
2006-12-12 20:14:58 +03:00
timeval_current_ofs ( r - > timeout , 0 ) ,
2006-12-12 21:52:25 +03:00
ildb_request_timeout , ildb_ac ) ;
2006-02-22 04:31:35 +03:00
}
2006-08-01 06:25:05 +04:00
req - > async . fn = ildb_callback ;
2006-12-12 21:52:25 +03:00
req - > async . private_data = ildb_ac ;
2006-02-22 04:31:35 +03:00
return LDB_SUCCESS ;
2006-08-01 06:25:05 +04:00
}
2006-12-12 20:20:38 +03:00
static int ildb_request_noop ( struct ildb_private * ildb , struct ldb_request * req )
2006-08-01 06:25:05 +04:00
{
2006-12-12 20:37:41 +03:00
struct ildb_context * ildb_ac = init_ildb_handle ( ildb , req ) ;
2006-08-01 06:25:05 +04:00
int ret = LDB_SUCCESS ;
2006-02-22 04:31:35 +03:00
2006-12-12 20:37:41 +03:00
if ( ! ildb_ac ) {
2006-08-01 06:25:05 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
if ( ildb_ac - > callback ) {
2006-12-12 20:20:38 +03:00
ret = ildb_ac - > callback ( ildb - > module - > ldb , ildb_ac - > context , NULL ) ;
2006-08-01 06:25:05 +04:00
}
2006-12-12 20:37:41 +03:00
ildb_ac - > handle - > state = LDB_ASYNC_DONE ;
2006-08-01 06:25:05 +04:00
return ret ;
2006-02-22 04:31:35 +03:00
}
2005-06-18 13:48:17 +04:00
2005-06-17 06:47:26 +04:00
/*
2006-02-22 04:31:35 +03:00
search for matching records using an asynchronous function
*/
2006-05-30 03:46:43 +04:00
static int ildb_search ( struct ldb_module * module , struct ldb_request * req )
2005-06-17 06:47:26 +04:00
{
2006-02-28 07:37:47 +03:00
struct ildb_private * ildb = talloc_get_type ( module - > private_data , struct ildb_private ) ;
2006-02-22 04:31:35 +03:00
struct ldap_message * msg ;
int n ;
2005-06-17 06:47:26 +04:00
2006-07-22 21:21:59 +04:00
req - > handle = NULL ;
2006-02-22 04:31:35 +03:00
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-22 04:31:35 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-06-18 13:01:09 +04:00
}
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-22 04:31:35 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-12-12 21:14:31 +03:00
msg = new_ldap_message ( req ) ;
2006-02-22 04:31:35 +03:00
if ( msg = = NULL ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , " Out of Memory " ) ;
2006-02-22 04:31:35 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
}
msg - > type = LDAP_TAG_SearchRequest ;
2006-05-29 05:30:02 +04:00
if ( req - > op . search . base = = NULL ) {
2006-08-25 10:45:47 +04:00
msg - > r . SearchRequest . basedn = talloc_strdup ( msg , " " ) ;
2005-08-18 19:02:01 +04:00
} else {
2006-11-22 05:05:19 +03:00
msg - > r . SearchRequest . basedn = ldb_dn_alloc_linearized ( msg , req - > op . search . base ) ;
2005-08-18 19:02:01 +04:00
}
2006-02-22 04:31:35 +03:00
if ( msg - > r . SearchRequest . basedn = = NULL ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( module - > ldb , " Unable to determine baseDN " ) ;
2006-02-22 04:31:35 +03:00
talloc_free ( msg ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2005-10-04 09:41:05 +04:00
}
2006-02-22 04:31:35 +03:00
2006-05-29 05:30:02 +04:00
if ( req - > op . search . scope = = LDB_SCOPE_DEFAULT ) {
2006-02-22 04:31:35 +03:00
msg - > r . SearchRequest . scope = LDB_SCOPE_SUBTREE ;
} else {
2006-05-29 05:30:02 +04:00
msg - > r . SearchRequest . scope = req - > op . search . scope ;
2005-11-08 03:11:45 +03:00
}
2006-02-22 04:31:35 +03:00
msg - > r . SearchRequest . deref = LDAP_DEREFERENCE_NEVER ;
msg - > r . SearchRequest . timelimit = 0 ;
msg - > r . SearchRequest . sizelimit = 0 ;
msg - > r . SearchRequest . attributesonly = 0 ;
2006-05-30 23:09:34 +04:00
msg - > r . SearchRequest . tree = discard_const ( req - > op . search . tree ) ;
2006-02-22 04:31:35 +03:00
2006-05-29 05:30:02 +04:00
for ( n = 0 ; req - > op . search . attrs & & req - > op . search . attrs [ n ] ; n + + ) /* noop */ ;
2006-02-22 04:31:35 +03:00
msg - > r . SearchRequest . num_attributes = n ;
2006-05-29 05:30:02 +04:00
msg - > r . SearchRequest . attributes = discard_const ( req - > op . search . attrs ) ;
msg - > controls = req - > controls ;
2005-11-08 03:11:45 +03:00
2006-12-12 20:14:58 +03:00
return ildb_request_send ( ildb , msg , req ) ;
2006-02-22 04:31:35 +03:00
}
/*
add a record
*/
2006-05-30 03:46:43 +04:00
static int ildb_add ( struct ldb_module * module , struct ldb_request * req )
2006-02-22 04:31:35 +03:00
{
2006-02-28 07:37:47 +03:00
struct ildb_private * ildb = talloc_get_type ( module - > private_data , struct ildb_private ) ;
2006-02-22 04:31:35 +03:00
struct ldap_message * msg ;
struct ldap_mod * * mods ;
int i , n ;
2005-06-17 06:47:26 +04:00
2006-07-22 21:21:59 +04:00
req - > handle = NULL ;
2006-02-22 04:31:35 +03:00
/* ignore ltdb specials */
2006-05-29 05:30:02 +04:00
if ( ldb_dn_is_special ( req - > op . add . message - > dn ) ) {
2006-12-12 20:20:38 +03:00
return ildb_request_noop ( ildb , req ) ;
2005-06-17 06:47:26 +04:00
}
2006-12-12 21:14:31 +03:00
msg = new_ldap_message ( req ) ;
2006-02-22 04:31:35 +03:00
if ( msg = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
msg - > type = LDAP_TAG_AddRequest ;
2006-01-06 07:01:23 +03:00
2006-11-22 05:05:19 +03:00
msg - > r . AddRequest . dn = ldb_dn_alloc_linearized ( msg , req - > op . add . message - > dn ) ;
2006-02-22 04:31:35 +03:00
if ( msg - > r . AddRequest . dn = = NULL ) {
talloc_free ( msg ) ;
return LDB_ERR_INVALID_DN_SYNTAX ;
2006-01-06 07:01:23 +03:00
}
2006-05-29 05:30:02 +04:00
mods = ildb_msg_to_mods ( msg , & n , req - > op . add . message , 0 ) ;
2006-02-22 04:31:35 +03:00
if ( mods = = NULL ) {
talloc_free ( msg ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
msg - > r . AddRequest . num_attributes = n ;
msg - > r . AddRequest . attributes = talloc_array ( msg , struct ldb_message_element , n ) ;
if ( msg - > r . AddRequest . attributes = = NULL ) {
talloc_free ( msg ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
for ( i = 0 ; i < n ; i + + ) {
msg - > r . AddRequest . attributes [ i ] = mods [ i ] - > attrib ;
}
2006-12-12 20:14:58 +03:00
return ildb_request_send ( ildb , msg , req ) ;
2005-06-17 06:47:26 +04:00
}
/*
2006-02-22 04:31:35 +03:00
modify a record
2005-06-17 06:47:26 +04:00
*/
2006-05-30 03:46:43 +04:00
static int ildb_modify ( struct ldb_module * module , struct ldb_request * req )
2005-06-17 06:47:26 +04:00
{
2006-02-28 07:37:47 +03:00
struct ildb_private * ildb = talloc_get_type ( module - > private_data , struct ildb_private ) ;
2006-02-22 04:31:35 +03:00
struct ldap_message * msg ;
2005-06-17 06:47:26 +04:00
struct ldap_mod * * mods ;
2006-02-22 04:31:35 +03:00
int i , n ;
2005-06-17 06:47:26 +04:00
2006-07-22 21:21:59 +04:00
req - > handle = NULL ;
2006-02-22 04:31:35 +03:00
/* ignore ltdb specials */
2006-05-29 05:30:02 +04:00
if ( ldb_dn_is_special ( req - > op . mod . message - > dn ) ) {
2006-12-12 20:20:38 +03:00
return ildb_request_noop ( ildb , req ) ;
2005-06-17 06:47:26 +04:00
}
2006-12-12 21:14:31 +03:00
msg = new_ldap_message ( req ) ;
2006-02-22 04:31:35 +03:00
if ( msg = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
msg - > type = LDAP_TAG_ModifyRequest ;
2006-11-22 05:05:19 +03:00
msg - > r . ModifyRequest . dn = ldb_dn_alloc_linearized ( msg , req - > op . mod . message - > dn ) ;
2006-02-22 04:31:35 +03:00
if ( msg - > r . ModifyRequest . dn = = NULL ) {
talloc_free ( msg ) ;
return LDB_ERR_INVALID_DN_SYNTAX ;
2005-06-17 06:47:26 +04:00
}
2006-05-29 05:30:02 +04:00
mods = ildb_msg_to_mods ( msg , & n , req - > op . mod . message , 1 ) ;
2006-02-22 04:31:35 +03:00
if ( mods = = NULL ) {
talloc_free ( msg ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
msg - > r . ModifyRequest . num_mods = n ;
msg - > r . ModifyRequest . mods = talloc_array ( msg , struct ldap_mod , n ) ;
if ( msg - > r . ModifyRequest . mods = = NULL ) {
talloc_free ( msg ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
for ( i = 0 ; i < n ; i + + ) {
msg - > r . ModifyRequest . mods [ i ] = * mods [ i ] ;
}
2006-12-12 20:14:58 +03:00
return ildb_request_send ( ildb , msg , req ) ;
2005-06-17 06:47:26 +04:00
}
/*
2006-02-22 04:31:35 +03:00
delete a record
2005-06-17 06:47:26 +04:00
*/
2006-05-30 03:46:43 +04:00
static int ildb_delete ( struct ldb_module * module , struct ldb_request * req )
2005-06-17 06:47:26 +04:00
{
2006-02-28 07:37:47 +03:00
struct ildb_private * ildb = talloc_get_type ( module - > private_data , struct ildb_private ) ;
2006-02-22 04:31:35 +03:00
struct ldap_message * msg ;
2006-07-22 21:21:59 +04:00
req - > handle = NULL ;
2005-06-17 06:47:26 +04:00
/* ignore ltdb specials */
2006-05-29 05:30:02 +04:00
if ( ldb_dn_is_special ( req - > op . del . dn ) ) {
2006-12-12 20:20:38 +03:00
return ildb_request_noop ( ildb , req ) ;
2005-06-17 06:47:26 +04:00
}
2006-12-12 21:14:31 +03:00
msg = new_ldap_message ( req ) ;
2006-02-22 04:31:35 +03:00
if ( msg = = NULL ) {
2005-10-31 05:13:02 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-08-18 19:02:01 +04:00
}
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
msg - > type = LDAP_TAG_DelRequest ;
2006-11-22 05:05:19 +03:00
msg - > r . DelRequest . dn = ldb_dn_alloc_linearized ( msg , req - > op . del . dn ) ;
2006-02-22 04:31:35 +03:00
if ( msg - > r . DelRequest . dn = = NULL ) {
talloc_free ( msg ) ;
2005-10-31 05:13:02 +03:00
return LDB_ERR_INVALID_DN_SYNTAX ;
2005-08-18 19:02:01 +04:00
}
2006-12-12 20:14:58 +03:00
return ildb_request_send ( ildb , msg , req ) ;
2006-02-22 04:31:35 +03:00
}
2005-06-17 06:47:26 +04:00
/*
2006-02-22 04:31:35 +03:00
rename a record
2005-06-17 06:47:26 +04:00
*/
2006-05-30 03:46:43 +04:00
static int ildb_rename ( struct ldb_module * module , struct ldb_request * req )
2005-06-17 06:47:26 +04:00
{
2006-02-28 07:37:47 +03:00
struct ildb_private * ildb = talloc_get_type ( module - > private_data , struct ildb_private ) ;
2006-02-22 04:31:35 +03:00
struct ldap_message * msg ;
2006-07-22 21:21:59 +04:00
req - > handle = NULL ;
2005-06-17 06:47:26 +04:00
/* ignore ltdb specials */
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-12-12 20:20:38 +03:00
return ildb_request_noop ( ildb , req ) ;
2005-06-17 06:47:26 +04:00
}
2006-12-12 21:14:31 +03:00
msg = new_ldap_message ( req ) ;
2006-02-22 04:31:35 +03:00
if ( msg = = NULL ) {
2005-10-31 05:13:02 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-08-18 19:02:01 +04:00
}
2006-02-22 04:31:35 +03:00
msg - > type = LDAP_TAG_ModifyDNRequest ;
2006-11-22 05:05:19 +03:00
msg - > r . ModifyDNRequest . dn = ldb_dn_alloc_linearized ( msg , req - > op . rename . olddn ) ;
2006-02-22 04:31:35 +03:00
if ( msg - > r . ModifyDNRequest . dn = = NULL ) {
talloc_free ( msg ) ;
2005-10-31 05:13:02 +03:00
return LDB_ERR_INVALID_DN_SYNTAX ;
2005-08-18 19:02:01 +04:00
}
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
msg - > r . ModifyDNRequest . newrdn =
talloc_asprintf ( msg , " %s=%s " ,
2006-11-02 02:31:26 +03:00
ldb_dn_get_rdn_name ( req - > op . rename . newdn ) ,
ldb_dn_escape_value ( msg , * ldb_dn_get_rdn_val ( req - > op . rename . newdn ) ) ) ;
2006-02-22 04:31:35 +03:00
if ( msg - > r . ModifyDNRequest . newrdn = = NULL ) {
talloc_free ( msg ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2005-06-17 06:47:26 +04:00
2006-02-22 04:31:35 +03:00
msg - > r . ModifyDNRequest . newsuperior =
2006-11-22 05:05:19 +03:00
ldb_dn_alloc_linearized ( msg , ldb_dn_get_parent ( msg , req - > op . rename . newdn ) ) ;
2006-02-22 04:31:35 +03:00
if ( msg - > r . ModifyDNRequest . newsuperior = = NULL ) {
talloc_free ( msg ) ;
return LDB_ERR_INVALID_DN_SYNTAX ;
}
2007-10-05 22:03:01 +04:00
msg - > r . ModifyDNRequest . deleteolddn = true ;
2006-02-22 04:31:35 +03:00
2006-12-12 20:14:58 +03:00
return ildb_request_send ( ildb , msg , req ) ;
2006-02-22 04:31:35 +03:00
}
2005-09-17 23:25:50 +04:00
static int ildb_start_trans ( struct ldb_module * module )
2005-06-17 06:47:26 +04:00
{
/* TODO implement a local locking mechanism here */
2006-05-30 03:46:43 +04:00
return LDB_SUCCESS ;
2005-06-17 06:47:26 +04:00
}
2005-09-24 19:42:15 +04:00
static int ildb_end_trans ( struct ldb_module * module )
2005-06-17 06:47:26 +04:00
{
2005-09-17 23:25:50 +04:00
/* TODO implement a local transaction mechanism here */
2005-06-17 06:47:26 +04:00
2006-05-30 03:46:43 +04:00
return LDB_SUCCESS ;
2005-09-24 19:42:15 +04:00
}
static int ildb_del_trans ( struct ldb_module * module )
{
/* TODO implement a local locking mechanism here */
2006-05-30 03:46:43 +04:00
return LDB_SUCCESS ;
2005-06-17 06:47:26 +04:00
}
2005-11-08 03:11:45 +03:00
static int ildb_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
}
2006-07-22 20:56:33 +04:00
static int ildb_wait ( struct ldb_handle * handle , enum ldb_wait_type type )
2005-06-18 13:48:17 +04:00
{
2006-07-22 20:56:33 +04:00
struct ildb_context * ac = talloc_get_type ( handle - > private_data , struct ildb_context ) ;
2006-02-22 04:31:35 +03:00
2006-03-10 18:27:16 +03:00
if ( handle - > state = = LDB_ASYNC_DONE ) {
return handle - > status ;
}
2006-02-22 04:31:35 +03:00
if ( ! ac ) {
return LDB_ERR_OPERATIONS_ERROR ;
2005-06-18 13:48:17 +04:00
}
2006-02-28 07:37:47 +03:00
handle - > state = LDB_ASYNC_INIT ;
2006-02-22 04:31:35 +03:00
switch ( type ) {
case LDB_WAIT_NONE :
if ( event_loop_once ( ac - > req - > conn - > event . event_ctx ) ! = 0 ) {
return LDB_ERR_OTHER ;
}
break ;
case LDB_WAIT_ALL :
while ( handle - > status = = LDB_SUCCESS & & handle - > state ! = LDB_ASYNC_DONE ) {
if ( event_loop_once ( ac - > req - > conn - > event . event_ctx ) ! = 0 ) {
return LDB_ERR_OTHER ;
}
}
break ;
default :
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-05-30 23:41:29 +04:00
return handle - > status ;
2006-02-22 04:31:35 +03:00
}
2005-06-18 13:48:17 +04:00
2006-02-28 07:37:47 +03:00
static const struct ldb_module_ops ildb_ops = {
. name = " ldap " ,
2006-05-30 03:46:43 +04:00
. search = ildb_search ,
. add = ildb_add ,
. modify = ildb_modify ,
. del = ildb_delete ,
. rename = ildb_rename ,
2006-02-28 07:37:47 +03:00
. request = ildb_request ,
. start_transaction = ildb_start_trans ,
. end_transaction = ildb_end_trans ,
. del_transaction = ildb_del_trans ,
2006-08-25 10:45:47 +04:00
. wait = ildb_wait
2006-02-28 07:37:47 +03:00
} ;
2005-06-17 06:47:26 +04:00
/*
connect to the database
*/
2006-03-05 19:05:26 +03:00
static int ildb_connect ( struct ldb_context * ldb , const char * url ,
2006-06-08 01:03:38 +04:00
unsigned int flags , const char * options [ ] ,
2006-12-12 19:56:53 +03:00
struct ldb_module * * _module )
2005-06-17 06:47:26 +04:00
{
2006-12-12 19:56:53 +03:00
struct ldb_module * module ;
struct ildb_private * ildb ;
2005-06-17 06:47:26 +04:00
NTSTATUS status ;
2005-10-01 03:46:41 +04:00
struct cli_credentials * creds ;
2005-06-17 06:47:26 +04:00
2006-12-12 19:56:53 +03:00
module = talloc ( ldb , struct ldb_module ) ;
if ( ! module ) {
ldb_oom ( ldb ) ;
return - 1 ;
}
talloc_set_name_const ( module , " ldb_ildap backend " ) ;
module - > ldb = ldb ;
module - > prev = module - > next = NULL ;
module - > private_data = NULL ;
module - > ops = & ildb_ops ;
ildb = talloc ( module , struct ildb_private ) ;
2005-06-17 06:47:26 +04:00
if ( ! ildb ) {
2005-06-18 11:42:21 +04:00
ldb_oom ( ldb ) ;
2005-06-17 06:47:26 +04:00
goto failed ;
}
2006-12-12 19:56:53 +03:00
module - > private_data = ildb ;
ildb - > module = module ;
2007-12-10 06:33:16 +03:00
ildb - > ldap = ldap4_new_connection ( ildb , ldb_get_opaque ( ldb , " loadparm " ) ,
ldb_get_opaque ( ldb , " EventContext " ) ) ;
2005-06-17 06:47:26 +04:00
if ( ! ildb - > ldap ) {
2005-06-18 11:42:21 +04:00
ldb_oom ( ldb ) ;
2005-06-17 06:47:26 +04:00
goto failed ;
}
2006-07-29 05:22:22 +04:00
if ( flags & LDB_FLG_RECONNECT ) {
2006-04-25 16:34:58 +04:00
ldap_set_reconn_params ( ildb - > ldap , 10 ) ;
}
2005-06-17 06:47:26 +04:00
status = ldap_connect ( ildb - > ldap , url ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-06-18 11:42:21 +04:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " Failed to connect to ldap URL '%s' - %s \n " ,
2007-03-08 09:23:39 +03:00
url , ldap_errstr ( ildb - > ldap , module , status ) ) ;
2005-06-17 06:47:26 +04:00
goto failed ;
}
2005-10-01 03:46:41 +04:00
/* caller can optionally setup credentials using the opaque token 'credentials' */
2005-11-05 14:13:22 +03:00
creds = talloc_get_type ( ldb_get_opaque ( ldb , " credentials " ) , struct cli_credentials ) ;
2005-10-01 03:46:41 +04:00
if ( creds = = NULL ) {
2005-11-05 14:13:22 +03:00
struct auth_session_info * session_info = talloc_get_type ( ldb_get_opaque ( ldb , " sessionInfo " ) , struct auth_session_info ) ;
2005-12-14 10:22:25 +03:00
if ( session_info ) {
2005-11-05 14:13:22 +03:00
creds = session_info - > credentials ;
}
2005-10-01 03:46:41 +04:00
}
if ( creds ! = NULL & & cli_credentials_authentication_requested ( creds ) ) {
2005-12-18 08:01:15 +03:00
const char * bind_dn = cli_credentials_get_bind_dn ( creds ) ;
if ( bind_dn ) {
const char * password = cli_credentials_get_password ( creds ) ;
status = ldap_bind_simple ( ildb - > ldap , bind_dn , password ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR , " Failed to bind - %s \n " ,
2007-03-08 09:23:39 +03:00
ldap_errstr ( ildb - > ldap , module , status ) ) ;
2005-12-18 08:01:15 +03:00
goto failed ;
}
} else {
2007-12-10 06:33:16 +03:00
status = ldap_bind_sasl ( ildb - > ldap , creds , ldb_get_opaque ( ldb , " loadparm " ) ) ;
2005-12-18 08:01:15 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR , " Failed to bind - %s \n " ,
2007-03-08 09:23:39 +03:00
ldap_errstr ( ildb - > ldap , module , status ) ) ;
2005-12-18 08:01:15 +03:00
goto failed ;
}
2005-06-18 13:01:09 +04:00
}
}
2006-12-12 19:56:53 +03:00
* _module = module ;
2005-06-18 11:42:21 +04:00
return 0 ;
2005-06-17 06:47:26 +04:00
failed :
2006-12-12 19:56:53 +03:00
talloc_free ( module ) ;
2005-06-18 11:42:21 +04:00
return - 1 ;
2005-06-17 06:47:26 +04:00
}
2008-02-20 06:33:43 +03:00
_PUBLIC_ const struct ldb_backend_ops ldb_ldap_backend_ops = {
2008-02-20 04:57:07 +03:00
. name = " ldap " ,
. connect_fn = ildb_connect
} ;
2008-02-29 03:06:05 +03:00
_PUBLIC_ const struct ldb_backend_ops ldb_ldapi_backend_ops = {
. name = " ldapi " ,
2008-02-20 04:57:07 +03:00
. connect_fn = ildb_connect
} ;
2008-02-20 06:33:43 +03:00
_PUBLIC_ const struct ldb_backend_ops ldb_ldaps_backend_ops = {
2008-02-20 04:57:07 +03:00
. name = " ldaps " ,
. connect_fn = ildb_connect
} ;