util_ldap_connection_t *ldc = param;
if (ldc) {
+ /* Release the rebind info for this connection. No more referral rebinds required. */
+ apr_ldap_rebind_remove(ldc->ldap);
/* unbind and disconnect from the LDAP server */
uldap_connection_unbind(ldc);
APR_LDAP_NONE,
&(result));
-
if (result != NULL && result->rc) {
ldc->reason = result->reason;
}
return(result->rc);
}
+ /* Now that we have an ldap struct, add it to the referral list for rebinds. */
+ rc = apr_ldap_rebind_add(ldc->pool, ldc->ldap, ldc->binddn, ldc->bindpw);
+ if (rc != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ "LDAP: Unable to add rebind cross reference entry. Out of memory?");
+ uldap_connection_unbind(ldc);
+ ldc->reason = "LDAP: Unable to add rebind cross reference entry.";
+ return(rc);
+ }
+
/* always default to LDAP V3 */
ldap_set_option(ldc->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
ldap_option = ldc->deref;
ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &ldap_option);
+ /* Set options for rebind and referrals. */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "LDAP: Setting referrals to %s.",
+ ((ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) ? "On" : "Off"));
+ apr_ldap_set_option(r->pool, ldc->ldap,
+ APR_LDAP_OPT_REFERRALS,
+ (void *)((ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) ?
+ LDAP_OPT_ON : LDAP_OPT_OFF),
+ &(result));
+ if (result->rc != LDAP_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "Unable to set LDAP_OPT_REFERRALS option to %s: %d.",
+ ((ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) ? "On" : "Off"),
+ result->rc);
+ result->reason = "Unable to set LDAP_OPT_REFERRALS.";
+ uldap_connection_unbind(ldc);
+ return(result->rc);
+ }
+
+ if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
+ /* Referral hop limit - only if referrals are enabled */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "Setting referral hop limit to %d.",
+ ldc->ReferralHopLimit);
+ apr_ldap_set_option(r->pool, ldc->ldap,
+ APR_LDAP_OPT_REFHOPLIMIT,
+ (void *)&ldc->ReferralHopLimit,
+ &(result));
+ if (result->rc != LDAP_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "Unable to set LDAP_OPT_REFHOPLIMIT option to %d: %d.",
+ ldc->ReferralHopLimit,
+ result->rc);
+ result->reason = "Unable to set LDAP_OPT_REFHOPLIMIT.";
+ uldap_connection_unbind(ldc);
+ return(result->rc);
+ }
+ }
+
/*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(r->pool, ldc->ldap, APR_LDAP_OPT_VERIFY_CERT,
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(r->server->module_config,
&ldap_module);
-
+ util_ldap_config_t *dc =
+ (util_ldap_config_t *) ap_get_module_config(r->per_dir_config, &ldap_module);
#if APR_HAS_THREADS
/* mutex lock this function */
l->deref = deref;
util_ldap_strdup((char**)&(l->binddn), binddn);
util_ldap_strdup((char**)&(l->bindpw), bindpw);
+ l->ChaseReferrals = dc->ChaseReferrals;
+ l->ReferralHopLimit = dc->ReferralHopLimit;
/* The security mode after parsing the URL will always be either
* APR_LDAP_NONE (ldap://) or APR_LDAP_SSL (ldaps://).
}
/* search for reqdn */
- if (AP_LDAP_IS_SERVER_DOWN(result = ldap_search_ext_s(ldc->ldap, (char *)reqdn, LDAP_SCOPE_BASE,
- "(objectclass=*)", NULL, 1,
- NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &res)))
+ result = ldap_search_ext_s(ldc->ldap, (char *)reqdn, LDAP_SCOPE_BASE,
+ "(objectclass=*)", NULL, 1,
+ NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &res);
+ if (AP_LDAP_IS_SERVER_DOWN(result))
{
ldc->reason = "DN Comparison ldap_search_ext_s() "
"failed with server down";
return result;
}
- if (AP_LDAP_IS_SERVER_DOWN(result = ldap_compare_s(ldc->ldap,
- (char *)dn,
- (char *)attrib,
- (char *)value))) {
+ result = ldap_compare_s(ldc->ldap,
+ (char *)dn,
+ (char *)attrib,
+ (char *)value);
+ if (AP_LDAP_IS_SERVER_DOWN(result)) {
/* connection failed - try again */
ldc->reason = "ldap_compare_s() failed with server down";
uldap_connection_unbind(ldc);
/* ...and entry is valid */
*binddn = apr_pstrdup(r->pool, search_nodep->dn);
if (attrs) {
- int i = 0, k = 0;
- while (attrs[k++]);
- *retvals = apr_pcalloc(r->pool, sizeof(char *) * k);
- while (search_nodep->vals[i]) {
- (*retvals)[i] = apr_pstrdup(r->pool,
- search_nodep->vals[i]);
- i++;
+ int i;
+ *retvals = apr_pcalloc(r->pool, sizeof(char *) * search_nodep->numvals);
+ for (i = 0; i < search_nodep->numvals; i++) {
+ (*retvals)[i] = apr_pstrdup(r->pool, search_nodep->vals[i]);
}
}
LDAP_CACHE_UNLOCK();
}
/* try do the search */
- if (AP_LDAP_IS_SERVER_DOWN(result = ldap_search_ext_s(ldc->ldap,
- (char *)basedn, scope,
- (char *)filter, attrs, 0,
- NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &res)))
+ result = ldap_search_ext_s(ldc->ldap,
+ (char *)basedn, scope,
+ (char *)filter, attrs, 0,
+ NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &res);
+ if (AP_LDAP_IS_SERVER_DOWN(result))
{
ldc->reason = "ldap_search_ext_s() for user failed with server down";
uldap_connection_unbind(ldc);
* fails, it means that the password is wrong (the dn obviously
* exists, since we just retrieved it)
*/
- if (AP_LDAP_IS_SERVER_DOWN(result = ldap_simple_bind_s(ldc->ldap,
- (char *)*binddn,
- (char *)bindpw))) {
+ result = ldap_simple_bind_s(ldc->ldap,
+ (char *)*binddn,
+ (char *)bindpw);
+ if (AP_LDAP_IS_SERVER_DOWN(result)) {
ldc->reason = "ldap_simple_bind_s() to check user credentials "
"failed with server down";
ldap_msgfree(res);
/* ...and entry is valid */
*binddn = apr_pstrdup(r->pool, search_nodep->dn);
if (attrs) {
- int i = 0, k = 0;
- while (attrs[k++]);
- *retvals = apr_pcalloc(r->pool, sizeof(char *) * k);
- while (search_nodep->vals[i]) {
- (*retvals)[i] = apr_pstrdup(r->pool,
- search_nodep->vals[i]);
- i++;
+ int i;
+ *retvals = apr_pcalloc(r->pool, sizeof(char *) * search_nodep->numvals);
+ for (i = 0; i < search_nodep->numvals; i++) {
+ (*retvals)[i] = apr_pstrdup(r->pool, search_nodep->vals[i]);
}
}
LDAP_CACHE_UNLOCK();
}
/* try do the search */
- if (AP_LDAP_IS_SERVER_DOWN(result = ldap_search_ext_s(ldc->ldap,
- (char *)basedn, scope,
- (char *)filter, attrs, 0,
- NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &res)))
+ result = ldap_search_ext_s(ldc->ldap,
+ (char *)basedn, scope,
+ (char *)filter, attrs, 0,
+ NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &res);
+ if (AP_LDAP_IS_SERVER_DOWN(result))
{
ldc->reason = "ldap_search_ext_s() for user failed with server down";
uldap_connection_unbind(ldc);
" timeout to %ld seconds.", getpid(), st->connectionTimeout);
#else
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server,
- "LDAP: Connection timout option not supported by the "
+ "LDAP: Connection timeout option not supported by the "
"LDAP SDK in use." );
#endif
}
+static const char *util_ldap_set_chase_referrals(cmd_parms *cmd,
+ void *config,
+ int mode)
+{
+ util_ldap_config_t *dc = config;
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
+ "LDAP: Setting refferal chasing %s",
+ (mode == AP_LDAP_CHASEREFERRALS_ON) ? "ON" : "OFF");
+
+ dc->ChaseReferrals = mode;
+
+ return(NULL);
+}
+
+static const char *util_ldap_set_referral_hop_limit(cmd_parms *cmd,
+ void *config,
+ const char *hop_limit)
+{
+ util_ldap_config_t *dc = config;
+
+ dc->ReferralHopLimit = atol(hop_limit);
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
+ "LDAP: Limit chased referrals to maximum of %d hops.",
+ dc->ReferralHopLimit);
+
+ return NULL;
+}
+
+static void *util_ldap_create_dir_config(apr_pool_t *p, char *d) {
+ util_ldap_config_t *dc =
+ (util_ldap_config_t *) apr_pcalloc(p,sizeof(util_ldap_config_t));
+
+ /* defaults are AP_LDAP_CHASEREFERRALS_ON and AP_LDAP_DEFAULT_HOPLIMIT */
+ dc->ChaseReferrals = AP_LDAP_CHASEREFERRALS_ON;
+ dc->ReferralHopLimit = AP_LDAP_DEFAULT_HOPLIMIT;
+
+ return dc;
+}
+
+
static void *util_ldap_create_config(apr_pool_t *p, server_rec *s)
{
util_ldap_state_t *st =
st->connectionTimeout = 10;
st->verify_svr_cert = 1;
+ /* Initialize the rebind callback's cross reference list. */
+ apr_ldap_rebind_init (p);
+
return st;
}
AP_INIT_TAKE23("LDAPTrustedGlobalCert", util_ldap_set_trusted_global_cert,
NULL, RSRC_CONF,
- "Takes three args; the file and/or directory containing "
- "the trusted CA certificates (and global client certs "
- "for Netware) used to validate the LDAP server. Second "
- "arg is the cert type for the first arg, one of CA_DER, "
- "CA_BASE64, CA_CERT7_DB, CA_SECMOD, CERT_DER, CERT_BASE64, "
- "CERT_KEY3_DB, CERT_NICKNAME, KEY_DER, or KEY_BASE64. "
- "Third arg is an optional passphrase if applicable."),
+ "Takes three arguments; the first argument is the cert "
+ "type of the second argument, one of CA_DER, CA_BASE64, "
+ "CA_CERT7_DB, CA_SECMOD, CERT_DER, CERT_BASE64, CERT_KEY3_DB, "
+ "CERT_NICKNAME, KEY_DER, or KEY_BASE64. The second argument "
+ "specifes the file and/or directory containing the trusted CA "
+ "certificates (and global client certs for Netware) used to "
+ "validate the LDAP server. The third argument is an optional "
+ "passphrase if applicable."),
AP_INIT_TAKE23("LDAPTrustedClientCert", util_ldap_set_trusted_client_cert,
NULL, RSRC_CONF,
- "Takes three args; the file and/or directory containing "
- "the client certificate, or certificate ID used to "
- "validate this LDAP client. Second arg is the cert type "
- "for the first arg, one of CA_DER, CA_BASE64, CA_CERT7_DB, "
- "CA_SECMOD, CERT_DER, CERT_BASE64, CERT_KEY3_DB, "
- "CERT_NICKNAME, KEY_DER, or KEY_BASE64. Third arg is an "
- "optional passphrase if applicable."),
+ "Takes three arguments: the first argument is the certificate "
+ "type of the second argument, one of CA_DER, CA_BASE64, "
+ "CA_CERT7_DB, CA_SECMOD, CERT_DER, CERT_BASE64, CERT_KEY3_DB, "
+ "CERT_NICKNAME, KEY_DER, or KEY_BASE64. The second argument "
+ "specifies the file and/or directory containing the client "
+ "certificate, or certificate ID used to validate this LDAP "
+ "client. The third argument is an optional passphrase if "
+ "applicable."),
AP_INIT_TAKE1("LDAPTrustedMode", util_ldap_set_trusted_mode,
NULL, RSRC_CONF,
"Specify the LDAP socket connection timeout in seconds "
"(default: 10)"),
+ AP_INIT_FLAG("LDAPReferrals", util_ldap_set_chase_referrals,
+ NULL, OR_AUTHCFG,
+ "Choose whether referrals are chased ['ON'|'OFF']. Default 'ON'"),
+
+ AP_INIT_TAKE1("LDAPReferralHopLimit", util_ldap_set_referral_hop_limit,
+ NULL, OR_AUTHCFG,
+ "Limit the number of referral hops that LDAP can follow. "
+ "(Integer value, default=" AP_LDAP_DEFAULT_HOPLIMIT_STR ")"),
+
{NULL}
};
module AP_MODULE_DECLARE_DATA ldap_module = {
STANDARD20_MODULE_STUFF,
- NULL, /* create dir config */
+ util_ldap_create_dir_config, /* create dir config */
NULL, /* merge dir config */
util_ldap_create_config, /* create server config */
util_ldap_merge_config, /* merge server config */