2004-03-31 10:45:39 +04:00
/*
ldb database library
Copyright ( C ) Andrew Tridgell 2004
* * 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
*/
/*
* Name : ldb
*
* Component : ldb ldap backend
*
* Description : core files for LDAP backend
*
* Author : Andrew Tridgell
*/
# include "includes.h"
2004-11-16 12:00:52 +03:00
# include "ldb/include/ldb.h"
# include "ldb/include/ldb_private.h"
2004-04-11 00:18:22 +04:00
# include "ldb/ldb_ldap/ldb_ldap.h"
2004-03-31 10:45:39 +04:00
2004-10-20 23:28:02 +04:00
/*
rename a record
*/
2005-08-18 19:02:01 +04:00
static int lldb_rename ( struct ldb_module * module , const struct ldb_dn * olddn , const struct ldb_dn * newdn )
2004-10-20 23:28:02 +04:00
{
2005-08-18 19:02:01 +04:00
TALLOC_CTX * local_ctx ;
2004-11-15 14:40:27 +03:00
struct lldb_private * lldb = module - > private_data ;
2004-10-20 23:28:02 +04:00
int ret = 0 ;
2005-08-18 19:02:01 +04:00
char * old_dn ;
char * newrdn ;
2004-10-20 23:28:02 +04:00
const char * parentdn = " " ;
/* ignore ltdb specials */
2005-08-18 19:02:01 +04:00
if ( ldb_dn_is_special ( olddn ) | | ldb_dn_is_special ( newdn ) ) {
2004-10-20 23:28:02 +04:00
return 0 ;
}
2005-08-18 19:02:01 +04:00
local_ctx = talloc_named ( lldb , 0 , " lldb_rename local context " ) ;
if ( local_ctx = = NULL ) {
2004-10-20 23:28:02 +04:00
return - 1 ;
}
2005-08-18 19:02:01 +04:00
old_dn = ldb_dn_linearize ( local_ctx , olddn ) ;
if ( old_dn = = NULL ) {
goto failed ;
}
newrdn = talloc_asprintf ( lldb , " %s=%s " ,
newdn - > components [ 0 ] . name ,
ldb_dn_escape_value ( lldb , newdn - > components [ 0 ] . value ) ) ;
if ( ! newrdn ) {
goto failed ;
}
parentdn = ldb_dn_linearize ( lldb , ldb_dn_get_parent ( lldb , newdn ) ) ;
if ( ! parentdn ) {
goto failed ;
2004-10-20 23:28:02 +04:00
}
2005-08-18 19:02:01 +04:00
lldb - > last_rc = ldap_rename_s ( lldb - > ldap , old_dn , newrdn , parentdn , 1 , NULL , NULL ) ;
2004-10-20 23:28:02 +04:00
if ( lldb - > last_rc ! = LDAP_SUCCESS ) {
ret = - 1 ;
}
2005-08-18 19:02:01 +04:00
talloc_free ( local_ctx ) ;
2004-10-20 23:28:02 +04:00
return ret ;
2005-08-18 19:02:01 +04:00
failed :
talloc_free ( local_ctx ) ;
return - 1 ;
2004-10-20 23:28:02 +04:00
}
2004-03-31 10:45:39 +04:00
/*
delete a record
*/
2005-08-18 19:02:01 +04:00
static int lldb_delete ( struct ldb_module * module , const struct ldb_dn * edn )
2004-03-31 10:45:39 +04:00
{
2004-11-15 14:40:27 +03:00
struct lldb_private * lldb = module - > private_data ;
2005-08-18 19:02:01 +04:00
char * dn ;
2004-03-31 10:45:39 +04:00
int ret = 0 ;
2004-05-01 13:45:56 +04:00
/* ignore ltdb specials */
2005-08-18 19:02:01 +04:00
if ( ldb_dn_is_special ( edn ) ) {
2004-05-01 13:45:56 +04:00
return 0 ;
}
2005-08-18 19:02:01 +04:00
dn = ldb_dn_linearize ( lldb , edn ) ;
2004-03-31 10:45:39 +04:00
lldb - > last_rc = ldap_delete_s ( lldb - > ldap , dn ) ;
if ( lldb - > last_rc ! = LDAP_SUCCESS ) {
ret = - 1 ;
}
2005-08-18 19:02:01 +04:00
talloc_free ( dn ) ;
2004-03-31 10:45:39 +04:00
return ret ;
}
/*
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 + + ) {
2005-01-02 10:49:29 +03:00
el - > values [ i ] . data = talloc_memdup ( el - > values , bval [ i ] - > bv_val , bval [ i ] - > bv_len ) ;
2004-04-03 16:29:21 +04:00
if ( ! el - > values [ i ] . data ) {
2004-03-31 10:45:39 +04:00
return - 1 ;
}
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
*/
2005-08-18 19:02:01 +04:00
static int lldb_search ( struct ldb_module * module , const struct ldb_dn * base ,
2004-03-31 10:45:39 +04:00
enum ldb_scope scope , const char * expression ,
2004-05-08 03:54:41 +04:00
const char * const * attrs , struct ldb_message * * * res )
2004-03-31 10:45:39 +04:00
{
2004-11-15 14:40:27 +03:00
struct ldb_context * ldb = module - > ldb ;
struct lldb_private * lldb = module - > private_data ;
2004-03-31 10:45:39 +04:00
int count , msg_count ;
2005-08-18 19:02:01 +04:00
char * search_base ;
2004-03-31 10:45:39 +04:00
LDAPMessage * ldapres , * msg ;
2005-08-18 19:02:01 +04:00
search_base = ldb_dn_linearize ( ldb , base ) ;
2004-11-15 15:30:28 +03:00
if ( base = = NULL ) {
2005-08-18 19:02:01 +04:00
search_base = talloc_strdup ( ldb , " " ) ;
}
if ( search_base = = NULL ) {
return - 1 ;
2004-11-15 15:30:28 +03:00
}
2005-06-14 23:15:17 +04:00
if ( expression = = NULL | | expression [ 0 ] = = ' \0 ' ) {
expression = " objectClass=* " ;
}
2005-08-18 19:02:01 +04:00
lldb - > last_rc = ldap_search_s ( lldb - > ldap , search_base , ( int ) scope ,
2004-10-28 17:19:39 +04:00
expression ,
discard_const_p ( char * , attrs ) ,
0 , & ldapres ) ;
2005-08-18 19:02:01 +04:00
talloc_free ( search_base ) ;
2004-03-31 10:45:39 +04:00
if ( lldb - > last_rc ! = LDAP_SUCCESS ) {
return - 1 ;
}
count = ldap_count_entries ( lldb - > ldap , ldapres ) ;
if ( count = = - 1 | | count = = 0 ) {
ldap_msgfree ( ldapres ) ;
return count ;
}
2005-01-12 19:00:01 +03:00
( * res ) = talloc_array ( lldb , struct ldb_message * , count + 1 ) ;
2004-03-31 10:45:39 +04:00
if ( ! * res ) {
ldap_msgfree ( ldapres ) ;
errno = ENOMEM ;
return - 1 ;
}
( * res ) [ 0 ] = NULL ;
msg_count = 0 ;
/* loop over all messages */
for ( msg = ldap_first_entry ( lldb - > ldap , ldapres ) ;
msg ;
msg = ldap_next_entry ( lldb - > ldap , msg ) ) {
BerElement * berptr = NULL ;
char * attr , * dn ;
if ( msg_count = = count ) {
/* hmm, got too many? */
2004-05-06 13:55:05 +04:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " Fatal: ldap message count inconsistent \n " ) ;
2004-03-31 10:45:39 +04:00
break ;
}
2005-01-12 19:00:01 +03:00
( * res ) [ msg_count ] = talloc ( * res , struct ldb_message ) ;
2004-03-31 10:45:39 +04:00
if ( ! ( * res ) [ msg_count ] ) {
goto failed ;
}
( * res ) [ msg_count + 1 ] = NULL ;
dn = ldap_get_dn ( lldb - > ldap , msg ) ;
if ( ! dn ) {
goto failed ;
}
2005-08-18 19:02:01 +04:00
( * res ) [ msg_count ] - > dn = ldb_dn_explode ( ( * res ) [ msg_count ] , dn ) ;
2004-03-31 10:45:39 +04:00
ldap_memfree ( dn ) ;
if ( ! ( * res ) [ msg_count ] - > dn ) {
goto failed ;
}
( * res ) [ msg_count ] - > num_elements = 0 ;
( * res ) [ msg_count ] - > elements = NULL ;
2004-04-28 11:32:37 +04:00
( * res ) [ msg_count ] - > private_data = NULL ;
2004-03-31 10:45:39 +04: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 ) {
2004-05-06 08:40:15 +04:00
lldb_add_msg_attr ( ldb , ( * res ) [ msg_count ] , attr , bval ) ;
2004-03-31 10:45:39 +04:00
ldap_value_free_len ( bval ) ;
}
ldap_memfree ( attr ) ;
}
if ( berptr ) ber_free ( berptr , 0 ) ;
msg_count + + ;
}
ldap_msgfree ( ldapres ) ;
return msg_count ;
failed :
2005-04-25 16:46:18 +04:00
if ( * res ) talloc_free ( * res ) ;
2004-03-31 10:45:39 +04:00
return - 1 ;
}
2005-06-13 13:10:17 +04:00
/*
search for matching records using a ldb_parse_tree
*/
2005-08-18 19:02:01 +04:00
static int lldb_search_bytree ( struct ldb_module * module , const struct ldb_dn * base ,
2005-06-13 13:10:17 +04:00
enum ldb_scope scope , struct ldb_parse_tree * tree ,
const char * const * attrs , struct ldb_message * * * res )
{
struct lldb_private * lldb = module - > private_data ;
char * expression ;
int ret ;
expression = ldb_filter_from_tree ( lldb , tree ) ;
if ( expression = = NULL ) {
return - 1 ;
}
ret = lldb_search ( module , base , scope , expression , attrs , res ) ;
talloc_free ( expression ) ;
return ret ;
}
2004-03-31 10:45:39 +04:00
/*
convert a ldb_message structure to a list of LDAPMod structures
ready for ldap_add ( ) or ldap_modify ( )
*/
2004-05-06 08:40:15 +04:00
static LDAPMod * * lldb_msg_to_mods ( struct ldb_context * ldb ,
const struct ldb_message * msg , int use_flags )
2004-03-31 10:45:39 +04:00
{
LDAPMod * * mods ;
2004-07-07 05:02:54 +04:00
unsigned int i , j ;
int num_mods = 0 ;
2004-03-31 10:45:39 +04:00
/* allocate maximum number of elements needed */
2005-01-12 19:00:01 +03:00
mods = talloc_array ( ldb , LDAPMod * , msg - > num_elements + 1 ) ;
2004-03-31 10:45:39 +04:00
if ( ! mods ) {
errno = ENOMEM ;
return NULL ;
}
mods [ 0 ] = NULL ;
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
2004-04-03 16:29:21 +04:00
const struct ldb_message_element * el = & msg - > elements [ i ] ;
2004-03-31 10:45:39 +04:00
2005-01-12 19:00:01 +03:00
mods [ num_mods ] = talloc ( ldb , LDAPMod ) ;
2004-03-31 10:45:39 +04:00
if ( ! mods [ num_mods ] ) {
goto failed ;
}
mods [ num_mods + 1 ] = NULL ;
mods [ num_mods ] - > mod_op = LDAP_MOD_BVALUES ;
if ( use_flags ) {
2004-04-03 16:29:21 +04:00
switch ( el - > flags & LDB_FLAG_MOD_MASK ) {
2004-03-31 10:45:39 +04:00
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 ;
}
}
2005-06-15 06:45:11 +04:00
mods [ num_mods ] - > mod_type = discard_const_p ( char , el - > name ) ;
2005-01-12 19:00:01 +03:00
mods [ num_mods ] - > mod_vals . modv_bvals = talloc_array ( mods [ num_mods ] ,
2005-01-02 10:49:29 +03:00
struct berval * ,
1 + el - > num_values ) ;
2004-03-31 10:45:39 +04:00
if ( ! mods [ num_mods ] - > mod_vals . modv_bvals ) {
goto failed ;
}
2004-04-03 16:29:21 +04:00
for ( j = 0 ; j < el - > num_values ; j + + ) {
2005-01-12 19:00:01 +03:00
mods [ num_mods ] - > mod_vals . modv_bvals [ j ] = talloc ( mods [ num_mods ] - > mod_vals . modv_bvals ,
2005-01-02 10:49:29 +03:00
struct berval ) ;
2004-04-03 16:29:21 +04:00
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 ;
2004-03-31 10:45:39 +04:00
}
2004-04-03 16:29:21 +04:00
mods [ num_mods ] - > mod_vals . modv_bvals [ j ] = NULL ;
2004-03-31 10:45:39 +04:00
num_mods + + ;
}
return mods ;
failed :
2005-01-02 10:49:29 +03:00
talloc_free ( mods ) ;
2004-03-31 10:45:39 +04:00
return NULL ;
}
/*
add a record
*/
2004-11-15 14:40:27 +03:00
static int lldb_add ( struct ldb_module * module , const struct ldb_message * msg )
2004-03-31 10:45:39 +04:00
{
2004-11-15 14:40:27 +03:00
struct ldb_context * ldb = module - > ldb ;
struct lldb_private * lldb = module - > private_data ;
2004-03-31 10:45:39 +04:00
LDAPMod * * mods ;
2005-08-18 19:02:01 +04:00
char * dn ;
2004-03-31 10:45:39 +04:00
int ret = 0 ;
2004-05-01 13:45:56 +04:00
/* ignore ltdb specials */
2005-08-18 19:02:01 +04:00
if ( ldb_dn_is_special ( msg - > dn ) ) {
2004-05-01 13:45:56 +04:00
return 0 ;
}
2004-05-06 08:40:15 +04:00
mods = lldb_msg_to_mods ( ldb , msg , 0 ) ;
2005-08-18 19:02:01 +04:00
if ( mods = = NULL ) {
return - 1 ;
}
dn = ldb_dn_linearize ( mods , msg - > dn ) ;
if ( dn = = NULL ) {
talloc_free ( mods ) ;
return - 1 ;
}
2004-03-31 10:45:39 +04:00
2005-08-18 19:02:01 +04:00
lldb - > last_rc = ldap_add_s ( lldb - > ldap , dn , mods ) ;
2004-03-31 10:45:39 +04:00
if ( lldb - > last_rc ! = LDAP_SUCCESS ) {
ret = - 1 ;
}
2005-01-02 10:49:29 +03:00
talloc_free ( mods ) ;
2004-03-31 10:45:39 +04:00
return ret ;
}
/*
modify a record
*/
2004-11-15 14:40:27 +03:00
static int lldb_modify ( struct ldb_module * module , const struct ldb_message * msg )
2004-03-31 10:45:39 +04:00
{
2004-11-15 14:40:27 +03:00
struct ldb_context * ldb = module - > ldb ;
struct lldb_private * lldb = module - > private_data ;
2004-03-31 10:45:39 +04:00
LDAPMod * * mods ;
2005-08-18 19:02:01 +04:00
char * dn ;
2004-03-31 10:45:39 +04:00
int ret = 0 ;
2004-05-01 13:45:56 +04:00
/* ignore ltdb specials */
2005-08-18 19:02:01 +04:00
if ( ldb_dn_is_special ( msg - > dn ) ) {
2004-05-01 13:45:56 +04:00
return 0 ;
}
2004-05-06 08:40:15 +04:00
mods = lldb_msg_to_mods ( ldb , msg , 1 ) ;
2005-08-18 19:02:01 +04:00
if ( mods = = NULL ) {
return - 1 ;
}
dn = ldb_dn_linearize ( mods , msg - > dn ) ;
if ( dn = = NULL ) {
talloc_free ( mods ) ;
return - 1 ;
}
2004-03-31 10:45:39 +04:00
2005-08-18 19:02:01 +04:00
lldb - > last_rc = ldap_modify_s ( lldb - > ldap , dn , mods ) ;
2004-03-31 10:45:39 +04:00
if ( lldb - > last_rc ! = LDAP_SUCCESS ) {
ret = - 1 ;
}
2005-01-02 10:49:29 +03:00
talloc_free ( mods ) ;
2004-03-31 10:45:39 +04:00
return ret ;
}
2004-11-21 18:51:54 +03:00
static int lldb_lock ( struct ldb_module * module , const char * lockname )
{
int ret = 0 ;
if ( lockname = = NULL ) {
return - 1 ;
}
/* TODO implement a local locking mechanism here */
return ret ;
}
static int lldb_unlock ( struct ldb_module * module , const char * lockname )
{
int ret = 0 ;
if ( lockname = = NULL ) {
return - 1 ;
}
/* TODO implement a local unlocking mechanism here */
return ret ;
}
2004-03-31 10:45:39 +04:00
/*
return extended error information
*/
2004-11-15 14:40:27 +03:00
static const char * lldb_errstring ( struct ldb_module * module )
2004-03-31 10:45:39 +04:00
{
2004-11-15 14:40:27 +03:00
struct lldb_private * lldb = module - > private_data ;
2004-03-31 10:45:39 +04:00
return ldap_err2string ( lldb - > last_rc ) ;
}
2004-11-15 14:40:27 +03:00
static const struct ldb_module_ops lldb_ops = {
2005-06-13 13:10:17 +04:00
. name = " ldap " ,
. search = lldb_search ,
. search_bytree = lldb_search_bytree ,
. add_record = lldb_add ,
. modify_record = lldb_modify ,
. delete_record = lldb_delete ,
. rename_record = lldb_rename ,
. named_lock = lldb_lock ,
. named_unlock = lldb_unlock ,
. errstring = lldb_errstring
2004-03-31 10:45:39 +04:00
} ;
2005-01-02 10:49:29 +03:00
static int lldb_destructor ( void * p )
{
struct lldb_private * lldb = p ;
ldap_unbind ( lldb - > ldap ) ;
return 0 ;
}
2004-03-31 10:45:39 +04:00
/*
connect to the database
*/
2005-06-18 11:42:21 +04:00
int lldb_connect ( struct ldb_context * ldb ,
const char * url ,
unsigned int flags ,
const char * options [ ] )
2004-03-31 10:45:39 +04:00
{
struct lldb_private * lldb = NULL ;
2005-06-18 11:42:21 +04:00
int version = 3 ;
2005-06-13 10:02:55 +04:00
2005-01-12 19:00:01 +03:00
lldb = talloc ( ldb , 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 ;
}
lldb - > ldap = NULL ;
lldb - > options = NULL ;
lldb - > last_rc = ldap_initialize ( & lldb - > ldap , url ) ;
if ( lldb - > last_rc ! = LDAP_SUCCESS ) {
2005-06-18 11:42:21 +04:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " ldap_initialize failed for URL '%s' - %s \n " ,
url , ldap_err2string ( lldb - > last_rc ) ) ;
2004-03-31 10:45:39 +04:00
goto failed ;
}
2005-01-02 10:49:29 +03:00
talloc_set_destructor ( lldb , lldb_destructor ) ;
2004-10-20 23:28:02 +04:00
lldb - > last_rc = ldap_set_option ( lldb - > ldap , LDAP_OPT_PROTOCOL_VERSION , & version ) ;
if ( lldb - > last_rc ! = LDAP_SUCCESS ) {
2005-06-18 11:42:21 +04:00
ldb_debug ( ldb , LDB_DEBUG_FATAL , " ldap_set_option failed - %s \n " ,
ldap_err2string ( lldb - > last_rc ) ) ;
2004-10-20 23:28:02 +04:00
}
2005-01-12 19:00:01 +03:00
ldb - > modules = talloc ( ldb , struct ldb_module ) ;
2004-11-15 14:40:27 +03:00
if ( ! ldb - > modules ) {
2005-06-18 11:42:21 +04:00
ldb_oom ( ldb ) ;
2004-11-15 14:40:27 +03:00
goto failed ;
}
ldb - > modules - > ldb = ldb ;
ldb - > modules - > prev = ldb - > modules - > next = NULL ;
ldb - > modules - > private_data = lldb ;
ldb - > modules - > ops = & lldb_ops ;
2004-03-31 10:45:39 +04:00
2005-06-18 11:42:21 +04:00
return 0 ;
2004-03-31 10:45:39 +04:00
failed :
2005-06-18 11:42:21 +04:00
talloc_free ( lldb ) ;
return - 1 ;
2004-03-31 10:45:39 +04:00
}
2004-04-11 00:18:22 +04:00