]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-meta/conn.c
don't lookup rootdn if the password is incorrect (ITS#4004)
[openldap] / servers / slapd / back-meta / conn.c
index 1379d8c3a1b10527d171b71715b111a097a6be5b..a0ae2801249fe69e0b607e747dff707e43900006 100644 (file)
@@ -178,16 +178,7 @@ meta_back_freeconn(
 
        assert( mc != NULL );
 
-retry_lock:;
-       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-       case LDAP_PVT_THREAD_EBUSY:
-       default:
-               ldap_pvt_thread_yield();
-               goto retry_lock;
-
-       case 0:
-               break;
-       }
+       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
 
        if ( --mc->mc_refcnt == 0 ) {
                meta_back_conn_free( mc );
@@ -217,8 +208,7 @@ meta_back_init_one_conn(
         * Already init'ed
         */
        if ( msc->msc_ld != NULL ) {
-               rs->sr_err = LDAP_SUCCESS;
-               goto error_return;
+               return rs->sr_err = LDAP_SUCCESS;
        }
        
        /*
@@ -242,14 +232,14 @@ meta_back_init_one_conn(
        }
 
 #ifdef HAVE_TLS
-       /* start TLS ("start-tls"/"try-start-tls" statements) */
+       /* start TLS ("tls [try-]{start|propagate}" statement) */
        if ( ( LDAP_BACK_USE_TLS( mi ) || ( op->o_conn->c_is_tls && LDAP_BACK_PROPAGATE_TLS( mi ) ) )
                        && !ldap_is_ldaps_url( mt->mt_uri ) )
        {
 #ifdef SLAP_STARTTLS_ASYNCHRONOUS
                /*
-                * use asynchronous StartTLS
-                * in case, chase referral (not implemented yet)
+                * use asynchronous StartTLS; in case, chase referral
+                * FIXME: OpenLDAP does not return referral on StartTLS yet
                 */
                int             msgid;
 
@@ -345,11 +335,6 @@ retry:;
                                (void *)&network_timeout );
        }
 
-       /*
-        * Sets a cookie for the rewrite session
-        */
-       ( void )rewrite_session_init( mt->mt_rwmap.rwm_rw, op->o_conn );
-
        /*
         * If the connection DN is not null, an attempt to rewrite it is made
         */
@@ -382,7 +367,13 @@ retry:;
        msc->msc_bound = META_UNBOUND;
 
 error_return:;
-       if ( rs->sr_err != LDAP_SUCCESS ) {
+       if ( rs->sr_err == LDAP_SUCCESS ) {
+               /*
+                * Sets a cookie for the rewrite session
+                */
+               ( void )rewrite_session_init( mt->mt_rwmap.rwm_rw, op->o_conn );
+
+       } else {
                rs->sr_err = slap_map_api2result( rs );
                if ( sendok & LDAP_BACK_SENDERR ) {
                        send_ldap_result( op, rs );
@@ -412,25 +403,23 @@ meta_back_retry(
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
 
 retry_lock:;
-       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-       case LDAP_PVT_THREAD_EBUSY:
-       default:
-               ldap_pvt_thread_yield();
-               goto retry_lock;
-
-       case 0:
-               break;
-       }
+       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
 
        assert( mc->mc_refcnt > 0 );
 
        if ( mc->mc_refcnt == 1 ) {
-               ldap_pvt_thread_mutex_lock( &mc->mc_mutex );
+               while ( ldap_pvt_thread_mutex_trylock( &mc->mc_mutex ) ) {
+                       ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+                       ldap_pvt_thread_yield();
+                       goto retry_lock;
+               }
 
                ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
                msc->msc_ld = NULL;
                msc->msc_bound = 0;
 
+               ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
+
                /* mc here must be the regular mc, reset and ready for init */
                rc = meta_back_init_one_conn( op, rs, mt, msc, sendok );
 
@@ -537,6 +526,7 @@ meta_back_get_candidate(
                         * a candidate, try using it (FIXME: YMMV) */
                        if ( mi->mi_defaulttarget != META_DEFAULT_TARGET_NONE
                                && meta_back_is_candidate( &mi->mi_targets[ mi->mi_defaulttarget ].mt_nsuffix,
+                                               mi->mi_targets[ mi->mi_defaulttarget ].mt_scope,
                                                ndn, op->o_tag == LDAP_REQ_SEARCH ? op->ors_scope : LDAP_SCOPE_BASE ) )
                        {
                                candidate = mi->mi_defaulttarget;
@@ -549,11 +539,16 @@ meta_back_get_candidate(
                        }
                        break;
                }
+
+       } else {
+               rs->sr_err = LDAP_SUCCESS;
        }
 
        return candidate;
 }
 
+static void    *meta_back_candidates_dummy;
+
 static void
 meta_back_candidates_keyfree(
        void            *key,
@@ -570,13 +565,12 @@ meta_back_candidates_get( Operation *op )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
        metacandidates_t        *mc;
-       SlapReply               *rs;
 
        if ( op->o_threadctx ) {
                void            *data = NULL;
 
                ldap_pvt_thread_pool_getkey( op->o_threadctx,
-                               meta_back_candidates_keyfree, &data, NULL );
+                               &meta_back_candidates_dummy, &data, NULL );
                mc = (metacandidates_t *)data;
 
        } else {
@@ -592,7 +586,7 @@ meta_back_candidates_get( Operation *op )
 
                        data = (void *)mc;
                        ldap_pvt_thread_pool_setkey( op->o_threadctx,
-                                       meta_back_candidates_keyfree, data,
+                                       &meta_back_candidates_dummy, data,
                                        meta_back_candidates_keyfree );
 
                } else {
@@ -670,16 +664,7 @@ meta_back_getconn(
 
        /* Searches for a metaconn in the avl tree */
        mc_curr.mc_conn = op->o_conn;
-retry_lock:;
-       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-       case LDAP_PVT_THREAD_EBUSY:
-       default:
-               ldap_pvt_thread_yield();
-               goto retry_lock;
-
-       case 0:
-               break;
-       }
+       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 );
        if ( mc ) {
@@ -745,9 +730,11 @@ retry_lock:;
                         * The target is activated; if needed, it is
                         * also init'd
                         */
-                       int lerr = meta_back_init_one_conn( op, rs, &mi->mi_targets[ i ],
-                                       &mc->mc_conns[ i ], sendok );
-                       if ( lerr == LDAP_SUCCESS ) {
+                       candidates[ i ].sr_err =
+                               meta_back_init_one_conn( op, rs,
+                                               &mi->mi_targets[ i ],
+                                               &mc->mc_conns[ i ], sendok );
+                       if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
                                candidates[ i ].sr_tag = META_CANDIDATE;
                                ncandidates++;
                                
@@ -759,7 +746,7 @@ retry_lock:;
                                 * be tried?
                                 */
                                candidates[ i ].sr_tag = META_NOT_CANDIDATE;
-                               err = lerr;
+                               err = candidates[ i ].sr_err;
                                continue;
                        }
                }
@@ -816,6 +803,10 @@ retry_lock:;
                        }
        
                        if ( rs->sr_err != LDAP_SUCCESS ) {
+                               if ( mc != NULL ) {
+                                       meta_back_release_conn( op, mc );
+                               }
+
                                if ( sendok & LDAP_BACK_SENDERR ) {
                                        if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
                                                rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
@@ -824,18 +815,24 @@ retry_lock:;
                                        rs->sr_text = NULL;
                                        rs->sr_matched = NULL;
                                }
+                       
                                return NULL;
                        }
                }
 
                if ( newparent && meta_back_get_candidate( op, rs, op->orr_nnewSup ) != i )
                {
+                       if ( mc != NULL ) {
+                               meta_back_release_conn( op, mc );
+                       }
+
                        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                        rs->sr_text = "cross-target rename not supported";
                        if ( sendok & LDAP_BACK_SENDERR ) {
                                send_ldap_result( op, rs );
                                rs->sr_text = NULL;
                        }
+
                        return NULL;
                }
 
@@ -848,16 +845,7 @@ retry_lock:;
                         * the reason is that the connection might have been
                         * created by meta_back_get_candidate() */
                        mc_curr.mc_conn = op->o_conn;
-retry_lock2:;
-                       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-                       case LDAP_PVT_THREAD_EBUSY:
-                       default:
-                               ldap_pvt_thread_yield();
-                               goto retry_lock2;
-
-                       case 0:
-                               break;
-                       }
+                       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 );
                        if ( mc != NULL ) {
@@ -902,6 +890,7 @@ retry_lock2:;
                        return NULL;
                }
 
+               candidates[ i ].sr_err = LDAP_SUCCESS;
                candidates[ i ].sr_tag = META_CANDIDATE;
                ncandidates++;
 
@@ -924,6 +913,7 @@ retry_lock2:;
                for ( i = 0; i < mi->mi_ntargets; 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 ) )
                        {
 
@@ -936,6 +926,7 @@ retry_lock2:;
                                                &mc->mc_conns[ i ], sendok );
                                if ( lerr == LDAP_SUCCESS ) {
                                        candidates[ i ].sr_tag = META_CANDIDATE;
+                                       candidates[ i ].sr_err = LDAP_SUCCESS;
                                        ncandidates++;
 
                                        Debug( LDAP_DEBUG_TRACE, "%s: meta_back_init_one_conn(%d)\n",
@@ -951,7 +942,8 @@ retry_lock2:;
                                        if ( new_conn ) {
                                                ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
                                        }
-                                       candidates[ i ].sr_tag = META_NOT_CANDIDATE;
+                                       /* leave the target candidate, but record the error for later use */
+                                       candidates[ i ].sr_err = lerr;
                                        err = lerr;
 
                                        Debug( LDAP_DEBUG_ANY, "%s: meta_back_init_one_conn(%d) failed: %d\n",
@@ -1002,16 +994,7 @@ done:;
                /*
                 * Inserts the newly created metaconn in the avl tree
                 */
-retry_lock3:;
-               switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-               case LDAP_PVT_THREAD_EBUSY:
-               default:
-                       ldap_pvt_thread_yield();
-                       goto retry_lock3;
-
-               case 0:
-                       break;
-               }
+               ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
                err = avl_insert( &mi->mi_conntree, ( caddr_t )mc,
                                meta_back_conn_cmp, meta_back_conn_dup );
 
@@ -1064,17 +1047,7 @@ meta_back_release_conn(
 
        assert( mc != NULL );
 
-retry_lock:;
-       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-       case LDAP_PVT_THREAD_EBUSY:
-       default:
-               ldap_pvt_thread_yield();
-               goto retry_lock;
-
-       case 0:
-               break;
-       }
-
+       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
        assert( mc->mc_refcnt > 0 );
        mc->mc_refcnt--;
        ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );