Return-Path: Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: (qmail 51353 invoked from network); 8 Nov 2006 20:44:19 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 8 Nov 2006 20:44:19 -0000 Received: (qmail 53994 invoked by uid 500); 8 Nov 2006 20:44:27 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 53903 invoked by uid 500); 8 Nov 2006 20:44:26 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 53853 invoked by uid 99); 8 Nov 2006 20:44:26 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Nov 2006 12:44:26 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Nov 2006 12:44:14 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id EDBE91A984A; Wed, 8 Nov 2006 12:43:46 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r472633 - /httpd/httpd/trunk/modules/ldap/util_ldap.c Date: Wed, 08 Nov 2006 20:43:46 -0000 To: cvs@httpd.apache.org From: bnicholes@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20061108204346.EDBE91A984A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: bnicholes Date: Wed Nov 8 12:43:46 2006 New Revision: 472633 URL: http://svn.apache.org/viewvc?view=rev&rev=472633 Log: Better detection and clean up of ldap connection that have been terminated by the ldap server. PR#40878 Submitted by: Rob Baily Reviewed by: bnicholes Modified: httpd/httpd/trunk/modules/ldap/util_ldap.c Modified: httpd/httpd/trunk/modules/ldap/util_ldap.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ldap/util_ldap.c?view=diff&rev=472633&r1=472632&r2=472633 ============================================================================== --- httpd/httpd/trunk/modules/ldap/util_ldap.c (original) +++ httpd/httpd/trunk/modules/ldap/util_ldap.c Wed Nov 8 12:43:46 2006 @@ -199,18 +199,10 @@ return APR_SUCCESS; } - -/* - * Connect to the LDAP server and binds. Does not connect if already - * connected (i.e. ldc->ldap is non-NULL.) Does not bind if already bound. - * - * Returns LDAP_SUCCESS on success; and an error code on failure - */ -static int uldap_connection_open(request_rec *r, - util_ldap_connection_t *ldc) +static int uldap_connection_init(request_rec *r, + util_ldap_connection_t *ldc ) { int rc = 0; - int failures = 0; int version = LDAP_VERSION3; apr_ldap_err_t *result = NULL; struct timeval timeOut = {10,0}; /* 10 second connection timeout */ @@ -218,126 +210,141 @@ (util_ldap_state_t *)ap_get_module_config(r->server->module_config, &ldap_module); - /* sanity check for NULL */ - if (!ldc) { - return -1; - } + /* Since the host will include a port if the default port is not used, + * always specify the default ports for the port parameter. This will + * allow a host string that contains multiple hosts the ability to mix + * some hosts with ports and some without. All hosts which do not + * specify a port will use the default port. + */ + apr_ldap_init(ldc->pool, &(ldc->ldap), + ldc->host, + APR_LDAP_SSL == ldc->secure ? LDAPS_PORT : LDAP_PORT, + APR_LDAP_NONE, + &(result)); - /* If the connection is already bound, return - */ - if (ldc->bound) - { - ldc->reason = "LDAP: connection open successful (already bound)"; - return LDAP_SUCCESS; + + if (result != NULL && result->rc) { + ldc->reason = result->reason; } - /* create the ldap session handle - */ if (NULL == ldc->ldap) { - /* Since the host will include a port if the default port is not used, - * always specify the default ports for the port parameter. This will - * allow a host string that contains multiple hosts the ability to mix - * some hosts with ports and some without. All hosts which do not - * specify a port will use the default port. - */ - apr_ldap_init(ldc->pool, &(ldc->ldap), - ldc->host, - APR_LDAP_SSL == ldc->secure ? LDAPS_PORT : LDAP_PORT, - APR_LDAP_NONE, - &(result)); - - - if (result != NULL && result->rc) { - ldc->reason = result->reason; + ldc->bound = 0; + if (NULL == ldc->reason) { + ldc->reason = "LDAP: ldap initialization failed"; } - - if (NULL == ldc->ldap) - { - ldc->bound = 0; - if (NULL == ldc->reason) { - ldc->reason = "LDAP: ldap initialization failed"; - } - else { - ldc->reason = result->reason; - } - return(result->rc); + else { + ldc->reason = result->reason; } + return(result->rc); + } - /* always default to LDAP V3 */ - ldap_set_option(ldc->ldap, LDAP_OPT_PROTOCOL_VERSION, &version); + /* always default to LDAP V3 */ + ldap_set_option(ldc->ldap, LDAP_OPT_PROTOCOL_VERSION, &version); - /* set client certificates */ - if (!apr_is_empty_array(ldc->client_certs)) { - apr_ldap_set_option(ldc->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT, - ldc->client_certs, &(result)); - if (LDAP_SUCCESS != result->rc) { - ldap_unbind_s(ldc->ldap); - ldc->ldap = NULL; - ldc->bound = 0; - ldc->reason = result->reason; - return(result->rc); - } + /* set client certificates */ + if (!apr_is_empty_array(ldc->client_certs)) { + apr_ldap_set_option(ldc->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT, + ldc->client_certs, &(result)); + if (LDAP_SUCCESS != result->rc) { + uldap_connection_unbind( ldc ); + ldc->reason = result->reason; + return(result->rc); } + } - /* switch on SSL/TLS */ - if (APR_LDAP_NONE != ldc->secure) { - apr_ldap_set_option(ldc->pool, ldc->ldap, - APR_LDAP_OPT_TLS, &ldc->secure, &(result)); - if (LDAP_SUCCESS != result->rc) { - ldap_unbind_s(ldc->ldap); - ldc->ldap = NULL; - ldc->bound = 0; - ldc->reason = result->reason; - return(result->rc); - } + /* switch on SSL/TLS */ + if (APR_LDAP_NONE != ldc->secure) { + apr_ldap_set_option(ldc->pool, ldc->ldap, + APR_LDAP_OPT_TLS, &ldc->secure, &(result)); + if (LDAP_SUCCESS != result->rc) { + uldap_connection_unbind( ldc ); + ldc->reason = result->reason; + return(result->rc); } + } - /* Set the alias dereferencing option */ - ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &(ldc->deref)); + /* Set the alias dereferencing option */ + ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &(ldc->deref)); /*XXX All of the #ifdef's need to be removed once apr-util 1.2 is released */ #ifdef APR_LDAP_OPT_VERIFY_CERT - apr_ldap_set_option(ldc->pool, ldc->ldap, - APR_LDAP_OPT_VERIFY_CERT, &(st->verify_svr_cert), &(result)); + apr_ldap_set_option(ldc->pool, ldc->ldap, + APR_LDAP_OPT_VERIFY_CERT, &(st->verify_svr_cert), &(result)); #else #if defined(LDAPSSL_VERIFY_SERVER) - if (st->verify_svr_cert) { - result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_SERVER); - } - else { - result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_NONE); - } + if (st->verify_svr_cert) { + result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_SERVER); + } + else { + result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_NONE); + } #elif defined(LDAP_OPT_X_TLS_REQUIRE_CERT) - /* This is not a per-connection setting so just pass NULL for the - Ldap connection handle */ - if (st->verify_svr_cert) { - int i = LDAP_OPT_X_TLS_DEMAND; - result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i); - } - else { - int i = LDAP_OPT_X_TLS_NEVER; - result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i); - } + /* This is not a per-connection setting so just pass NULL for the + Ldap connection handle */ + if (st->verify_svr_cert) { + int i = LDAP_OPT_X_TLS_DEMAND; + result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i); + } + else { + int i = LDAP_OPT_X_TLS_NEVER; + result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i); + } #endif #endif #ifdef LDAP_OPT_NETWORK_TIMEOUT - if (st->connectionTimeout > 0) { - timeOut.tv_sec = st->connectionTimeout; - } + if (st->connectionTimeout > 0) { + timeOut.tv_sec = st->connectionTimeout; + } - if (st->connectionTimeout >= 0) { - rc = apr_ldap_set_option(ldc->pool, ldc->ldap, LDAP_OPT_NETWORK_TIMEOUT, - (void *)&timeOut, &(result)); - if (APR_SUCCESS != rc) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, - "LDAP: Could not set the connection timeout"); - } + if (st->connectionTimeout >= 0) { + rc = apr_ldap_set_option(ldc->pool, ldc->ldap, LDAP_OPT_NETWORK_TIMEOUT, + (void *)&timeOut, &(result)); + if (APR_SUCCESS != rc) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "LDAP: Could not set the connection timeout"); } + } #endif + return(rc); +} + +/* + * Connect to the LDAP server and binds. Does not connect if already + * connected (i.e. ldc->ldap is non-NULL.) Does not bind if already bound. + * + * Returns LDAP_SUCCESS on success; and an error code on failure + */ +static int uldap_connection_open(request_rec *r, + util_ldap_connection_t *ldc) +{ + int rc = 0; + int failures = 0; + + /* sanity check for NULL */ + if (!ldc) { + return -1; + } + /* If the connection is already bound, return + */ + if (ldc->bound) + { + ldc->reason = "LDAP: connection open successful (already bound)"; + return LDAP_SUCCESS; + } + + /* create the ldap session handle + */ + if (NULL == ldc->ldap) + { + rc = uldap_connection_init( r, ldc ); + if (LDAP_SUCCESS != rc) + { + return rc; + } } @@ -356,16 +363,22 @@ (char *)ldc->bindpw); if (LDAP_SERVER_DOWN != rc) { break; - } + } else if (failures == 5) { + /* attempt to init the connection once again */ + uldap_connection_unbind( ldc ); + rc = uldap_connection_init( r, ldc ); + if (LDAP_SUCCESS != rc) + { + break; + } + } } /* free the handle if there was an error */ if (LDAP_SUCCESS != rc) { - ldap_unbind_s(ldc->ldap); - ldc->ldap = NULL; - ldc->bound = 0; + uldap_connection_unbind(ldc); ldc->reason = "LDAP: ldap_simple_bind_s() failed"; } else {