util_ldap.c revision 0894cd17fe3f614bf01dbf84f1414756bd5a34c3
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/* Copyright 2001-2004 The Apache Software Foundation
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Licensed under the Apache License, Version 2.0 (the "License");
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * you may not use this file except in compliance with the License.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * You may obtain a copy of the License at
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Unless required by applicable law or agreed to in writing, software
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * distributed under the License is distributed on an "AS IS" BASIS,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * See the License for the specific language governing permissions and
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * limitations under the License.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * util_ldap.c: LDAP things
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Original code from auth_ldap module for Apache v1.3:
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Copyright 1998, 1999 Enbridge Pipelines Inc.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Copyright 1999-2001 Dave Carrigan
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#error mod_ldap requires APR-util to have LDAP support built in
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* defines for certificate file types
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelevoid *util_ldap_create_config(apr_pool_t *p, server_rec *s);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Some definitions to help between various versions of apache.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define DOCTYPE_HTML_2_0 "<!DOCTYPE HTML PUBLIC \"-//IETF//" \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "DTD HTML 2.0//EN\">\n"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define DOCTYPE_HTML_3_2 "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "DTD HTML 3.2 Final//EN\">\n"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define DOCTYPE_HTML_4_0S "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "DTD HTML 4.0//EN\"\n" \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define DOCTYPE_HTML_4_0T "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "DTD HTML 4.0 Transitional//EN\"\n" \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n"
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define DOCTYPE_HTML_4_0F "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "DTD HTML 4.0 Frameset//EN\"\n" \
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "\"http://www.w3.org/TR/REC-html40/frameset.dtd\">\n"
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 util_ldap_state_t *st = (util_ldap_state_t *)ap_get_module_config(r->server->module_config, &ldap_module);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele "<html><head><title>LDAP Cache Information</title></head>\n", r);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_rputs("<body bgcolor='#ffffff'><h1 align=center>LDAP Cache Information</h1>\n", r);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/* ------------------------------------------------------------------ */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Closes an LDAP connection by unlocking it. The next time
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * util_ldap_connection_find() is called this connection will be
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * available for reuse.
a3388213b2b4d46b356be205e38204e67b4304d8rbowenLDAP_DECLARE(void) util_ldap_connection_close(util_ldap_connection_t *ldc)
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * QUESTION:
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * Is it safe leaving bound connections floating around between the
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * different modules? Keeping the user bound is a performance boost,
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * but it is also a potential security problem - maybe.
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * For now we unbind the user when we finish with a connection, but
a3388213b2b4d46b356be205e38204e67b4304d8rbowen * we don't have to...
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* mark our connection as available for reuse */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Destroys an LDAP connection by unbinding and closing the connection to
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * the LDAP server. It is used to bring the connection back to a known
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * state after an error, and during pool cleanup.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabeleLDAP_DECLARE_NONSTD(apr_status_t) util_ldap_connection_unbind(void *param)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Clean up an LDAP connection by unbinding and unlocking the connection.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * This function is registered with the pool cleanup function - causing
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * the LDAP connections to be shut down cleanly on graceful restart.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabeleLDAP_DECLARE_NONSTD(apr_status_t) util_ldap_connection_cleanup(void *param)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* unbind and disconnect from the LDAP server */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* free the username and password */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* unlock this entry */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Connect to the LDAP server and binds. Does not connect if already
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * connected (i.e. ldc->ldap is non-NULL.) Does not bind if already bound.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * Returns LDAP_SUCCESS on success; and an error code on failure
4ab980a06412fd86f52a6d054fb7e26de155c530erikabeleLDAP_DECLARE(int) util_ldap_connection_open(request_rec *r,
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* sanity check for NULL */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* If the connection is already bound, return
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ldc->reason = "LDAP: connection open successful (already bound)";
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* create the ldap session handle
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 /* set client certificates */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele apr_ldap_set_option(ldc->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT,
return(rc);
&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
l->bound = 0;
p->next = l;
#if APR_HAS_THREADS
int compare_dn_on_server)
int result = 0;
int failures = 0;
char *searchdn;
util_ldap_state_t *st = (util_ldap_state_t *)ap_get_module_config(r->server->module_config, &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;
goto start_over;
return result;
if (curl) {
return result;
int result = 0;
int failures = 0;
&ldap_module);
if (curl) {
return result;
return result;
(char *)dn,
(char *)attrib,
(char *)value))
== LDAP_SERVER_DOWN) {
goto start_over;
if (curl) {
return LDAP_COMPARE_TRUE;
return LDAP_COMPARE_FALSE;
return LDAP_NO_SUCH_ATTRIBUTE;
return result;
const char ***retvals)
int result = 0;
char *dn;
int count;
int failures = 0;
&ldap_module);
if (curl) {
return LDAP_SUCCESS;
return result;
return result;
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++]);
while (attrs[i]) {
char **values;
if (curl) {
return LDAP_SUCCESS;
const char ***retvals)
int result = 0;
char *dn;
int count;
int failures = 0;
&ldap_module);
if (curl) {
return LDAP_SUCCESS;
return result;
return result;
goto start_over;
return result;
if (count == 0 )
return LDAP_NO_SUCH_OBJECT;
if (attrs) {
while (attrs[k++]);
while (attrs[i]) {
char **values;
if (curl) {
return LDAP_SUCCESS;
&ldap_module);
return NULL;
&ldap_module);
if (file) {
return NULL;
&ldap_module);
return NULL;
&ldap_module);
return NULL;
&ldap_module);
return NULL;
&ldap_module);
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;
static const char *util_ldap_set_trusted_global_cert(cmd_parms *cmd, void *dummy, const char *type, const char *file, const char *password)
&ldap_module);
int cert_type = 0;
return err;
if (type) {
return(NULL);
static const char *util_ldap_set_trusted_client_cert(cmd_parms *cmd, void *config, const char *type, const char *file, const char *password)
&ldap_module);
int cert_type = 0;
if (type) {
return(NULL);
&ldap_module);
mode);
return(NULL);
&ldap_module);
return err;
return NULL;
return st;
return st;
return APR_SUCCESS;
void *data;
int rc;
if (!data) {
return OK;
result = apr_global_mutex_create(&st->util_ldap_cache_lock, st->lock_file, APR_LOCK_DEFAULT, st->pool);
return result;
#ifdef AP_NEED_SET_MUTEX_PERMS
return result;
while (s_vhost) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "LDAP cache: LDAPSharedCacheSize is zero, disabling shared memory cache");
NULL,
&(result_err));
return(OK);
{NULL}