LDAP_REBIND_PROC *ldap_back_rebind_f = ldap_back_default_rebind;
static int
-ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs );
+ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
static int
ldap_back_prepare_conn( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
* bind with the configured identity assertion */
/* NOTE: use with care */
if ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
- ldap_back_proxy_authz_bind( lc, op, rs );
+ ldap_back_proxy_authz_bind( lc, op, rs, LDAP_BACK_SENDERR );
if ( !LDAP_BACK_CONN_ISBOUND( lc ) ) {
rc = 1;
goto done;
}
void
-ldap_back_release_conn(
+ldap_back_release_conn_lock(
Operation *op,
SlapReply *rs,
- ldapconn_t *lc )
+ ldapconn_t *lc,
+ int dolock )
{
ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private;
- ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
+ }
assert( lc->lc_refcnt > 0 );
lc->lc_refcnt--;
LDAP_BACK_CONN_BINDING_CLEAR( lc );
- ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
+ }
}
/*
while ( lc->lc_refcnt > 1 ) {
ldap_pvt_thread_yield();
- if (( rc = LDAP_BACK_CONN_ISBOUND( lc )))
+ rc = LDAP_BACK_CONN_ISBOUND( lc );
+ if ( rc ) {
return rc;
+ }
}
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
+ }
+ LDAP_BACK_CONN_BINDING_SET( lc );
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
+ }
+
/*
* FIXME: we need to let clients use proxyAuthz
* otherwise we cannot do symmetric pools of servers;
( BER_BVISNULL( &lc->lc_bound_ndn ) ||
( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
{
- (void)ldap_back_proxy_authz_bind( lc, op, rs );
+ (void)ldap_back_proxy_authz_bind( lc, op, rs, sendok );
goto done;
}
rc = ldap_back_op_result( lc, op, rs, msgid, 0, sendok );
if ( rc == LDAP_SUCCESS ) {
LDAP_BACK_CONN_ISBOUND_SET( lc );
-
- } else {
- ldap_back_release_conn( op, rs, lc );
}
done:;
+ LDAP_BACK_CONN_BINDING_CLEAR( lc );
rc = LDAP_BACK_CONN_ISBOUND( lc );
+ if ( !rc ) {
+ ldap_back_release_conn_lock( op, rs, lc, dolock );
+ }
return rc;
}
}
static int
-ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs )
+ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
{
ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private;
struct berval binddn = slap_empty_bv;
if ( BER_BVISNULL( &ndn ) && li->li_idassert_authz == NULL ) {
if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
- send_ldap_result( op, rs );
+ if ( sendok & LDAP_BACK_SENDERR ) {
+ send_ldap_result( op, rs );
+ }
LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
} else {
&authcDN, &authcDN );
if ( rs->sr_err != LDAP_SUCCESS ) {
if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
- send_ldap_result( op, rs );
+ if ( sendok & LDAP_BACK_SENDERR ) {
+ send_ldap_result( op, rs );
+ }
LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
} else {
(void *)li->li_idassert_secprops );
if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
- send_ldap_result( op, rs );
+ rs->sr_err = LDAP_OTHER;
+ if ( sendok & LDAP_BACK_SENDERR ) {
+ send_ldap_result( op, rs );
+ }
LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
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 );
+ if ( sendok & LDAP_BACK_SENDERR ) {
+ send_ldap_result( op, rs );
+ }
} else {
LDAP_BACK_CONN_ISBOUND_SET( lc );
/* unsupported! */
LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
- send_ldap_result( op, rs );
+ if ( sendok & LDAP_BACK_SENDERR ) {
+ send_ldap_result( op, rs );
+ }
goto done;
}
- rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_SENDERR );
+ rc = ldap_back_op_result( lc, op, rs, msgid, 0, sendok );
if ( rc == LDAP_SUCCESS ) {
LDAP_BACK_CONN_ISBOUND_SET( lc );
}
int ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock );
ldapconn_t *ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok );
-void ldap_back_release_conn( Operation *op, SlapReply *rs, ldapconn_t *lc );
+void ldap_back_release_conn_lock( Operation *op, SlapReply *rs, ldapconn_t *lc, int dolock );
+#define ldap_back_release_conn(op, rs, lc) ldap_back_release_conn_lock((op), (rs), (lc), 1)
int ldap_back_dobind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
int ldap_back_retry( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
int ldap_back_map_result( SlapReply *rs );
int i;
char **attrs = NULL;
int freetext = 0;
- int do_retry = 1;
+ int do_retry = 1, dont_retry = 0;
LDAPControl **ctrls = NULL;
/* FIXME: shouldn't this be null? */
const char *save_matched = rs->sr_matched;
rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
goto finish;
}
+ continue;
+
+ } else {
+ /* don't retry any more */
+ dont_retry = 1;
+ }
+
- } else if ( rc == LDAP_RES_SEARCH_ENTRY ) {
+ if ( rc == LDAP_RES_SEARCH_ENTRY ) {
Entry ent = { 0 };
struct berval bdn = BER_BVNULL;
}
}
- if ( rc == -1 ) {
+ if ( rc == -1 && dont_retry == 0 ) {
if ( do_retry ) {
do_retry = 0;
- if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
+ if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
goto retry;
}
}
time_t mt_network_timeout;
time_t mt_idle_timeout;
struct timeval mt_bind_timeout;
-#define META_BIND_TIMEOUT 10000
+#define META_BIND_TIMEOUT LDAP_BACK_RESULT_UTIMEOUT
time_t mt_timeout[ LDAP_BACK_OP_LAST ];
} metatarget_t;
metaconn_t *mc );
extern int
-meta_back_retry(
+meta_back_retry_lock(
Operation *op,
SlapReply *rs,
metaconn_t *mc,
int candidate,
- ldap_back_send_t sendok );
+ ldap_back_send_t sendok,
+ int dolock );
+#define meta_back_retry(op, rs, mc, candidate, sendok) \
+ meta_back_retry_lock((op), (rs), (mc), (candidate), (sendok), 1)
extern void
meta_back_conn_free(
int ispriv,
ldap_back_send_t sendok );
+extern int
+meta_back_single_bind(
+ Operation *op,
+ SlapReply *rs,
+ metaconn_t *mc,
+ int candidate,
+ int massage );
+
extern int
meta_back_dobind(
Operation *op,
metaconn_t *mc,
ldap_back_send_t sendok );
-int
+extern int
meta_back_single_dobind(
Operation *op,
SlapReply *rs,
*/
LDAP_REBIND_PROC *meta_back_rebind_f = meta_back_default_rebind;
-static int
-meta_back_single_bind(
- Operation *op,
- SlapReply *rs,
- metaconn_t *mc,
- int candidate,
- int massage );
-
int
meta_back_bind( Operation *op, SlapReply *rs )
{
*
* attempts to perform a bind with creds
*/
-static int
+int
meta_back_single_bind(
Operation *op,
SlapReply *rs,
switch ( ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) ) {
case 0:
snprintf( buf, sizeof( buf ),
- "ldap_result=0 nretries=%d%s\n",
+ "ldap_result=0 nretries=%d%s",
nretries, rebinding ? " rebinding" : "" );
Debug( LDAP_DEBUG_ANY,
"%s meta_back_single_bind[%d]: %s.\n",
tv = mt->mt_bind_timeout;
goto retry;
}
+
rs->sr_err = LDAP_BUSY;
if ( rebinding ) {
ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
case -1:
ldap_get_option( msc->msc_ld, LDAP_OPT_ERROR_NUMBER,
- &rs->sr_err );
+ &rs->sr_err );
if ( rebinding ) {
ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
/* fallthru */
case -1:
- ldap_get_option( msc->msc_ld,
- LDAP_OPT_ERROR_NUMBER, &rs->sr_err );
+ ldap_get_option( msc->msc_ld, LDAP_OPT_ERROR_NUMBER,
+ &rs->sr_err );
if ( rebinding ) {
ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
for ( i = 0; i < mi->mi_ntargets; i++ ) {
metatarget_t *mt = &mi->mi_targets[ i ];
metasingleconn_t *msc = &mc->mc_conns[ i ];
- int rc;
+ int rc, do_retry = 1;
char *rootdn = NULL;
/*
continue;
}
+retry:;
if ( isroot && !BER_BVISNULL( &mi->mi_targets[ i ].mt_pseudorootdn ) )
{
Operation op2 = *op;
if ( rc != LDAP_SUCCESS ) {
char buf[ SLAP_TEXT_BUFLEN ];
+ if ( rc == LDAP_UNAVAILABLE && do_retry ) {
+ do_retry = 0;
+ if ( meta_back_retry_lock( op, rs, mc, i, LDAP_BACK_DONTSEND, 0 ) ) {
+ goto retry;
+ }
+ }
+
snprintf( buf, sizeof( buf ),
"meta_back_dobind[%d]: (%s) err=%d.",
i, rootdn ? rootdn : "anonymous", rc );
}
/*
- * meta_back_retry
+ * meta_back_retry_lock
*
* Retries one connection
*/
int
-meta_back_retry(
+meta_back_retry_lock(
Operation *op,
SlapReply *rs,
metaconn_t *mc,
int candidate,
- ldap_back_send_t sendok )
+ ldap_back_send_t sendok,
+ int dolock )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metatarget_t *mt = &mi->mi_targets[ candidate ];
if ( mc->mc_refcnt == 1 ) {
char buf[ SLAP_TEXT_BUFLEN ];
- while ( ldap_pvt_thread_mutex_trylock( &mc->mc_mutex ) ) {
+ while ( dolock && ldap_pvt_thread_mutex_trylock( &mc->mc_mutex ) ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
ldap_pvt_thread_yield();
goto retry_lock;
LDAP_BACK_CONN_ISPRIV( mc ), sendok );
if ( rc == LDAP_SUCCESS ) {
- rc = meta_back_single_dobind( op, rs, mc, candidate,
+ if ( be_isroot( op ) && !BER_BVISNULL( &mi->mi_targets[ candidate ].mt_pseudorootdn ) )
+ {
+ Operation op2 = *op;
+
+ op2.o_tag = LDAP_REQ_BIND;
+ op2.o_req_dn = mi->mi_targets[ candidate ].mt_pseudorootdn;
+ op2.o_req_ndn = mi->mi_targets[ candidate ].mt_pseudorootdn;
+ op2.orb_cred = mi->mi_targets[ candidate ].mt_pseudorootpw;
+ op2.orb_method = LDAP_AUTH_SIMPLE;
+
+ rc = meta_back_single_bind( &op2, rs, mc, candidate, 0 );
+
+ } else {
+ rc = meta_back_single_dobind( op, rs, mc, candidate,
sendok, mt->mt_nretries, 0 );
+ }
}
- ldap_pvt_thread_mutex_unlock( &mc->mc_mutex );
+ if ( dolock ) {
+ ldap_pvt_thread_mutex_unlock( &mc->mc_mutex );
+ }
}
if ( rc != LDAP_SUCCESS ) {
exit 0
fi
-if test "x$LVL" = "x0" ; then
- echo "test020 needs a minimal log level; setting to LDAP_DEBUG_NONE..."
- LVL=2048
-fi
-
mkdir -p $TESTDIR $DBDIR1 $DBDIR2
# Test proxy caching:
echo "Starting proxy cache on TCP/IP port $PORT2..."
. $CONFFILTER < $PROXYCACHECONF > $CONF2
-$SLAPD -f $CONF2 -h $URI2 -d $LVL > $LOG2 2>&1 &
+$SLAPD -f $CONF2 -h $URI2 -d $LVL -d trace > $LOG2 2>&1 &
CACHEPID=$!
if test $WAIT != 0 ; then
echo CACHEPID $CACHEPID