mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-06 10:46:21 +08:00
allow per-target retry in searches; taint invalid connections; don't massage the pseudorootdn (ITS#4150)
This commit is contained in:
parent
d67a2f2044
commit
852e4e3109
@ -184,6 +184,7 @@ typedef struct metaconn_t {
|
||||
struct slap_conn *mc_conn;
|
||||
ldap_pvt_thread_mutex_t mc_mutex;
|
||||
unsigned mc_refcnt;
|
||||
int mc_tainted;
|
||||
|
||||
struct berval mc_local_ndn;
|
||||
/* NOTE: msc_mscflags is used to recycle the #define
|
||||
|
@ -46,7 +46,8 @@ meta_back_single_bind(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
metaconn_t *mc,
|
||||
int candidate );
|
||||
int candidate,
|
||||
int massage );
|
||||
|
||||
int
|
||||
meta_back_bind( Operation *op, SlapReply *rs )
|
||||
@ -124,6 +125,7 @@ meta_back_bind( Operation *op, SlapReply *rs )
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
int lerr;
|
||||
Operation op2 = *op;
|
||||
int massage = 1;
|
||||
|
||||
/*
|
||||
* Skip non-candidates
|
||||
@ -177,9 +179,12 @@ meta_back_bind( Operation *op, SlapReply *rs )
|
||||
op2.o_req_ndn = mi->mi_targets[ i ].mt_pseudorootdn;
|
||||
op2.orb_cred = mi->mi_targets[ i ].mt_pseudorootpw;
|
||||
op2.orb_method = LDAP_AUTH_SIMPLE;
|
||||
|
||||
massage = 0;
|
||||
}
|
||||
|
||||
lerr = meta_back_single_bind( &op2, rs, mc, i );
|
||||
lerr = meta_back_single_bind( &op2, rs, mc, i, massage );
|
||||
|
||||
if ( lerr != LDAP_SUCCESS ) {
|
||||
rs->sr_err = lerr;
|
||||
candidates[ i ].sr_tag = META_NOT_CANDIDATE;
|
||||
@ -274,12 +279,12 @@ meta_back_single_bind(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
metaconn_t *mc,
|
||||
int candidate )
|
||||
int candidate,
|
||||
int massage )
|
||||
{
|
||||
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
|
||||
metatarget_t *mt = &mi->mi_targets[ candidate ];
|
||||
struct berval mdn = BER_BVNULL;
|
||||
dncookie dc;
|
||||
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
|
||||
int msgid,
|
||||
rebinding = 0;
|
||||
@ -300,14 +305,21 @@ meta_back_single_bind(
|
||||
/*
|
||||
* Rewrite the bind dn if needed
|
||||
*/
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.ctx = "bindDN";
|
||||
if ( massage ) {
|
||||
dncookie dc;
|
||||
|
||||
if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
||||
send_ldap_result( op, rs );
|
||||
return -1;
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.ctx = "bindDN";
|
||||
|
||||
if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
||||
send_ldap_result( op, rs );
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
mdn = op->o_req_dn;
|
||||
}
|
||||
|
||||
/* FIXME: this fixes the bind problem right now; we need
|
||||
@ -378,27 +390,7 @@ retry:;
|
||||
|
||||
rc = slap_map_api2result( rs );
|
||||
if ( rs->sr_err == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) {
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
|
||||
if ( mc->mc_refcnt == 1 ) {
|
||||
meta_clear_one_candidate( msc );
|
||||
LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
|
||||
|
||||
( 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, mc, msc, LDAP_BACK_CONN_ISPRIV( mc ),
|
||||
candidate == mc->mc_authz_target,
|
||||
LDAP_BACK_DONTSEND );
|
||||
|
||||
} else {
|
||||
/* can't do anything about it */
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
|
||||
|
||||
rc = meta_back_retry( op, rs, mc, candidate, LDAP_BACK_DONTSEND );
|
||||
if ( rc ) {
|
||||
if ( nretries > 0 ) {
|
||||
nretries--;
|
||||
@ -552,6 +544,9 @@ retry:;
|
||||
|
||||
rc = slap_map_api2result( rs );
|
||||
if ( rc == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) {
|
||||
/* NOTE: we do not use meta_back_retry() here
|
||||
* to avoid circular loops; mc_mutex is set
|
||||
* by the caller */
|
||||
if ( dolock ) {
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
|
||||
}
|
||||
@ -569,7 +564,6 @@ retry:;
|
||||
LDAP_BACK_CONN_ISPRIV( mc ),
|
||||
candidate == mc->mc_authz_target,
|
||||
LDAP_BACK_DONTSEND );
|
||||
|
||||
|
||||
} else {
|
||||
/* can't do anything about it */
|
||||
@ -685,7 +679,7 @@ meta_back_dobind(
|
||||
|
||||
rootdn = mi->mi_targets[ i ].mt_pseudorootdn.bv_val;
|
||||
|
||||
rc = meta_back_single_bind( &op2, rs, mc, i );
|
||||
rc = meta_back_single_bind( &op2, rs, mc, i, 0 );
|
||||
|
||||
} else {
|
||||
rc = meta_back_single_dobind( op, rs, mc, i,
|
||||
|
@ -172,6 +172,7 @@ metaconn_alloc(
|
||||
mc->mc_authz_target = META_BOUND_NONE;
|
||||
ldap_pvt_thread_mutex_init( &mc->mc_mutex );
|
||||
mc->mc_refcnt = 1;
|
||||
mc->mc_tainted = 0;
|
||||
|
||||
return mc;
|
||||
}
|
||||
@ -447,6 +448,10 @@ retry_lock:;
|
||||
goto retry_lock;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "%s meta_back_retry: retrying uri=\"%s\" DN=\"%s\"\n",
|
||||
op->o_log_prefix, mt->mt_uri,
|
||||
BER_BVISNULL( &msc->msc_bound_ndn ) ? "" : msc->msc_bound_ndn.bv_val );
|
||||
|
||||
meta_clear_one_candidate( msc );
|
||||
LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
|
||||
|
||||
@ -465,6 +470,10 @@ retry_lock:;
|
||||
ldap_pvt_thread_mutex_unlock( &mc->mc_mutex );
|
||||
}
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
mc->mc_tainted = 1;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
|
||||
|
||||
return rc == LDAP_SUCCESS ? 1 : 0;
|
||||
@ -720,6 +729,13 @@ meta_back_getconn(
|
||||
mc = (metaconn_t *)avl_find( mi->mi_conntree,
|
||||
(caddr_t)&mc_curr, meta_back_conn_cmp );
|
||||
if ( mc ) {
|
||||
if ( mc->mc_tainted ) {
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "remote server unavailable";
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mc->mc_refcnt++;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
|
||||
@ -1122,5 +1138,8 @@ meta_back_release_conn(
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
|
||||
assert( mc->mc_refcnt > 0 );
|
||||
mc->mc_refcnt--;
|
||||
if ( mc->mc_refcnt == 0 && mc->mc_tainted ) {
|
||||
meta_back_conn_free( mc );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
|
||||
}
|
||||
|
@ -43,7 +43,13 @@ meta_send_entry(
|
||||
int i,
|
||||
LDAPMessage *e );
|
||||
|
||||
static int
|
||||
typedef enum meta_search_candidate_t {
|
||||
META_SEARCH_ERR = -1,
|
||||
META_SEARCH_NOT_CANDIDATE,
|
||||
META_SEARCH_CANDIDATE
|
||||
} meta_search_candidate_t;
|
||||
|
||||
static meta_search_candidate_t
|
||||
meta_back_search_start(
|
||||
Operation *op,
|
||||
SlapReply *rs,
|
||||
@ -61,6 +67,7 @@ meta_back_search_start(
|
||||
struct berval mfilter = BER_BVNULL;
|
||||
char **mapped_attrs = NULL;
|
||||
int rc;
|
||||
meta_search_candidate_t retcode;
|
||||
struct timeval tv, *tvp = NULL;
|
||||
|
||||
/* should we check return values? */
|
||||
@ -105,7 +112,7 @@ meta_back_search_start(
|
||||
/*
|
||||
* this target is no longer candidate
|
||||
*/
|
||||
return 0;
|
||||
return META_SEARCH_NOT_CANDIDATE;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -145,7 +152,7 @@ meta_back_search_start(
|
||||
/*
|
||||
* this target is no longer candidate
|
||||
*/
|
||||
return 0;
|
||||
return META_SEARCH_NOT_CANDIDATE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,14 +168,14 @@ meta_back_search_start(
|
||||
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
|
||||
rs->sr_text = "Operation not allowed";
|
||||
send_ldap_result( op, rs );
|
||||
return -1;
|
||||
return META_SEARCH_ERR;
|
||||
|
||||
case REWRITE_REGEXEC_ERR:
|
||||
|
||||
/*
|
||||
* this target is no longer candidate
|
||||
*/
|
||||
return 0;
|
||||
return META_SEARCH_NOT_CANDIDATE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -185,7 +192,7 @@ meta_back_search_start(
|
||||
/*
|
||||
* this target is no longer candidate
|
||||
*/
|
||||
rc = 0;
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -198,7 +205,7 @@ meta_back_search_start(
|
||||
/*
|
||||
* this target is no longer candidate
|
||||
*/
|
||||
rc = 0;
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -211,11 +218,11 @@ meta_back_search_start(
|
||||
op->o_ctrls, NULL, tvp, op->ors_slimit,
|
||||
&candidates[ candidate ].sr_msgid );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
rc = 1;
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
|
||||
} else {
|
||||
candidates[ candidate ].sr_msgid = -1;
|
||||
rc = 0;
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
}
|
||||
|
||||
done:;
|
||||
@ -229,7 +236,7 @@ done:;
|
||||
free( mbase.bv_val );
|
||||
}
|
||||
|
||||
return rc;
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int
|
||||
@ -284,14 +291,15 @@ meta_back_search( Operation *op, SlapReply *rs )
|
||||
|
||||
switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) )
|
||||
{
|
||||
case 0:
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case META_SEARCH_CANDIDATE:
|
||||
candidates[ i ].sr_type = REP_INTERMEDIATE;
|
||||
++ncandidates;
|
||||
break;
|
||||
|
||||
case -1:
|
||||
case META_SEARCH_ERR:
|
||||
rc = -1;
|
||||
goto finish;
|
||||
}
|
||||
@ -386,6 +394,7 @@ meta_back_search( Operation *op, SlapReply *rs )
|
||||
* get a LDAP_TIMELIMIT_EXCEEDED from
|
||||
* one of them ...
|
||||
*/
|
||||
get_result:;
|
||||
rc = ldap_result( msc->msc_ld, candidates[ i ].sr_msgid,
|
||||
0, &tv, &res );
|
||||
|
||||
@ -411,21 +420,37 @@ meta_back_search( Operation *op, SlapReply *rs )
|
||||
} else if ( rc == -1 ) {
|
||||
really_bad:;
|
||||
/* something REALLY bad happened! */
|
||||
( void )meta_clear_unused_candidates( op, -1 );
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
savepriv = op->o_private;
|
||||
op->o_private = (void *)i;
|
||||
send_ldap_result( op, rs );
|
||||
op->o_private = savepriv;
|
||||
|
||||
/* anything else needs be done? */
|
||||
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
||||
candidates[ i ].sr_type = REP_RESULT;
|
||||
|
||||
/* FIXME: res should not need to be freed */
|
||||
assert( res == NULL );
|
||||
if ( meta_back_retry( op, rs, mc, i, LDAP_BACK_DONTSEND ) ) {
|
||||
switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) )
|
||||
{
|
||||
case META_SEARCH_CANDIDATE:
|
||||
goto get_result;
|
||||
|
||||
goto finish;
|
||||
default:
|
||||
rc = rs->sr_err = LDAP_OTHER;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When no candidates are left,
|
||||
* the outer cycle finishes
|
||||
*/
|
||||
candidates[ i ].sr_msgid = -1;
|
||||
--ncandidates;
|
||||
rs->sr_err = candidates[ i ].sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "remote server unavailable";
|
||||
|
||||
} else if ( rc == LDAP_RES_SEARCH_ENTRY ) {
|
||||
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
||||
/* don't retry any more... */
|
||||
candidates[ i ].sr_type = REP_RESULT;
|
||||
}
|
||||
|
||||
if ( --op->ors_slimit == -1 ) {
|
||||
ldap_msgfree( res );
|
||||
res = NULL;
|
||||
@ -477,6 +502,11 @@ really_bad:;
|
||||
char **references = NULL;
|
||||
int cnt;
|
||||
|
||||
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
||||
/* don't retry any more... */
|
||||
candidates[ i ].sr_type = REP_RESULT;
|
||||
}
|
||||
|
||||
is_ok++;
|
||||
|
||||
rc = ldap_parse_reference( msc->msc_ld, res,
|
||||
@ -525,7 +555,7 @@ really_bad:;
|
||||
|
||||
/* cleanup */
|
||||
if ( references ) {
|
||||
ldap_value_free( references );
|
||||
ber_memvfree( (void **)references );
|
||||
}
|
||||
|
||||
if ( rs->sr_ctrls ) {
|
||||
@ -537,6 +567,11 @@ really_bad:;
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
char **references = NULL;
|
||||
|
||||
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
|
||||
/* don't retry any more... */
|
||||
candidates[ i ].sr_type = REP_RESULT;
|
||||
}
|
||||
|
||||
if ( ldap_parse_result( msc->msc_ld,
|
||||
res,
|
||||
&candidates[ i ].sr_err,
|
||||
@ -550,6 +585,7 @@ really_bad:;
|
||||
LDAP_OPT_ERROR_NUMBER,
|
||||
&rs->sr_err );
|
||||
sres = slap_map_api2result( rs );
|
||||
candidates[ i ].sr_type = REP_RESULT;
|
||||
goto really_bad;
|
||||
}
|
||||
|
||||
@ -611,7 +647,7 @@ really_bad:;
|
||||
( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
|
||||
|
||||
/* cleanup */
|
||||
ldap_value_free( references );
|
||||
ber_memvfree( (void **)references );
|
||||
|
||||
if ( rs->sr_v2ref == NULL ) {
|
||||
rs->sr_v2ref = sr_ref;
|
||||
|
Loading…
Reference in New Issue
Block a user