From 112be0118e43c161d44de6e852cca9f517bb653d Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sat, 24 Sep 2005 18:39:26 +0000 Subject: [PATCH] cleanup states/timeout handling in back-ldap/meta; add connection pooling and defer of pseudoroot bind to back-meta --- servers/slapd/back-ldap/back-ldap.h | 65 ++++- servers/slapd/back-ldap/bind.c | 376 ++++++++++++++------------- servers/slapd/back-ldap/proto-ldap.h | 2 + servers/slapd/back-ldap/search.c | 6 +- servers/slapd/back-ldap/unbind.c | 2 +- servers/slapd/back-meta/back-meta.h | 21 +- servers/slapd/back-meta/bind.c | 228 ++++++++++++---- servers/slapd/back-meta/candidates.c | 1 + servers/slapd/back-meta/compare.c | 5 +- servers/slapd/back-meta/config.c | 90 +++++-- servers/slapd/back-meta/conn.c | 178 ++++++++++--- servers/slapd/back-meta/search.c | 4 +- servers/slapd/back-meta/unbind.c | 5 +- 13 files changed, 664 insertions(+), 319 deletions(-) diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index 828b55261e..787a27db98 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -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" diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index 0df5202bed..93f5cff445 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -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 diff --git a/servers/slapd/back-ldap/proto-ldap.h b/servers/slapd/back-ldap/proto-ldap.h index 1a812f3d87..80600e391c 100644 --- a/servers/slapd/back-ldap/proto-ldap.h +++ b/servers/slapd/back-ldap/proto-ldap.h @@ -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 */ diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 213de64871..45bc2e9152 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -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 */ diff --git a/servers/slapd/back-ldap/unbind.c b/servers/slapd/back-ldap/unbind.c index 17d0bb763b..e097d0ae7a 100644 --- a/servers/slapd/back-ldap/unbind.c +++ b/servers/slapd/back-ldap/unbind.c @@ -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 ); diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index df9bfdf023..5a7f92e1c2 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -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 */ -#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 */ diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index eb25c58fe0..17dab2f397 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -34,7 +34,12 @@ #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, diff --git a/servers/slapd/back-meta/candidates.c b/servers/slapd/back-meta/candidates.c index aa8c7628df..1254a26184 100644 --- a/servers/slapd/back-meta/candidates.c +++ b/servers/slapd/back-meta/candidates.c @@ -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 ); } diff --git a/servers/slapd/back-meta/compare.c b/servers/slapd/back-meta/compare.c index 82d407fe73..65fdde05f0 100644 --- a/servers/slapd/back-meta/compare.c +++ b/servers/slapd/back-meta/compare.c @@ -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; diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index 143bbe573a..1c596de133 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -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 ? diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index a0ae280124..0c8d140166 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -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; diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 3dec260d23..0847a92638 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -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 { diff --git a/servers/slapd/back-meta/unbind.c b/servers/slapd/back-meta/unbind.c index 93a694b02b..ed4bc96e30 100644 --- a/servers/slapd/back-meta/unbind.c +++ b/servers/slapd/back-meta/unbind.c @@ -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 ] ); -- 2.39.5