util_ldap.c revision 1f299703465bd9975d94e9f229f76af807442de2
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht/* Licensed to the Apache Software Foundation (ASF) under one or more
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * contributor license agreements. See the NOTICE file distributed with
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * this work for additional information regarding copyright ownership.
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * The ASF licenses this file to You under the Apache License, Version 2.0
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu * (the "License"); you may not use this file except in compliance with
2643008447e30b6025f742eb6a661f38be756b1eSimon Ulbricht * the License. You may obtain a copy of the License at
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * Unless required by applicable law or agreed to in writing, software
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * distributed under the License is distributed on an "AS IS" BASIS,
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * See the License for the specific language governing permissions and
2643008447e30b6025f742eb6a661f38be756b1eSimon Ulbricht * limitations under the License.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Original code from auth_ldap module for Apache v1.3:
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Copyright 1998, 1999 Enbridge Pipelines Inc.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Copyright 1999-2001 Dave Carrigan
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht#error mod_ldap requires APR-util to have LDAP support built in
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* Default define for ldap functions that need a SIZELIMIT but
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * do not have the define
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * XXX This should be removed once a supporting #define is
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * released through APR-Util.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht apr_global_mutex_lock(st->util_ldap_cache_lock); \
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht apr_global_mutex_unlock(st->util_ldap_cache_lock); \
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic void util_ldap_strdup (char **str, const char *newstr)
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Status Handler
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * --------------
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * This handler generates a status page about the current performance of
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * the LDAP cache. It is enabled as follows:
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * <Location /ldap-status>
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * SetHandler ldap-status
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * </Location>
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht util_ldap_state_t *st = (util_ldap_state_t *)
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht ap_get_module_config(r->server->module_config,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht "<html><head><title>LDAP Cache Information</title></head>\n", r);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht ap_rputs("<body bgcolor='#ffffff'><h1 align=center>LDAP Cache Information"
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht "</h1>\n", r);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* ------------------------------------------------------------------ */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Closes an LDAP connection by unlocking it. The next time
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * uldap_connection_find() is called this connection will be
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * available for reuse.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic void uldap_connection_close(util_ldap_connection_t *ldc)
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Is it safe leaving bound connections floating around between the
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * different modules? Keeping the user bound is a performance boost,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * but it is also a potential security problem - maybe.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * For now we unbind the user when we finish with a connection, but
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * we don't have to...
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* mark our connection as available for reuse */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Destroys an LDAP connection by unbinding and closing the connection to
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * the LDAP server. It is used to bring the connection back to a known
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * state after an error, and during pool cleanup.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic apr_status_t uldap_connection_unbind(void *param)
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Clean up an LDAP connection by unbinding and unlocking the connection.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic apr_status_t uldap_connection_cleanup(void *param)
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* unbind and disconnect from the LDAP server */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* free the username and password */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* unlock this entry */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic int uldap_connection_init(request_rec *r,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht struct timeval timeOut = {10,0}; /* 10 second connection timeout */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* Since the host will include a port if the default port is not used,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * always specify the default ports for the port parameter. This will
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * allow a host string that contains multiple hosts the ability to mix
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * some hosts with ports and some without. All hosts which do not
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * specify a port will use the default port.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht APR_LDAP_SSL == ldc->secure ? LDAPS_PORT : LDAP_PORT,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht ldc->reason = "LDAP: ldap initialization failed";
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* always default to LDAP V3 */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht ldap_set_option(ldc->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* set client certificates */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht if (!apr_is_empty_array(ldc->client_certs)) {
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht apr_ldap_set_option(r->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* switch on SSL/TLS */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* Set the alias dereferencing option */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &ldap_option);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/*XXX All of the #ifdef's need to be removed once apr-util 1.2 is released */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht APR_LDAP_OPT_VERIFY_CERT, &(st->verify_svr_cert), &(result));
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_SERVER);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_NONE);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* This is not a per-connection setting so just pass NULL for the
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht Ldap connection handle */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
dff3a9487508aa2818afddb29bad1b3314e5e2a6Simon Ulbricht result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht rc = apr_ldap_set_option(r->pool, ldc->ldap, LDAP_OPT_NETWORK_TIMEOUT,
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht "LDAP: Could not set the connection timeout");
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht * Connect to the LDAP server and binds. Does not connect if already
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht * connected (i.e. ldc->ldap is non-NULL.) Does not bind if already bound.
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht * Returns LDAP_SUCCESS on success; and an error code on failure
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbrichtstatic int uldap_connection_open(request_rec *r,
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht /* sanity check for NULL */
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht /* If the connection is already bound, return
98e4e0125755acbcd5e0729556cd2bcfc4ee3973Simon Ulbricht ldc->reason = "LDAP: connection open successful (already bound)";
212a71a59d30f82bc1d22cc9cfd6b36968afb4f2Simon Ulbricht /* create the ldap session handle
return rc;
return(rc);
static util_ldap_connection_t *
&ldap_module);
#if APR_HAS_THREADS
#if APR_HAS_THREADS
#if APR_HAS_THREADS
#if APR_HAS_THREADS
l->bound = 0;
#if APR_HAS_THREADS
#if APR_HAS_THREADS
return NULL;
#if APR_HAS_THREADS
l->bound = 0;
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;
== LDAP_SERVER_DOWN)
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))
== LDAP_SERVER_DOWN) {
goto start_over;
if (curl) {
void *junk;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "[%" APR_PID_T_FMT "] cache_compare: Cache insertion failure.", getpid());
return LDAP_COMPARE_TRUE;
return LDAP_COMPARE_FALSE;
return LDAP_NO_SUCH_ATTRIBUTE;
return result;
int failures = 0;
&ldap_module);
int base_sgcIndex = 0;
int lcl_sgl_processedFlag = 0;
struct mod_auth_ldap_groupattr_entry_t *sgc_ents = (struct mod_auth_ldap_groupattr_entry_t *) subgroupclasses->elts;
return result;
return LDAP_COMPARE_FALSE;
tmp_local_sgl->subgroupDNs = apr_pcalloc(r->pool, sizeof(char *) * compare_nodep->subgroupList->len);
return LDAP_COMPARE_FALSE;
return result;
return result;
goto start_over;
return result;
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 LDAP_COMPARE_FALSE;
if (tmp_local_sgl) {
if (tmp_local_sgl) {
int sgindex = 0;
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) {
while (attrs[k++]);
return LDAP_SUCCESS;
return result;
return result;
== LDAP_SERVER_DOWN)
goto start_over;
return result;
if (count == 0 )
return LDAP_NO_SUCH_OBJECT;
return LDAP_INVALID_CREDENTIALS;
(char *)*binddn,
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) {
while (attrs[k++]);
return LDAP_SUCCESS;
return result;
return result;
== LDAP_SERVER_DOWN)
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)
&ldap_module);
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)
&ldap_module);
return err;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
return NULL;
#if APR_HAS_THREADS
return st;
void *overridesv)
#if APR_HAS_THREADS
return st;
return APR_SUCCESS;
&ldap_module);
void *data;
int rc;
if (!data) {
NULL);
return OK;
return DONE;
NULL);
return result;
#ifdef AP_NEED_SET_MUTEX_PERMS
return result;
while (s_vhost) {
&ldap_module);
NULL,
&(result_err));
return(OK);
&ldap_module);
{NULL}