Pierangelo Masarati's bugfixes and enhancements for suffix-massaging.

See the Changes file for detailed description.
This commit is contained in:
Howard Chu 2001-01-19 21:27:20 +00:00
parent a728b2c073
commit 4703fe82b2
16 changed files with 836 additions and 86 deletions

View File

@ -0,0 +1,121 @@
Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
The backend back-ldap has been modified as follows:
* The LDAP handlers have been put under an avl tree, in an attempt
to improve the access to connections in heavy loaded environments
(many clients connecting simultaneously for long times, e.g.
authenticators that make successive searches and binds without
renewing the handler).
This required to change the lcs member of struct ldapinfo into
an (Avlnode *) member called conntree.
The member next in the ldapconn struct has been eliminated because
it is no longer needed.
* The ldap_back_dobind function has been forced to return the value
of the bound flag instead of void; there is no longer need to test
for the flag outside the function as a test was already in.
Now the function can be called as
if ( !ldap_back_dobind( lc, op ) ) {
/* handle error */
}
* The suffix of the operations can be "massaged", i.e. changed to
a different suffix to implement what has been termed a
"virtual naming context": an incoming request with a certain
base or related to a certain dn is turned into a request to a different
server with the base or the dn changed in its terminal part (the naming
context). The resulting entries, if any, have the real naming context
changed back into the virtual naming context.
This required to add a suffixMassage configuration line of the form
suffix "virtual naming context"
suffixMassage "virtual naming context" "real naming context"
(the name of the configuration parameter will be changed to something
more appropriate as will result from a debate in the -devel mailing
list).
The "virtual naming context" must appear in a suffix configuration line
so the server can select the appropriate backend; then the suffixMassage
configuration line maps the "virtual" and the "real" naming contexts
back and forth.
This allows one to map multiple real naming contexts as branches
of a single naming context, provided these reside on the same server:
suffix "ou=Branch 1, o=My Org, c=IT"
suffixMassage "ou=Branch 1, o=My Org, c=IT" "o=Org 1, c=IT"
suffix "ou=Branch 2, o=My Org, c=IT"
suffixMassage "ou=Branch 2, o=My Org, c=IT" "dc=host, dc=net"
suffix "o=My Org, c=IT"
suffixMassage "o=My Org, c=IT" "dc=host, dc=it"
Note that the "same server" limitation can be overcome by using
multiple back-ldap databases, each pointing to the appropriate
server.
Another choice, which would not allow multiple naming contexts
being served by the same database, is to use the "dn" part of the
"uri" configuration parameter, e.g.:
suffix "virtual naming context"
uri "ldap://ldap.my.org:port/real naming context"
This has not been implemented yet.
A possible future enhancement will allow the ldap backend to handle
multiple servers within a single naming context.
Two functions, ldap_back_dn_massage and ldap_back_dn_restore, have
been added. The former changes the bind dn or the search base,
in case its terminal portion matches the "virtual naming context"
of a suffixMassage entry, to the corresponding "real naming context"
suffixed value.
The latter turns the entry's dn back to the "virtual naming context"
suffixed form if the real dn terminal portion matches any "real naming
context" part of a suffixMassage configuration line.
The deferred bind required to add the bound_dn member to the ldapconn
struct.
As of the time of this writing, all the backend operations that
require writing (add, delete, modify, modrdn) have been added the
massaging capability; it can be safely turned off by turning on
the readonly mode at the backend level. The massaging is performed
only on the dn of the entry that is modified, and in the modrdn
operation it affects both the old and the newSuperior dn.
* Cleanup/minor bug fixes/software enhancements:
- the suffix member (unused) has been eliminated (commented out)
from the ldapinfo struct.
- bind.c:ldap_back_op_result: a check of the value of "match" and
"msg" variables is added before freeing them (got a NULL "match"
when the server the backend points to was restarted).
- search.c:ldap_send_entry: the member a_desc in the (Attribute *)
"attr" must be set to NULL before calling slap_str2ad, otherwise
an assertion fails (ITS #919).
- search.c:ldap_send_entry: the entry's ent.e_dn and ent.e_ndn members
need be freed before returning because they were allocated inside
the routine.
- modify.c:ldap_back_modify: the Modifications member sml_op needs be
ORed with LDAP_MOD_BVALUES to force the ldap_modify_s routine
handle the modifications as bervals:
mods[i].mod_op = ml->sml_op | LDAP_MOD_BVALUES;
* Notes:
- there a possible memory leak in the backend, because the memory
occupation of the slapd processes steadily grows when it is
repeatedly accessed.
- when writing (add/modify) lastmod must be set to OFF otherwise
the lastmod attributes will be added to the entry mods and the
target server will complain about
ldap_modify: Constraint violation
ldap_modify: additional info: no user modification allowed

View File

@ -21,3 +21,13 @@ to the following restrictions:
ever read sources, credits should appear in the documentation.
4. This notice may not be removed or altered.
Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
This software is being modified by Pierangelo Masarati.
The previously reported conditions apply to the modified code as well.
Changes in the original code are highlighted where required.
Credits for the original code go to the author, Howard Chu.

View File

@ -1,9 +1,11 @@
# $OpenLDAP$
SRCS = init.c config.c search.c bind.c unbind.c add.c compare.c \
delete.c modify.c modrdn.c group.c attribute.c
delete.c modify.c modrdn.c group.c attribute.c \
suffixmassage.c
OBJS = init.lo config.lo search.lo bind.lo unbind.lo add.lo compare.lo \
delete.lo modify.lo modrdn.lo group.lo attribute.lo
delete.lo modify.lo modrdn.lo group.lo attribute.lo \
suffixmassage.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries

View File

@ -0,0 +1,101 @@
back-proxy
A proxy that handles a pool of URI associated to a unique suffix.
Each request is spread over the different URIs and results are
masqueraded to appear as coming from a unique server.
Suppose a company has two branches, whose existing DS have URIs
"ldap://ldap.branch1.com/o=Branch 1, c=US"
"ldap://ldap.branch2.it/o=Branch 2, c=IT"
and it wants to propose to the outer world as a unique URI
"ldap://ldap.company.net/dc=company, dc=net"
It could do some rewriting to map everything that comes in with a base dn
of "o=Branch 1, dc=company, dc=net" as the URI of the Branch 1, and
everything that comes in with a base dn of "o=Branch 2, dc=company, dc=net"
as the URI of Branch 2, and by rewriting all the dns back to the new, uniform
base. Everything that comes in with a base dn of "dc=company, dc=net" should
be handled locally and propagated to the two branch URIs if a subtree
(or at least onelevel) search is required.
Operations:
- bind
- unbind
- search
- compare
- add
- modify
- modrdn
- delete
- abandon
The input of each operation may be related to:
exact dn exact parent ancestor
-------------------------------------------------------------
bind x
unbind
search x x x
compare x
add x
modify x
modrdn x
delete x
abandon
The backend must rely on a dn fetching mechanism. Each operation requires
to determine as early as possible which URI will be able to satisfy it.
Apart from searches, which by definition are usually allowed to return
multiple results, and apart from unbind and abandon, which do not return any
result, all the remaining operations require the related entry to be unique.
A major problem isposed by the uniqueness of the dns. As far as the suffixes
are masqueraded by a common suffix, tyhe dns are no longer guaranteed to be
unique. This backend relies on the assumption that the uniqueness of the
dns is guaranteed.
Two layers of depth in dn fetching are envisaged.
The first layer is provided by a backend-side cache made of previously
retrieved entries. The cache relates each rdn (i.e. the dn apart from the
common suffix) to the pool of URIs that are expected to contain a subset
of its children.
The second layer is provided by a fetching function that spawns a search for
each URI in the pool determined by the cache if the correct URI has not been
directly determined.
Note that, as the remote servers may have been updated by some direct
operation, this mechanism does not guarantee the uniqueness of the result.
So write operations will require to skip the cache search and to perform
the exaustive search of all the URIs unless some hint mechanism is provided
to the backend (e.g. a server is read-only).
Again, the lag between the fetching of the required dn and the actual
read/write may result in a failure; however, this applies to any LDAP
operation AFAIK.
- bind
if updates are to be strictly honored, a bind operation is performed against
each URI; otherwise, it is performed against the URIs resulting from a
cache-level dn fetch.
- unbind
nothing to say; all the open handles related to the connection are reset.
- search
if updates are to be strictly honored, a search operation is performed agaist
each URI. Note that this needs be performed also when the backend suffix
is used as base. In case the base is stricter, the URI pool may be restricted
by performing a cache dn fetch of the base first.
- compare
the same applies to the compare dn.
- add
this operation is delicate. Unless the dn up to the top-level part excluded
can be uniquely associated to a URI, and unless its uniqueness can be trusted,
no add operation should be allowed.

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -50,18 +59,20 @@ ldap_back_add(
Attribute *a;
LDAPMod **attrs;
lc = ldap_back_getconn(li, conn, op);
if (!lc)
return( -1 );
char *mdn;
if (!lc->bound) {
ldap_back_dobind(lc, op);
if (!lc->bound)
return( -1 );
lc = ldap_back_getconn(li, conn, op);
if ( !lc || !ldap_back_dobind( lc, op ) ) {
return( -1 );
}
mdn = ldap_back_dn_massage( li, ch_strdup( e->e_dn ), 0 );
if ( mdn == NULL ) {
return( -1 );
}
/* Count number of attributes in entry */
for (i=1, a=e->e_attrs; a; i++, a=a->a_next)
for (i = 1, a = e->e_attrs; a; i++, a = a->a_next)
;
/* Create array of LDAPMods for ldap_add() */
@ -75,9 +86,10 @@ ldap_back_add(
attrs[i]->mod_vals.modv_bvals = a->a_vals;
}
ldap_add_s(lc->ld, e->e_dn, attrs);
ldap_add_s(lc->ld, mdn, attrs);
for (--i; i>= 0; --i)
free(attrs[i]);
free(attrs);
free( mdn );
return( ldap_back_op_result( lc, op ));
}

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#ifndef SLAPD_LDAP_H
@ -37,28 +46,37 @@ struct slap_conn;
struct slap_op;
struct ldapconn {
struct ldapconn *next;
struct slap_conn *conn;
LDAP *ld;
char *bound_dn;
int bound;
};
struct ldapinfo {
char *url;
#if 0 /* unused! */
char *suffix;
#endif /* 0 */
char **suffix_massage;
char *binddn;
char *bindpw;
ldap_pvt_thread_mutex_t conn_mutex;
struct ldapconn *lcs;
Avlnode *conntree;
};
struct ldapconn *ldap_back_getconn(struct ldapinfo *li, struct slap_conn *conn,
struct slap_op *op);
void ldap_back_dobind(struct ldapconn *lc, Operation *op);
int ldap_back_dobind(struct ldapconn *lc, Operation *op);
int ldap_back_map_result(int err);
int ldap_back_op_result(struct ldapconn *lc, Operation *op);
int back_ldap_LTX_init_module(int argc, char *argv[]);
char *ldap_back_dn_massage(struct ldapinfo *li, char *dn, int normalized);
char *ldap_back_dn_restore(struct ldapinfo *li, char *dn, int normalized);
int conn_cmp(const void *, const void *);
int conn_dup(void *, void *);
LDAP_END_DECL
#endif

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -33,6 +42,8 @@
#include <ac/socket.h>
#include <ac/string.h>
#define AVL_INTERNAL
#include "slap.h"
#include "back-ldap.h"
@ -51,35 +62,116 @@ ldap_back_bind(
struct ldapinfo *li = (struct ldapinfo *) be->be_private;
struct ldapconn *lc;
char *mdn = NULL;
int rc = 0;
*edn = NULL;
lc = ldap_back_getconn(li, conn, op);
if (!lc)
if ( !lc ) {
return( -1 );
}
if (ldap_bind_s(lc->ld, dn, cred->bv_val, method) != LDAP_SUCCESS)
return( ldap_back_op_result(lc, op) );
mdn = ldap_back_dn_massage( li, ch_strdup( dn ), 0 );
if ( mdn == NULL ) {
return -1;
}
lc->bound = 1;
return( 0 );
if (ldap_bind_s(lc->ld, mdn, cred->bv_val, method) != LDAP_SUCCESS) {
rc = ldap_back_op_result( lc, op );
} else {
lc->bound = 1;
}
free( mdn );
return( rc );
}
/*
* conn_cmp
*
* compares two struct ldapconn based on the value of the conn pointer;
* used by avl stuff
*/
int
conn_cmp(
const void *c1,
const void *c2
)
{
struct ldapconn *lc1 = (struct ldapconn *)c1;
struct ldapconn *lc2 = (struct ldapconn *)c2;
return ( ( lc1->conn < lc2->conn ) ? -1 : ( ( lc1->conn > lc2-> conn ) ? 1 : 0 ) );
}
/*
* conn_dup
*
* returns -1 in case a duplicate struct ldapconn has been inserted;
* used by avl stuff
*/
int
conn_dup(
void *c1,
void *c2
)
{
struct ldapconn *lc1 = (struct ldapconn *)c1;
struct ldapconn *lc2 = (struct ldapconn *)c2;
return( ( lc1->conn == lc2->conn ) ? -1 : 0 );
}
static void ravl_print( Avlnode *root, int depth )
{
int i;
if ( root == 0 )
return;
ravl_print( root->avl_right, depth+1 );
for ( i = 0; i < depth; i++ )
printf( " " );
printf( "c(%d) %d\n", ((struct ldapconn *) root->avl_data)->conn->c_connid, root->avl_bf );
ravl_print( root->avl_left, depth+1 );
}
static void myprint( Avlnode *root )
{
printf( "********\n" );
if ( root == 0 )
printf( "\tNULL\n" );
else
ravl_print( root, 0 );
printf( "********\n" );
}
struct ldapconn *
ldap_back_getconn(struct ldapinfo *li, Connection *conn, Operation *op)
{
struct ldapconn *lc;
struct ldapconn *lc, lc_curr;
LDAP *ld;
/* Searches for a ldapconn in the avl tree */
lc_curr.conn = conn;
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
for (lc = li->lcs; lc; lc=lc->next)
if (lc->conn == conn)
break;
lc = (struct ldapconn *)avl_find( li->conntree,
(caddr_t)&lc_curr, conn_cmp );
ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
/* Looks like we didn't get a bind. Open a new session... */
if (!lc) {
int vers = conn->c_protocol;
int err = ldap_initialize(&ld, li->url);
if (err != LDAP_SUCCESS) {
err = ldap_back_map_result(err);
send_ldap_result( conn, op, err,
@ -94,26 +186,65 @@ ldap_back_getconn(struct ldapinfo *li, Connection *conn, Operation *op)
lc = (struct ldapconn *)ch_malloc(sizeof(struct ldapconn));
lc->conn = conn;
lc->ld = ld;
if ( lc->conn->c_cdn != NULL && lc->conn->c_cdn[0] != '\0' ) {
lc->bound_dn = ldap_back_dn_massage( li,
ch_strdup( lc->conn->c_cdn ), 0 );
} else {
lc->bound_dn = NULL;
}
lc->bound = 0;
/* Inserts the newly created ldapconn in the avl tree */
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
lc->next = li->lcs;
li->lcs = lc;
err = avl_insert( &li->conntree, (caddr_t)lc,
conn_cmp, conn_dup );
#if 1
myprint( li->conntree );
#endif
ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
Debug( LDAP_DEBUG_TRACE,
"=>ldap_back_getconn: conn %d inserted\n",
lc->conn->c_connid, 0, 0 );
/* Err could be -1 in case a duplicate ldapconn is inserted */
if ( err != 0 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
NULL, "internal server error", NULL, NULL );
/* better destroy the ldapconn struct? */
return( NULL );
}
} else {
Debug( LDAP_DEBUG_TRACE,
"=>ldap_back_getconn: conn %d fetched\n",
lc->conn->c_connid, 0, 0 );
}
return( lc );
}
void
/*
* ldap_back_dobind
*
* Note: as the check for the value of lc->bound was already here, I removed
* it from all the callers, and I made the function return the flag, so
* it can be used to simplify the check.
*/
int
ldap_back_dobind(struct ldapconn *lc, Operation *op)
{
if (lc->bound)
return;
if (lc->bound) {
return( lc->bound );
}
if (ldap_bind_s(lc->ld, lc->conn->c_cdn, NULL, LDAP_AUTH_SIMPLE) !=
LDAP_SUCCESS)
if (ldap_bind_s(lc->ld, lc->bound_dn, NULL, LDAP_AUTH_SIMPLE) !=
LDAP_SUCCESS) {
ldap_back_op_result(lc, op);
else
lc->bound = 1;
return( 0 );
} /* else */
return( lc->bound = 1 );
}
/* Map API errors to protocol errors... */
@ -166,16 +297,17 @@ ldap_back_map_result(int err)
int
ldap_back_op_result(struct ldapconn *lc, Operation *op)
{
int err;
char *msg;
char *match;
int err = LDAP_SUCCESS;
char *msg = NULL;
char *match = NULL;
ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &err);
ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &msg);
ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
err = ldap_back_map_result(err);
send_ldap_result( lc->conn, op, err, match, msg, NULL, NULL );
free(match);
free(msg);
/* better test the pointers before freeing? */
if ( match ) free( match );
if ( msg ) free( msg );
return( (err==LDAP_SUCCESS) ? 0 : -1 );
}

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -48,17 +57,21 @@ ldap_back_compare(
{
struct ldapinfo *li = (struct ldapinfo *) be->be_private;
struct ldapconn *lc;
char *mdn;
lc = ldap_back_getconn(li, conn, op);
if (!lc)
if (!lc || !ldap_back_dobind( lc, op ) ) {
return( -1 );
if (!lc->bound) {
ldap_back_dobind(lc, op);
if (!lc->bound)
return( -1 );
}
ldap_compare_s( lc->ld, dn, ava->aa_desc->ad_cname->bv_val, ava->aa_value->bv_val );
mdn = ldap_back_dn_massage( li, ch_strdup( dn ), 0 );
if ( mdn == NULL ) {
return -1;
}
ldap_compare_s( lc->ld, mdn, ava->aa_desc->ad_cname->bv_val, ava->aa_value->bv_val );
free( mdn );
return( ldap_back_op_result( lc, op ) );
}

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -101,6 +110,49 @@ ldap_back_db_config(
return( 1 );
}
li->bindpw = ch_strdup(argv[1]);
/* dn massaging */
} else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
char *dn, *massaged_dn;
BackendDB *tmp_be;
if ( argc != 3 ) {
fprintf( stderr,
"%s: line %d: syntax is \"suffixMassage <suffix> <massaged suffix>\"\n",
fname, lineno );
return( 1 );
}
tmp_be = select_backend( argv[1], 0 );
if ( tmp_be != NULL && tmp_be != be ) {
fprintf( stderr,
"%s: line %d: suffix already in use by another backend in"
" \"suffixMassage <suffix> <massaged suffix>\"\n",
fname, lineno );
return( 1 );
}
tmp_be = select_backend( argv[2], 0 );
if ( tmp_be != NULL ) {
fprintf( stderr,
"%s: line %d: massaged suffix already in use by another backend in"
" \"suffixMassage <suffix> <massaged suffix>\"\n",
fname, lineno );
return( 1 );
}
dn = ch_strdup( argv[1] );
charray_add( &li->suffix_massage, dn );
(void) dn_normalize( dn );
charray_add( &li->suffix_massage, dn );
massaged_dn = ch_strdup( argv[2] );
charray_add( &li->suffix_massage, massaged_dn );
(void) dn_normalize( massaged_dn );
charray_add( &li->suffix_massage, massaged_dn );
free( dn );
free( massaged_dn );
/* anything else */
} else {

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -48,16 +57,22 @@ ldap_back_delete(
struct ldapinfo *li = (struct ldapinfo *) be->be_private;
struct ldapconn *lc;
lc = ldap_back_getconn( li, conn, op );
if (!lc)
return( -1 );
char *mdn;
if (!lc->bound) {
ldap_back_dobind(lc, op);
if (!lc->bound)
return( -1 );
lc = ldap_back_getconn( li, conn, op );
if ( !lc || !ldap_back_dobind( lc, op ) ) {
return( -1 );
}
ldap_delete_s( lc->ld, dn );
mdn = ldap_back_dn_massage( li, ch_strdup( dn ), 0 );
if ( mdn == NULL ) {
return( -1 );
}
ldap_delete_s( lc->ld, mdn );
free( mdn );
return( ldap_back_op_result( lc, op ) );
}

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -103,6 +112,16 @@ ldap_back_db_init(
return li == NULL;
}
static void
conn_free(
struct ldapconn *lc
)
{
ldap_unbind(lc->ld);
if ( lc->bound_dn) free( lc->bound_dn );
free( lc );
}
int
ldap_back_db_destroy(
Backend *be
@ -112,6 +131,9 @@ ldap_back_db_destroy(
if (be->be_private) {
li = (struct ldapinfo *)be->be_private;
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
if (li->url) {
free(li->url);
li->url = NULL;
@ -124,6 +146,15 @@ ldap_back_db_destroy(
free(li->bindpw);
li->bindpw = NULL;
}
if (li->suffix_massage) {
ldap_value_free( li->suffix_massage );
li->suffix_massage = NULL;
}
if (li->conntree) {
avl_free( li->conntree, (AVL_FREE) conn_free );
}
ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
ldap_pvt_thread_mutex_destroy( &li->conn_mutex );
}

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -53,14 +62,16 @@ ldap_back_modify(
Modifications *ml;
int i;
lc = ldap_back_getconn(li, conn, op);
if (!lc)
return( -1 );
char *mdn;
if (!lc->bound) {
ldap_back_dobind(lc, op);
if (!lc->bound)
return( -1 );
lc = ldap_back_getconn(li, conn, op);
if ( !lc || !ldap_back_dobind( lc, op ) ) {
return( -1 );
}
mdn = ldap_back_dn_massage( li, ch_strdup( dn ), 0 );
if ( mdn == NULL ) {
return( -1 );
}
for (i=0, ml=modlist; ml; i++,ml=ml->sml_next)
@ -79,13 +90,16 @@ ldap_back_modify(
for (i=0, ml=modlist; ml; i++, ml=ml->sml_next) {
modv[i] = &mods[i];
mods[i].mod_op = ml->sml_op;
mods[i].mod_op = ml->sml_op | LDAP_MOD_BVALUES;
mods[i].mod_type = ml->sml_desc->ad_cname->bv_val;
mods[i].mod_bvalues = ml->sml_bvalues;
}
ldap_modify_s( lc->ld, dn, modv );
free(mods);
free(modv);
ldap_modify_s( lc->ld, mdn, modv );
free( mdn );
free(mods);
free(modv);
return( ldap_back_op_result( lc, op ));
}

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -51,21 +60,37 @@ ldap_back_modrdn(
struct ldapinfo *li = (struct ldapinfo *) be->be_private;
struct ldapconn *lc;
char *mdn, *mnewSuperior;
lc = ldap_back_getconn( li, conn, op );
if (!lc)
if ( !lc ) {
return( -1 );
}
if (newSuperior) {
int version = LDAP_VERSION3;
ldap_set_option( lc->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
}
if (!lc->bound) {
ldap_back_dobind(lc, op);
if (!lc->bound)
mnewSuperior = ldap_back_dn_massage( li,
ch_strdup( newSuperior ), 0 );
if ( mnewSuperior == NULL ) {
return( -1 );
}
}
ldap_rename2_s( lc->ld, dn, newrdn, newSuperior, deleteoldrdn );
if ( !ldap_back_dobind(lc, op) ) {
return( -1 );
}
mdn = ldap_back_dn_massage( li, ch_strdup( dn ), 0 );
if ( mdn == NULL ) {
return( -1 );
}
ldap_rename2_s( lc->ld, mdn, newrdn, mnewSuperior, deleteoldrdn );
free( mdn );
if ( mnewSuperior ) free( mnewSuperior );
return( ldap_back_op_result( lc, op ) );
}

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -64,9 +73,12 @@ ldap_back_search(
int i, rc, msgid, sres = LDAP_SUCCESS;
char *match = NULL, *err = NULL;
char *mbase;
lc = ldap_back_getconn(li, conn, op);
if (!lc)
if ( !lc ) {
return( -1 );
}
if (deref != -1)
ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&deref);
@ -74,13 +86,17 @@ ldap_back_search(
ldap_set_option( lc->ld, LDAP_OPT_TIMELIMIT, (void *)&time);
if (size != -1)
ldap_set_option( lc->ld, LDAP_OPT_SIZELIMIT, (void *)&size);
if (!lc->bound) {
ldap_back_dobind(lc, op);
if (!lc->bound)
return( -1 );
if ( !ldap_back_dobind( lc, op ) ) {
return( -1 );
}
if ((msgid = ldap_search(lc->ld, base, scope, filterstr, attrs,
mbase = ldap_back_dn_massage( li, ch_strdup( base ), 0 );
if ( mbase == NULL ) {
return -1;
}
if ((msgid = ldap_search(lc->ld, mbase, scope, filterstr, attrs,
attrsonly)) == -1)
fail: return( ldap_back_op_result(lc, op) );
@ -132,6 +148,8 @@ fail: return( ldap_back_op_result(lc, op) );
free(match);
if (err)
free(err);
if (mbase)
free(mbase);
return( 0 );
}
@ -145,6 +163,7 @@ ldap_send_entry(
int attrsonly
)
{
struct ldapinfo *li = (struct ldapinfo *) be->be_private;
char *a;
Entry ent;
BerElement *ber = NULL;
@ -152,8 +171,8 @@ ldap_send_entry(
struct berval *dummy = NULL;
const char *text;
ent.e_dn = ldap_get_dn(lc->ld, e);
ent.e_ndn = ch_strdup( ent.e_dn);
ent.e_dn = ldap_back_dn_restore( li, ldap_get_dn(lc->ld, e), 0 );
ent.e_ndn = ch_strdup( ent.e_dn );
(void) dn_normalize( ent.e_ndn );
ent.e_id = 0;
ent.e_attrs = 0;
@ -187,4 +206,9 @@ ldap_send_entry(
}
if (ber)
ber_free(ber,0);
if ( ent.e_dn )
free( ent.e_dn );
if ( ent.e_ndn )
free( ent.e_ndn );
}

View File

@ -0,0 +1,157 @@
/* suffixmassage.c - massages ldap backend dns */
/* $OpenLDAP$ */
/*
* Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* Module back-ldap, originally developed by Howard Chu
*
* has been modified by Pierangelo Masarati. The original copyright
* notice has been maintained.
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to alter it and redistribute it, subject
* to the following restrictions:
*
* 1. The author is not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits should appear in the documentation.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/socket.h>
#include "slap.h"
#include "back-ldap.h"
/*
* ldap_back_dn_massage
*
* Aliases the suffix; based on suffix_alias (servers/slapd/suffixalias.c).
*/
char *
ldap_back_dn_massage(
struct ldapinfo *li,
char *dn,
int normalized
)
{
int i, dnLength;
if ( dn == NULL ) {
return NULL;
}
if ( li == NULL ) {
return dn;
}
dnLength = strlen ( dn );
for ( i = 0;
li->suffix_massage != NULL && li->suffix_massage[i] != NULL;
i += 4 ) {
int aliasLength = strlen( li->suffix_massage[i+normalized] );
int diff = dnLength - aliasLength;
if ( diff < 0 ) {
/* alias is longer than dn */
continue;
} else if ( diff > 0 ) {
if ( normalized && ( ! DN_SEPARATOR(dn[diff-1]) ) ) {
/* boundary is not at a DN separator */
continue;
}
/* At a DN Separator */
/* XXX or an escaped separator... oh well */
}
if ( !strcmp( li->suffix_massage[i+normalized], &dn[diff] ) ) {
char *oldDN = dn;
dn = ch_malloc( diff + strlen( li->suffix_massage[i+2+normalized] ) + 1 );
strncpy( dn, oldDN, diff );
strcpy( &dn[diff], li->suffix_massage[i+2+normalized] );
Debug( LDAP_DEBUG_ARGS,
"ldap_back_dn_massage:"
" converted \"%s\" to \"%s\"\n",
oldDN, dn, 0 );
free( oldDN );
break;
}
}
return dn;
}
/*
* ldap_back_dn_restore
*
* Restores the original suffix;
* based on suffix_alias (servers/slapd/suffixalias.c).
*/
char *
ldap_back_dn_restore(
struct ldapinfo *li,
char *dn,
int normalized
)
{
int i, dnLength;
if ( dn == NULL ) {
return NULL;
}
if ( li == NULL ) {
return dn;
}
dnLength = strlen ( dn );
for ( i = 0;
li->suffix_massage != NULL && li->suffix_massage[i] != NULL;
i += 4 ) {
int aliasLength = strlen( li->suffix_massage[i+2+normalized] );
int diff = dnLength - aliasLength;
if ( diff < 0 ) {
/* alias is longer than dn */
continue;
} else if ( diff > 0 ) {
if ( normalized && ( ! DN_SEPARATOR(dn[diff-1]) ) ) {
/* boundary is not at a DN separator */
continue;
}
/* At a DN Separator */
/* XXX or an escaped separator... oh well */
}
if ( !strcmp( li->suffix_massage[i+2+normalized], &dn[diff] ) ) {
char *oldDN = dn;
dn = ch_malloc( diff + strlen( li->suffix_massage[i+normalized] ) + 1 );
strncpy( dn, oldDN, diff );
strcpy( &dn[diff], li->suffix_massage[i+normalized] );
Debug( LDAP_DEBUG_ARGS,
"ldap_back_dn_restore:"
" converted \"%s\" to \"%s\"\n",
oldDN, dn, 0 );
free( oldDN );
break;
}
}
return dn;
}

View File

@ -24,6 +24,15 @@
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
*
*
* Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
*
* This software is being modified by Pierangelo Masarati.
* The previously reported conditions apply to the modified code as well.
* Changes in the original code are highlighted where required.
* Credits for the original code go to the author, Howard Chu.
*/
#include "portable.h"
@ -43,20 +52,34 @@ ldap_back_conn_destroy(
)
{
struct ldapinfo *li = (struct ldapinfo *) be->be_private;
struct ldapconn *lc, *lp;
struct ldapconn *lc, lc_curr;
Debug( LDAP_DEBUG_TRACE,
"=>ldap_back_conn_destroy: fetching conn %d\n",
conn->c_connid, 0, 0 );
lc_curr.conn = conn;
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
for (lc = li->lcs, lp = (struct ldapconn *)&li->lcs; lc;
lp=lc, lc=lc->next)
if (lc->conn == conn) {
lp->next = lc->next;
break;
}
lc = avl_delete( &li->conntree, (caddr_t)&lc_curr, conn_cmp );
ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
if (lc) {
Debug( LDAP_DEBUG_TRACE,
"=>ldap_back_conn_destroy: destroying conn %d\n",
lc->conn->c_connid, 0, 0 );
/*
* Needs a test because the handler may be corrupted,
* and calling ldap_unbind on a corrupted header results
* in a segmentation fault
*/
ldap_unbind(lc->ld);
free(lc);
if ( lc->bound_dn ) {
free( lc->bound_dn );
}
free( lc );
}
/* no response to unbind */