]> git.sur5r.net Git - openldap/commitdiff
Pierangelo Masarati's bugfixes and enhancements for suffix-massaging.
authorHoward Chu <hyc@openldap.org>
Fri, 19 Jan 2001 21:27:20 +0000 (21:27 +0000)
committerHoward Chu <hyc@openldap.org>
Fri, 19 Jan 2001 21:27:20 +0000 (21:27 +0000)
See the Changes file for detailed description.

16 files changed:
servers/slapd/back-ldap/Changes [new file with mode: 0644]
servers/slapd/back-ldap/Copyright
servers/slapd/back-ldap/Makefile.in
servers/slapd/back-ldap/TODO.proxy [new file with mode: 0644]
servers/slapd/back-ldap/add.c
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/compare.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/delete.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/modify.c
servers/slapd/back-ldap/modrdn.c
servers/slapd/back-ldap/search.c
servers/slapd/back-ldap/suffixmassage.c [new file with mode: 0644]
servers/slapd/back-ldap/unbind.c

diff --git a/servers/slapd/back-ldap/Changes b/servers/slapd/back-ldap/Changes
new file mode 100644 (file)
index 0000000..ded43c3
--- /dev/null
@@ -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
+
index c70463833d3ed138b92bcde26d92939cb4202610..4b23929e7a7945cfa27c0cc8d2a5bf253fd5ca39 100644 (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.
+
index 2f740a1e5d4b120f988b80cf9da4ee92d851d6ee..38f42798c51f38371726c0924f9bcf3a1e4829de 100644 (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
diff --git a/servers/slapd/back-ldap/TODO.proxy b/servers/slapd/back-ldap/TODO.proxy
new file mode 100644 (file)
index 0000000..41ada65
--- /dev/null
@@ -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.
index 656a6e6cbfad6e91e6c34da5110f93ed901acc35..f282ee0f9098cf2ea6045cfcf741398da03a59ba 100644 (file)
  *    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;
 
+       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() */
@@ -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 ));
 }
index 0fd098642e6b5c75d85e0fd22c95ccf597daf133..fdbe1a2d9c0d4504ffb19f79e738e7719f58bee0 100644 (file)
  *    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
index 67ce0fc16a8b894b74f88e9ac886334f243808c6..6fa83775b13a87549c583edea8770afd01314862 100644 (file)
  *    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 );
+       }
+
+       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,
@@ -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 );
 }
index e342f6ee43f415d11e351909a32f2f955f3e2f5f..e5db2342a7e41ab64c27ff71c17b7a64d2cfdea6 100644 (file)
  *    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 ) );
 }
index 4b0078f96c856940b5ec719fb7deed70c99c125f..5113ed617d08e3e888d6cef3eb492aae7d12c137 100644 (file)
  *    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 {
index 2035493684b400ee69eaee8205174e2d6c9134a3..4b92412be12769c6c2fe1f4f399ff8705e6569aa 100644 (file)
  *    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;
 
+       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 ) );
 }
index 7e4fabca09e0194690f5f7cccd1287f72df2e5c3..9d49b424a05730585c05ba0467b6b55ee7210f3b 100644 (file)
  *    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 );
        }
 
index ff9ac9f6d85096236acbaa94334ecd56c895e090..9b11c27b5736a7fc79f9272c8a67a322c7e5356a 100644 (file)
  *    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;
 
+       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)
@@ -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 ));
 }
index fd54b36aa24c6732a1580ef27348d43ceaca2e9c..66761c0a739de37d0b3b3ec03a9863cd63f4fe8f 100644 (file)
  *    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);
+               
+               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 ) );
 }
index d188c249c9ed874c1934536d53bbd3ce66456266..240a85736b2b576eb67f09b049fa30925d3fee68 100644 (file)
  *    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 );
+       }
+
+       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) );
 
@@ -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 );
 }
diff --git a/servers/slapd/back-ldap/suffixmassage.c b/servers/slapd/back-ldap/suffixmassage.c
new file mode 100644 (file)
index 0000000..aa49ef2
--- /dev/null
@@ -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;
+}
+
index 83d5609a42d3b37c65e0e44597a138a1dc34ca54..574ef6ba60e44d64c5784acd60e2a4cd4b383e5a 100644 (file)
  *    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 */