util_ldap.c revision 3dfeb02cfb853d8717ca0cc259b59fea610173f5
/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
* applicable.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* util_ldap.c: LDAP things
*
* Original code from auth_ldap module for Apache v1.3:
* Copyright 1998, 1999 Enbridge Pipelines Inc.
* Copyright 1999-2001 Dave Carrigan
*/
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
#include "util_ldap.h"
#include "util_ldap_cache.h"
#include <apr_strings.h>
#include <unistd.h>
#endif
#if !APR_HAS_LDAP
#endif
#ifdef AP_NEED_SET_MUTEX_PERMS
#include "unixd.h"
#endif
/* defines for certificate file types
*/
#define LDAP_CA_TYPE_UNKNOWN 0
#define LDAP_CA_TYPE_DER 1
#define LDAP_CA_TYPE_BASE64 2
#define LDAP_CA_TYPE_CERT7_DB 3
int util_ldap_handler(request_rec *r);
/*
* Some definitions to help between various versions of apache.
*/
#ifndef DOCTYPE_HTML_2_0
#define DOCTYPE_HTML_2_0 "<!DOCTYPE HTML PUBLIC \"-//IETF//" \
"DTD HTML 2.0//EN\">\n"
#endif
#ifndef DOCTYPE_HTML_3_2
#define DOCTYPE_HTML_3_2 "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
"DTD HTML 3.2 Final//EN\">\n"
#endif
#ifndef DOCTYPE_HTML_4_0S
#define DOCTYPE_HTML_4_0S "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
"DTD HTML 4.0//EN\"\n" \
#endif
#ifndef DOCTYPE_HTML_4_0T
#define DOCTYPE_HTML_4_0T "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
"DTD HTML 4.0 Transitional//EN\"\n" \
#endif
#ifndef DOCTYPE_HTML_4_0F
#define DOCTYPE_HTML_4_0F "<!DOCTYPE HTML PUBLIC \"-//W3C//" \
"DTD HTML 4.0 Frameset//EN\"\n" \
#endif
#define LDAP_CACHE_LOCK() \
if (st->util_ldap_cache_lock) \
#define LDAP_CACHE_UNLOCK() \
if (st->util_ldap_cache_lock) \
{
if (*str) {
}
if (newstr) {
}
}
/*
* Status Handler
* --------------
*
* This handler generates a status page about the current performance of
* the LDAP cache. It is enabled as follows:
*
* <Location /ldap-status>
* SetHandler ldap-status
* </Location>
*
*/
static int util_ldap_handler(request_rec *r)
{
&ldap_module);
if (r->method_number != M_GET)
return DECLINED;
return DECLINED;
}
r->content_type = "text/html";
if (r->header_only)
return OK;
"<html><head><title>LDAP Cache Information</title></head>\n", r);
ap_rputs("<body bgcolor='#ffffff'><h1 align=center>LDAP Cache Information"
"</h1>\n", r);
util_ald_cache_display(r, st);
return OK;
}
/* ------------------------------------------------------------------ */
/*
* Closes an LDAP connection by unlocking it. The next time
* uldap_connection_find() is called this connection will be
* available for reuse.
*/
{
/*
* QUESTION:
*
* Is it safe leaving bound connections floating around between the
* different modules? Keeping the user bound is a performance boost,
* but it is also a potential security problem - maybe.
*
* For now we unbind the user when we finish with a connection, but
* we don't have to...
*/
/* mark our connection as available for reuse */
#if APR_HAS_THREADS
#endif
}
/*
* Destroys an LDAP connection by unbinding and closing the connection to
* the LDAP server. It is used to bring the connection back to a known
* state after an error, and during pool cleanup.
*/
{
if (ldc) {
}
}
return APR_SUCCESS;
}
/*
* Clean up an LDAP connection by unbinding and unlocking the connection.
* This function is registered with the pool cleanup function - causing
* the LDAP connections to be shut down cleanly on graceful restart.
*/
{
if (ldc) {
/* unbind and disconnect from the LDAP server */
/* free the username and password */
}
}
/* unlock this entry */
}
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,
{
int rc = 0;
int failures = 0;
int version = LDAP_VERSION3;
&ldap_module);
/* sanity check for NULL */
if (!ldc) {
return -1;
}
/* If the connection is already bound, return
*/
{
return LDAP_SUCCESS;
}
/* create the ldap session handle
*/
{
/* 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.
*/
&(result));
}
{
}
else {
}
}
/* set client certificates */
}
}
}
}
/* Set the alias dereferencing option */
/* always default to LDAP V3 */
#ifdef LDAP_OPT_NETWORK_TIMEOUT
if (st->connectionTimeout > 0) {
}
if (st->connectionTimeout >= 0) {
if (APR_SUCCESS != rc) {
"LDAP: Could not set the connection timeout");
}
}
#endif
}
/* loop trying to bind up to 10 times if LDAP_SERVER_DOWN error is
* returned. Break out of the loop on Success or any other error.
*
* NOTE: Looping is probably not a great idea. If the server isn't
* responding the chances it will respond after a few tries are poor.
* However, the original code looped and it only happens on
* the error condition.
*/
{
if (LDAP_SERVER_DOWN != rc) {
break;
}
}
/* free the handle if there was an error
*/
if (LDAP_SUCCESS != rc)
{
}
else {
}
return(rc);
}
/*
* Compare client certificate arrays.
*
* Returns 1 on compare failure, 0 otherwise.
*/
{
int i = 0;
/* arrays both NULL? if so, then equal */
return 0;
}
/* arrays different length or either NULL? If so, then not equal */
return 1;
}
/* run an actual comparison */
return 1;
}
}
/* if we got here, the cert arrays were identical */
return 0;
}
/*
* Find an existing ldap connection struct that matches the
* provided ldap connection parameters.
*
* If not found in the cache, a new ldc structure will be allocated
* from st->pool and returned to the caller. If found in the cache,
* a pointer to the existing ldc structure will be returned.
*/
static util_ldap_connection_t *
{
struct util_ldap_connection_t *l, *p; /* To traverse the linked list */
int secureflag = secure;
&ldap_module);
#if APR_HAS_THREADS
/* mutex lock this function */
}
#endif
if (secure < APR_LDAP_NONE) {
}
/* Search for an exact connection match in the list that is not
* being used.
*/
#if APR_HAS_THREADS
#endif
{
break;
}
#if APR_HAS_THREADS
/* If this connection didn't match the criteria, then we
* need to unlock the mutex so it is available to be reused.
*/
}
#endif
p = l;
}
/* If nothing found, search again, but we don't care about the
* binddn and bindpw this time.
*/
if (!l) {
#if APR_HAS_THREADS
#endif
{
/* the bind credentials have changed */
l->bound = 0;
break;
}
#if APR_HAS_THREADS
/* If this connection didn't match the criteria, then we
* need to unlock the mutex so it is available to be reused.
*/
}
#endif
p = l;
}
}
/* artificially disable cache */
/* l = NULL; */
/* If no connection what found after the second search, we
* must create one.
*/
if (!l) {
/*
* Add the new connection entry to the linked list. Note that we
* don't actually establish an LDAP connection yet; that happens
* the first time authentication is requested.
*/
/* create the details to the pool in st */
#if APR_HAS_THREADS
#endif
l->bound = 0;
/* The security mode after parsing the URL will always be either
* APR_LDAP_NONE (ldap://) or APR_LDAP_SSL (ldaps://).
* If the security setting is NONE, override it to the security
* setting optionally supplied by the admin using LDAPTrustedMode
*/
l->secure = secureflag;
/* save away a copy of the client cert list that is presently valid */
/* add the cleanup to the pool */
apr_pool_cleanup_register(l->pool, l,
if (p) {
p->next = l;
}
else {
st->connections = l;
}
}
#if APR_HAS_THREADS
#endif
return l;
}
/* ------------------------------------------------------------------ */
/*
* Compares two DNs to see if they're equal. The only way to do this correctly
* is to search for the dn and then do ldap_get_dn() on the result. This should
* match the initial dn, since it would have been also retrieved with
* ldap_get_dn(). This is expensive, so if the configuration value
* compare_dn_on_server is false, just does an ordinary strcmp.
*
* The lock for the ldap cache should already be acquired.
*/
const char *reqdn, int compare_dn_on_server)
{
int result = 0;
int failures = 0;
char *searchdn;
&ldap_module);
/* get cache entry (or create one) */
}
/* a simple compare? */
if (!compare_dn_on_server) {
/* unlock this read lock */
return LDAP_COMPARE_FALSE;
}
else {
return LDAP_COMPARE_TRUE;
}
}
if (curl) {
/* no - it's a server side compare */
/* is it in the compare cache? */
/* If it's in the cache, it's good */
/* unlock this read lock */
return LDAP_COMPARE_TRUE;
}
/* unlock this read lock */
}
if (failures++ > 10) {
/* too many failures */
return result;
}
/* make a server connection */
/* connect to server failed */
return result;
}
/* search for reqdn */
== LDAP_SERVER_DOWN)
{
"failed with server down";
goto start_over;
}
if (result != LDAP_SUCCESS) {
/* search for reqdn failed - no match */
return result;
}
/* compare unsuccessful */
}
else {
if (curl) {
/* compare successful - add to the compare cache */
{
}
}
}
return result;
}
/*
* Does an generic ldap_compare operation. It accepts a cache that it will use
* to lookup the compare in the cache. We cache two kinds of compares
* (require group compares) and (require user compares). Each compare has a different
* cache node: require group includes the DN; require user does not because the
* require user cache is owned by the
*
*/
{
int result = 0;
int failures = 0;
&ldap_module);
/* get cache entry (or create one) */
}
if (curl) {
/* make a comparison to the cache */
curtime = apr_time_now();
the_compare_node.result = 0;
if (compare_nodep != NULL) {
/* found it... */
/* ...but it is too old */
}
else {
/* ...and it is good */
/* unlock this read lock */
return compare_nodep->result;
}
return compare_nodep->result;
}
return compare_nodep->result;
}
else {
return compare_nodep->result;
}
}
}
/* unlock this read lock */
}
if (failures++ > 10) {
/* too many failures */
return result;
}
/* connect failed */
return result;
}
(char *)dn,
(char *)attrib,
(char *)value))
== LDAP_SERVER_DOWN) {
/* connection failed - try again */
goto start_over;
}
if ((LDAP_COMPARE_TRUE == result) ||
(LDAP_COMPARE_FALSE == result) ||
(LDAP_NO_SUCH_ATTRIBUTE == result)) {
if (curl) {
/* compare completed; caching result */
/* If the node doesn't exist then insert it, otherwise just update
* it with the last results
*/
if ( (compare_nodep == NULL)
{
}
else {
}
}
if (LDAP_COMPARE_TRUE == result) {
return LDAP_COMPARE_TRUE;
}
else if (LDAP_COMPARE_FALSE == result) {
return LDAP_COMPARE_FALSE;
}
else {
return LDAP_NO_SUCH_ATTRIBUTE;
}
}
return result;
}
const char ***retvals)
{
int numvals = 0;
int result = 0;
char *dn;
int count;
int failures = 0;
&ldap_module);
/* Get the cache node for this url */
&curnode);
}
if (curl) {
if (search_nodep != NULL) {
/* found entry in search cache... */
curtime = apr_time_now();
/*
* Remove this item from the cache if its expired. If the sent
* password doesn't match the storepassword, the entry will
* be removed and readded later if the credentials pass
* authentication.
*/
/* ...but entry is too old */
}
else if ( (search_nodep->bindpw)
{
/* ...and entry is valid */
return LDAP_SUCCESS;
}
}
/* unlock this read lock */
}
/*
* At this point, there is no valid cached search, so lets do the search.
*/
/*
* If LDAP operation fails due to LDAP_SERVER_DOWN, control returns here.
*/
if (failures++ > 10) {
return result;
}
return result;
}
/* try do the search */
== LDAP_SERVER_DOWN)
{
goto start_over;
}
/* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */
if (result != LDAP_SUCCESS) {
return result;
}
/*
* We should have found exactly one entry; to find a different
* number is an error.
*/
if (count != 1)
{
if (count == 0 )
else
"or more matches)";
return LDAP_NO_SUCH_OBJECT;
}
/* Grab the dn, copy it into the pool, and free it again */
/*
* A bind to the server with an empty password always succeeds, so
* we check to ensure that the password is not empty. This implies
* that users who actually do have empty passwords will never be
* able to authenticate with this module. I don't see this as a big
* problem.
*/
return LDAP_INVALID_CREDENTIALS;
}
/*
* Attempt to bind with the retrieved dn and the password. If the bind
* fails, it means that the password is wrong (the dn obviously
* exists, since we just retrieved it)
*/
(char *)*binddn,
(char *)bindpw)) == LDAP_SERVER_DOWN) {
"failed with server down";
goto start_over;
}
/* failure? if so - return */
if (result != LDAP_SUCCESS) {
return result;
}
else {
/*
* We have just bound the connection to a different user and password
* combination, which might be reused unintentionally next time this
* connection is used from the connection pool. To ensure no confusion,
* we mark the connection as unbound.
*/
}
/*
* Get values for the provided attributes.
*/
if (attrs) {
int k = 0;
int i = 0;
while (attrs[k++]);
numvals = k;
while (attrs[i]) {
char **values;
int j = 0;
/* get values */
j++;
}
i++;
}
}
/*
* Add the new username to the search cache.
*/
if (curl) {
/* Search again to make sure that another thread didn't ready insert
* this node into the cache before we got here. If it does exist then
* update the lastbind
*/
if ((search_nodep == NULL) ||
/* Nothing in cache, insert new entry */
}
else if ((!search_nodep->bindpw) ||
/* Entry in cache is invalid, remove it and insert new one */
}
else {
/* Cache entry is valid, update lastbind */
}
}
return LDAP_SUCCESS;
}
/*
* This function will return the DN of the entry matching userid.
* It is used to get the DN in case some other module than mod_auth_ldap
* has authenticated the user.
* The function is basically a copy of uldap_cache_checkuserid
* with password checking removed.
*/
{
int numvals = 0;
int result = 0;
char *dn;
int count;
int failures = 0;
&ldap_module);
/* Get the cache node for this url */
&curnode);
}
if (curl) {
if (search_nodep != NULL) {
/* found entry in search cache... */
curtime = apr_time_now();
/*
* Remove this item from the cache if its expired.
*/
/* ...but entry is too old */
}
else {
/* ...and entry is valid */
return LDAP_SUCCESS;
}
}
/* unlock this read lock */
}
/*
* At this point, there is no valid cached search, so lets do the search.
*/
/*
* If LDAP operation fails due to LDAP_SERVER_DOWN, control returns here.
*/
if (failures++ > 10) {
return result;
}
return result;
}
/* try do the search */
== LDAP_SERVER_DOWN)
{
goto start_over;
}
/* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */
if (result != LDAP_SUCCESS) {
return result;
}
/*
* We should have found exactly one entry; to find a different
* number is an error.
*/
if (count != 1)
{
if (count == 0 )
else
"or more matches)";
return LDAP_NO_SUCH_OBJECT;
}
/* Grab the dn, copy it into the pool, and free it again */
/*
* Get values for the provided attributes.
*/
if (attrs) {
int k = 0;
int i = 0;
while (attrs[k++]);
numvals = k;
while (attrs[i]) {
char **values;
int j = 0;
/* get values */
j++;
}
i++;
}
}
/*
* Add the new username to the search cache.
*/
if (curl) {
/* Search again to make sure that another thread didn't ready insert
* this node into the cache before we got here. If it does exist then
* update the lastbind
*/
if ((search_nodep == NULL) ||
/* Nothing in cache, insert new entry */
}
/*
* Don't update lastbind on entries with bindpw because
* we haven't verified that password. It's OK to update
* the entry if there is no password in it.
*/
else if (!search_nodep->bindpw) {
/* Cache entry is valid, update lastbind */
}
}
return LDAP_SUCCESS;
}
/*
* Reports if ssl support is enabled
*
* 1 = enabled, 0 = not enabled
*/
static int uldap_ssl_supported(request_rec *r)
{
return(st->ssl_supported);
}
/* ---------------------------------------- */
/* config directives */
const char *bytes)
{
&ldap_module);
return NULL;
}
const char *file)
{
&ldap_module);
if (file) {
}
else {
}
"LDAP cache: Setting shared memory cache file to %s bytes.",
st->cache_file);
return NULL;
}
const char *ttl)
{
&ldap_module);
"[%d] ldap cache: Setting cache TTL to %ld microseconds.",
return NULL;
}
const char *size)
{
&ldap_module);
if (st->search_cache_size < 0) {
st->search_cache_size = 0;
}
"[%d] ldap cache: Setting search cache size to %ld entries.",
return NULL;
}
const char *ttl)
{
&ldap_module);
"[%d] ldap cache: Setting operation cache TTL to %ld microseconds.",
return NULL;
}
const char *size)
{
&ldap_module);
if (st->compare_cache_size < 0) {
st->compare_cache_size = 0;
}
"[%d] ldap cache: Setting operation cache size to %ld "
return NULL;
}
/**
* Parse the certificate type.
*
* The type can be one of the following:
* CA_DER, CA_BASE64, CA_CERT7_DB, CA_SECMOD, CERT_DER, CERT_BASE64,
* CERT_KEY3_DB, CERT_NICKNAME, KEY_DER, KEY_BASE64
*
* If no matches are found, APR_LDAP_CA_TYPE_UNKNOWN is returned.
*/
static const int util_ldap_parse_cert_type(const char *type) {
/* Authority file in binary DER format */
return APR_LDAP_CA_TYPE_DER;
}
/* Authority file in Base64 format */
return APR_LDAP_CA_TYPE_BASE64;
}
return APR_LDAP_CA_TYPE_CERT7_DB;
}
return APR_LDAP_CA_TYPE_SECMOD;
}
/* Client cert file in DER format */
return APR_LDAP_CERT_TYPE_DER;
}
/* Client cert file in Base64 format */
return APR_LDAP_CERT_TYPE_BASE64;
}
/* Client cert file in PKCS#12 format */
return APR_LDAP_CERT_TYPE_PFX;
}
return APR_LDAP_CERT_TYPE_KEY3_DB;
}
/* Netscape client cert nickname */
return APR_LDAP_CERT_TYPE_NICKNAME;
}
/* Client cert key file in DER format */
return APR_LDAP_KEY_TYPE_DER;
}
/* Client cert key file in Base64 format */
return APR_LDAP_KEY_TYPE_BASE64;
}
/* Client cert key file in PKCS#12 format */
return APR_LDAP_KEY_TYPE_PFX;
}
else {
return APR_LDAP_CA_TYPE_UNKNOWN;
}
}
/**
* Set LDAPTrustedGlobalCert.
*
* This directive takes either two or three arguments:
* - certificate type
* - certificate file / directory / nickname
* - certificate password (optional)
*
* This directive may only be used globally.
*/
void *dummy,
const char *type,
const char *file,
const char *password)
{
&ldap_module);
int cert_type = 0;
return err;
}
/* handle the certificate type */
if (type) {
if (APR_LDAP_CA_TYPE_UNKNOWN == cert_type) {
"not recognised. It should be one "
"of CA_DER, CA_BASE64, CA_CERT7_DB, "
"CA_SECMOD, CERT_DER, CERT_BASE64, "
"CERT_KEY3_DB, CERT_NICKNAME, "
"KEY_DER, KEY_BASE64", type);
}
}
else {
return "Certificate type was not specified.";
}
"LDAP: SSL trusted global cert - %s (type %s)",
/* add the certificate to the global array */
/* if file is a file or path, fix the path */
if (cert_type != APR_LDAP_CA_TYPE_UNKNOWN &&
!= APR_SUCCESS))
{
"LDAP: Could not open SSL trusted certificate "
"authority file - %s",
return "Invalid global certificate file path";
}
}
return(NULL);
}
/**
* Set LDAPTrustedClientCert.
*
* This directive takes either two or three arguments:
* - certificate type
* - certificate file / directory / nickname
* - certificate password (optional)
*/
void *config,
const char *type,
const char *file,
const char *password)
{
&ldap_module);
int cert_type = 0;
/* handle the certificate type */
if (type) {
if (APR_LDAP_CA_TYPE_UNKNOWN == cert_type) {
"not recognised. It should be one "
"of CERT_DER, CERT_BASE64, "
"CERT_NICKNAME, CERT_PFX,"
"KEY_DER, KEY_BASE64, KEY_PFX",
type);
}
else if (APR_LDAP_CA_TYPE_DER == cert_type ||
"only valid within a "
"LDAPTrustedGlobalCert directive. "
"Only CERT_DER, CERT_BASE64, "
"CERT_NICKNAME, KEY_DER, and "
"KEY_BASE64 may be used.", type);
}
}
else {
return "Certificate type was not specified.";
}
"LDAP: SSL trusted client cert - %s (type %s)",
/* add the certificate to the global array */
/* if file is a file or path, fix the path */
if (cert_type != APR_LDAP_CA_TYPE_UNKNOWN &&
!= APR_SUCCESS))
{
"LDAP: Could not open SSL client certificate "
"file - %s",
return "Invalid client certificate file path";
}
}
return(NULL);
}
/**
* Set LDAPTrustedMode.
*
* This directive sets what encryption mode to use on a connection:
* - None (No encryption)
* - SSL (SSL encryption)
* - STARTTLS (TLS encryption)
*/
const char *mode)
{
&ldap_module);
"LDAP: SSL trusted mode - %s",
mode);
}
}
}
else {
return "Invalid LDAPTrustedMode setting: must be one of NONE, "
}
return(NULL);
}
void *dummy,
const char *ttl)
{
&ldap_module);
return err;
}
#ifdef LDAP_OPT_NETWORK_TIMEOUT
"[%d] ldap connection: Setting connection timeout to "
#else
"LDAP: Connection timout option not supported by the "
"LDAP SDK in use." );
#endif
return NULL;
}
{
st->ssl_supported = 0;
st->secure_set = 0;
return st;
}
void *overridesv)
{
return st;
}
{
server_rec *s = data;
s->module_config, &ldap_module);
if (st->ssl_supported) {
}
return APR_SUCCESS;
}
{
char buf[MAX_STRING_LEN];
&ldap_module);
void *data;
const char *userdata_key = "util_ldap_init";
int rc;
/* util_ldap_post_config() will be called twice. Don't bother
* going through all of the initialization on the first call
* because it will just be thrown away.*/
if (!data) {
/* If the cache file already exists then delete it. Otherwise we are
* going to run into problems creating the shared memory. */
if (st->cache_file) {
NULL);
}
#endif
return OK;
}
/* initializing cache if shared memory size is not zero and we already
* don't have shm address
*/
#endif
if (result != APR_SUCCESS) {
"LDAP cache: error while creating a shared memory "
"segment: %s", buf);
}
if (st->cache_file) {
NULL);
}
else
#endif
if (result != APR_SUCCESS) {
return result;
}
#ifdef AP_NEED_SET_MUTEX_PERMS
if (result != APR_SUCCESS) {
"LDAP cache: failed to set mutex permissions");
return result;
}
#endif
/* merge config in all vhost */
while (s_vhost) {
st_vhost = (util_ldap_state_t *)
&ldap_module);
"LDAP merging Shared Cache conf: shm=0x%pp rmm=0x%pp "
#endif
}
}
else {
"LDAP cache: LDAPSharedCacheSize is zero, disabling "
"shared memory cache");
}
#endif
/* log the LDAP SDK used
*/
{
apr_ldap_info(p, &(result));
}
}
/*
* Initialize SSL support, and log the result for the benefit of the admin.
*
* If SSL is not supported it is not necessarily an error, as the
* application may not want to use it.
*/
rc = apr_ldap_ssl_init(p,
NULL,
0,
&(result_err));
if (APR_SUCCESS == rc) {
}
if (APR_SUCCESS == rc) {
"LDAP: SSL support available" );
}
else {
st->ssl_supported = 0;
if (NULL != result_err) {
result_err->reason);
}
"LDAP: SSL support unavailable" );
}
return(OK);
}
{
&ldap_module);
if (!st->util_ldap_cache_lock) return;
if (sts != APR_SUCCESS) {
"Failed to initialise global mutex %s in child process %"
APR_PID_T_FMT ".",
return;
}
else {
"Initialisation of global mutex %s in child process %"
" successful.",
}
}
command_rec util_ldap_cmds[] = {
"Set the size of the shared memory cache (in bytes). Use "
"0 to disable the shared memory cache. (default: 100000)"),
"Set the file name for the shared memory cache."),
"Set the maximum number of entries that are possible in the "
"LDAP search cache. Use 0 for no limit. "
"-1 disables the cache. (default: 1024)"),
"Set the maximum time (in seconds) that an item can be "
"cached in the LDAP search cache. Use 0 for no limit. "
"(default 600)"),
"Set the maximum number of entries that are possible "
"in the LDAP compare cache. Use 0 for no limit. "
"Use -1 to disable the cache. (default: 1024)"),
"Set the maximum time (in seconds) that an item is cached "
"in the LDAP operation cache. Use 0 for no limit. "
"(default: 600)"),
"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."),
"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."),
"Specify the type of security that should be applied to "
"an LDAP connection. One of; NONE, SSL or STARTTLS."),
"Specify the LDAP socket connection timeout in seconds "
"(default: 10)"),
{NULL}
};
static void util_ldap_register_hooks(apr_pool_t *p)
{
}
NULL, /* create dir config */
NULL, /* merge dir config */
util_ldap_create_config, /* create server config */
util_ldap_merge_config, /* merge server config */
util_ldap_cmds, /* command table */
util_ldap_register_hooks, /* set up request processing hooks */
};