See the Changes file for detailed description.
--- /dev/null
+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
+
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.
+
# $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
--- /dev/null
+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.
* 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"
Attribute *a;
LDAPMod **attrs;
+ 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 );
+ 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() */
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 ));
}
* 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
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
* 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"
#include <ac/socket.h>
#include <ac/string.h>
+
+#define AVL_INTERNAL
#include "slap.h"
#include "back-ldap.h"
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 );
+ }
+
+ mdn = ldap_back_dn_massage( li, ch_strdup( dn ), 0 );
+ if ( mdn == NULL ) {
+ return -1;
+ }
+
+ 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 );
+}
- if (ldap_bind_s(lc->ld, dn, cred->bv_val, method) != LDAP_SUCCESS)
- return( ldap_back_op_result(lc, op) );
+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( " " );
- lc->bound = 1;
- return( 0 );
+ 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,
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... */
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 );
}
* 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"
{
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 ) );
}
* 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"
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 {
* 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"
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 );
+ mdn = ldap_back_dn_massage( li, ch_strdup( dn ), 0 );
+ if ( mdn == NULL ) {
+ return( -1 );
}
+
+ ldap_delete_s( lc->ld, mdn );
- ldap_delete_s( lc->ld, dn );
+ free( mdn );
+
return( ldap_back_op_result( lc, op ) );
}
* 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"
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
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;
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 );
}
* 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"
Modifications *ml;
int i;
+ 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 );
+ 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)
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 ));
}
* 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"
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);
+
+ mnewSuperior = ldap_back_dn_massage( li,
+ ch_strdup( newSuperior ), 0 );
+ if ( mnewSuperior == NULL ) {
+ return( -1 );
+ }
}
- if (!lc->bound) {
- ldap_back_dobind(lc, op);
- if (!lc->bound)
- return( -1 );
+ if ( !ldap_back_dobind(lc, op) ) {
+ return( -1 );
}
- ldap_rename2_s( lc->ld, dn, newrdn, newSuperior, deleteoldrdn );
+ 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 ) );
}
* 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"
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);
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 );
+ }
+
+ mbase = ldap_back_dn_massage( li, ch_strdup( base ), 0 );
+ if ( mbase == NULL ) {
+ return -1;
}
- if ((msgid = ldap_search(lc->ld, base, scope, filterstr, attrs,
+ if ((msgid = ldap_search(lc->ld, mbase, scope, filterstr, attrs,
attrsonly)) == -1)
fail: return( ldap_back_op_result(lc, op) );
free(match);
if (err)
free(err);
+ if (mbase)
+ free(mbase);
return( 0 );
}
int attrsonly
)
{
+ struct ldapinfo *li = (struct ldapinfo *) be->be_private;
char *a;
Entry ent;
BerElement *ber = NULL;
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;
}
if (ber)
ber_free(ber,0);
+
+ if ( ent.e_dn )
+ free( ent.e_dn );
+ if ( ent.e_ndn )
+ free( ent.e_ndn );
}
--- /dev/null
+/* 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;
+}
+
* 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"
)
{
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 */