]> git.sur5r.net Git - openldap/commitdiff
StartTLS (ITS#3507) + chain overlay fixes and improvements
authorPierangelo Masarati <ando@openldap.org>
Mon, 24 Jan 2005 09:38:11 +0000 (09:38 +0000)
committerPierangelo Masarati <ando@openldap.org>
Mon, 24 Jan 2005 09:38:11 +0000 (09:38 +0000)
21 files changed:
servers/slapd/back-ldap/add.c
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/chain.c
servers/slapd/back-ldap/compare.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/delete.c
servers/slapd/back-ldap/extended.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/modify.c
servers/slapd/back-ldap/modrdn.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldap/search.c
servers/slapd/back-meta/back-meta.h
tests/data/chain.out
tests/data/chainmod.out
tests/data/chainref.out [new file with mode: 0644]
tests/data/test-chain1.ldif
tests/data/test-chain2.ldif
tests/scripts/defines.sh
tests/scripts/test032-chain

index 1805a31b3e40429cca9ab5160bf4acb849ec7e62..eb272c76628fa067c9f8f489fc96d056725be588 100644 (file)
@@ -46,14 +46,14 @@ ldap_back_add(
        int             isupdate;
        int             do_retry = 1;
        LDAPControl     **ctrls = NULL;
-       int             rc = LDAP_SUCCESS;
 
+       rs->sr_err = LDAP_SUCCESS;
+       
        Debug( LDAP_DEBUG_ARGS, "==> ldap_back_add(\"%s\")\n",
                        op->o_req_dn.bv_val, 0, 0 );
 
-       lc = ldap_back_getconn( op, rs );
-       if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
-               rc = -1;
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
+       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                goto cleanup;
        }
 
@@ -89,20 +89,19 @@ ldap_back_add(
        attrs[ i ] = NULL;
 
        ctrls = op->o_ctrls;
-       rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
-       if ( rc != LDAP_SUCCESS ) {
+       rs->sr_err = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
+       if ( rs->sr_err != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
-               rc = -1;
                goto cleanup;
        }
 
 retry:
        rs->sr_err = ldap_add_ext( lc->lc_ld, op->o_req_dn.bv_val, attrs,
                        ctrls, NULL, &msgid );
-       rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
+       rs->sr_err = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
-               if ( ldap_back_retry( lc, op, rs ) ) {
+               if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
        }
@@ -118,8 +117,8 @@ cleanup:
        }
 
        Debug( LDAP_DEBUG_ARGS, "<== ldap_back_add(\"%s\"): %d\n",
-                       op->o_req_dn.bv_val, rc, 0 );
+                       op->o_req_dn.bv_val, rs->sr_err, 0 );
 
-       return rc;
+       return rs->sr_err;
 }
 
index 3f5b109d371bf53fdbb2d79ff7e0b88ce733586f..174a7039c580685be77921ebb4e0ed18345279d9 100644 (file)
@@ -90,12 +90,23 @@ struct ldapinfo {
        /* end of ID assert stuff */
 
        ldap_pvt_thread_mutex_t         conn_mutex;
-       int             savecred;
+       unsigned        flags;
+#define LDAP_BACK_F_NONE               0x00U
+#define LDAP_BACK_F_SAVECRED           0x01U
+#define LDAP_BACK_F_USE_TLS            0x02U
+#define LDAP_BACK_F_TLS_CRITICAL       ( 0x04U | LDAP_BACK_F_USE_TLS )
        Avlnode         *conntree;
 
        int             rwm_started;
 };
 
+typedef enum ldap_back_send_t {
+       LDAP_BACK_DONTSEND              = 0x00,
+       LDAP_BACK_SENDOK                = 0x01,
+       LDAP_BACK_SENDERR               = 0x02,
+       LDAP_BACK_SENDRESULT            = (LDAP_BACK_SENDOK|LDAP_BACK_SENDERR)
+} ldap_back_send_t;
+
 LDAP_END_DECL
 
 #include "proto-ldap.h"
index f7446f35c9c4250ac25720ee81de3bdf16f77bc7..998ce2453789f33bb4b960e32f5a94c81dd56d24 100644 (file)
@@ -16,7 +16,7 @@
  * <http://www.OpenLDAP.org/license.html>.
  */
 /* ACKNOWLEDGEMENTS:
- * This work was initially developed by the Howard Chu for inclusion
+ * This work was initially developed by Howard Chu for inclusion
  * in OpenLDAP Software and subsequently enhanced by Pierangelo
  * Masarati.
  */
@@ -41,6 +41,9 @@ static LDAP_REBIND_PROC       ldap_back_rebind;
 static int
 ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs );
 
+static int
+ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
+
 int
 ldap_back_bind( Operation *op, SlapReply *rs )
 {
@@ -50,9 +53,9 @@ ldap_back_bind( Operation *op, SlapReply *rs )
        int rc = 0;
        ber_int_t msgid;
 
-       lc = ldap_back_getconn( op, rs );
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        if ( !lc ) {
-               return( -1 );
+               return rs->sr_err;
        }
 
        if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) {
@@ -65,7 +68,7 @@ ldap_back_bind( Operation *op, SlapReply *rs )
        rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val,
                        LDAP_SASL_SIMPLE,
                        &op->orb_cred, op->o_ctrls, NULL, &msgid );
-       rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
+       rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
 
        if ( rc == LDAP_SUCCESS ) {
                /* If defined, proxyAuthz will be used also when
@@ -84,7 +87,7 @@ ldap_back_bind( Operation *op, SlapReply *rs )
                lc->lc_bound = 1;
                ber_dupbv( &lc->lc_bound_ndn, &op->o_req_ndn );
 
-               if ( li->savecred ) {
+               if ( li->flags & LDAP_BACK_F_SAVECRED ) {
                        if ( !BER_BVISNULL( &lc->lc_cred ) ) {
                                memset( lc->lc_cred.bv_val, 0,
                                                lc->lc_cred.bv_len );
@@ -219,12 +222,76 @@ ldap_back_freeconn( Operation *op, struct ldapconn *lc )
        return 0;
 }
 
+static int
+ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
+{
+       struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+       int             vers = op->o_protocol;
+       LDAP            *ld = NULL;
+
+       assert( lcp != NULL );
+
+       rs->sr_err = ldap_initialize( &ld, li->url );
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               goto error_return;
+       }
+
+       /* Set LDAP version. This will always succeed: If the client
+        * bound with a particular version, then so can we.
+        */
+       ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers );
+
+       /* Set LDAP version. This will always succeed: If the client
+        * bound with a particular version, then so can we.
+        */
+       ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
+                       (const void *)&vers );
+
+       /* FIXME: configurable? */
+       ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
+
+       if ( ( li->flags & LDAP_BACK_F_USE_TLS )
+                       && !ldap_is_ldaps_url( li->url )
+                       && ( rs->sr_err = ldap_start_tls_s( ld, NULL, NULL ) ) != LDAP_SUCCESS )
+       {
+               /* if StartTLS is requested, only attempt it if the URL
+                * is not "ldaps://"; this may occur not only in case
+                * of misconfiguration, but also when used in the chain 
+                * overlay, where the "uri" can be parsed out of a referral */
+               if ( rs->sr_err == LDAP_SERVER_DOWN
+                               || ( li->flags & LDAP_BACK_F_TLS_CRITICAL ) )
+               {
+                       ldap_unbind_ext_s( ld, NULL, NULL );
+                       goto error_return;
+               }
+       }
+
+       if ( *lcp == NULL ) {
+               *lcp = (struct ldapconn *)ch_malloc( sizeof( struct ldapconn ) );
+               memset( *lcp, 0, sizeof( struct ldapconn ) );
+       }
+       (*lcp)->lc_ld = ld;
+
+error_return:;
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               rs->sr_err = slap_map_api2result( rs );
+               if ( sendok & LDAP_BACK_SENDERR ) {
+                       if ( rs->sr_text == NULL ) {
+                               rs->sr_text = "ldap_initialize() failed";
+                       }
+                       send_ldap_result( op, rs );
+                       rs->sr_text = NULL;
+               }
+       }
+
+       return rs->sr_err;
+}
+
 struct ldapconn *
-ldap_back_getconn( Operation *op, SlapReply *rs )
+ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
 {
        struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
        struct ldapconn *lc, lc_curr;
-       LDAP            *ld;
        int             is_priv = 0;
 
        /* Searches for a ldapconn in the avl tree */
@@ -258,31 +325,12 @@ ldap_back_getconn( Operation *op, SlapReply *rs )
 
        /* Looks like we didn't get a bind. Open a new session... */
        if ( !lc ) {
-               int vers = op->o_protocol;
-               rs->sr_err = ldap_initialize( &ld, li->url );
-               
-               if ( rs->sr_err != LDAP_SUCCESS ) {
-                       rs->sr_err = slap_map_api2result( rs );
-                       if ( rs->sr_text == NULL ) {
-                               rs->sr_text = "ldap_initialize() failed";
-                       }
-                       if ( op->o_conn ) {
-                               send_ldap_result( op, rs );
-                       }
-                       rs->sr_text = NULL;
-                       return( NULL );
+               /* lc here must be NULL */
+               if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
+                       return NULL;
                }
-               /* Set LDAP version. This will always succeed: If the client
-                * bound with a particular version, then so can we.
-                */
-               ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
-                               (const void *)&vers );
-               /* FIXME: configurable? */
-               ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
 
-               lc = (struct ldapconn *)ch_malloc( sizeof( struct ldapconn ) );
                lc->lc_conn = lc_curr.lc_conn;
-               lc->lc_ld = ld;
                ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn );
 
                ldap_pvt_thread_mutex_init( &lc->lc_mutex );
@@ -320,18 +368,18 @@ ldap_back_getconn( Operation *op, SlapReply *rs )
                /* Err could be -1 in case a duplicate ldapconn is inserted */
                if ( rs->sr_err != 0 ) {
                        ldap_back_conn_free( lc );
-                       if ( op->o_conn ) {
+                       if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
                                send_ldap_error( op, rs, LDAP_OTHER,
                                "internal server error" );
                        }
-                       return( NULL );
+                       return NULL;
                }
        } else {
                Debug( LDAP_DEBUG_TRACE,
                        "=>ldap_back_getconn: conn %p fetched\n", (void *) lc, 0, 0 );
        }
        
-       return( lc );
+       return lc;
 }
 
 /*
@@ -341,12 +389,19 @@ ldap_back_getconn( Operation *op, SlapReply *rs )
  * 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, SlapReply *rs )
+static int
+ldap_back_dobind_int(
+       struct ldapconn         *lc,
+       Operation               *op,
+       SlapReply               *rs,
+       ldap_back_send_t        sendok,
+       int                     retries )
 {      
        int             rc;
        ber_int_t       msgid;
 
+       assert( retries >= 0 );
+
        ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
        if ( !lc->lc_bound ) {
                /*
@@ -373,12 +428,33 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs )
                        goto done;
                }
 
+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 );
-               
-               rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
+
+               if ( rs->sr_err == LDAP_SERVER_DOWN ) {
+                       if ( retries > 0 ) {
+                               ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
+                               lc->lc_ld = NULL;
+
+                               /* lc here must be the regular lc, reset and ready for init */
+                               if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
+                                       return 0;
+                               }
+
+                               retries--;
+                               goto retry;
+                       }
+
+                       ldap_back_freeconn( op, lc );
+                       rs->sr_err = slap_map_api2result( rs );
+
+                       return 0;
+               }
+
+               rc = ldap_back_op_result( lc, op, rs, msgid, sendok );
                if ( rc == LDAP_SUCCESS ) {
                        lc->lc_bound = 1;
                }
@@ -390,6 +466,12 @@ done:;
        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 );
+}
+
 /*
  * ldap_back_rebind
  *
@@ -400,7 +482,9 @@ static int
 ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
        ber_int_t msgid, void *params )
 {
-       struct ldapconn *lc = params;
+       struct ldapconn *lc = (struct ldapconn *)params;
+
+       /* FIXME: add checks on the URL/identity? */
 
        return ldap_sasl_bind_s( ld, lc->lc_bound_ndn.bv_val,
                        LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, NULL );
@@ -408,11 +492,11 @@ ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
 
 int
 ldap_back_op_result(
-               struct ldapconn *lc,
-               Operation       *op,
-               SlapReply       *rs,
-               ber_int_t       msgid,
-               int             sendok )
+               struct ldapconn         *lc,
+               Operation               *op,
+               SlapReply               *rs,
+               ber_int_t               msgid,
+               ldap_back_send_t        sendok )
 {
        char            *match = NULL;
        LDAPMessage     *res = NULL;
@@ -474,7 +558,10 @@ retry:;
                        rs->sr_matched = match;
                }
        }
-       if ( op->o_conn && ( sendok || rs->sr_err != LDAP_SUCCESS ) ) {
+       if ( op->o_conn &&
+                       ( ( sendok & LDAP_BACK_SENDOK ) 
+                         || ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) )
+       {
                send_ldap_result( op, rs );
        }
        if ( match ) {
@@ -493,37 +580,20 @@ retry:;
 
 /* return true if bound, false if failed */
 int
-ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs )
+ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
 {
-       struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
-       int vers = op->o_protocol;
-       LDAP *ld;
-
        ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
        ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
+       lc->lc_ld = NULL;
        lc->lc_bound = 0;
-       rs->sr_err = ldap_initialize( &ld, li->url );
-               
-       if ( rs->sr_err != LDAP_SUCCESS ) {
-               rs->sr_err = slap_map_api2result( rs );
-               if ( rs->sr_text == NULL ) {
-                       rs->sr_text = "ldap_initialize() failed";
-               }
-               if ( op->o_conn ) {
-                       send_ldap_result( op, rs );
-               }
-               rs->sr_text = NULL;
+
+       /* lc here must be the regular lc, reset and ready for init */
+       if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
                return 0;
        }
-       /* Set LDAP version. This will always succeed: If the client
-        * bound with a particular version, then so can we.
-        */
-       ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers );
-       /* FIXME: configurable? */
-       ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
-       lc->lc_ld = ld;
+
        ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );
-       return ldap_back_dobind( lc, op, rs );
+       return ldap_back_dobind_int( lc, op, rs, sendok, 0 );
 }
 
 static int
@@ -695,7 +765,7 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs )
                goto done;
        }
 
-       rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
+       rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR );
        if ( rc == LDAP_SUCCESS ) {
                lc->lc_bound = 1;
        }
index 58b6106cf071f0ad6b5ba7db1b6dc864d084ac5e..67927c40d767c0c98eb6d788c79ee3af13abe3bf 100644 (file)
 
 static BackendInfo *lback;
 
-#if 0
-static int
-ldap_chain_chk_referrals( Operation *op, SlapReply *rs )
-{
-       return LDAP_SUCCESS;
-}
-#endif
-
 static int
 ldap_chain_operational( Operation *op, SlapReply *rs )
 {
-       /* trap entries generated by back-ldap.
+       /* Trap entries generated by back-ldap.
+        * 
         * FIXME: we need a better way to recognize them; a cleaner
         * solution would be to be able to intercept the response
         * of be_operational(), so that we can divert only those
@@ -57,8 +50,11 @@ ldap_chain_operational( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
+/*
+ * Search specific response that strips entryDN from entries
+ */
 static int
-ldap_chain_cb_response( Operation *op, SlapReply *rs )
+ldap_chain_cb_search_response( Operation *op, SlapReply *rs )
 {
        assert( op->o_tag == LDAP_REQ_SEARCH );
 
@@ -82,83 +78,159 @@ ldap_chain_cb_response( Operation *op, SlapReply *rs )
                }
                
                return SLAP_CB_CONTINUE;
+
+       } else if ( rs->sr_type == REP_RESULT ) {
+               /* back-ldap tried to send result */
+               op->o_callback->sc_private = (void *)(1);
        }
 
        return 0;
 }
 
+/*
+ * Dummy response that simply traces if back-ldap tried to send 
+ * anything to the client
+ */
+static int
+ldap_chain_cb_response( Operation *op, SlapReply *rs )
+{
+       if ( rs->sr_type == REP_RESULT ) {
+               op->o_callback->sc_private = (void *)(1);
+
+       } else if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH )
+       {
+               /* strip the entryDN attribute, but keep returning results */
+               (void)ldap_chain_cb_search_response( op, rs );
+       }
+
+       return SLAP_CB_CONTINUE;
+}
+
+static int
+ldap_chain_op(
+       Operation       *op,
+       SlapReply       *rs,
+       int             ( *op_f )( Operation *op, SlapReply *rs ), 
+       BerVarray       ref )
+{
+       slap_overinst   *on = (slap_overinst *) op->o_bd->bd_info;
+       struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
+       int             rc;
+
+       if ( lip->url != NULL ) {
+               op->o_bd->be_private = on->on_bi.bi_private;
+               return ( *op_f )( op, rs );
+       }
+
+       li = *lip;
+       op->o_bd->be_private = &li;
+
+       /* if we parse the URI then by no means 
+        * we can cache stuff or reuse connections, 
+        * because in back-ldap there's no caching
+        * based on the URI value, which is supposed
+        * to be set once for all (correct?) */
+       op->o_do_not_cache = 1;
+
+       for ( ; !BER_BVISNULL( ref ); ref++ ) {
+               LDAPURLDesc     *srv;
+               char            *save_dn;
+                       
+               /* We're setting the URI of the first referral;
+                * what if there are more?
+
+Document: draft-ietf-ldapbis-protocol-27.txt
+
+4.1.10. Referral 
+   ...
+   If the client wishes to progress the operation, it MUST follow the 
+   referral by contacting one of the supported services. If multiple 
+   URIs are present, the client assumes that any supported URI may be 
+   used to progress the operation. 
+
+                * so we actually need to follow exactly one,
+                * and we can assume any is fine.
+                */
+       
+               /* parse reference and use 
+                * proto://[host][:port]/ only */
+               rc = ldap_url_parse_ext( ref->bv_val, &srv );
+               if ( rc != LDAP_URL_SUCCESS ) {
+                       /* try next */
+                       rc = LDAP_OTHER;
+                       continue;
+               }
+
+               /* remove DN essentially because later on 
+                * ldap_initialize() will parse the URL 
+                * as a comma-separated URL list */
+               save_dn = srv->lud_dn;
+               srv->lud_dn = "";
+               srv->lud_scope = LDAP_SCOPE_DEFAULT;
+               li.url = ldap_url_desc2str( srv );
+               srv->lud_dn = save_dn;
+               ldap_free_urldesc( srv );
+
+               if ( li.url == NULL ) {
+                       /* try next */
+                       rc = LDAP_OTHER;
+                       continue;
+               }
+
+               rc = ( *op_f )( op, rs );
+
+               ldap_memfree( li.url );
+               li.url = NULL;
+               
+               if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
+                       break;
+               }
+       }
+
+       return rc;
+}
+
 static int
 ldap_chain_response( Operation *op, SlapReply *rs )
 {
        slap_overinst   *on = (slap_overinst *) op->o_bd->bd_info;
        void            *private = op->o_bd->be_private;
-       slap_callback   *sc = op->o_callback;
+       slap_callback   *sc = op->o_callback,
+                       sc2 = { 0 };
        int             rc = 0;
        int             cache = op->o_do_not_cache;
-       char            *authzid = NULL;
        BerVarray       ref;
        struct berval   ndn = op->o_ndn;
 
        struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
 
-       if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF )
+       if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) {
                return SLAP_CB_CONTINUE;
+       }
+
+       /*
+        * TODO: add checks on who/when chain operations; e.g.:
+        *   a) what identities are authorized
+        *   b) what request DN (e.g. only chain requests rooted at <DN>)
+        *   c) what referral URIs
+        *   d) what protocol scheme (e.g. only ldaps://)
+        *   e) what ssf
+        */
 
        ref = rs->sr_ref;
        rs->sr_ref = NULL;
 
-       op->o_callback = NULL;
-
-       if ( lip->url == NULL ) {
-               /* if we parse the URI then by no means 
-                * we can cache stuff or reuse connections, 
-                * because in back-ldap there's no caching
-                * based on the URI value, which is supposed
-                * to be set once for all (correct?) */
-               op->o_do_not_cache = 1;
-
-               /* FIXME: we're setting the URI of the first referral;
-                * what if there are more?  Is this something we should
-                * worry about? */
-               li = *lip;
-               op->o_bd->be_private = &li;
-
-               if ( rs->sr_type != REP_SEARCHREF ) {
-                       LDAPURLDesc     *srv;
-                       char            *save_dn;
-
-                       /* parse reference and use 
-                        * proto://[host][:port]/ only */
-                       rc = ldap_url_parse_ext( ref[0].bv_val, &srv );
-                       if ( rc != LDAP_URL_SUCCESS ) {
-                               /* error */
-                               return 1;
-                       }
-
-                       /* remove DN essentially because later on 
-                        * ldap_initialize() will parse the URL 
-                        * as a comma-separated URL list */
-                       save_dn = srv->lud_dn;
-                       srv->lud_dn = "";
-                       srv->lud_scope = LDAP_SCOPE_DEFAULT;
-                       li.url = ldap_url_desc2str( srv );
-                       srv->lud_dn = save_dn;
-                       ldap_free_urldesc( srv );
-
-                       if ( li.url == NULL ) {
-                               /* error */
-                               return 1;
-                       }
-               }
-
-       } else {
-               op->o_bd->be_private = on->on_bi.bi_private;
-       }
+       /* we need this to know if back-ldap returned any result */
+       sc2.sc_response = ldap_chain_cb_response;
+       op->o_callback = &sc2;
 
        /* Chaining can be performed by a privileged user on behalf
         * of normal users, using the ProxyAuthz control, by exploiting
         * the identity assertion feature of back-ldap; see idassert-*
         * directives in slapd-ldap(5).
+        *
+        * FIXME: the idassert-authcDN is one, will it be fine regardless
+        * of the URI we obtain from the referral?
         */
 
        switch ( op->o_tag ) {
@@ -166,10 +238,10 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                struct berval   rndn = op->o_req_ndn;
                Connection      *conn = op->o_conn;
 
+               /* FIXME: can we really get a referral for binds? */
                op->o_req_ndn = slap_empty_bv;
-
                op->o_conn = NULL;
-               rc = lback->bi_op_bind( op, rs );
+               rc = ldap_chain_op( op, rs, lback->bi_op_bind, ref );
                op->o_req_ndn = rndn;
                op->o_conn = conn;
                }
@@ -182,7 +254,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                        char            textbuf[ SLAP_TEXT_BUFLEN ];
                        size_t          textlen = sizeof( textbuf );
 
-                       /* global overlay; create entry */
+                       /* global overlay: create entry */
                        /* NOTE: this is a hack to use the chain overlay
                         * as global.  I expect to be able to remove this
                         * soon by using slap_mods2entry() earlier in
@@ -197,7 +269,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                                break;
                        }
                }
-               rc = lback->bi_op_add( op, rs );
+               rc = ldap_chain_op( op, rs, lback->bi_op_add, ref );
                if ( cleanup_attrs ) {
                        attrs_free( op->ora_e->e_attrs );
                        op->ora_e->e_attrs = NULL;
@@ -205,32 +277,38 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                break;
                }
        case LDAP_REQ_DELETE:
-               rc = lback->bi_op_delete( op, rs );
+               rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref );
                break;
        case LDAP_REQ_MODRDN:
-               rc = lback->bi_op_modrdn( op, rs );
+               rc = ldap_chain_op( op, rs, lback->bi_op_modrdn, ref );
                break;
        case LDAP_REQ_MODIFY:
-               rc = lback->bi_op_modify( op, rs );
+               rc = ldap_chain_op( op, rs, lback->bi_op_modify, ref );
                break;
        case LDAP_REQ_COMPARE:
-               rc = lback->bi_op_compare( op, rs );
+               rc = ldap_chain_op( op, rs, lback->bi_op_compare, ref );
                break;
        case LDAP_REQ_SEARCH:
                if ( rs->sr_type == REP_SEARCHREF ) {
                        struct berval   *curr = ref,
                                        odn = op->o_req_dn,
                                        ondn = op->o_req_ndn;
-                       slap_callback   sc2 = { 0 };
-                       int             tmprc = 0;
-                       ber_len_t       refcnt = 0;
-                       BerVarray       newref = NULL;
-
-                       sc2.sc_response = ldap_chain_cb_response;
-                       op->o_callback = &sc2;
 
                        rs->sr_type = REP_SEARCH;
 
+                       sc2.sc_response = ldap_chain_cb_search_response;
+
+                       li = *lip;
+                       li.url = NULL;
+                       op->o_bd->be_private = &li;
+                       
+                       /* if we parse the URI then by no means 
+                        * we can cache stuff or reuse connections, 
+                        * because in back-ldap there's no caching
+                        * based on the URI value, which is supposed
+                        * to be set once for all (correct?) */
+                       op->o_do_not_cache = 1;
+
                        /* copy the private info because we need to modify it */
                        for ( ; !BER_BVISNULL( &curr[0] ); curr++ ) {
                                LDAPURLDesc     *srv;
@@ -238,11 +316,11 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 
                                /* parse reference and use
                                 * proto://[host][:port]/ only */
-                               tmprc = ldap_url_parse_ext( curr[0].bv_val, &srv );
-                               if ( tmprc != LDAP_URL_SUCCESS ) {
-                                       /* error */
-                                       rc = 1;
-                                       goto end_of_searchref;
+                               rc = ldap_url_parse_ext( curr[0].bv_val, &srv );
+                               if ( rc != LDAP_URL_SUCCESS ) {
+                                       /* try next */
+                                       rs->sr_err = LDAP_OTHER;
+                                       continue;
                                }
 
                                /* remove DN essentially because later on 
@@ -263,15 +341,15 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                                ldap_free_urldesc( srv );
 
                                if ( li.url == NULL ) {
-                                       /* error */
-                                       rc = 1;
-                                       goto end_of_searchref;
+                                       /* try next */
+                                       rs->sr_err = LDAP_OTHER;
+                                       continue;
                                }
 
 
                                /* FIXME: should we also copy filter and scope?
                                 * according to RFC3296, no */
-                               tmprc = lback->bi_op_search( op, rs );
+                               rc = lback->bi_op_search( op, rs );
 
                                ldap_memfree( li.url );
                                li.url = NULL;
@@ -281,76 +359,51 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                                op->o_tmpfree( op->o_req_ndn.bv_val,
                                                op->o_tmpmemctx );
 
-                               if ( tmprc ) {
-                                       /* error */
-                                       rc = 1;
-                                       goto end_of_searchref;
-                               }
-
-                               if ( rs->sr_err != LDAP_SUCCESS ) {
-                                       /* if search was not successful,
-                                        * at least return the referral! */
-                                       /* FIXME: assumes referrals 
-                                        * are always created via
-                                        * referral_rewrite() and freed via
-                                        * ber_bvarray_free( rs->sr_ref ) */
-                                       newref = ch_realloc( newref, sizeof( struct berval ) * (refcnt + 2) );
-                                       ber_dupbv( &newref[ refcnt ], &curr[ 0 ] );
-                                       refcnt++;
-                                       BER_BVZERO( &newref[ refcnt ] );
+                               if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
+                                       break;
                                }
                        }
 
-end_of_searchref:;
                        op->o_req_dn = odn;
                        op->o_req_ndn = ondn;
                        rs->sr_type = REP_SEARCHREF;
                        rs->sr_entry = NULL;
 
-                       /* if the error was bad, it was already returned
-                        * by back-ldap; destroy the referrals left;
-                        * otherwise, let the frontend return them. */
-                       if ( newref ) {
-                               if ( rc == 0 ) {
-                                       rc = SLAP_CB_CONTINUE;
-                                       if ( ref != default_referral ) {
-                                               ber_bvarray_free( ref );
-                                       }
-                                       ref = newref;
-
-                               } else {
-                                       ber_bvarray_free( newref );
-                               }
+                       if ( rc != LDAP_SUCCESS ) {
+                               /* couldn't chase any of the referrals */
+                               rc = SLAP_CB_CONTINUE;
                        }
                        
                } else {
-                       rc = lback->bi_op_search( op, rs );
+                       rc = ldap_chain_op( op, rs, lback->bi_op_search, ref );
                }
                break;
        case LDAP_REQ_EXTENDED:
-               rc = lback->bi_extended( op, rs );
+               rc = ldap_chain_op( op, rs, lback->bi_extended, ref );
                /* FIXME: ldap_back_extended() by design 
                 * doesn't send result; frontend is expected
                 * to send it... */
                if ( rc != SLAPD_ABANDON ) {
                        send_ldap_extended( op, rs );
+                       rc = LDAP_SUCCESS;
                }
                break;
        default:
                rc = SLAP_CB_CONTINUE;
                break;
        }
+
+       if ( sc2.sc_private == NULL ) {
+               op->o_callback = NULL;
+               rc = rs->sr_err = slap_map_api2result( rs );
+               send_ldap_result( op, rs );
+       }
+
        op->o_do_not_cache = cache;
        op->o_bd->be_private = private;
        op->o_callback = sc;
        op->o_ndn = ndn;
-       if ( authzid ) {
-               op->o_tmpfree( authzid, op->o_tmpmemctx );
-       }
        rs->sr_ref = ref;
-       if ( lip->url == NULL && li.url != NULL ) {
-               ldap_memfree( li.url );
-       }
 
        return rc;
 }
@@ -388,9 +441,9 @@ ldap_chain_db_init(
        BackendDB *be
 )
 {
-       slap_overinst *on = (slap_overinst *) be->bd_info;
-       void *private = be->be_private;
-       int rc;
+       slap_overinst   *on = (slap_overinst *)be->bd_info;
+       int             rc;
+       BackendDB       bd = *be;
 
        if ( lback == NULL ) {
                lback = backend_info( "ldap" );
@@ -400,10 +453,9 @@ ldap_chain_db_init(
                }
        }
 
-       be->be_private = NULL;
-       rc = lback->bi_db_init( be );
-       on->on_bi.bi_private = be->be_private;
-       be->be_private = private;
+       bd.be_private = NULL;
+       rc = lback->bi_db_init( &bd );
+       on->on_bi.bi_private = bd.be_private;
 
        return rc;
 }
@@ -447,10 +499,6 @@ chain_init( void )
        
        ldapchain.on_response = ldap_chain_response;
 
-#if 0
-       ldapchain.on_bi.bi_chk_referrals = ldap_chain_chk_referrals;
-#endif
-
        return overlay_register( &ldapchain );
 }
 
index ffa9f6bf77de6a5a59c1543a23b85839eef0d5ff..a538e3d4b27cb9ea94822dcd77c7463f1ea161a6 100644 (file)
@@ -42,9 +42,8 @@ ldap_back_compare(
        LDAPControl     **ctrls = NULL;
        int             rc = LDAP_SUCCESS;
 
-       lc = ldap_back_getconn( op, rs );
-       if (!lc || !ldap_back_dobind( lc, op, rs ) ) {
-               rc = -1;
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
+       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                goto cleanup;
        }
 
@@ -52,7 +51,6 @@ ldap_back_compare(
        rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
-               rc = -1;
                goto cleanup;
        }
 
@@ -61,10 +59,10 @@ retry:
                        op->orc_ava->aa_desc->ad_cname.bv_val,
                        &op->orc_ava->aa_value, 
                        ctrls, NULL, &msgid );
-       rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
-       if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
+       rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
+       if ( rc == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
-               if ( ldap_back_retry(lc, op, rs ) ) {
+               if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
        }
@@ -72,5 +70,5 @@ retry:
 cleanup:
        (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
        
-       return rc;
+       return rs->sr_err;
 }
index fd85eecea310a91fbd53191a9395e69b0b602591..470becaa3cef9d773b84355b1799bcf7192142d1 100644 (file)
@@ -213,6 +213,27 @@ ldap_back_db_config(
                li->url = ch_strdup( argv[ 1 ] );
 #endif
 
+       /* start tls */
+       } else if ( strcasecmp( argv[0], "start-tls" ) == 0 ) {
+               if ( argc != 1 ) {
+                       fprintf( stderr,
+       "%s: line %d: start-tls takes no arguments\n",
+                                       fname, lineno );
+                       return( 1 );
+               }
+               li->flags |= LDAP_BACK_F_TLS_CRITICAL;
+       
+       /* try start tls */
+       } else if ( strcasecmp( argv[0], "try-start-tls" ) == 0 ) {
+               if ( argc != 1 ) {
+                       fprintf( stderr,
+       "%s: line %d: try-start-tls takes no arguments\n",
+                                       fname, lineno );
+                       return( 1 );
+               }
+               li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
+               li->flags |= LDAP_BACK_F_USE_TLS;
+       
        /* name to use for ldap_back_group */
        } else if ( strcasecmp( argv[0], "acl-authcdn" ) == 0
                        || strcasecmp( argv[0], "binddn" ) == 0 )
@@ -272,7 +293,7 @@ ldap_back_db_config(
                                        fname, lineno );
                        return( 1 );
                }
-               li->savecred = 1;
+               li->flags |= LDAP_BACK_F_SAVECRED;
        
        /* intercept exop_who_am_i? */
        } else if ( strcasecmp( argv[0], "proxy-whoami" ) == 0 ) {
@@ -360,8 +381,8 @@ ldap_back_exop_whoami(
 
                ctrls[0] = &c;
                op2.o_ndn = op->o_conn->c_ndn;
-               lc = ldap_back_getconn(&op2, rs);
-               if (!lc || !ldap_back_dobind( lc, op, rs )) {
+               lc = ldap_back_getconn(&op2, rs, LDAP_BACK_SENDERR);
+               if (!lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR )) {
                        return -1;
                }
                c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
@@ -379,7 +400,7 @@ retry:
                                        &rs->sr_err);
                                if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) {
                                        do_retry = 0;
-                                       if ( ldap_back_retry( lc, op, rs ) )
+                                       if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) )
                                                goto retry;
                                }
                                ldap_back_freeconn( op, lc );
index 4b0ce6b25c4df268440031f957a7d8e5cfb2ae0a..3d6575be57c9153453c57d0a167635f690c72627 100644 (file)
@@ -42,9 +42,9 @@ ldap_back_delete(
        int             do_retry = 1;
        int             rc = LDAP_SUCCESS;
 
-       lc = ldap_back_getconn( op, rs );
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        
-       if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
+       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                rc = -1;
                goto cleanup;
        }
@@ -60,10 +60,10 @@ ldap_back_delete(
 retry:
        rs->sr_err = ldap_delete_ext( lc->lc_ld, op->o_req_ndn.bv_val,
                        ctrls, NULL, &msgid );
-       rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
+       rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
        if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) {
                do_retry = 0;
-               if ( ldap_back_retry (lc, op, rs ) ) {
+               if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
        }
index d4202d4c2b7e8971c9c3ee35382447ee9d7ef4e2..8fb7e44a53955b55048d6d586d52692b0acb0e87 100644 (file)
@@ -56,8 +56,8 @@ ldap_back_extended(
                         * called twice; maybe we could avoid the 
                         * ldap_back_dobind() call inside each extended()
                         * call ... */
-                       lc = ldap_back_getconn( op, rs );
-                       if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
+                       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
+                       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                                return -1;
                        }
 
@@ -99,8 +99,8 @@ ldap_back_exop_passwd(
        int             rc, isproxy;
        int             do_retry = 1;
 
-       lc = ldap_back_getconn( op, rs );
-       if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
+       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                return -1;
        }
 
@@ -154,7 +154,7 @@ retry:
                rs->sr_err = slap_map_api2result( rs );
                if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                        do_retry = 0;
-                       if ( ldap_back_retry(lc, op, rs ) ) {
+                       if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                                goto retry;
                        }
                }
index b00c579d36479c0792b4d0a9f796200e84031933..84f47becbd447c63b667605bb9a207c04a4fbf7f 100644 (file)
@@ -144,10 +144,10 @@ ldap_back_db_open( BackendDB *be )
                /* FIXME: disabled because namingContexts doesn't have
                 * a matching rule, and using an MRA filter doesn't work
                 * because the normalized assertion is compared to the 
-                * non-normalized value, which in general differ.
-                * See ITS#3406 */
+                * non-normalized value, which in general differs from
+                * the normalized one.  See ITS#3406 */
                struct berval   filter,
-                               base = BER_BVC( "cn=Databases,cn=Monitor" );
+                               base = BER_BVC( "cn=Databases," SLAPD_MONITOR );
                struct berval   vals[ 2 ];
                Attribute       a = { 0 };
 
index cc551243a1d095efeeda6dbdafaa2226d8312b78..0936bb4e0f75463795e24873309a31964bddb411 100644 (file)
@@ -46,8 +46,8 @@ ldap_back_modify(
        int             do_retry = 1;
        LDAPControl     **ctrls = NULL;
 
-       lc = ldap_back_getconn( op, rs );
-       if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
+       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                return -1;
        }
 
@@ -106,10 +106,10 @@ ldap_back_modify(
 retry:
        rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_ndn.bv_val, modv,
                        ctrls, NULL, &msgid );
-       rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
+       rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
-               if ( ldap_back_retry(lc, op, rs ) ) {
+               if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
        }
index 92cce0a749d5dd7b6a844d025ceafe275eb9bfd5..22554b24307742c3912b2d388bfc86832eb89d4e 100644 (file)
@@ -43,8 +43,8 @@ ldap_back_modrdn(
        int             rc = LDAP_SUCCESS;
        char            *newSup = NULL;
 
-       lc = ldap_back_getconn( op, rs );
-       if ( !lc || !ldap_back_dobind( lc, op, rs ) ) {
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
+       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                return( -1 );
        }
 
@@ -67,10 +67,10 @@ retry:
        rs->sr_err = ldap_rename( lc->lc_ld, op->o_req_ndn.bv_val,
                        op->orr_newrdn.bv_val, newSup,
                        op->orr_deleteoldrdn, ctrls, NULL, &msgid );
-       rc = ldap_back_op_result( lc, op, rs, msgid, 1 );
+       rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT );
        if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) {
                do_retry = 0;
-               if ( ldap_back_retry( lc, op, rs ) ) {
+               if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
        }
index eadc7d3949fd8228b947f9db3af785a58f37fa1e..8c85f507f414e1a8d1f44ba4876820f8c6412377 100644 (file)
@@ -49,12 +49,12 @@ extern BI_connection_destroy        ldap_back_conn_destroy;
 extern BI_entry_get_rw         ldap_back_entry_get;
 
 int ldap_back_freeconn( Operation *op, struct ldapconn *lc );
-struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs);
-int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs);
-int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs);
+struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs, ldap_back_send_t sendok);
+int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok);
+int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok);
 int ldap_back_map_result(SlapReply *rs);
 int ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs,
-       ber_int_t msgid, int sendok);
+       ber_int_t msgid, ldap_back_send_t sendok);
 int    back_ldap_LTX_init_module(int argc, char *argv[]);
 
 extern int ldap_back_conn_cmp( const void *c1, const void *c2);
index bf78dec637e58b79092969fc217bbbfd33d17795..b42352614f65e09159e8df6bfb80efcedadff3dd 100644 (file)
@@ -60,17 +60,17 @@ ldap_back_search(
        int             do_retry = 1;
        LDAPControl     **ctrls = NULL;
 
-       lc = ldap_back_getconn( op, rs );
+       lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        if ( !lc ) {
-               return -1;
+               return rs->sr_err;
        }
 
        /*
         * FIXME: in case of values return filter, we might want
         * to map attrs and maybe rewrite value
         */
-       if ( !ldap_back_dobind( lc, op, rs ) ) {
-               return -1;
+       if ( !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
+               return rs->sr_err;
        }
 
        /* should we check return values? */
@@ -120,7 +120,7 @@ retry:
 
        if ( rs->sr_err != LDAP_SUCCESS ) {
 fail:;
-               rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
+               rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR );
                if ( freeconn ) {
                        ldap_back_freeconn( op, lc );
                        lc = NULL;
@@ -249,7 +249,7 @@ fail:;
        if ( rc == -1 ) {
                if ( do_retry ) {
                        do_retry = 0;
-                       if ( ldap_back_retry( lc, op, rs ) ) {
+                       if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                                goto retry;
                        }
                }
@@ -500,7 +500,6 @@ ldap_back_entry_get(
                        *e = NULL;
        char            *gattr[3];
        char            *filter = NULL;
-       Connection      *oconn;
        SlapReply       rs;
        int             do_retry = 1;
        LDAPControl     **ctrls = NULL;
@@ -508,16 +507,12 @@ ldap_back_entry_get(
        /* Tell getconn this is a privileged op */
        do_not_cache = op->o_do_not_cache;
        op->o_do_not_cache = 1;
-       lc = ldap_back_getconn( op, &rs );
-       oconn = op->o_conn;
-       op->o_conn = NULL;
-       if ( !lc || !ldap_back_dobind( lc, op, &rs ) ) {
+       lc = ldap_back_getconn( op, &rs, LDAP_BACK_DONTSEND );
+       if ( !lc || !ldap_back_dobind( lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
                op->o_do_not_cache = do_not_cache;
-               op->o_conn = oconn;
-               return 1;
+               return rs.sr_err;
        }
        op->o_do_not_cache = do_not_cache;
-       op->o_conn = oconn;
 
        if ( at ) {
                if ( oc && at != slap_schema.si_ad_objectClass ) {
@@ -555,7 +550,7 @@ retry:
        if ( rc != LDAP_SUCCESS ) {
                if ( rc == LDAP_SERVER_DOWN && do_retry ) {
                        do_retry = 0;
-                       if ( ldap_back_retry( lc, op, &rs ) ) {
+                       if ( ldap_back_retry( lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
                                goto retry;
                        }
                }
index 50dd8e584b69db06a09d7a17558d74539a4e9030..3ead454bb45ad38946787d6598467ee48531a9cf 100644 (file)
@@ -85,15 +85,6 @@ typedef struct dncookie {
 #define META_BIND_NRETRIES     3
 #define META_BIND_TIMEOUT      1000
 
-int ldap_back_freeconn( Operation *op, struct ldapconn *lc );
-struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs);
-int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs);
-int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs);
-int ldap_back_map_result(SlapReply *rs);
-int ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs,
-       ber_int_t msgid, int sendok);
-int    back_ldap_LTX_init_module(int argc, char *argv[]);
-
 int ldap_back_dn_massage(dncookie *dc, struct berval *dn,
        struct berval *res);
 
index 3d5347398908e68de367ed539c07af7c79aab9bb..985f5dd4df487d1d134c70f48e7b89683674940c 100644 (file)
@@ -386,6 +386,10 @@ pager: +1 313 555 7671
 facsimileTelephoneNumber: +1 313 555 7762
 telephoneNumber: +1 313 555 4177
 
+dn: ou=Other,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Other
+
 dn: ou=People,dc=example,dc=com
 objectClass: organizationalUnit
 objectClass: extensibleObject
index a15e26f52801a4efe6f18ba15e2fb71021c5287f..67970afc2f8c6d8040c0cab65eeca7e074f86b21 100644 (file)
@@ -365,6 +365,10 @@ pager: +1 313 555 7671
 facsimileTelephoneNumber: +1 313 555 7762
 telephoneNumber: +1 313 555 4177
 
+dn: ou=Other,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Other
+
 dn: ou=People,dc=example,dc=com
 objectClass: organizationalUnit
 objectClass: extensibleObject
diff --git a/tests/data/chainref.out b/tests/data/chainref.out
new file mode 100644 (file)
index 0000000..bec3250
--- /dev/null
@@ -0,0 +1,4 @@
+dn: ou=Other,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Other
+
index 7f419fd20ce13a1b45abffbbba99b364bf56a288..76e22f7629f627750015b3ae6f189c5fa3a68b36 100644 (file)
@@ -29,6 +29,14 @@ objectclass: extensibleobject
 ou: Groups
 ref: @URI2@ou=Groups,dc=example,dc=com
 
+dn: ou=Other,dc=example,dc=com
+objectclass: referral
+objectclass: extensibleobject
+ou: Other
+# invalid URI first to test failover capabilities (search only)
+ref: @URI3@ou=Other,dc=example,dc=com
+ref: @URI2@ou=Other,dc=example,dc=com
+
 dn: ou=Alumni Association,ou=People,dc=example,dc=com
 objectclass: organizationalUnit
 ou: Alumni Association
index fe0cd3e920f5c236934fa02a86a3354a02f3e8c4..e1fb680216e8b4f365ae2e38294715cac3019e88 100644 (file)
@@ -81,3 +81,8 @@ cn: Dir Man
 sn: Manager
 description: Manager of the directory
 userpassword:: c2VjcmV0
+
+dn: ou=Other,dc=example,dc=com
+objectclass: organizationalUnit
+ou: Other
+
index c083e666d8291cdf9718933ca8ff92211ca1f773..bb6d4011d4bb622ea12fd090081bbc96dff7bde4 100755 (executable)
@@ -235,6 +235,7 @@ LDAPGLUEOUT=$DATADIR/ldapglue.out
 LDAPGLUEANONYMOUSOUT=$DATADIR/ldapglueanonymous.out
 RELAYOUT=$DATADIR/relay.out
 CHAINOUT=$DATADIR/chain.out
+CHAINREFOUT=$DATADIR/chainref.out
 CHAINMODOUT=$DATADIR/chainmod.out
 SQLREAD=$DATADIR/sql-read.out
 SQLWRITE=$DATADIR/sql-write.out
index de27ec0fce855c383982382ac3fc599630eb6534..7bf073a3fdb7ac50fdc3beff4c88b6bbb99f4690 100755 (executable)
@@ -110,6 +110,31 @@ for P in $PORT1 $PORT2 ; do
                test $KILLSERVERS != no && kill -HUP $KILLPIDS
                exit 1
        fi
+
+       echo "Reading the referral entry "ou=Other,$BASEDN" as anonymous on port $P..."
+       $LDAPSEARCH -h $LOCALHOST -p $P -b "ou=Other,$BASEDN" -S "" \
+                > $SEARCHOUT 2>&1
+
+       RC=$?
+       if test $RC != 0 ; then
+               echo "ldapsearch failed ($RC)!"
+               test $KILLSERVERS != no && kill -HUP $KILLPIDS
+               exit $RC
+       fi
+
+       echo "Filtering ldapsearch results..."
+       . $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
+       echo "Filtering original ldif used to create database..."
+       . $LDIFFILTER < $CHAINREFOUT > $LDIFFLT
+       echo "Comparing filter output..."
+       $CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+               
+       if test $? != 0 ; then
+               echo "comparison failed - chained search didn't succeed"
+               test $KILLSERVERS != no && kill -HUP $KILLPIDS
+               exit 1
+fi
+
 done
 
 #