util_ldap.c revision 97cd2f98ad4abe68aaaba96b5bfc9ebf7109a2c1
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/* Licensed to the Apache Software Foundation (ASF) under one or more
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * contributor license agreements. See the NOTICE file distributed with
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * this work for additional information regarding copyright ownership.
5f5d1b4cc970b7f06ff8ef6526128e9a27303d88nd * The ASF licenses this file to You under the Apache License, Version 2.0
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * (the "License"); you may not use this file except in compliance with
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * the License. You may obtain a copy of the License at
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * Unless required by applicable law or agreed to in writing, software
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * distributed under the License is distributed on an "AS IS" BASIS,
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * See the License for the specific language governing permissions and
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * limitations under the License.
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * util_ldap.c: LDAP things
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * Original code from auth_ldap module for Apache v1.3:
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * Copyright 1998, 1999 Enbridge Pipelines Inc.
7db9f691a00ead175b03335457ca296a33ddf31bnd * Copyright 1999-2001 Dave Carrigan
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive#error mod_ldap requires APR-util to have LDAP support built in
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive/* Default define for ldap functions that need a SIZELIMIT but
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * do not have the define
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * XXX This should be removed once a supporting #define is
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * released through APR-Util.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#if !defined(LDAP_OPT_NETWORK_TIMEOUT) && defined(LDAP_OPT_CONNECT_TIMEOUT)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define LDAP_OPT_NETWORK_TIMEOUT LDAP_OPT_CONNECT_TIMEOUT
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic const char *ldap_cache_mutex_type = "ldap-cache";
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic apr_status_t uldap_connection_unbind(void *param);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define LDAP_CACHE_LOCK() do { \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define LDAP_CACHE_UNLOCK() do { \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele apr_global_mutex_unlock(st->util_ldap_cache_lock); \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic void util_ldap_strdup (char **str, const char *newstr)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Status Handler
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * --------------
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * This handler generates a status page about the current performance of
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * the LDAP cache. It is enabled as follows:
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * <Location /ldap-status>
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * SetHandler ldap-status
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * </Location>
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele st = (util_ldap_state_t *) ap_get_module_config(r->server->module_config,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_set_content_type(r, "text/html; charset=ISO-8859-1");
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "<html><head><title>LDAP Cache Information</title></head>\n", r);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_rputs("<body bgcolor='#ffffff'><h1 align=center>LDAP Cache Information"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "</h1>\n", r);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/* ------------------------------------------------------------------ */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Closes an LDAP connection by unlocking it. The next time
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * uldap_connection_find() is called this connection will be
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * available for reuse.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic void uldap_connection_close(util_ldap_connection_t *ldc)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* We leave bound LDAP connections floating around in our pool,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * but always check/fix the binddn/bindpw when we take them out
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * of the pool
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* mark our connection as available for reuse */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Destroys an LDAP connection by unbinding and closing the connection to
5d7e5de2da57434c8e68c8fa49cbf6d70ee0f817slive * the LDAP server. It is used to bring the connection back to a known
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * state after an error.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic apr_status_t uldap_connection_unbind(void *param)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* forget the rebind info for this conn */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/* not presently used, not part of the API */
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * util_ldap_connection_remove frees all storage associated with the LDAP
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * connection and removes it completely from the per-virtualhost list of
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * connections
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * The caller should hold the lock for this connection
a3388213b2b4d46b356be205e38204e67b4304d8rbowenstatic apr_status_t util_ldap_connection_remove (void *param) {
d94fadc8231669a4e710869f290ed57a8232a61drbowen util_ldap_connection_t *ldc = param, *l = NULL, *prev = NULL;
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Remove ldc from the list */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (l == ldc) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Destory the pool associated with this connection */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele struct timeval connectionTimeout = {10,0}; /* 10 second connection timeout */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Since the host will include a port if the default port is not used,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * always specify the default ports for the port parameter. This will
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * allow a host string that contains multiple hosts the ability to mix
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * some hosts with ports and some without. All hosts which do not
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * specify a port will use the default port.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele APR_LDAP_SSL == ldc->secure ? LDAPS_PORT : LDAP_PORT,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* something really bad happened */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Now that we have an ldap struct, add it to the referral list for rebinds. */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele rc = apr_ldap_rebind_add(ldc->rebind_pool, ldc->ldap, ldc->binddn, ldc->bindpw);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "LDAP: Unable to add rebind cross reference entry. Out of memory?");
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ldc->reason = "LDAP: Unable to add rebind cross reference entry.";
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* always default to LDAP V3 */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ldap_set_option(ldc->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* set client certificates */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele apr_ldap_set_option(r->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* switch on SSL/TLS */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Set the alias dereferencing option */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &ldap_option);
&(result));
if ((ldc->ReferralHopLimit != AP_LDAP_HOPLIMIT_UNSET) && ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
&(result));
#ifdef APR_LDAP_OPT_VERIFY_CERT
#if defined(LDAPSSL_VERIFY_SERVER)
int i = LDAP_OPT_X_TLS_DEMAND;
int i = LDAP_OPT_X_TLS_NEVER;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
#ifdef LDAP_OPT_TIMEOUT
return(rc);
int rc;
int ldaprc;
#ifdef LDAP_OPT_ERROR_NUMBER
#ifdef LDAP_OPT_RESULT_CODE
return LDAP_OTHER;
else if (rc == 0) {
return rc;
int rc = 0;
int failures = 0;
int new_connection = 0;
if (!ldc) {
return LDAP_SUCCESS;
return rc;
&ldap_module);
failures++;
return(rc);
static util_ldap_connection_t *
&ldap_module);
#if APR_HAS_THREADS
#if APR_HAS_THREADS
/* Go ahead (by falling through) and use it, so we don't create more just to unbind some other old ones */
#if APR_HAS_THREADS
#if APR_HAS_THREADS
#if APR_HAS_THREADS
#if APR_HAS_THREADS
return NULL;
#if APR_HAS_THREADS
l->bound = 0;
#if APR_HAS_THREADS
return NULL;
p->next = l;
#if APR_HAS_THREADS
int result = 0;
int failures = 0;
char *searchdn;
&ldap_module);
if (!compare_dn_on_server) {
return LDAP_COMPARE_FALSE;
return LDAP_COMPARE_TRUE;
if (curl) {
return LDAP_COMPARE_TRUE;
return result;
return result;
failures++;
goto start_over;
failures++;
goto start_over;
return result;
if (curl) {
return result;
int result = 0;
int failures = 0;
&ldap_module);
if (curl) {
return result;
return result;
return result;
(char *)dn,
(char *)attrib,
(char *)value);
failures++;
goto start_over;
failures++;
goto start_over;
if (curl) {
void *junk;
return LDAP_COMPARE_TRUE;
return LDAP_COMPARE_FALSE;
return LDAP_NO_SUCH_ATTRIBUTE;
return result;
const char *url,
const char *dn,
char **subgroupAttrs,
int failures = 0;
&ldap_module);
if (!subgroupAttrs) {
return res;
return res;
return res;
failures++;
goto start_over;
failures++;
goto start_over;
return res;
if (subgroupAttrs) {
char **values;
int val_index = 0;
if (values) {
val_index = 0;
tmp_sgcIndex = 0;
tmp_sgcIndex++;
val_index++;
indx++;
int sgindex;
char **group;
return res;
char **subgroupAttrs,
int cur_subgroup_depth,
int max_subgroup_depth)
&ldap_module);
return LDAP_COMPARE_FALSE;
return result;
sizeof(util_compare_subgroup_t));
if (!tmp_local_sgl) {
dn);
dn);
if (!tmp_local_sgl) {
if (sgl_copy) {
if (!tmp_local_sgl) {
return result;
sgindex++;
return result;
const char ***retvals)
int numvals = 0;
int result = 0;
char *dn;
int count;
int failures = 0;
&ldap_module);
&curnode);
if (curl) {
if (attrs) {
return LDAP_SUCCESS;
return result;
return result;
failures++;
goto start_over;
return result;
if (count == 0 )
return LDAP_NO_SUCH_OBJECT;
return LDAP_INVALID_CREDENTIALS;
failures++;
goto start_over;
return result;
if (attrs) {
while (attrs[k++]);
numvals = k;
while (attrs[i]) {
char **values;
if (curl) {
return LDAP_SUCCESS;
int numvals = 0;
int result = 0;
char *dn;
int count;
int failures = 0;
&ldap_module);
&curnode);
if (curl) {
if (attrs) {
return LDAP_SUCCESS;
return result;
return result;
failures++;
goto start_over;
return result;
if (count == 0 )
return LDAP_NO_SUCH_OBJECT;
if (attrs) {
while (attrs[k++]);
numvals = k;
while (attrs[i]) {
char **values;
if (curl) {
return LDAP_SUCCESS;
const char *bytes)
&ldap_module);
return err;
return NULL;
const char *file)
&ldap_module);
return err;
if (file) {
return NULL;
const char *ttl)
&ldap_module);
return err;
return NULL;
const char *size)
&ldap_module);
return err;
return NULL;
const char *ttl)
&ldap_module);
return err;
return NULL;
const char *size)
&ldap_module);
return err;
return NULL;
return APR_LDAP_CA_TYPE_DER;
return APR_LDAP_CA_TYPE_BASE64;
return APR_LDAP_CA_TYPE_CERT7_DB;
return APR_LDAP_CA_TYPE_SECMOD;
return APR_LDAP_CERT_TYPE_DER;
return APR_LDAP_CERT_TYPE_BASE64;
return APR_LDAP_CERT_TYPE_PFX;
return APR_LDAP_CERT_TYPE_KEY3_DB;
return APR_LDAP_CERT_TYPE_NICKNAME;
return APR_LDAP_KEY_TYPE_DER;
return APR_LDAP_KEY_TYPE_BASE64;
return APR_LDAP_KEY_TYPE_PFX;
return APR_LDAP_CA_TYPE_UNKNOWN;
void *dummy,
const char *type,
const char *file,
const char *password)
&ldap_module);
int cert_type = 0;
return err;
if (type) {
!= APR_SUCCESS))
return(NULL);
void *config,
const char *type,
const char *file,
const char *password)
int cert_type = 0;
if (type) {
type);
!= APR_SUCCESS))
return(NULL);
const char *mode)
&ldap_module);
mode);
return(NULL);
void *dummy,
int mode)
&ldap_module);
return err;
return(NULL);
void *dummy,
const char *ttl)
#ifdef LDAP_OPT_NETWORK_TIMEOUT
&ldap_module);
return err;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
return NULL;
void *config,
int mode)
return(NULL);
void *config,
const char *arg) {
#ifdef AP_LDAP_OPT_DEBUG
&ldap_module);
return err;
#ifndef AP_LDAP_OPT_DEBUG
return NULL;
void *config,
const char *hop_limit)
return "LDAPReferralHopLimit must be greater than zero (Use 'LDAPReferrals Off' to disable referral chasing)";
return NULL;
return dc;
void *dummy,
const char *val)
long timeout;
char *endptr;
&ldap_module);
return err;
if (timeout < 0) {
if (timeout) {
timeout);
#ifndef LDAP_OPT_TIMEOUT
return NULL;
void *dummy,
const char *val)
&ldap_module);
if (timeout < 0) {
return NULL;
void *dummy,
const char *val)
&ldap_module);
return err;
if (timeout < 0) {
return NULL;
void *dummy,
const char *val)
&ldap_module);
return err;
if (val < 0) {
return NULL;
#if APR_HAS_THREADS
return st;
void *overridesv)
#if APR_HAS_THREADS
return st;
return APR_SUCCESS;
APR_LOCK_DEFAULT, 0);
return result;
return OK;
&ldap_module);
int rc;
NULL);
return OK;
return DONE;
return result;
while (s_vhost) {
&ldap_module);
NULL,
&(result_err));
apr_ldap_rebind_init (p);
#ifdef AP_LDAP_OPT_DEBUG
return(OK);
&ldap_module);
{NULL}