]> git.sur5r.net Git - openldap/commitdiff
cleanup states/timeout handling in back-ldap/meta; add connection pooling and defer...
authorPierangelo Masarati <ando@openldap.org>
Sat, 24 Sep 2005 18:39:26 +0000 (18:39 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sat, 24 Sep 2005 18:39:26 +0000 (18:39 +0000)
13 files changed:
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldap/search.c
servers/slapd/back-ldap/unbind.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/candidates.c
servers/slapd/back-meta/compare.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/search.c
servers/slapd/back-meta/unbind.c

index 828b55261eef1afa22773232406acc5242068fd4..787a27db980d4f5b713d3939ef6515c00f6a5d07 100644 (file)
@@ -28,15 +28,55 @@ LDAP_BEGIN_DECL
 
 struct ldapconn {
        Connection              *lc_conn;
-#define        LDAP_BACK_PRIV_CONN     ((void *)0x0)
-#define        LDAP_BACK_PRIV_CONN_TLS ((void *)0x1)
+#define        LDAP_BACK_PCONN         ((void *)0x0)
+#define        LDAP_BACK_PCONN_TLS     ((void *)0x1)
+#define        LDAP_BACK_PCONN_ID(c)   ((void *)(c) > LDAP_BACK_PCONN_TLS ? (c)->c_connid : -1)
+#ifdef HAVE_TLS
+#define        LDAP_BACK_PCONN_SET(op) ((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_TLS : LDAP_BACK_PCONN)
+#else /* ! HAVE_TLS */
+#define        LDAP_BACK_PCONN_SET(op) (LDAP_BACK_PCONN)
+#endif /* ! HAVE_TLS */
+
        LDAP                    *lc_ld;
        struct berval           lc_cred;
        struct berval           lc_bound_ndn;
        struct berval           lc_local_ndn;
-       int                     lc_bound;
-       int                     lc_ispriv;
-       int                     lc_is_tls;
+       unsigned                lc_lcflags;
+#define LDAP_BACK_CONN_ISSET(lc,f)     ((lc)->lc_lcflags & (f))
+#define        LDAP_BACK_CONN_SET(lc,f)        ((lc)->lc_lcflags |= (f))
+#define        LDAP_BACK_CONN_CLEAR(lc,f)      ((lc)->lc_lcflags &= ~(f))
+#define        LDAP_BACK_CONN_CPY(lc,f,mlc) \
+       do { \
+               if ( ((f) & (mlc)->lc_lcflags) == (f) ) { \
+                       (lc)->lc_lcflags |= (f); \
+               } else { \
+                       (lc)->lc_lcflags &= ~(f); \
+               } \
+       } while ( 0 )
+
+#define        LDAP_BACK_FCONN_ISBOUND (0x01)
+#define        LDAP_BACK_FCONN_ISANON  (0x02)
+#define        LDAP_BACK_FCONN_ISBMASK (LDAP_BACK_FCONN_ISBOUND|LDAP_BACK_FCONN_ISANON)
+#define        LDAP_BACK_FCONN_ISPRIV  (0x04)
+#define        LDAP_BACK_FCONN_ISTLS   (0x08)
+
+#define        LDAP_BACK_CONN_ISBOUND(lc)              LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND)
+#define        LDAP_BACK_CONN_ISBOUND_SET(lc)          LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND)
+#define        LDAP_BACK_CONN_ISBOUND_CLEAR(lc)        LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISBMASK)
+#define        LDAP_BACK_CONN_ISBOUND_CPY(lc, mlc)     LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISBOUND, (mlc))
+#define        LDAP_BACK_CONN_ISANON(lc)               LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISANON)
+#define        LDAP_BACK_CONN_ISANON_SET(lc)           LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISANON)
+#define        LDAP_BACK_CONN_ISANON_CLEAR(lc)         LDAP_BACK_CONN_ISBOUND_CLEAR((lc))
+#define        LDAP_BACK_CONN_ISANON_CPY(lc, mlc)      LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISANON, (mlc))
+#define        LDAP_BACK_CONN_ISPRIV(lc)               LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISPRIV)
+#define        LDAP_BACK_CONN_ISPRIV_SET(lc)           LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISPRIV)
+#define        LDAP_BACK_CONN_ISPRIV_CLEAR(lc)         LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISPRIV)
+#define        LDAP_BACK_CONN_ISPRIV_CPY(lc, mlc)      LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISPRIV, (mlc))
+#define        LDAP_BACK_CONN_ISTLS(lc)                LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISTLS)
+#define        LDAP_BACK_CONN_ISTLS_SET(lc)            LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISTLS)
+#define        LDAP_BACK_CONN_ISTLS_CLEAR(lc)          LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISTLS)
+#define        LDAP_BACK_CONN_ISTLS_CPY(lc, mlc)       LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISTLS, (mlc))
+
        unsigned                lc_refcnt;
        unsigned                lc_flags;
 };
@@ -89,6 +129,12 @@ struct ldapinfo {
        BerVarray       idassert_authz;
        /* end of ID assert stuff */
 
+       int             nretries;
+#define LDAP_BACK_RETRY_UNDEFINED      (-2)
+#define LDAP_BACK_RETRY_FOREVER                (-1)
+#define LDAP_BACK_RETRY_NEVER          (0)
+#define LDAP_BACK_RETRY_DEFAULT                (3)
+
        ldap_pvt_thread_mutex_t         conn_mutex;
        unsigned        flags;
 #define LDAP_BACK_F_NONE               0x00U
@@ -129,6 +175,15 @@ typedef enum ldap_back_send_t {
 /* define to use asynchronous StartTLS */
 #define SLAP_STARTTLS_ASYNCHRONOUS
 
+/* timeout to use when calling ldap_result() */
+#define        LDAP_BACK_RESULT_TIMEOUT        (0)
+#define        LDAP_BACK_RESULT_UTIMEOUT       (100000)
+#define        LDAP_BACK_TV_SET(tv) \
+       do { \
+               (tv)->tv_sec = LDAP_BACK_RESULT_TIMEOUT; \
+               (tv)->tv_usec = LDAP_BACK_RESULT_UTIMEOUT; \
+       } while ( 0 )
+
 LDAP_END_DECL
 
 #include "proto-ldap.h"
index 0df5202bed0ed7fa9177e5d8d67595b929b0f074..93f5cff445748f5130a6be828a4d81bb21e9f6da 100644 (file)
@@ -37,7 +37,9 @@
 
 #define PRINT_CONNTREE 0
 
-static LDAP_REBIND_PROC        ldap_back_rebind;
+static LDAP_REBIND_PROC        ldap_back_default_rebind;
+
+LDAP_REBIND_PROC       *ldap_back_rebind_f = ldap_back_default_rebind;
 
 static int
 ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs );
@@ -63,7 +65,7 @@ ldap_back_bind( Operation *op, SlapReply *rs )
                ch_free( lc->lc_bound_ndn.bv_val );
                BER_BVZERO( &lc->lc_bound_ndn );
        }
-       lc->lc_bound = 0;
+       LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
 
        /* method is always LDAP_AUTH_SIMPLE if we got here */
        rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val,
@@ -79,13 +81,13 @@ ldap_back_bind( Operation *op, SlapReply *rs )
                /* NOTE: use with care */
                if ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
                        ldap_back_proxy_authz_bind( lc, op, rs );
-                       if ( lc->lc_bound == 0 ) {
+                       if ( !LDAP_BACK_CONN_ISBOUND( lc ) ) {
                                rc = 1;
                                goto done;
                        }
                }
 
-               lc->lc_bound = 1;
+               LDAP_BACK_CONN_ISBOUND_SET( lc );
                ber_dupbv( &lc->lc_bound_ndn, &op->o_req_ndn );
 
                if ( LDAP_BACK_SAVECRED( li ) ) {
@@ -94,13 +96,15 @@ ldap_back_bind( Operation *op, SlapReply *rs )
                                                lc->lc_cred.bv_len );
                        }
                        ber_bvreplace( &lc->lc_cred, &op->orb_cred );
-                       ldap_set_rebind_proc( lc->lc_ld, ldap_back_rebind, lc );
+                       ldap_set_rebind_proc( lc->lc_ld, ldap_back_rebind_f, lc );
                }
        }
 done:;
 
        /* must re-insert if local DN changed as result of bind */
-       if ( lc->lc_bound && !dn_match( &op->o_req_ndn, &lc->lc_local_ndn ) ) {
+       if ( LDAP_BACK_CONN_ISBOUND( lc )
+               && !dn_match( &op->o_req_ndn, &lc->lc_local_ndn ) )
+       {
                int             lerr;
 
                /* wait for all other ops to release the connection */
@@ -251,16 +255,17 @@ ldap_back_start_tls(
        int             *is_tls,
        const char      *url,
        unsigned        flags,
+       int             retries,
        const char      **text )
 {
        int             rc = LDAP_SUCCESS;
-       struct ldapinfo li;
+       struct ldapinfo dummy;
 
-       /* this is ridicolous... */
-       li.flags = flags;
+       /* this is ridiculous... */
+       dummy.flags = flags;
 
        /* start TLS ("tls-[try-]{start,propagate}" statements) */
-       if ( ( LDAP_BACK_USE_TLS( &li ) || ( *is_tls && LDAP_BACK_PROPAGATE_TLS( &li ) ) )
+       if ( ( LDAP_BACK_USE_TLS( &dummy ) || ( *is_tls && LDAP_BACK_PROPAGATE_TLS( &dummy ) ) )
                                && !ldap_is_ldaps_url( url ) )
        {
 #ifdef SLAP_STARTTLS_ASYNCHRONOUS
@@ -285,8 +290,9 @@ ldap_back_start_tls(
                rc = ldap_start_tls( ld, NULL, NULL, &msgid );
                if ( rc == LDAP_SUCCESS ) {
                        LDAPMessage     *res = NULL;
-                       int             retries = 1;
-                       struct timeval  tv = { 0, 100000 };
+                       struct timeval  tv;
+
+                       LDAP_BACK_TV_SET( &tv );
 
 retry:;
                        rc = ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res );
@@ -294,10 +300,12 @@ retry:;
                                rc = LDAP_OTHER;
 
                        } else if ( rc == 0 ) {
-                               if ( retries ) {
-                                       retries--;
-                                       tv.tv_sec = 0;
-                                       tv.tv_usec = 100000;
+                               if ( retries != LDAP_BACK_RETRY_NEVER ) {
+                                       ldap_pvt_thread_yield();
+                                       if ( retries > 0 ) {
+                                               retries--;
+                                       }
+                                       LDAP_BACK_TV_SET( &tv );
                                        goto retry;
                                }
                                rc = LDAP_OTHER;
@@ -359,7 +367,7 @@ retry:;
                        break;
 
                default:
-                       if ( LDAP_BACK_TLS_CRITICAL( &li ) ) {
+                       if ( LDAP_BACK_TLS_CRITICAL( &dummy ) ) {
                                *text = "could not start TLS";
                                break;
                        }
@@ -406,9 +414,8 @@ ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, lda
        }
 
 #ifdef HAVE_TLS
-       rs->sr_err = ldap_back_start_tls( ld,
-                       op->o_protocol, &is_tls,
-                       li->url, li->flags, &rs->sr_text );
+       rs->sr_err = ldap_back_start_tls( ld, op->o_protocol, &is_tls,
+                       li->url, li->flags, li->nretries, &rs->sr_text );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                ldap_unbind_ext( ld, NULL, NULL );
                goto error_return;
@@ -422,7 +429,11 @@ ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, lda
        (*lcp)->lc_ld = ld;
        (*lcp)->lc_refcnt = 1;
 #ifdef HAVE_TLS
-       (*lcp)->lc_is_tls = is_tls;
+       if ( is_tls ) {
+               LDAP_BACK_CONN_ISTLS_SET( *lcp );
+       } else {
+               LDAP_BACK_CONN_ISTLS_CLEAR( *lcp );
+       }
 #endif /* HAVE_TLS */
 
 error_return:;
@@ -448,41 +459,24 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                        lc_curr = { 0 };
        int             refcnt = 1;
 
-       /* Searches for a ldapconn in the avl tree */
-
-       /* Explicit binds must not be shared */
-       if ( op->o_tag == LDAP_REQ_BIND || SLAP_IS_AUTHZ_BACKEND( op ) ) {
-               lc_curr.lc_conn = op->o_conn;
-
-       } else {
-#ifdef HAVE_TLS
-               if ( op->o_conn->c_is_tls ) {
-                       lc_curr.lc_conn = LDAP_BACK_PRIV_CONN_TLS;
-               } else
-#endif /* HAVE_TLS */
-               {
-                       lc_curr.lc_conn = LDAP_BACK_PRIV_CONN;
-               }
-       }
-       
        /* Internal searches are privileged and shared. So is root. */
-       /* FIXME: there seem to be concurrency issues */
        if ( op->o_do_not_cache || be_isroot( op ) ) {
+               LDAP_BACK_CONN_ISPRIV_SET( &lc_curr );
                lc_curr.lc_local_ndn = op->o_bd->be_rootndn;
-#ifdef HAVE_TLS
-               if ( op->o_conn->c_is_tls ) {
-                       lc_curr.lc_conn = LDAP_BACK_PRIV_CONN_TLS;
-               } else
-#endif /* HAVE_TLS */
-               {
-                       lc_curr.lc_conn = LDAP_BACK_PRIV_CONN;
-               }
-               lc_curr.lc_ispriv = 1;
+               lc_curr.lc_conn = LDAP_BACK_PCONN_SET( op );
 
        } else {
                lc_curr.lc_local_ndn = op->o_ndn;
+               /* Explicit binds must not be shared */
+               if ( op->o_tag == LDAP_REQ_BIND || SLAP_IS_AUTHZ_BACKEND( op ) ) {
+                       lc_curr.lc_conn = op->o_conn;
+       
+               } else {
+                       lc_curr.lc_conn = LDAP_BACK_PCONN_SET( op );
+               }
        }
 
+       /* Searches for a ldapconn in the avl tree */
        ldap_pvt_thread_mutex_lock( &li->conn_mutex );
 
        lc = (struct ldapconn *)avl_find( li->conntree, 
@@ -501,10 +495,10 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                lc->lc_conn = lc_curr.lc_conn;
                ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn );
 
-               if ( lc_curr.lc_ispriv ) {
+               if ( LDAP_BACK_CONN_ISPRIV( &lc_curr ) ) {
                        ber_dupbv( &lc->lc_cred, &li->acl_passwd );
                        ber_dupbv( &lc->lc_bound_ndn, &li->acl_authcDN );
-                       lc->lc_ispriv = lc_curr.lc_ispriv;
+                       LDAP_BACK_CONN_ISPRIV_SET( lc );
 
                } else {
                        BER_BVZERO( &lc->lc_cred );
@@ -521,12 +515,12 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                 * check if the non-TLS connection was already
                 * in cache; in case, destroy the newly created
                 * connection and use the existing one */
-               if ( lc->lc_conn == LDAP_BACK_PRIV_CONN_TLS
+               if ( lc->lc_conn == LDAP_BACK_PCONN_TLS
                                && !ldap_tls_inplace( lc->lc_ld ) )
                {
                        struct ldapconn *tmplc;
                        
-                       lc_curr.lc_conn = LDAP_BACK_PRIV_CONN;
+                       lc_curr.lc_conn = LDAP_BACK_PCONN;
                        ldap_pvt_thread_mutex_lock( &li->conn_mutex );
                        tmplc = (struct ldapconn *)avl_find( li->conntree, 
                                        (caddr_t)&lc_curr, ldap_back_conn_cmp );
@@ -543,7 +537,7 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                }
 #endif /* HAVE_TLS */
 
-               lc->lc_bound = 0;
+               LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
 
                /* Inserts the newly created ldapconn in the avl tree */
                ldap_pvt_thread_mutex_lock( &li->conn_mutex );
@@ -615,153 +609,160 @@ ldap_back_dobind_int(
        int                     retries,
        int                     dolock )
 {      
-       int             rc;
+       struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+
+       int             rc = LDAP_BACK_CONN_ISBOUND( lc );
        ber_int_t       msgid;
 
        assert( retries >= 0 );
 
-       if ( !lc->lc_bound ) {
-               struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+       if ( rc ) {
+               return rc;
+       }
 
-               /*
-                * FIXME: we need to let clients use proxyAuthz
-                * otherwise we cannot do symmetric pools of servers;
-                * we have to live with the fact that a user can
-                * authorize itself as any ID that is allowed
-                * by the authzTo directive of the "proxyauthzdn".
-                */
-               /*
-                * NOTE: current Proxy Authorization specification
-                * and implementation do not allow proxy authorization
-                * control to be provided with Bind requests
-                */
-               /*
-                * if no bind took place yet, but the connection is bound
-                * and the "idassert-authcDN" (or other ID) is set, 
-                * then bind as the asserting identity and explicitly 
-                * add the proxyAuthz control to every operation with the
-                * dn bound to the connection as control value.
-                * This is done also if this is the authrizing backend,
-                * but the "override" flag is given to idassert.
-                * It allows to use SASL bind and yet proxyAuthz users
-                */
-               if ( op->o_conn != NULL &&
-                               !op->o_do_not_cache &&
-                               ( BER_BVISNULL( &lc->lc_bound_ndn ) ||
-                                 ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
-               {
-                       (void)ldap_back_proxy_authz_bind( lc, op, rs );
-                       goto done;
-               }
+       /*
+        * FIXME: we need to let clients use proxyAuthz
+        * otherwise we cannot do symmetric pools of servers;
+        * we have to live with the fact that a user can
+        * authorize itself as any ID that is allowed
+        * by the authzTo directive of the "proxyauthzdn".
+        */
+       /*
+        * NOTE: current Proxy Authorization specification
+        * and implementation do not allow proxy authorization
+        * control to be provided with Bind requests
+        */
+       /*
+        * if no bind took place yet, but the connection is bound
+        * and the "idassert-authcDN" (or other ID) is set, 
+        * then bind as the asserting identity and explicitly 
+        * add the proxyAuthz control to every operation with the
+        * dn bound to the connection as control value.
+        * This is done also if this is the authrizing backend,
+        * but the "override" flag is given to idassert.
+        * It allows to use SASL bind and yet proxyAuthz users
+        */
+       if ( op->o_conn != NULL &&
+                       !op->o_do_not_cache &&
+                       ( BER_BVISNULL( &lc->lc_bound_ndn ) ||
+                         ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
+       {
+               (void)ldap_back_proxy_authz_bind( lc, op, rs );
+               goto done;
+       }
 
 #ifdef HAVE_CYRUS_SASL
-               if ( lc->lc_ispriv && li->acl_authmethod == LDAP_AUTH_SASL ) {
-                       void            *defaults = NULL;
-
-#if 1  /* will deal with this later... */
-                       if ( li->acl_secprops != NULL ) {
-                               rc = ldap_set_option( lc->lc_ld,
-                                       LDAP_OPT_X_SASL_SECPROPS, li->acl_secprops);
-
-                               if( rc != LDAP_OPT_SUCCESS ) {
-                                       Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
-                                               "(%s,SECPROPS,\"%s\") failed!\n",
-                                               li->url, li->acl_secprops, 0 );
-                                       goto done;
-                               }
-                       }
-#endif
+       if ( LDAP_BACK_CONN_ISPRIV( lc )
+               && li->acl_authmethod == LDAP_AUTH_SASL )
+       {
+               void            *defaults = NULL;
 
-                       defaults = lutil_sasl_defaults( lc->lc_ld,
-                                       li->acl_sasl_mech.bv_val,
-                                       li->acl_sasl_realm.bv_val,
-                                       li->acl_authcID.bv_val,
-                                       li->acl_passwd.bv_val,
-                                       NULL );
+               if ( li->acl_secprops != NULL ) {
+                       rc = ldap_set_option( lc->lc_ld,
+                               LDAP_OPT_X_SASL_SECPROPS, li->acl_secprops);
 
-                       rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld,
-                                       li->acl_authcDN.bv_val,
-                                       li->acl_sasl_mech.bv_val, NULL, NULL,
-                                       LDAP_SASL_QUIET, lutil_sasl_interact,
-                                       defaults );
+                       if ( rc != LDAP_OPT_SUCCESS ) {
+                               Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
+                                       "(%s,SECPROPS,\"%s\") failed!\n",
+                                       li->url, li->acl_secprops, 0 );
+                               goto done;
+                       }
+               }
 
-                       lutil_sasl_freedefs( defaults );
+               defaults = lutil_sasl_defaults( lc->lc_ld,
+                               li->acl_sasl_mech.bv_val,
+                               li->acl_sasl_realm.bv_val,
+                               li->acl_authcID.bv_val,
+                               li->acl_passwd.bv_val,
+                               NULL );
+
+               rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld,
+                               li->acl_authcDN.bv_val,
+                               li->acl_sasl_mech.bv_val, NULL, NULL,
+                               LDAP_SASL_QUIET, lutil_sasl_interact,
+                               defaults );
 
-                       rs->sr_err = slap_map_api2result( rs );
-                       if ( rs->sr_err != LDAP_SUCCESS ) {
-                               lc->lc_bound = 0;
-                               send_ldap_result( op, rs );
+               lutil_sasl_freedefs( defaults );
 
-                       } else {
-                               lc->lc_bound = 1;
-                       }
-                       goto done;
+               rs->sr_err = slap_map_api2result( rs );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
+                       send_ldap_result( op, rs );
+
+               } else {
+                       LDAP_BACK_CONN_ISBOUND_SET( lc );
                }
+               goto done;
+       }
 #endif /* HAVE_CYRUS_SASL */
 
 retry:;
-               rs->sr_err = ldap_sasl_bind( lc->lc_ld,
-                               lc->lc_bound_ndn.bv_val,
-                               LDAP_SASL_SIMPLE, &lc->lc_cred,
-                               NULL, NULL, &msgid );
-
-               if ( rs->sr_err == LDAP_SERVER_DOWN ) {
-                       if ( retries > 0 ) {
-                               if ( dolock ) {
-                                       ldap_pvt_thread_mutex_lock( &li->conn_mutex );
-                               }
+       rs->sr_err = ldap_sasl_bind( lc->lc_ld,
+                       lc->lc_bound_ndn.bv_val,
+                       LDAP_SASL_SIMPLE, &lc->lc_cred,
+                       NULL, NULL, &msgid );
+
+       if ( rs->sr_err == LDAP_SERVER_DOWN ) {
+               if ( retries != LDAP_BACK_RETRY_NEVER ) {
+                       if ( dolock ) {
+                               ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+                       }
 
-                               assert( lc->lc_refcnt > 0 );
-                               if ( lc->lc_refcnt == 1 ) {
-                                       ldap_unbind_ext( lc->lc_ld, NULL, NULL );
-                                       lc->lc_ld = NULL;
+                       assert( lc->lc_refcnt > 0 );
+                       if ( lc->lc_refcnt == 1 ) {
+                               ldap_unbind_ext( lc->lc_ld, NULL, NULL );
+                               lc->lc_ld = NULL;
 
-                                       /* lc here must be the regular lc, reset and ready for init */
-                                       rs->sr_err = ldap_back_prepare_conn( &lc, op, rs, sendok );
-                               }
-                               if ( dolock ) {
-                                       ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
-                               }
-                               if ( rs->sr_err == LDAP_SUCCESS ) {
+                               /* lc here must be the regular lc, reset and ready for init */
+                               rs->sr_err = ldap_back_prepare_conn( &lc, op, rs, sendok );
+                       }
+                       if ( dolock ) {
+                               ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+                       }
+                       if ( rs->sr_err == LDAP_SUCCESS ) {
+                               if ( retries > 0 ) {
                                        retries--;
-                                       goto retry;
                                }
+                               goto retry;
                        }
+               }
 
-                       ldap_back_freeconn( op, lc );
-                       rs->sr_err = slap_map_api2result( rs );
+               ldap_back_freeconn( op, lc );
+               rs->sr_err = slap_map_api2result( rs );
 
-                       return 0;
-               }
+               return 0;
+       }
 
-               rc = ldap_back_op_result( lc, op, rs, msgid, sendok );
-               if ( rc == LDAP_SUCCESS ) {
-                       lc->lc_bound = 1;
+       rc = ldap_back_op_result( lc, op, rs, msgid, sendok );
+       if ( rc == LDAP_SUCCESS ) {
+               LDAP_BACK_CONN_ISBOUND_SET( lc );
 
-               } else {
-                       ldap_back_release_conn( op, rs, lc );
-               }
+       } else {
+               ldap_back_release_conn( op, rs, lc );
        }
 
 done:;
-       rc = lc->lc_bound;
+       rc = LDAP_BACK_CONN_ISBOUND( lc );
+
        return rc;
 }
 
 int
 ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
 {
-       return ldap_back_dobind_int( lc, op, rs, sendok, 1, 1 );
+       struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+
+       return ldap_back_dobind_int( lc, op, rs, sendok, li->nretries, 1 );
 }
 
 /*
- * ldap_back_rebind
+ * ldap_back_default_rebind
  *
  * This is a callback used for chasing referrals using the same
  * credentials as the original user on this session.
  */
 static int 
-ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
+ldap_back_default_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
        ber_int_t msgid, void *params )
 {
        struct ldapconn *lc = (struct ldapconn *)params;
@@ -771,11 +772,12 @@ ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
        assert( lc != NULL );
 
        if ( !ldap_tls_inplace( ld ) ) {
-               int             is_tls = lc->lc_is_tls,
+               int             is_tls = LDAP_BACK_CONN_ISTLS( lc ),
                                rc;
                const char      *text = NULL;
 
-               rc = ldap_back_start_tls( ld, 0, &is_tls, url, lc->lc_flags, &text );
+               rc = ldap_back_start_tls( ld, 0, &is_tls, url, lc->lc_flags,
+                       LDAP_BACK_RETRY_DEFAULT, &text );
                if ( rc != LDAP_SUCCESS ) {
                        return rc;
                }
@@ -810,14 +812,15 @@ ldap_back_op_result(
         * remote server response */
        if ( ERR_OK( rs->sr_err ) ) {
                int             rc;
-               struct timeval  tv = { 0, 100000 };
+               struct timeval  tv;
+
+               LDAP_BACK_TV_SET( &tv );
 
 retry:;
                /* if result parsing fails, note the failure reason */
                switch ( ldap_result( lc->lc_ld, msgid, 1, &tv, &res ) ) {
                case 0:
-                       tv.tv_sec = 0;
-                       tv.tv_usec = 100000;    /* 0.1 s */
+                       LDAP_BACK_TV_SET( &tv );
                        ldap_pvt_thread_yield();
                        goto retry;
 
@@ -888,7 +891,7 @@ ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_se
        if ( lc->lc_refcnt == 1 ) {
                ldap_unbind_ext( lc->lc_ld, NULL, NULL );
                lc->lc_ld = NULL;
-               lc->lc_bound = 0;
+               LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
 
                /* lc here must be the regular lc, reset and ready for init */
                rc = ldap_back_prepare_conn( &lc, op, rs, sendok );
@@ -963,7 +966,7 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs )
                        if ( rs->sr_err != LDAP_SUCCESS ) {
                                if ( li->idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
                                        send_ldap_result( op, rs );
-                                       lc->lc_bound = 0;
+                                       LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
 
                                } else {
                                        rs->sr_err = LDAP_SUCCESS;
@@ -1021,18 +1024,17 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs )
                        }
                }
 
-#if 0  /* will deal with this later... */
-               if ( sasl_secprops != NULL ) {
-                       rs->sr_err = ldap_set_option( lc->lc_ld, LDAP_OPT_X_SASL_SECPROPS,
-                               (void *) sasl_secprops );
+               if ( li->idassert_secprops != NULL ) {
+                       rs->sr_err = ldap_set_option( lc->lc_ld,
+                               LDAP_OPT_X_SASL_SECPROPS,
+                               (void *)li->idassert_secprops );
 
                        if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
                                send_ldap_result( op, rs );
-                               lc->lc_bound = 0;
+                               LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
                                goto done;
                        }
                }
-#endif
 
                defaults = lutil_sasl_defaults( lc->lc_ld,
                                li->idassert_sasl_mech.bv_val,
@@ -1046,37 +1048,38 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs )
                                LDAP_SASL_QUIET, lutil_sasl_interact,
                                defaults );
 
-               lutil_sasl_freedefs( defaults );
-               if ( freeauthz ) {
-                       slap_sl_free( authzID.bv_val, op->o_tmpmemctx );
-               }
-
                rs->sr_err = slap_map_api2result( rs );
                if ( rs->sr_err != LDAP_SUCCESS ) {
-                       lc->lc_bound = 0;
+                       LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
                        send_ldap_result( op, rs );
 
                } else {
-                       lc->lc_bound = 1;
+                       LDAP_BACK_CONN_ISBOUND_SET( lc );
+               }
+
+               lutil_sasl_freedefs( defaults );
+               if ( freeauthz ) {
+                       slap_sl_free( authzID.bv_val, op->o_tmpmemctx );
                }
+
                goto done;
 #endif /* HAVE_CYRUS_SASL */
        }
 
        switch ( li->idassert_authmethod ) {
+       case LDAP_AUTH_NONE:
+               LDAP_BACK_CONN_ISBOUND_SET( lc );
+               goto done;
+
        case LDAP_AUTH_SIMPLE:
                rs->sr_err = ldap_sasl_bind( lc->lc_ld,
                                binddn.bv_val, LDAP_SASL_SIMPLE,
                                &bindcred, NULL, NULL, &msgid );
                break;
 
-       case LDAP_AUTH_NONE:
-               lc->lc_bound = 1;
-               goto done;
-
        default:
                /* unsupported! */
-               lc->lc_bound = 0;
+               LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
                rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
                send_ldap_result( op, rs );
                goto done;
@@ -1084,10 +1087,10 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs )
 
        rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR );
        if ( rc == LDAP_SUCCESS ) {
-               lc->lc_bound = 1;
+               LDAP_BACK_CONN_ISBOUND_SET( lc );
        }
 done:;
-       return lc->lc_bound;
+       return LDAP_BACK_CONN_ISBOUND( lc );
 }
 
 /*
@@ -1179,7 +1182,8 @@ ldap_back_proxy_authz_ctrl(
 
        } else if ( li->idassert_authmethod == LDAP_AUTH_SASL ) {
                if ( ( li->idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ )
-                               /* && ( !BER_BVISNULL( &op->o_conn->c_ndn ) || lc->lc_bound ) */ )
+                               /* && ( !BER_BVISNULL( &op->o_conn->c_ndn )
+                                       || LDAP_BACK_CONN_ISBOUND( lc ) ) */ )
                {
                        /* already asserted in SASL via native authz */
                        /* NOTE: the test on lc->lc_bound is used to trap
index 1a812f3d879bfcaad608d43c188d3487736452d1..80600e391c5dbf1d88142361aef226b918460a4f 100644 (file)
@@ -78,6 +78,8 @@ ldap_back_proxy_authz_ctrl_free(
 
 extern int chain_init( void );
 
+extern LDAP_REBIND_PROC                *ldap_back_rebind_f;
+
 LDAP_END_DECL
 
 #endif /* PROTO_LDAP_H */
index 213de648712559325c36dae08239d85ef45dd3db..45bc2e91528176b0d50b2b1efe8503bec151df06 100644 (file)
@@ -178,8 +178,7 @@ ldap_back_search(
                stoptime = op->o_time + op->ors_tlimit;
 
        } else {
-               tv.tv_sec = 0;
-               tv.tv_usec = 100000;
+               LDAP_BACK_TV_SET( &tv );
        }
 
        if ( op->ors_attrs ) {
@@ -264,8 +263,7 @@ fail:;
                }
 
                if ( rc == 0 ) {
-                       tv.tv_sec = 0;
-                       tv.tv_usec = 100000;
+                       LDAP_BACK_TV_SET( &tv );
                        ldap_pvt_thread_yield();
 
                        /* check time limit */
index 17d0bb763b740b41eaacc20d4d161e6269047d82..e097d0ae7a725f9338e4c85a94b10f1d0d4f4777 100644 (file)
@@ -55,7 +55,7 @@ ldap_back_conn_destroy(
        if ( lc ) {
                Debug( LDAP_DEBUG_TRACE,
                        "=>ldap_back_conn_destroy: destroying conn %ld (refcnt=%u)\n",
-                       lc->lc_conn->c_connid, lc->lc_refcnt, 0 );
+                       LDAP_BACK_PCONN_ID( lc->lc_conn ), lc->lc_refcnt, 0 );
 
                assert( lc->lc_refcnt == 0 );
 
index df9bfdf0237bfbad3791b69c1b225bfb464d0e0f..5a7f92e1c2dca5046f9eb2ea5b250b960f2b8755 100644 (file)
@@ -166,10 +166,16 @@ typedef struct metasingleconn_t {
        LDAP                    *msc_ld;
        struct berval           msc_bound_ndn;
        struct berval           msc_cred;
+       unsigned                msc_mscflags;
+       /* NOTE: lc_lcflags is redefined to msc_mscflags to reuse the macros
+        * defined for back-ldap */
+#define        lc_lcflags              msc_mscflags
+#if 0
        int                     msc_bound;
 #define META_UNBOUND           0
 #define META_BOUND             1
 #define META_ANONYMOUS         2
+#endif
 
        struct metainfo_t       *msc_info;
 } metasingleconn_t;
@@ -179,11 +185,16 @@ typedef struct metaconn_t {
        ldap_pvt_thread_mutex_t mc_mutex;
        unsigned                mc_refcnt;
        
+       struct berval           mc_local_ndn;
+       /* NOTE: msc_mscflags is used to recycle the #define
+        * in metasingleconn_t */
+       unsigned                msc_mscflags;
+
        /*
         * means that the connection is bound; 
         * of course only one target actually is ...
         */
-       int                     mc_auth_target;
+       int                     mc_authz_target;
 #define META_BOUND_NONE                (-1)
 #define META_BOUND_ALL         (-2)
        /* supersedes the connection stuff */
@@ -258,10 +269,14 @@ typedef struct metainfo_t {
 
        unsigned                flags;
 /* uses flags as defined in <back-ldap/back-ldap.h> */
-#define        META_BACK_F_ONERR_STOP  0x00010000U
+#define        META_BACK_F_ONERR_STOP          0x00010000U
+#define        META_BACK_F_DEFER_ROOTDN_BIND   0x00020000U
+
 #define        META_BACK_ONERR_STOP(mi)        ( (mi)->flags & META_BACK_F_ONERR_STOP )
 #define        META_BACK_ONERR_CONTINUE(mi)    ( !META_BACK_ONERR_CONTINUE( (mi) ) )
 
+#define META_BACK_DEFER_ROOTDN_BIND(mi)        ( (mi)->flags & META_BACK_F_DEFER_ROOTDN_BIND )
+
        int                     mi_version;
        time_t                  mi_timeout[ META_OP_LAST ];
 } metainfo_t;
@@ -404,6 +419,8 @@ meta_dncache_delete_entry(
 extern void
 meta_dncache_free( void *entry );
 
+extern LDAP_REBIND_PROC                *meta_back_rebind_f;
+
 LDAP_END_DECL
 
 #endif /* SLAPD_META_H */
index eb25c58fe01452ca927466c78c57df73e12e184d..17dab2f39712ceb34df2f693cf95ef7b93b62f0e 100644 (file)
 #include "../back-ldap/back-ldap.h"
 #include "back-meta.h"
 
-static LDAP_REBIND_PROC        meta_back_rebind;
+static LDAP_REBIND_PROC        meta_back_default_rebind;
+
+/*
+ * a module could register a replacement for this function
+ */
+LDAP_REBIND_PROC       *meta_back_rebind_f = meta_back_default_rebind;
 
 static int
 meta_back_single_bind(
@@ -50,15 +55,18 @@ meta_back_bind( Operation *op, SlapReply *rs )
        metaconn_t      *mc = NULL;
 
        int             rc = LDAP_OTHER,
-                       i, gotit = 0, isroot = 0;
+                       i,
+                       gotit = 0,
+                       isroot = 0;
 
        SlapReply       *candidates = meta_back_candidates_get( op );
 
        rs->sr_err = LDAP_SUCCESS;
 
-       Debug( LDAP_DEBUG_ARGS, "meta_back_bind: dn: %s.\n%s%s",
-                       op->o_req_dn.bv_val, "", "" );
+       Debug( LDAP_DEBUG_ARGS, "%s meta_back_bind: dn=\"%s\".\n",
+               op->o_log_prefix, op->o_req_dn.bv_val, 0 );
 
+       /* the test on the bind method should be superfluous */
        if ( op->orb_method == LDAP_AUTH_SIMPLE
                && be_isroot_dn( op->o_bd, &op->o_req_ndn ) )
        {
@@ -68,6 +76,14 @@ meta_back_bind( Operation *op, SlapReply *rs )
                        send_ldap_result( op, rs );
                        return rs->sr_err;
                }
+
+               if ( META_BACK_DEFER_ROOTDN_BIND( mi ) ) {
+                       rs->sr_err = LDAP_SUCCESS;
+                       rs->sr_text = NULL;
+                       send_ldap_result( op, rs );
+                       return rs->sr_err;
+               }
+
                isroot = 1;
        }
 
@@ -76,11 +92,18 @@ meta_back_bind( Operation *op, SlapReply *rs )
         * invalidCredentials */
        mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_DONTSEND );
        if ( !mc ) {
+               char    buf[ SLAP_TEXT_BUFLEN ];
+
+               snprintf( buf, sizeof( buf ),
+                       "meta_back_bind: no target "
+                       "for dn \"%s\" (%d%s%s).",
+                       op->o_req_dn.bv_val, rs->sr_err,
+                       rs->sr_text ? ". " : "",
+                       rs->sr_text ? rs->sr_text : "" );
                Debug( LDAP_DEBUG_ANY,
-                               "meta_back_bind: no target "
-                               "for dn \"%s\" (%d: %s).\n",
-                               op->o_req_dn.bv_val, rs->sr_err,
-                               rs->sr_text ? rs->sr_text : "" );
+                       "%s %s\n",
+                       op->o_log_prefix, buf, 0 );
+
                /* FIXME: there might be cases where we don't want
                 * to map the error onto invalidCredentials */
                switch ( rs->sr_err ) {
@@ -97,7 +120,7 @@ meta_back_bind( Operation *op, SlapReply *rs )
        /*
         * Each target is scanned ...
         */
-       mc->mc_auth_target = META_BOUND_NONE;
+       mc->mc_authz_target = META_BOUND_NONE;
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
                int             lerr;
                Operation       op2 = *op;
@@ -110,6 +133,9 @@ meta_back_bind( Operation *op, SlapReply *rs )
                }
 
                if ( gotit == 0 ) {
+                       /* set rc to LDAP_SUCCESS only if at least
+                        * one candidate has been tried */
+                       rc = LDAP_SUCCESS;
                        gotit = 1;
 
                } else if ( isroot == 0 ) {
@@ -118,13 +144,35 @@ meta_back_bind( Operation *op, SlapReply *rs )
                         * ONE CANDIDATE ONLY!
                         */
                        Debug( LDAP_DEBUG_ANY,
-                                       "==>meta_back_bind: more than one"
-                                       " candidate is trying to bind...\n",
-                                       0, 0, 0 );
+                               "### %s meta_back_bind: more than one"
+                               " candidate is trying to bind...\n",
+                               op->o_log_prefix, 0, 0 );
                }
 
-               if ( isroot && !BER_BVISNULL( &mi->mi_targets[ i ].mt_pseudorootdn ) )
-               {
+               if ( isroot ) {
+                       if ( BER_BVISNULL( &mi->mi_targets[ i ].mt_pseudorootdn ) )
+                       {
+                               metasingleconn_t        *msc = &mc->mc_conns[ i ];
+
+                               /* skip the target if no pseudorootdn is provided */
+                               if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
+                                       ch_free( msc->msc_bound_ndn.bv_val );
+                                       BER_BVZERO( &msc->msc_bound_ndn );
+                               }
+
+                               if ( LDAP_BACK_SAVECRED( mi ) &&
+                                       !BER_BVISNULL( &msc->msc_cred ) )
+                               {
+                                       /* destroy sensitive data */
+                                       memset( msc->msc_cred.bv_val, 0,
+                                               msc->msc_cred.bv_len );
+                                       ch_free( msc->msc_cred.bv_val );
+                                       BER_BVZERO( &msc->msc_cred );
+                               }
+
+                               continue;
+                       }
+
                        op2.o_req_dn = mi->mi_targets[ i ].mt_pseudorootdn;
                        op2.o_req_ndn = mi->mi_targets[ i ].mt_pseudorootdn;
                        op2.orb_cred = mi->mi_targets[ i ].mt_pseudorootpw;
@@ -140,23 +188,60 @@ meta_back_bind( Operation *op, SlapReply *rs )
                                rc = rs->sr_err;
                                break;
                        }
-                               
-               } else {
-                       rc = LDAP_SUCCESS;
                }
        }
 
-       if ( isroot && rc == LDAP_SUCCESS ) {
-               mc->mc_auth_target = META_BOUND_ALL;
-               ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ) );
+       /* must re-insert if local DN changed as result of bind */
+       if ( rc == LDAP_SUCCESS ) {
+               if ( isroot ) {
+                       mc->mc_authz_target = META_BOUND_ALL;
+                       ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ) );
+               }
+
+               if ( !dn_match( &op->o_req_ndn, &mc->mc_local_ndn ) ) {
+                       int             lerr;
+
+                       /* wait for all other ops to release the connection */
+retry_lock:;
+                       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
+                       if ( mc->mc_refcnt > 1 ) {
+                               ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+                               ldap_pvt_thread_yield();
+                               goto retry_lock;
+                       }
+
+                       assert( mc->mc_refcnt == 1 );
+                       mc = avl_delete( &mi->mi_conntree, (caddr_t)mc,
+                               meta_back_conn_cmp );
+                       assert( mc != NULL );
+
+                       ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
+                       lerr = avl_insert( &mi->mi_conntree, (caddr_t)mc,
+                               meta_back_conn_cmp, meta_back_conn_dup );
+                       ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+                       if ( lerr == -1 ) {
+                               for ( i = 0; i < mi->mi_ntargets; ++i ) {
+                                       if ( mc->mc_conns[ i ].msc_ld != NULL ) {
+                                               meta_clear_one_candidate( &mc->mc_conns[ i ] );
+                                       }
+                               }
+
+                               /* we can do this because mc_refcnt == 1 */
+                               mc->mc_refcnt = 0;
+                               meta_back_conn_free( mc );
+                               mc = NULL;
+                       }
+               }
        }
 
-       meta_back_release_conn( op, mc );
+       if ( mc != NULL ) {
+               meta_back_release_conn( op, mc );
+       }
 
        /*
         * rc is LDAP_SUCCESS if at least one bind succeeded,
         * err is the last error that occurred during a bind;
-        * if at least (and at most?) one bind succeedes, fine.
+        * if at least (and at most?) one bind succeeds, fine.
         */
        if ( rc != LDAP_SUCCESS ) {
                
@@ -170,11 +255,12 @@ meta_back_bind( Operation *op, SlapReply *rs )
                 */
                if ( rs->sr_err == LDAP_SUCCESS && gotit == 0 ) {
                        rs->sr_err = LDAP_INVALID_CREDENTIALS;
+               } else {
+                       rs->sr_err = slap_map_api2result( rs );
                }
-
-               rs->sr_err = slap_map_api2result( rs );
                send_ldap_result( op, rs );
                return rs->sr_err;
+
        }
 
        return LDAP_SUCCESS;
@@ -199,11 +285,24 @@ meta_back_single_bind(
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
        int                     msgid,
                                rebinding = 0;
+
        
+       if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
+               ch_free( msc->msc_bound_ndn.bv_val );
+               BER_BVZERO( &msc->msc_bound_ndn );
+       }
+
+       if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
+               /* destroy sensitive data */
+               memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
+               ch_free( msc->msc_cred.bv_val );
+               BER_BVZERO( &msc->msc_cred );
+       }
+
        /*
         * Rewrite the bind dn if needed
         */
-       dc.target = &mi->mi_targets[ candidate ];
+       dc.target = mt;
        dc.conn = op->o_conn;
        dc.rs = rs;
        dc.ctx = "bindDN";
@@ -216,7 +315,7 @@ meta_back_single_bind(
        /* FIXME: this fixes the bind problem right now; we need
         * to use the asynchronous version to get the "matched"
         * and more in case of failure ... */
-       /* FIXME: should be check if at least some of the op->o_ctrls
+       /* FIXME: should we check if at least some of the op->o_ctrls
         * can/should be passed? */
 rebind:;
        rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val,
@@ -224,10 +323,12 @@ rebind:;
                        op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_SUCCESS ) {
                LDAPMessage     *res;
-               struct timeval  tv = { 0, 100000 };
+               struct timeval  tv;
                int             rc;
                int             nretries = mt->mt_nretries;
 
+               LDAP_BACK_TV_SET( &tv );
+
                /*
                 * handle response!!!
                 */
@@ -247,8 +348,7 @@ retry:;
                                if ( nretries > 0 ) {
                                        nretries--;
                                }
-                               tv.tv_sec = 0;
-                               tv.tv_usec = 100000;
+                               LDAP_BACK_TV_SET( &tv );
                                goto retry;
                        }
                        rs->sr_err = LDAP_BUSY;
@@ -284,7 +384,7 @@ retry:;
                                if ( mc->mc_refcnt == 1 ) {
                                        ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
                                        msc->msc_ld = NULL;
-                                       msc->msc_bound = 0;
+                                       LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
 
                                        ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
 
@@ -326,12 +426,12 @@ retry:;
        }
 
        ber_bvreplace( &msc->msc_bound_ndn, &op->o_req_dn );
-       msc->msc_bound = META_BOUND;
-       mc->mc_auth_target = candidate;
+       LDAP_BACK_CONN_ISBOUND_SET( msc );
+       mc->mc_authz_target = candidate;
 
        if ( LDAP_BACK_SAVECRED( mi ) ) {
                ber_bvreplace( &msc->msc_cred, &op->orb_cred );
-               ldap_set_rebind_proc( msc->msc_ld, meta_back_rebind, msc );
+               ldap_set_rebind_proc( msc->msc_ld, meta_back_rebind_f, msc );
        }
 
        if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED
@@ -366,11 +466,13 @@ meta_back_single_dobind(
        metatarget_t            *mt = &mi->mi_targets[ candidate ];
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
        int                     rc;
-       struct berval           cred = BER_BVC( "" );
+       static struct berval    cred = BER_BVC( "" );
        int                     msgid,
                                rebinding = 0,
                                save_nretries = nretries;
 
+       assert( !LDAP_BACK_CONN_ISBOUND( msc ) );
+
        /*
         * Otherwise an anonymous bind is performed
         * (note: if the target was already bound, the anonymous
@@ -381,7 +483,7 @@ meta_back_single_dobind(
                BER_BVZERO( &msc->msc_bound_ndn );
        }
                
-       if ( !BER_BVISNULL( &msc->msc_cred ) ) {
+       if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &msc->msc_cred ) ) {
                /* destroy sensitive data */
                memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
                ber_memfree( msc->msc_cred.bv_val );
@@ -395,7 +497,9 @@ rebind:;
                        NULL, NULL, &msgid );
        if ( rc == LDAP_SUCCESS ) {
                LDAPMessage     *res;
-               struct timeval  tv = { 0, 100000 };
+               struct timeval  tv;
+
+               LDAP_BACK_TV_SET( &tv );
 
                /*
                 * handle response!!!
@@ -416,8 +520,7 @@ retry:;
                                if ( nretries > 0 ) {
                                        nretries--;
                                }
-                               tv.tv_sec = 0;
-                               tv.tv_usec = 100000;
+                               LDAP_BACK_TV_SET( &tv );
                                goto retry;
                        }
 
@@ -457,7 +560,7 @@ retry:;
                                if ( mc->mc_refcnt == 1 ) {
                                        ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
                                        msc->msc_ld = NULL;
-                                       msc->msc_bound = 0;
+                                       LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
 
                                        ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
 
@@ -532,7 +635,8 @@ meta_back_dobind(
 
        Debug( LDAP_DEBUG_TRACE,
                "%s meta_back_dobind: conn=%ld%s\n",
-               op->o_log_prefix, mc->mc_conn->c_connid,
+               op->o_log_prefix,
+               LDAP_BACK_PCONN_ID( mc->mc_conn ),
                isroot ? " (isroot)" : "" );
 
        ldap_pvt_thread_mutex_lock( &mc->mc_mutex );
@@ -540,7 +644,7 @@ meta_back_dobind(
        /*
         * all the targets are bound as pseudoroot
         */
-       if ( mc->mc_auth_target == META_BOUND_ALL ) {
+       if ( mc->mc_authz_target == META_BOUND_ALL ) {
                bound = 1;
                goto done;
        }
@@ -549,6 +653,7 @@ meta_back_dobind(
                metatarget_t            *mt = &mi->mi_targets[ i ];
                metasingleconn_t        *msc = &mc->mc_conns[ i ];
                int                     rc;
+               char                    *rootdn = NULL;
 
                /*
                 * Not a candidate
@@ -562,12 +667,8 @@ meta_back_dobind(
                /*
                 * If the target is already bound it is skipped
                 */
-               if ( msc->msc_bound == META_BOUND && mc->mc_auth_target == i ) {
+               if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
                        ++bound;
-
-                       Debug( LDAP_DEBUG_TRACE, "%s meta_back_dobind[%d]: "
-                                       "authcTarget\n",
-                                       op->o_log_prefix, i, 0 );
                        continue;
                }
 
@@ -581,6 +682,8 @@ meta_back_dobind(
                        op2.orb_cred = mi->mi_targets[ i ].mt_pseudorootpw;
                        op2.orb_method = LDAP_AUTH_SIMPLE;
 
+                       rootdn = mi->mi_targets[ i ].mt_pseudorootdn.bv_val;
+
                        rc = meta_back_single_bind( &op2, rs, mc, i );
 
                } else {
@@ -589,9 +692,14 @@ meta_back_dobind(
                }
 
                if ( rc != LDAP_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY, "%s meta_back_dobind[%d]: "
-                                       "(anonymous) err=%d\n",
-                                       op->o_log_prefix, i, rc );
+                       char            buf[ SLAP_TEXT_BUFLEN ];
+
+                       snprintf( buf, sizeof( buf ),
+                               "meta_back_dobind[%d]: (%s) err=%d.",
+                               i, rootdn ? rootdn : "anonymous", rc );
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s %s\n",
+                               op->o_log_prefix, buf, 0 );
 
                        /*
                         * null cred bind should always succeed
@@ -609,11 +717,17 @@ meta_back_dobind(
                        continue;
                } /* else */
                
-               Debug( LDAP_DEBUG_TRACE, "%s meta_back_dobind[%d]: "
-                               "(anonymous)\n",
-                               op->o_log_prefix, i, 0 );
-
-               msc->msc_bound = META_ANONYMOUS;
+               Debug( LDAP_DEBUG_TRACE,
+                       "%s meta_back_dobind[%d]: "
+                       "(%s)\n",
+                       op->o_log_prefix, i,
+                       rootdn ? rootdn : "anonymous" );
+
+               if ( rootdn ) {
+                       LDAP_BACK_CONN_ISBOUND_SET( msc );
+               } else {
+                       LDAP_BACK_CONN_ISANON_SET( msc );
+               }
                ++bound;
        }
 
@@ -622,7 +736,7 @@ done:;
 
        Debug( LDAP_DEBUG_TRACE,
                "%s meta_back_dobind: conn=%ld bound=%d\n",
-               op->o_log_prefix, mc->mc_conn->c_connid, bound );
+               op->o_log_prefix, LDAP_BACK_PCONN_ID( mc->mc_conn ), bound );
 
        if ( bound == 0 ) {
                meta_back_release_conn( op, mc );
@@ -639,13 +753,13 @@ done:;
 }
 
 /*
- * meta_back_rebind
+ * meta_back_default_rebind
  *
  * This is a callback used for chasing referrals using the same
  * credentials as the original user on this session.
  */
 static int 
-meta_back_rebind(
+meta_back_default_rebind(
        LDAP                    *ld,
        LDAP_CONST char         *url,
        ber_tag_t               request,
index aa8c7628df6bdf65931d52121a10919903ff9406..1254a26184ea52ec93a5dea7de2c2524309dc2d7 100644 (file)
@@ -188,6 +188,7 @@ meta_clear_one_candidate(
        }
 
        if ( !BER_BVISNULL( &msc->msc_cred ) ) {
+               memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
                ber_memfree( msc->msc_cred.bv_val );
                BER_BVZERO( &msc->msc_cred );
        }
index 82d407fe734adb7ce4bd330bf5933831d69d0e66..65fdde05f01c50c9a084b29dacd6ba974f750884 100644 (file)
@@ -176,10 +176,9 @@ meta_back_compare( Operation *op, SlapReply *rs )
                        metasingleconn_t        *msc = &mc->mc_conns[ i ];
                        int                     lrc;
                        LDAPMessage             *res = NULL;
-                       struct timeval          tv = { 0 };
+                       struct timeval          tv;
 
-                       tv.tv_sec = 0;
-                       tv.tv_usec = 100000;    /* 0.1 s */
+                       LDAP_BACK_TV_SET( &tv );
 
                        if ( msgid[ i ] == -1 ) {
                                continue;
index 143bbe573a56a3df32efea628328639279d382b8..1c596de1339fd83ba0e2282506664b80300cfa1c 100644 (file)
@@ -69,6 +69,21 @@ new_target(
        return 0;
 }
 
+static int
+check_true_false( char *str )
+{
+       if ( strcasecmp( str, "true" ) == 0 || strcasecmp( str, "yes" ) == 0 ) {
+               return 1;
+       }
+
+       if ( strcasecmp( str, "false" ) == 0 || strcasecmp( str, "no" ) == 0 ) {
+               return 0;
+       }
+
+       return -1;
+}
+
+
 int
 meta_back_db_config(
                BackendDB       *be,
@@ -378,20 +393,23 @@ meta_back_db_config(
 
                if ( argc == 1 ) {
                        fprintf( stderr,
-       "%s: line %d: deprecated use of \"rebind-as-user {NO|yes}\" with no arguments.\n",
+       "%s: line %d: deprecated use of \"rebind-as-user {FALSE|true}\" with no arguments.\n",
                            fname, lineno );
                        mi->flags |= LDAP_BACK_F_SAVECRED;
 
                } else {
-                       if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+                       switch ( check_true_false( argv[ 1 ] ) ) {
+                       case 0:
                                mi->flags &= ~LDAP_BACK_F_SAVECRED;
+                               break;
 
-                       } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+                       case 1:
                                mi->flags |= LDAP_BACK_F_SAVECRED;
+                               break;
 
-                       } else {
+                       default:
                                fprintf( stderr,
-       "%s: line %d: \"rebind-as-user {NO|yes}\" unknown argument \"%s\".\n",
+       "%s: line %d: \"rebind-as-user {FALSE|true}\" unknown argument \"%s\".\n",
                                    fname, lineno, argv[ 1 ] );
                                return 1;
                        }
@@ -404,21 +422,24 @@ meta_back_db_config(
 
                if ( argc != 2 ) {
                        fprintf( stderr,
-       "%s: line %d: \"chase-referrals\" needs 1 argument.\n",
+       "%s: line %d: \"chase-referrals {TRUE|false}\" needs 1 argument.\n",
                                        fname, lineno );
                        return( 1 );
                }
 
                /* this is the default; we add it because the default might change... */
-               if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+               switch ( check_true_false( argv[ 1 ] ) ) {
+               case 1:
                        *flagsp |= LDAP_BACK_F_CHASE_REFERRALS;
+                       break;
 
-               } else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+               case 0:
                        *flagsp &= ~LDAP_BACK_F_CHASE_REFERRALS;
+                       break;
 
-               } else {
+               default:
                        fprintf( stderr,
-               "%s: line %d: \"chase-referrals {YES|no}\": unknown argument \"%s\".\n",
+               "%s: line %d: \"chase-referrals {TRUE|false}\": unknown argument \"%s\".\n",
                                        fname, lineno, argv[ 1 ] );
                        return( 1 );
                }
@@ -467,25 +488,31 @@ meta_back_db_config(
 
                if ( argc != 2 ) {
                        fprintf( stderr,
-               "%s: line %d: \"t-f-support {NO|yes|discover}\" needs 1 argument.\n",
+               "%s: line %d: \"t-f-support {FALSE|true|discover}\" needs 1 argument.\n",
                                        fname, lineno );
                        return( 1 );
                }
 
-               if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+               switch ( check_true_false( argv[ 1 ] ) ) {
+               case 0:
                        *flagsp &= ~(LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER);
+                       break;
 
-               } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+               case 1:
                        *flagsp |= LDAP_BACK_F_SUPPORT_T_F;
+                       break;
 
-               } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
-                       *flagsp |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+               default:
+                       if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
+                               *flagsp |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
 
-               } else {
-                       fprintf( stderr,
+                       } else {
+                               fprintf( stderr,
        "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
-                               fname, lineno, argv[ 1 ] );
-                       return 1;
+                                       fname, lineno, argv[ 1 ] );
+                               return 1;
+                       }
+                       break;
                }
 
        /* onerr? */
@@ -510,6 +537,31 @@ meta_back_db_config(
                        return 1;
                }
 
+       /* bind-defer? */
+       } else if ( strcasecmp( argv[ 0 ], "pseudoroot-bind-defer" ) == 0 ) {
+               if ( argc != 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: \"pseudoroot-bind-defer {FALSE|true}\" takes 1 argument\n",
+                           fname, lineno );
+                       return( 1 );
+               }
+
+               switch ( check_true_false( argv[ 1 ] ) ) {
+               case 0:
+                       mi->flags &= ~META_BACK_F_DEFER_ROOTDN_BIND;
+                       break;
+
+               case 1:
+                       mi->flags |= META_BACK_F_DEFER_ROOTDN_BIND;
+                       break;
+
+               default:
+                       fprintf( stderr,
+       "%s: line %d: \"pseudoroot-bind-defer {FALSE|true}\": invalid arg \"%s\".\n",
+                               fname, lineno, argv[ 1 ] );
+                       return 1;
+               }
+
        } else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) {
                char    *sep, *next;
                time_t  *tv = mi->mi_ntargets ?
index a0ae2801249fe69e0b607e747dff707e43900006..0c8d140166ad33eba1676524c58b451fff3a7607 100644 (file)
@@ -52,7 +52,17 @@ meta_back_conn_cmp(
 {
        metaconn_t      *mc1 = ( metaconn_t * )c1;
         metaconn_t     *mc2 = ( metaconn_t * )c2;
+       int             rc;
        
+       /* If local DNs don't match, it is definitely not a match */
+       rc = ber_bvcmp( &mc1->mc_local_ndn, &mc2->mc_local_ndn );
+       if ( rc ) {
+               return rc;
+       }
+
+       /* For shared sessions, conn is NULL. Only explicitly
+        * bound sessions will have non-NULL conn.
+        */
        return SLAP_PTRCMP( mc1->mc_conn, mc2->mc_conn );
 }
 
@@ -70,7 +80,14 @@ meta_back_conn_dup(
        metaconn_t      *mc1 = ( metaconn_t * )c1;
        metaconn_t      *mc2 = ( metaconn_t * )c2;
 
-       return( ( mc1->mc_conn == mc2->mc_conn ) ? -1 : 0 );
+       /* Cannot have more than one shared session with same DN */
+       if ( dn_match( &mc1->mc_local_ndn, &mc2->mc_local_ndn ) &&
+                               mc1->mc_conn == mc2->mc_conn )
+       {
+               return -1;
+       }
+               
+       return 0;
 }
 
 /*
@@ -80,7 +97,8 @@ meta_back_conn_dup(
 static void
 ravl_print( Avlnode *root, int depth )
 {
-       int     i;
+       int             i;
+       metaconn_t      *mc = (metaconn_t *)root->avl_data;
        
        if ( root == 0 ) {
                return;
@@ -92,7 +110,11 @@ ravl_print( Avlnode *root, int depth )
                printf( "    " );
        }
 
-       printf( "c(%d) %d\n", ( ( metaconn_t * )root->avl_data )->mc_conn->c_connid, root->avl_bf );
+       printf( "c(%d%s%s) %d\n",
+               LDAP_BACK_PCONN_ID( mc->mc_conn ),
+               BER_BVISNULL( &mc->mc_local_ndn ) ? "" : ": ",
+               BER_BVISNULL( &mc->mc_local_ndn ) ? "" : mc->mc_local_ndn.bv_val,
+               root->avl_bf );
        
        ravl_print( root->avl_left, depth + 1 );
 }
@@ -141,11 +163,13 @@ metaconn_alloc(
                mc->mc_conns[ i ].msc_ld = NULL;
                BER_BVZERO( &mc->mc_conns[ i ].msc_bound_ndn );
                BER_BVZERO( &mc->mc_conns[ i ].msc_cred );
-               mc->mc_conns[ i ].msc_bound = META_UNBOUND;
+               LDAP_BACK_CONN_ISBOUND_CLEAR( &mc->mc_conns[ i ] );
                mc->mc_conns[ i ].msc_info = mi;
        }
 
-       mc->mc_auth_target = META_BOUND_NONE;
+       BER_BVZERO( &mc->mc_local_ndn );
+       mc->msc_mscflags = 0;
+       mc->mc_authz_target = META_BOUND_NONE;
        ldap_pvt_thread_mutex_init( &mc->mc_mutex );
        mc->mc_refcnt = 1;
 
@@ -165,6 +189,10 @@ meta_back_conn_free(
        assert( mc != NULL );
        assert( mc->mc_refcnt == 0 );
 
+       if ( !BER_BVISNULL( &mc->mc_local_ndn ) ) {
+               free( mc->mc_local_ndn.bv_val );
+       }
+
        ldap_pvt_thread_mutex_destroy( &mc->mc_mutex );
        free( mc );
 }
@@ -247,7 +275,9 @@ meta_back_init_one_conn(
                if ( rs->sr_err == LDAP_SUCCESS ) {
                        LDAPMessage     *res = NULL;
                        int             rc, nretries = mt->mt_nretries;
-                       struct timeval  tv = { 0, 0 };
+                       struct timeval  tv;
+
+                       LDAP_BACK_TV_SET( &tv );
 
 retry:;
                        rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res );
@@ -259,8 +289,7 @@ retry:;
                                        if ( nretries > 0 ) {
                                                nretries--;
                                        }
-                                       tv.tv_sec = 0;
-                                       tv.tv_usec = 100000;
+                                       LDAP_BACK_TV_SET( &tv );
                                        goto retry;
                                }
                                rs->sr_err = LDAP_OTHER;
@@ -364,7 +393,7 @@ retry:;
                ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
        }
 
-       msc->msc_bound = META_UNBOUND;
+       LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
 
 error_return:;
        if ( rs->sr_err == LDAP_SUCCESS ) {
@@ -416,7 +445,7 @@ retry_lock:;
 
                ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
                msc->msc_ld = NULL;
-               msc->msc_bound = 0;
+               LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
 
                ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
 
@@ -446,7 +475,7 @@ meta_back_conn_cb( Operation *op, SlapReply *rs )
 
        switch ( rs->sr_type ) {
        case REP_SEARCH:
-               ((int *)op->o_callback->sc_private)[0] = (int)op->o_private;
+               ((long *)op->o_callback->sc_private)[0] = (long)op->o_private;
                break;
 
        case REP_SEARCHREF:
@@ -662,8 +691,26 @@ meta_back_getconn(
 
        SlapReply       *candidates = meta_back_candidates_get( op );
 
+       /* Internal searches are privileged and shared. So is root. */
+       /* FIXME: there seem to be concurrency issues */
+       if ( op->o_do_not_cache || be_isroot( op ) ) {
+               mc_curr.mc_local_ndn = op->o_bd->be_rootndn;
+               LDAP_BACK_CONN_ISPRIV_SET( &mc_curr );
+               mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
+
+       } else {
+               mc_curr.mc_local_ndn = op->o_ndn;
+
+               /* Explicit binds must not be shared */
+               if ( op->o_tag == LDAP_REQ_BIND || SLAP_IS_AUTHZ_BACKEND( op ) ) {
+                       mc_curr.mc_conn = op->o_conn;
+       
+               } else {
+                       mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
+               }
+       }
+
        /* Searches for a metaconn in the avl tree */
-       mc_curr.mc_conn = op->o_conn;
        ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
        mc = (metaconn_t *)avl_find( mi->mi_conntree, 
                (caddr_t)&mc_curr, meta_back_conn_cmp );
@@ -720,24 +767,41 @@ meta_back_getconn(
                /* Looks like we didn't get a bind. Open a new session... */
                if ( mc == NULL ) {
                        mc = metaconn_alloc( op );
-                       mc->mc_conn = op->o_conn;
+                       mc->mc_conn = mc_curr.mc_conn;
+                       ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
                        new_conn = 1;
                }
 
                for ( i = 0; i < mi->mi_ntargets; i++ ) {
+                       metatarget_t            *mt = &mi->mi_targets[ i ];
+                       metasingleconn_t        *msc = &mc->mc_conns[ i ];
 
                        /*
                         * The target is activated; if needed, it is
                         * also init'd
                         */
-                       candidates[ i ].sr_err =
-                               meta_back_init_one_conn( op, rs,
-                                               &mi->mi_targets[ i ],
-                                               &mc->mc_conns[ i ], sendok );
+                       candidates[ i ].sr_err = meta_back_init_one_conn( op,
+                               rs, mt, msc, sendok );
                        if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
                                candidates[ i ].sr_tag = META_CANDIDATE;
                                ncandidates++;
-                               
+       
+                               if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
+                                       ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
+                                       ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
+                                       LDAP_BACK_CONN_ISPRIV_SET( msc );
+
+                               } else {
+                                       BER_BVZERO( &msc->msc_cred );
+                                       BER_BVZERO( &msc->msc_bound_ndn );
+                                       if ( !BER_BVISEMPTY( &op->o_ndn )
+                                               && SLAP_IS_AUTHZ_BACKEND( op )
+                                               && i == mc->mc_authz_target )
+                                       {
+                                               ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
+                                       }
+                               }
+                       
                        } else {
                                
                                /*
@@ -785,7 +849,10 @@ meta_back_getconn(
        }
 
        if ( op_type == META_OP_REQUIRE_SINGLE ) {
-               int     j;
+               metatarget_t            *mt = NULL;
+               metasingleconn_t        *msc = NULL;
+
+               int                     j;
 
                for ( j = 0; j < mi->mi_ntargets; j++ ) {
                        candidates[ j ].sr_tag = META_NOT_CANDIDATE;
@@ -844,7 +911,6 @@ meta_back_getconn(
                        /* Retries searching for a metaconn in the avl tree
                         * the reason is that the connection might have been
                         * created by meta_back_get_candidate() */
-                       mc_curr.mc_conn = op->o_conn;
                        ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
                        mc = (metaconn_t *)avl_find( mi->mi_conntree, 
                                (caddr_t)&mc_curr, meta_back_conn_cmp );
@@ -856,7 +922,8 @@ meta_back_getconn(
                        /* Looks like we didn't get a bind. Open a new session... */
                        if ( mc == NULL ) {
                                mc = metaconn_alloc( op );
-                               mc->mc_conn = op->o_conn;
+                               mc->mc_conn = mc_curr.mc_conn;
+                               ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
                                new_conn = 1;
                        }
                }
@@ -866,13 +933,15 @@ meta_back_getconn(
                 */
                ( void )meta_clear_unused_candidates( op, i );
 
+               mt = &mi->mi_targets[ i ];
+               msc = &mc->mc_conns[ i ];
+
                /*
                 * The target is activated; if needed, it is
                 * also init'd. In case of error, meta_back_init_one_conn
                 * sends the appropriate result.
                 */
-               err = meta_back_init_one_conn( op, rs, &mi->mi_targets[ i ],
-                               &mc->mc_conns[ i ], sendok );
+               err = meta_back_init_one_conn( op, rs, mt, msc, sendok );
                if ( err != LDAP_SUCCESS ) {
                        /*
                         * FIXME: in case one target cannot
@@ -881,7 +950,7 @@ meta_back_getconn(
                         */
                        candidates[ i ].sr_tag = META_NOT_CANDIDATE;
                        if ( new_conn ) {
-                               (void)meta_clear_one_candidate( &mc->mc_conns[ i ] );
+                               (void)meta_clear_one_candidate( msc );
                                meta_back_freeconn( op, mc );
 
                        } else {
@@ -898,6 +967,22 @@ meta_back_getconn(
                        *candidate = i;
                }
 
+               if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
+                       ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
+                       ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
+                       LDAP_BACK_CONN_ISPRIV_SET( msc );
+
+               } else {
+                       BER_BVZERO( &msc->msc_cred );
+                       BER_BVZERO( &msc->msc_bound_ndn );
+                       if ( !BER_BVISEMPTY( &op->o_ndn )
+                               && SLAP_IS_AUTHZ_BACKEND( op )
+                               && i == mc->mc_authz_target )
+                       {
+                               ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
+                       }
+               }
+                       
        /*
         * if no unique candidate ...
         */
@@ -906,15 +991,20 @@ meta_back_getconn(
                /* Looks like we didn't get a bind. Open a new session... */
                if ( mc == NULL ) {
                        mc = metaconn_alloc( op );
-                       mc->mc_conn = op->o_conn;
+                       mc->mc_conn = mc_curr.mc_conn;
+                       ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
                        new_conn = 1;
                }
 
                for ( i = 0; i < mi->mi_ntargets; i++ ) {
+                       metatarget_t            *mt = &mi->mi_targets[ i ];
+                       metasingleconn_t        *msc = &mc->mc_conns[ i ];
+
                        if ( i == cached 
-                               || meta_back_is_candidate( &mi->mi_targets[ i ].mt_nsuffix,
-                                               mi->mi_targets[ i ].mt_scope,
-                                               &op->o_req_ndn, LDAP_SCOPE_SUBTREE ) )
+                               || meta_back_is_candidate( &mt->mt_nsuffix,
+                                               mt->mt_scope,
+                                               &op->o_req_ndn,
+                                               LDAP_SCOPE_SUBTREE ) )
                        {
 
                                /*
@@ -922,13 +1012,28 @@ meta_back_getconn(
                                 * also init'd
                                 */
                                int lerr = meta_back_init_one_conn( op, rs,
-                                               &mi->mi_targets[ i ],
-                                               &mc->mc_conns[ i ], sendok );
+                                               mt, msc, sendok );
                                if ( lerr == LDAP_SUCCESS ) {
                                        candidates[ i ].sr_tag = META_CANDIDATE;
                                        candidates[ i ].sr_err = LDAP_SUCCESS;
                                        ncandidates++;
 
+                                       if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
+                                               ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
+                                               ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
+                                               LDAP_BACK_CONN_ISPRIV_SET( msc );
+
+                                       } else {
+                                               BER_BVZERO( &msc->msc_cred );
+                                               BER_BVZERO( &msc->msc_bound_ndn );
+                                               if ( !BER_BVISEMPTY( &op->o_ndn )
+                                                       && SLAP_IS_AUTHZ_BACKEND( op )
+                                                       && i == mc->mc_authz_target )
+                                               {
+                                                       ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
+                                               }
+                                       }
+                       
                                        Debug( LDAP_DEBUG_TRACE, "%s: meta_back_init_one_conn(%d)\n",
                                                op->o_log_prefix, i, 0 );
 
@@ -940,7 +1045,7 @@ meta_back_getconn(
                                         * be tried?
                                         */
                                        if ( new_conn ) {
-                                               ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
+                                               ( void )meta_clear_one_candidate( msc );
                                        }
                                        /* leave the target candidate, but record the error for later use */
                                        candidates[ i ].sr_err = lerr;
@@ -954,7 +1059,7 @@ meta_back_getconn(
 
                        } else {
                                if ( new_conn ) {
-                                       ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
+                                       ( void )meta_clear_one_candidate( msc );
                                }
                                candidates[ i ].sr_tag = META_NOT_CANDIDATE;
                        }
@@ -1013,7 +1118,8 @@ done:;
                if ( err != 0 ) {
                        Debug( LDAP_DEBUG_ANY,
                                "%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
-                               op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
+                               op->o_log_prefix, ncandidates,
+                               LDAP_BACK_PCONN_ID( mc->mc_conn ) );
                
                        rs->sr_err = LDAP_OTHER;
                        rs->sr_text = "Internal server error";
@@ -1027,12 +1133,14 @@ done:;
 
                Debug( LDAP_DEBUG_TRACE,
                        "%s meta_back_getconn: candidates=%d conn=%ld inserted\n",
-                       op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
+                       op->o_log_prefix, ncandidates,
+                       LDAP_BACK_PCONN_ID( mc->mc_conn ) );
 
        } else {
                Debug( LDAP_DEBUG_TRACE,
                        "%s meta_back_getconn: candidates=%d conn=%ld fetched\n",
-                       op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
+                       op->o_log_prefix, ncandidates,
+                       LDAP_BACK_PCONN_ID( mc->mc_conn ) );
        }
        
        return mc;
index 3dec260d23bb91fd43986b1ccc2d760378f4f41e..0847a92638c72fa84c658bb2a77b6fad928851e0 100644 (file)
@@ -358,7 +358,6 @@ meta_back_search( Operation *op, SlapReply *rs )
 
        if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
                stoptime = op->o_time + op->ors_tlimit;
-               tv.tv_sec = 0;
        }
 
        /*
@@ -703,8 +702,7 @@ really_bad:;
                }
 
                if ( gotit == 0 ) {
-                       tv.tv_sec = 0;
-                        tv.tv_usec = 100000;   /* 0.1 s */
+                       LDAP_BACK_TV_SET( &tv );
                         ldap_pvt_thread_yield();
 
                } else {
index 93a694b02bf9b6fa8ce73bbe7bfb243fc4dd10b0..ed4bc96e30e82339f83857ef7ce7e01f22632b0c 100644 (file)
@@ -57,13 +57,10 @@ meta_back_conn_destroy(
        if ( mc ) {
                Debug( LDAP_DEBUG_TRACE,
                        "=>meta_back_conn_destroy: destroying conn %ld\n",
-                       mc->mc_conn->c_connid, 0, 0 );
+                       LDAP_BACK_PCONN_ID( mc->mc_conn ), 0, 0 );
                
                assert( mc->mc_refcnt == 0 );
 
-               /*
-                * Cleanup rewrite session
-                */
                for ( i = 0; i < mi->mi_ntargets; ++i ) {
                        if ( mc->mc_conns[ i ].msc_ld != NULL ) {
                                meta_clear_one_candidate( &mc->mc_conns[ i ] );