util_ldap.c revision 54091ac5c596337658fc568231ca1a900abdc5fe
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* Licensed to the Apache Software Foundation (ASF) under one or more
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * contributor license agreements. See the NOTICE file distributed with
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * this work for additional information regarding copyright ownership.
bc8fd1b0b1afdf89b8d28eefa8cd74e26ba97986fielding * The ASF licenses this file to You under the Apache License, Version 2.0
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * (the "License"); you may not use this file except in compliance with
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * the License. You may obtain a copy of the License at
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * http://www.apache.org/licenses/LICENSE-2.0
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Unless required by applicable law or agreed to in writing, software
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * distributed under the License is distributed on an "AS IS" BASIS,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * See the License for the specific language governing permissions and
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * limitations under the License.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * util_ldap.c: LDAP things
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Original code from auth_ldap module for Apache v1.3:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Copyright 1998, 1999 Enbridge Pipelines Inc.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Copyright 1999-2001 Dave Carrigan
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "httpd.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "http_config.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "http_core.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "http_log.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "http_protocol.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "http_request.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "util_mutex.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "util_ldap.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include "util_ldap_cache.h"
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include <apr_strings.h>
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#if APR_HAVE_UNISTD_H
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include <unistd.h>
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#endif
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#if !APR_HAS_LDAP
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#error mod_ldap requires APR-util to have LDAP support built in
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#endif
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* Default define for ldap functions that need a SIZELIMIT but
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * do not have the define
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * XXX This should be removed once a supporting #define is
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * released through APR-Util.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#ifndef APR_LDAP_SIZELIMIT
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define APR_LDAP_SIZELIMIT -1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#endif
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#ifdef LDAP_OPT_DEBUG_LEVEL
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define AP_LDAP_OPT_DEBUG LDAP_OPT_DEBUG_LEVEL
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#else
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#ifdef LDAP_OPT_DEBUG
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define AP_LDAP_OPT_DEBUG LDAP_OPT_DEBUG
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#endif
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#endif
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define AP_LDAP_HOPLIMIT_UNSET -1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define AP_LDAP_CHASEREFERRALS_OFF 0
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define AP_LDAP_CHASEREFERRALS_ON 1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define AP_LDAP_CONNPOOL_DEFAULT -1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define AP_LDAP_CONNPOOL_INFINITE -2
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbmodule AP_MODULE_DECLARE_DATA ldap_module;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic const char *ldap_cache_mutex_type = "ldap-cache";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic apr_status_t uldap_connection_unbind(void *param);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define LDAP_CACHE_LOCK() do { \
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (st->util_ldap_cache_lock) \
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb apr_global_mutex_lock(st->util_ldap_cache_lock); \
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb} while (0)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#define LDAP_CACHE_UNLOCK() do { \
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (st->util_ldap_cache_lock) \
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb apr_global_mutex_unlock(st->util_ldap_cache_lock); \
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb} while (0)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void util_ldap_strdup (char **str, const char *newstr)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb{
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (*str) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb free(*str);
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames *str = NULL;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (newstr) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *str = strdup(newstr);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb}
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/*
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * Status Handler
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * --------------
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz *
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * This handler generates a status page about the current performance of
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * the LDAP cache. It is enabled as follows:
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz *
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * <Location /ldap-status>
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * SetHandler ldap-status
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * </Location>
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic int util_ldap_handler(request_rec *r)
4f9c22c4f27571d54197be9674e1fc0d528192aestriker{
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe util_ldap_state_t *st;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb r->allowed |= (1 << M_GET);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (r->method_number != M_GET) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return DECLINED;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (strcmp(r->handler, "ldap-status")) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return DECLINED;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
4f9c22c4f27571d54197be9674e1fc0d528192aestriker st = (util_ldap_state_t *) ap_get_module_config(r->server->module_config,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb &ldap_module);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ap_set_content_type(r, "text/html; charset=ISO-8859-1");
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe if (r->header_only)
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe return OK;
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ap_rputs(DOCTYPE_HTML_3_2
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick "<html><head><title>LDAP Cache Information</title></head>\n", r);
c2cf53a40a9814eb91db2cdf820f97d943f21628coar ap_rputs("<body bgcolor='#ffffff'><h1 align=center>LDAP Cache Information"
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe "</h1>\n", r);
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar util_ald_cache_display(r, st);
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar return OK;
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe}
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/* ------------------------------------------------------------------ */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/*
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * Closes an LDAP connection by unlocking it. The next time
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * uldap_connection_find() is called this connection will be
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * available for reuse.
3e392a5afd51526de3cb15d57ee46d8cb160ae65gregames */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowestatic void uldap_connection_close(util_ldap_connection_t *ldc)
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe{
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe /* We leave bound LDAP connections floating around in our pool,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * but always check/fix the binddn/bindpw when we take them out
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * of the pool
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (!ldc->keep) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe uldap_connection_unbind(ldc);
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe }
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe else {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe /* mark our connection as available for reuse */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ldc->freed = apr_time_now();
4f9c22c4f27571d54197be9674e1fc0d528192aestriker#if APR_HAS_THREADS
3e392a5afd51526de3cb15d57ee46d8cb160ae65gregames apr_thread_mutex_unlock(ldc->lock);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe#endif
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe}
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/*
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe * Destroys an LDAP connection by unbinding and closing the connection to
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe * the LDAP server. It is used to bring the connection back to a known
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe * state after an error.
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowestatic apr_status_t uldap_connection_unbind(void *param)
4f9c22c4f27571d54197be9674e1fc0d528192aestriker{
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe util_ldap_connection_t *ldc = param;
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe if (ldc) {
c2cf53a40a9814eb91db2cdf820f97d943f21628coar if (ldc->ldap) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ldap_unbind_s(ldc->ldap);
4775dfc34c90fada8c7c4d6a57ed8a3114d55c2dtrawick ldc->ldap = NULL;
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe }
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ldc->bound = 0;
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe /* forget the rebind info for this conn */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe apr_ldap_rebind_remove(ldc->ldap);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe apr_pool_clear(ldc->rebind_pool);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe }
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe }
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe return APR_SUCCESS;
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe}
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/* not presently used, not part of the API */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe#if 0
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/*
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * util_ldap_connection_remove frees all storage associated with the LDAP
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * connection and removes it completely from the per-virtualhost list of
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * connections
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe *
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe * The caller should hold the lock for this connection
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe */
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowestatic apr_status_t util_ldap_connection_remove (void *param) {
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe util_ldap_connection_t *ldc = param, *l = NULL, *prev = NULL;
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe util_ldap_state_t *st;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe if (!ldc) return APR_SUCCESS;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe st = ldc->st;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe uldap_connection_unbind(ldc);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar#if APR_HAS_THREADS
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe apr_thread_mutex_lock(st->mutex);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe#endif
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe /* Remove ldc from the list */
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe for (l=st->connections; l; l=l->next) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe if (l == ldc) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (prev) {
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe prev->next = l->next;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar }
c2cf53a40a9814eb91db2cdf820f97d943f21628coar else {
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe st->connections = l->next;
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz }
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz break;
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz }
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe prev = l;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
c2cf53a40a9814eb91db2cdf820f97d943f21628coar
c2cf53a40a9814eb91db2cdf820f97d943f21628coar if (ldc->bindpw) {
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe free((void*)ldc->bindpw);
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz }
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (ldc->binddn) {
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz free((void*)ldc->binddn);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe }
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe#if APR_HAS_THREADS
4f9c22c4f27571d54197be9674e1fc0d528192aestriker apr_thread_mutex_unlock(ldc->lock);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe apr_thread_mutex_unlock(st->mutex);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker#endif
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe /* Destory the pool associated with this connection */
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz apr_pool_destroy(ldc->pool);
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz return APR_SUCCESS;
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe}
4f9c22c4f27571d54197be9674e1fc0d528192aestriker#endif
c2cf53a40a9814eb91db2cdf820f97d943f21628coar
c2cf53a40a9814eb91db2cdf820f97d943f21628coarstatic int uldap_connection_init(request_rec *r,
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe util_ldap_connection_t *ldc)
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz{
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz int rc = 0, ldap_option = 0;
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz int version = LDAP_VERSION3;
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe apr_ldap_err_t *result = NULL;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker#ifdef LDAP_OPT_NETWORK_TIMEOUT
c2cf53a40a9814eb91db2cdf820f97d943f21628coar struct timeval connectionTimeout = {10,0}; /* 10 second connection timeout */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar#endif
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe util_ldap_state_t *st =
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz &ldap_module);
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe /* Since the host will include a port if the default port is not used,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * always specify the default ports for the port parameter. This will
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe * allow a host string that contains multiple hosts the ability to mix
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * some hosts with ports and some without. All hosts which do not
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * specify a port will use the default port.
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker apr_ldap_init(r->pool, &(ldc->ldap),
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ldc->host,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe APR_LDAP_SSL == ldc->secure ? LDAPS_PORT : LDAP_PORT,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe APR_LDAP_NONE,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz &(result));
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe if (NULL == result) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe /* something really bad happened */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ldc->bound = 0;
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe if (NULL == ldc->reason) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ldc->reason = "LDAP: ldap initialization failed";
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe }
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe return(APR_EGENERAL);
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe }
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe if (result->rc) {
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ldc->reason = result->reason;
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ldc->bound = 0;
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe return result->rc;
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe if (NULL == ldc->ldap)
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe {
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ldc->bound = 0;
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe if (NULL == ldc->reason) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe ldc->reason = "LDAP: ldap initialization failed";
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe }
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe else {
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ldc->reason = result->reason;
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe }
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe return(result->rc);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* Now that we have an ldap struct, add it to the referral list for rebinds. */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker rc = apr_ldap_rebind_add(ldc->rebind_pool, ldc->ldap, ldc->binddn, ldc->bindpw);
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe if (rc != APR_SUCCESS) {
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp "LDAP: Unable to add rebind cross reference entry. Out of memory?");
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe uldap_connection_unbind(ldc);
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ldc->reason = "LDAP: Unable to add rebind cross reference entry.";
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp return(rc);
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe }
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe }
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe /* always default to LDAP V3 */
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ldap_set_option(ldc->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe /* set client certificates */
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp if (!apr_is_empty_array(ldc->client_certs)) {
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp apr_ldap_set_option(r->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT,
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp ldc->client_certs, &(result));
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp if (LDAP_SUCCESS != result->rc) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker uldap_connection_unbind( ldc );
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp ldc->reason = result->reason;
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp return(result->rc);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* switch on SSL/TLS */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (APR_LDAP_NONE != ldc->secure) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker apr_ldap_set_option(r->pool, ldc->ldap,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker APR_LDAP_OPT_TLS, &ldc->secure, &(result));
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp if (LDAP_SUCCESS != result->rc) {
7a2edaa0193cbb0d79a65a8461a609a9402aea49brianp uldap_connection_unbind( ldc );
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ldc->reason = result->reason;
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe return(result->rc);
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe }
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe }
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe /* Set the alias dereferencing option */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ldap_option = ldc->deref;
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &ldap_option);
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe /* Set options for rebind and referrals. */
cc9582e53aead2a044077c4a92f3dfc3605590b3wrowe ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "LDAP: Setting referrals to %s.",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ((ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) ? "On" : "Off"));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb apr_ldap_set_option(r->pool, ldc->ldap,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb APR_LDAP_OPT_REFERRALS,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb (void *)((ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) ?
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb LDAP_OPT_ON : LDAP_OPT_OFF),
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb &(result));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (result->rc != LDAP_SUCCESS) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Unable to set LDAP_OPT_REFERRALS option to %s: %d.",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ((ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) ? "On" : "Off"),
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb result->rc);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb result->reason = "Unable to set LDAP_OPT_REFERRALS.";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = result->reason;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb uldap_connection_unbind(ldc);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return(result->rc);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if ((ldc->ReferralHopLimit != AP_LDAP_HOPLIMIT_UNSET) && ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Referral hop limit - only if referrals are enabled and a hop limit is explicitly requested */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Setting referral hop limit to %d.",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->ReferralHopLimit);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb apr_ldap_set_option(r->pool, ldc->ldap,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb APR_LDAP_OPT_REFHOPLIMIT,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb (void *)&ldc->ReferralHopLimit,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb &(result));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (result->rc != LDAP_SUCCESS) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick "Unable to set LDAP_OPT_REFHOPLIMIT option to %d: %d.",
c2cf53a40a9814eb91db2cdf820f97d943f21628coar ldc->ReferralHopLimit,
c2cf53a40a9814eb91db2cdf820f97d943f21628coar result->rc);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb result->reason = "Unable to set LDAP_OPT_REFHOPLIMIT.";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = result->reason;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb uldap_connection_unbind(ldc);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe return(result->rc);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe/*XXX All of the #ifdef's need to be removed once apr-util 1.2 is released */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe#ifdef APR_LDAP_OPT_VERIFY_CERT
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe apr_ldap_set_option(r->pool, ldc->ldap, APR_LDAP_OPT_VERIFY_CERT,
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe &(st->verify_svr_cert), &(result));
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe#else
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe#if defined(LDAPSSL_VERIFY_SERVER)
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (st->verify_svr_cert) {
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_SERVER);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe else {
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_NONE);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe#elif defined(LDAP_OPT_X_TLS_REQUIRE_CERT)
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz /* This is not a per-connection setting so just pass NULL for the
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe Ldap connection handle */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar if (st->verify_svr_cert) {
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe int i = LDAP_OPT_X_TLS_DEMAND;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz else {
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz int i = LDAP_OPT_X_TLS_NEVER;
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
659ad814f714e556bdd03e1d771cba156baab92ewrowe#endif
659ad814f714e556bdd03e1d771cba156baab92ewrowe#endif
659ad814f714e556bdd03e1d771cba156baab92ewrowe
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe#ifdef LDAP_OPT_NETWORK_TIMEOUT
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar if (st->connectionTimeout > 0) {
11fb2f3611e6ff9a541e10b13e3108934f828141gregames connectionTimeout.tv_sec = st->connectionTimeout;
11fb2f3611e6ff9a541e10b13e3108934f828141gregames }
11fb2f3611e6ff9a541e10b13e3108934f828141gregames
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz if (st->connectionTimeout >= 0) {
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz rc = apr_ldap_set_option(r->pool, ldc->ldap, LDAP_OPT_NETWORK_TIMEOUT,
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz (void *)&connectionTimeout, &(result));
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz if (APR_SUCCESS != rc) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe "LDAP: Could not set the connection timeout");
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker#endif
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe#ifdef LDAP_OPT_TIMEOUT
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /*
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * LDAP_OPT_TIMEOUT is not portable, but it influences all synchronous ldap
2f1949bb0e3c209db94c8d521cba7380b9d11421trawick * function calls and not just ldap_search_ext_s(), which accepts a timeout
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * parameter.
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * XXX: It would be possible to simulate LDAP_OPT_TIMEOUT by replacing all
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * XXX: synchronous ldap function calls with asynchronous calls and using
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * XXX: ldap_result() with a timeout.
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (st->opTimeout) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker rc = apr_ldap_set_option(r->pool, ldc->ldap, LDAP_OPT_TIMEOUT,
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe st->opTimeout, &(result));
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar if (APR_SUCCESS != rc) {
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar "LDAP: Could not set LDAP_OPT_TIMEOUT");
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe#endif
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe return(rc);
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz}
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz/*
7c301a1818939f85da8f3629cc3e9b5588610ef0jerenkrantz * Replacement function for ldap_simple_bind_s() with a timeout.
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * To do this in a portable way, we have to use ldap_simple_bind() and
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * ldap_result().
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe *
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Returns LDAP_SUCCESS on success; and an error code on failure
8aefbd756763807188d2e3ce336a8680e4893066wrowe */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int uldap_simple_bind(util_ldap_connection_t *ldc, char *binddn,
8aefbd756763807188d2e3ce336a8680e4893066wrowe char* bindpw, struct timeval *timeout)
8aefbd756763807188d2e3ce336a8680e4893066wrowe{
8aefbd756763807188d2e3ce336a8680e4893066wrowe LDAPMessage *result;
8aefbd756763807188d2e3ce336a8680e4893066wrowe int rc;
8aefbd756763807188d2e3ce336a8680e4893066wrowe int msgid = ldap_simple_bind(ldc->ldap, binddn, bindpw);
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (msgid == -1) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe ldc->reason = "LDAP: ldap_simple_bind() failed";
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* -1 is LDAP_SERVER_DOWN in openldap, use something else */
8aefbd756763807188d2e3ce336a8680e4893066wrowe return LDAP_OTHER;
8aefbd756763807188d2e3ce336a8680e4893066wrowe }
8aefbd756763807188d2e3ce336a8680e4893066wrowe rc = ldap_result(ldc->ldap, msgid, 0, timeout, &result);
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (rc == -1) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe ldc->reason = "LDAP: ldap_simple_bind() result retrieval failed";
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* -1 is LDAP_SERVER_DOWN in openldap, use something else */
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe rc = LDAP_OTHER;
8aefbd756763807188d2e3ce336a8680e4893066wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe else if (rc == 0) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe ldc->reason = "LDAP: ldap_simple_bind() timed out";
8aefbd756763807188d2e3ce336a8680e4893066wrowe rc = LDAP_TIMEOUT;
2fa5b5878e7567e2875807c3e2a2b3b0d3ef74bewrowe } else if (ldap_parse_result(ldc->ldap, result, &rc, NULL, NULL, NULL,
2fa5b5878e7567e2875807c3e2a2b3b0d3ef74bewrowe NULL, 1) == -1) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "LDAP: ldap_simple_bind() parse result failed";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
8aefbd756763807188d2e3ce336a8680e4893066wrowe return rc;
8aefbd756763807188d2e3ce336a8680e4893066wrowe}
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe
a8d11d78181478da6a672f7fbc58b8d523351f49wrowe/*
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * Connect to the LDAP server and binds. Does not connect if already
23c6309e36a63b13b61c35999c978017521993d6wrowe * connected (i.e. ldc->ldap is non-NULL.) Does not bind if already bound.
23c6309e36a63b13b61c35999c978017521993d6wrowe *
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * Returns LDAP_SUCCESS on success; and an error code on failure
23c6309e36a63b13b61c35999c978017521993d6wrowe */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int uldap_connection_open(request_rec *r,
23c6309e36a63b13b61c35999c978017521993d6wrowe util_ldap_connection_t *ldc)
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick{
4f9c22c4f27571d54197be9674e1fc0d528192aestriker int rc = 0;
23c6309e36a63b13b61c35999c978017521993d6wrowe int failures = 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe int new_connection = 0;
8aefbd756763807188d2e3ce336a8680e4893066wrowe util_ldap_state_t *st;
8aefbd756763807188d2e3ce336a8680e4893066wrowe
cf6ef072483172309861d06e85b1aeff4573c060wrowe /* sanity check for NULL */
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (!ldc) {
cf6ef072483172309861d06e85b1aeff4573c060wrowe return -1;
8aefbd756763807188d2e3ce336a8680e4893066wrowe }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* If the connection is already bound, return
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe */
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick if (ldc->bound)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ldc->reason = "LDAP: connection open successful (already bound)";
a8d11d78181478da6a672f7fbc58b8d523351f49wrowe return LDAP_SUCCESS;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
8aefbd756763807188d2e3ce336a8680e4893066wrowe
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* create the ldap session handle
cf6ef072483172309861d06e85b1aeff4573c060wrowe */
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (NULL == ldc->ldap)
cf6ef072483172309861d06e85b1aeff4573c060wrowe {
8aefbd756763807188d2e3ce336a8680e4893066wrowe new_connection = 1;
cf6ef072483172309861d06e85b1aeff4573c060wrowe rc = uldap_connection_init( r, ldc );
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (LDAP_SUCCESS != rc)
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp {
cf6ef072483172309861d06e85b1aeff4573c060wrowe return rc;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
cf6ef072483172309861d06e85b1aeff4573c060wrowe }
cf6ef072483172309861d06e85b1aeff4573c060wrowe
cf6ef072483172309861d06e85b1aeff4573c060wrowe
cf6ef072483172309861d06e85b1aeff4573c060wrowe st = (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
cf6ef072483172309861d06e85b1aeff4573c060wrowe &ldap_module);
cf6ef072483172309861d06e85b1aeff4573c060wrowe
cf6ef072483172309861d06e85b1aeff4573c060wrowe /* loop trying to bind up to 10 times if LDAP_SERVER_DOWN error is
cf6ef072483172309861d06e85b1aeff4573c060wrowe * returned. If LDAP_TIMEOUT is returned on the first try, maybe the
cf6ef072483172309861d06e85b1aeff4573c060wrowe * connection was idle for a long time and has been dropped by a firewall.
69adb3d949e3dd17c0492a01fc2cf298832c7eefwrowe * In this case close the connection immediately and try again.
69adb3d949e3dd17c0492a01fc2cf298832c7eefwrowe *
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick * On Success or any other error, break out of the loop.
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick *
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick * NOTE: Looping is probably not a great idea. If the server isn't
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick * responding the chances it will respond after a few tries are poor.
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick * However, the original code looped and it only happens on
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick * the error condition.
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick */
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick for (failures=0; failures<10; failures++)
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick {
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick rc = uldap_simple_bind(ldc, (char *)ldc->binddn, (char *)ldc->bindpw,
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick st->opTimeout);
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick if ((AP_LDAP_IS_SERVER_DOWN(rc) && failures == 5) ||
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick (rc == LDAP_TIMEOUT && failures == 0))
d75626f0952c6152a99acd013a4f127d46f0f9edtrawick {
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (rc == LDAP_TIMEOUT && !new_connection) {
cf6ef072483172309861d06e85b1aeff4573c060wrowe ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar "ldap_simple_bind() timed out on reused "
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "connection, dropped by firewall?");
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "attempt to re-init the connection");
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar uldap_connection_unbind( ldc );
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe rc = uldap_connection_init( r, ldc );
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (LDAP_SUCCESS != rc)
4f9c22c4f27571d54197be9674e1fc0d528192aestriker {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe break;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
23c6309e36a63b13b61c35999c978017521993d6wrowe else if (!AP_LDAP_IS_SERVER_DOWN(rc)) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker break;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
c2cf53a40a9814eb91db2cdf820f97d943f21628coar "ldap_simple_bind() failed with server down "
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "(try %d)", failures + 1);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* free the handle if there was an error
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe */
a9a4544168a37b43bd180b3703ccee995f27a80awrowe if (LDAP_SUCCESS != rc)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe {
a9a4544168a37b43bd180b3703ccee995f27a80awrowe uldap_connection_unbind(ldc);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ldc->reason = "LDAP: ldap_simple_bind() failed";
a9a4544168a37b43bd180b3703ccee995f27a80awrowe }
a9a4544168a37b43bd180b3703ccee995f27a80awrowe else {
a9a4544168a37b43bd180b3703ccee995f27a80awrowe ldc->bound = 1;
a9a4544168a37b43bd180b3703ccee995f27a80awrowe ldc->reason = "LDAP: connection open successful";
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return(rc);
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar}
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/*
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * Compare client certificate arrays.
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe *
8aefbd756763807188d2e3ce336a8680e4893066wrowe * Returns 1 on compare failure, 0 otherwise.
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowestatic int compare_client_certs(apr_array_header_t *srcs,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe apr_array_header_t *dests)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe{
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe int i = 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe struct apr_ldap_opt_tls_cert_t *src, *dest;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* arrays both NULL? if so, then equal */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (srcs == NULL && dests == NULL) {
cf6ef072483172309861d06e85b1aeff4573c060wrowe return 0;
cf6ef072483172309861d06e85b1aeff4573c060wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* arrays different length or either NULL? If so, then not equal */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (srcs == NULL || dests == NULL || srcs->nelts != dests->nelts) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe return 1;
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz }
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz /* run an actual comparison */
cf6ef072483172309861d06e85b1aeff4573c060wrowe src = (struct apr_ldap_opt_tls_cert_t *)srcs->elts;
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe dest = (struct apr_ldap_opt_tls_cert_t *)dests->elts;
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe for (i = 0; i < srcs->nelts; i++) {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe if ((strcmp(src[i].path, dest[i].path)) ||
4f9c22c4f27571d54197be9674e1fc0d528192aestriker (src[i].type != dest[i].type) ||
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* One is passwordless? If so, then not equal */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ((src[i].password == NULL) ^ (dest[i].password == NULL)) ||
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe (src[i].password != NULL && dest[i].password != NULL &&
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe strcmp(src[i].password, dest[i].password))) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return 1;
8aefbd756763807188d2e3ce336a8680e4893066wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* if we got here, the cert arrays were identical */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
8aefbd756763807188d2e3ce336a8680e4893066wrowe}
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe/*
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe * Find an existing ldap connection struct that matches the
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe * provided ldap connection parameters.
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe *
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe * If not found in the cache, a new ldc structure will be allocated
59513b1275fdc2021d4949ee03ae8229469abb86wrowe * from st->pool and returned to the caller. If found in the cache,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * a pointer to the existing ldc structure will be returned.
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe */
4f9c22c4f27571d54197be9674e1fc0d528192aestrikerstatic util_ldap_connection_t *
4f9c22c4f27571d54197be9674e1fc0d528192aestriker uldap_connection_find(request_rec *r,
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe const char *host, int port,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker const char *binddn, const char *bindpw,
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe deref_options deref, int secure)
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe{
4f9c22c4f27571d54197be9674e1fc0d528192aestriker struct util_ldap_connection_t *l, *p; /* To traverse the linked list */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe int secureflag = secure;
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe apr_time_t now = apr_time_now();
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestriker util_ldap_state_t *st =
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe &ldap_module);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe util_ldap_config_t *dc =
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe (util_ldap_config_t *) ap_get_module_config(r->per_dir_config, &ldap_module);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe#if APR_HAS_THREADS
cf6ef072483172309861d06e85b1aeff4573c060wrowe /* mutex lock this function */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe apr_thread_mutex_lock(st->mutex);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe#endif
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe if (secure < APR_LDAP_NONE) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker secureflag = st->secure;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* Search for an exact connection match in the list that is not
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * being used.
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker for (l=st->connections,p=NULL; l; l=l->next) {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe#if APR_HAS_THREADS
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (APR_SUCCESS == apr_thread_mutex_trylock(l->lock)) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker#endif
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe if ( (l->port == port) && (strcmp(l->host, host) == 0)
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe && ((!l->binddn && !binddn) || (l->binddn && binddn
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe && !strcmp(l->binddn, binddn)))
4f9c22c4f27571d54197be9674e1fc0d528192aestriker && ((!l->bindpw && !bindpw) || (l->bindpw && bindpw
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe && !strcmp(l->bindpw, bindpw)))
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe && (l->deref == deref) && (l->secure == secureflag)
4f9c22c4f27571d54197be9674e1fc0d528192aestriker && !compare_client_certs(dc->client_certs, l->client_certs))
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe if (st->connection_pool_ttl > 0) {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe if (l->bound && (now - l->freed) > st->connection_pool_ttl) {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker "Removing LDAP connection last used %" APR_TIME_T_FMT " seconds ago",
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe (now - l->freed) / APR_USEC_PER_SEC);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe uldap_connection_unbind(l);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* Go ahead (by falling through) and use it, so we don't create more just to unbind some other old ones */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe }
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe }
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe break;
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe }
cf6ef072483172309861d06e85b1aeff4573c060wrowe#if APR_HAS_THREADS
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* If this connection didn't match the criteria, then we
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * need to unlock the mutex so it is available to be reused.
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe apr_thread_mutex_unlock(l->lock);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe }
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe#endif
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe p = l;
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe }
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* If nothing found, search again, but we don't care about the
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe * binddn and bindpw this time.
38bcc87d9a06e8ba81165421403f275eca4e313btrawick */
38bcc87d9a06e8ba81165421403f275eca4e313btrawick if (!l) {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe for (l=st->connections,p=NULL; l; l=l->next) {
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz#if APR_HAS_THREADS
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe if (APR_SUCCESS == apr_thread_mutex_trylock(l->lock)) {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe#endif
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe if ((l->port == port) && (strcmp(l->host, host) == 0) &&
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe (l->deref == deref) && (l->secure == secureflag) &&
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe !compare_client_certs(dc->client_certs, l->client_certs))
4f9c22c4f27571d54197be9674e1fc0d528192aestriker {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* the bind credentials have changed */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* no check for connection_pool_ttl, since we are unbinding any way */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe uldap_connection_unbind(l);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe util_ldap_strdup((char**)&(l->binddn), binddn);
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe util_ldap_strdup((char**)&(l->bindpw), bindpw);
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz break;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz#if APR_HAS_THREADS
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* If this connection didn't match the criteria, then we
cf6ef072483172309861d06e85b1aeff4573c060wrowe * need to unlock the mutex so it is available to be reused.
cf6ef072483172309861d06e85b1aeff4573c060wrowe */
8aefbd756763807188d2e3ce336a8680e4893066wrowe apr_thread_mutex_unlock(l->lock);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe#endif
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe p = l;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* artificially disable cache */
cf6ef072483172309861d06e85b1aeff4573c060wrowe/* l = NULL; */
cf6ef072483172309861d06e85b1aeff4573c060wrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* If no connection was found after the second search, we
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * must create one.
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz */
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (!l) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe apr_pool_t *newpool;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (apr_pool_create(&newpool, NULL) != APR_SUCCESS) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "util_ldap: Failed to create memory pool");
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz#if APR_HAS_THREADS
4f9c22c4f27571d54197be9674e1fc0d528192aestriker apr_thread_mutex_unlock(st->mutex);
548b2980e83f609186a76e98fb245d02e8547bc3jerenkrantz#endif
548b2980e83f609186a76e98fb245d02e8547bc3jerenkrantz return NULL;
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe }
548b2980e83f609186a76e98fb245d02e8547bc3jerenkrantz
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz /*
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz * Add the new connection entry to the linked list. Note that we
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * don't actually establish an LDAP connection yet; that happens
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * the first time authentication is requested.
8aefbd756763807188d2e3ce336a8680e4893066wrowe */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* create the details of this connection in the new pool */
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe l = apr_pcalloc(newpool, sizeof(util_ldap_connection_t));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe l->pool = newpool;
8aefbd756763807188d2e3ce336a8680e4893066wrowe l->st = st;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe#if APR_HAS_THREADS
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe apr_thread_mutex_create(&l->lock, APR_THREAD_MUTEX_DEFAULT, l->pool);
8aefbd756763807188d2e3ce336a8680e4893066wrowe apr_thread_mutex_lock(l->lock);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker#endif
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe l->bound = 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe l->host = apr_pstrdup(l->pool, host);
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar l->port = port;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe l->deref = deref;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar util_ldap_strdup((char**)&(l->binddn), binddn);
8aefbd756763807188d2e3ce336a8680e4893066wrowe util_ldap_strdup((char**)&(l->bindpw), bindpw);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe l->ChaseReferrals = dc->ChaseReferrals;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker l->ReferralHopLimit = dc->ReferralHopLimit;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* The security mode after parsing the URL will always be either
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * APR_LDAP_NONE (ldap://) or APR_LDAP_SSL (ldaps://).
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * If the security setting is NONE, override it to the security
f08810eff40a2bddd2bc0103453c4ae775ea62bewrowe * setting optionally supplied by the admin using LDAPTrustedMode
f08810eff40a2bddd2bc0103453c4ae775ea62bewrowe */
f08810eff40a2bddd2bc0103453c4ae775ea62bewrowe l->secure = secureflag;
f08810eff40a2bddd2bc0103453c4ae775ea62bewrowe
f08810eff40a2bddd2bc0103453c4ae775ea62bewrowe /* save away a copy of the client cert list that is presently valid */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe l->client_certs = apr_array_copy_hdr(l->pool, dc->client_certs);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* whether or not to keep this connection in the pool when it's returned */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe l->keep = (st->connection_pool_ttl == 0) ? 0 : 1;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (l->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (apr_pool_create(&(l->rebind_pool), l->pool) != APR_SUCCESS) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "util_ldap: Failed to create memory pool");
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe#if APR_HAS_THREADS
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe apr_thread_mutex_unlock(st->mutex);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe#endif
4f9c22c4f27571d54197be9674e1fc0d528192aestriker return NULL;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (p) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe p->next = l;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
8aefbd756763807188d2e3ce336a8680e4893066wrowe else {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar st->connections = l;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar#if APR_HAS_THREADS
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar apr_thread_mutex_unlock(st->mutex);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe#endif
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar return l;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe}
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/* ------------------------------------------------------------------ */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/*
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * Compares two DNs to see if they're equal. The only way to do this correctly
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * is to search for the dn and then do ldap_get_dn() on the result. This should
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * match the initial dn, since it would have been also retrieved with
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * ldap_get_dn(). This is expensive, so if the configuration value
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * compare_dn_on_server is false, just does an ordinary strcmp.
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe *
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe * The lock for the ldap cache should already be acquired.
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int uldap_cache_comparedn(request_rec *r, util_ldap_connection_t *ldc,
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar const char *url, const char *dn,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe const char *reqdn, int compare_dn_on_server)
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar{
8aefbd756763807188d2e3ce336a8680e4893066wrowe int result = 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe util_url_node_t *curl;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker util_url_node_t curnode;
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz util_dn_compare_node_t *node;
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz util_dn_compare_node_t newnode;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker int failures = 0;
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz LDAPMessage *res, *entry;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe char *searchdn;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz util_ldap_state_t *st = (util_ldap_state_t *)
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz ap_get_module_config(r->server->module_config,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz &ldap_module);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* get cache entry (or create one) */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe LDAP_CACHE_LOCK();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe curnode.url = url;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (curl == NULL) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe curl = util_ald_create_caches(st, url);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
8aefbd756763807188d2e3ce336a8680e4893066wrowe LDAP_CACHE_UNLOCK();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* a simple compare? */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (!compare_dn_on_server) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* unlock this read lock */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (strcmp(dn, reqdn)) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "DN Comparison FALSE (direct strcmp())";
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar return LDAP_COMPARE_FALSE;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar else {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "DN Comparison TRUE (direct strcmp())";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return LDAP_COMPARE_TRUE;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (curl) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* no - it's a server side compare */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe LDAP_CACHE_LOCK();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* is it in the compare cache? */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe newnode.reqdn = (char *)reqdn;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe node = util_ald_cache_fetch(curl->dn_compare_cache, &newnode);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (node != NULL) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* If it's in the cache, it's good */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* unlock this read lock */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker LDAP_CACHE_UNLOCK();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "DN Comparison TRUE (cached)";
4f9c22c4f27571d54197be9674e1fc0d528192aestriker return LDAP_COMPARE_TRUE;
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* unlock this read lock */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe LDAP_CACHE_UNLOCK();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoarstart_over:
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (failures++ > 10) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* too many failures */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return result;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* make a server connection */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* connect to server failed */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return result;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* search for reqdn */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker result = ldap_search_ext_s(ldc->ldap, (char *)reqdn, LDAP_SCOPE_BASE,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz "(objectclass=*)", NULL, 1,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz NULL, NULL, st->opTimeout, APR_LDAP_SIZELIMIT, &res);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (AP_LDAP_IS_SERVER_DOWN(result))
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "DN Comparison ldap_search_ext_s() "
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "failed with server down";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe uldap_connection_unbind(ldc);
c2cf53a40a9814eb91db2cdf820f97d943f21628coar goto start_over;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (result == LDAP_TIMEOUT && failures == 0) {
c2cf53a40a9814eb91db2cdf820f97d943f21628coar /*
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe * we are reusing a connection that doesn't seem to be active anymore
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * (firewall state drop?), let's try a new connection.
4f9c22c4f27571d54197be9674e1fc0d528192aestriker */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz ldc->reason = "DN Comparison ldap_search_ext_s() "
4f9c22c4f27571d54197be9674e1fc0d528192aestriker "failed with timeout";
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz uldap_connection_unbind(ldc);
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe goto start_over;
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe }
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (result != LDAP_SUCCESS) {
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz /* search for reqdn failed - no match */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz ldc->reason = "DN Comparison ldap_search_ext_s() failed";
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe return result;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe entry = ldap_first_entry(ldc->ldap, res);
2787ef5edc27fa4f6777ba8d51aa48fd9fdf54bbwrowe searchdn = ldap_get_dn(ldc->ldap, entry);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldap_msgfree(res);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (strcmp(dn, searchdn) != 0) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* compare unsuccessful */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "DN Comparison FALSE (checked on server)";
8aefbd756763807188d2e3ce336a8680e4893066wrowe result = LDAP_COMPARE_FALSE;
2520f59894a3e07fefa881ef68aaded763a8d447ben }
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz else {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar if (curl) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* compare successful - add to the compare cache */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe LDAP_CACHE_LOCK();
8aefbd756763807188d2e3ce336a8680e4893066wrowe newnode.reqdn = (char *)reqdn;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar newnode.dn = (char *)dn;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar node = util_ald_cache_fetch(curl->dn_compare_cache, &newnode);
8aefbd756763807188d2e3ce336a8680e4893066wrowe if ( (node == NULL)
4f9c22c4f27571d54197be9674e1fc0d528192aestriker || (strcmp(reqdn, node->reqdn) != 0)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe || (strcmp(dn, node->dn) != 0))
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe {
8aefbd756763807188d2e3ce336a8680e4893066wrowe util_ald_cache_insert(curl->dn_compare_cache, &newnode);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz LDAP_CACHE_UNLOCK();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "DN Comparison TRUE (checked on server)";
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz result = LDAP_COMPARE_TRUE;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz ldap_memfree(searchdn);
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz return result;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe}
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe/*
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz * Does an generic ldap_compare operation. It accepts a cache that it will use
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz * to lookup the compare in the cache. We cache two kinds of compares
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz * (require group compares) and (require user compares). Each compare has a
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz * different cache node: require group includes the DN; require user does not
8aefbd756763807188d2e3ce336a8680e4893066wrowe * because the require user cache is owned by the
4f9c22c4f27571d54197be9674e1fc0d528192aestriker *
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe */
4f9c22c4f27571d54197be9674e1fc0d528192aestrikerstatic int uldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe const char *url, const char *dn,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe const char *attrib, const char *value)
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar{
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe int result = 0;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar util_url_node_t *curl;
8aefbd756763807188d2e3ce336a8680e4893066wrowe util_url_node_t curnode;
cf6ef072483172309861d06e85b1aeff4573c060wrowe util_compare_node_t *compare_nodep;
cf6ef072483172309861d06e85b1aeff4573c060wrowe util_compare_node_t the_compare_node;
cf6ef072483172309861d06e85b1aeff4573c060wrowe apr_time_t curtime = 0; /* silence gcc -Wall */
cf6ef072483172309861d06e85b1aeff4573c060wrowe int failures = 0;
cf6ef072483172309861d06e85b1aeff4573c060wrowe
cf6ef072483172309861d06e85b1aeff4573c060wrowe util_ldap_state_t *st = (util_ldap_state_t *)
cf6ef072483172309861d06e85b1aeff4573c060wrowe ap_get_module_config(r->server->module_config,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker &ldap_module);
cf6ef072483172309861d06e85b1aeff4573c060wrowe
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /* get cache entry (or create one) */
cf6ef072483172309861d06e85b1aeff4573c060wrowe LDAP_CACHE_LOCK();
4f9c22c4f27571d54197be9674e1fc0d528192aestriker curnode.url = url;
69adb3d949e3dd17c0492a01fc2cf298832c7eefwrowe curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);
69adb3d949e3dd17c0492a01fc2cf298832c7eefwrowe if (curl == NULL) {
cf6ef072483172309861d06e85b1aeff4573c060wrowe curl = util_ald_create_caches(st, url);
cf6ef072483172309861d06e85b1aeff4573c060wrowe }
cf6ef072483172309861d06e85b1aeff4573c060wrowe LDAP_CACHE_UNLOCK();
cf6ef072483172309861d06e85b1aeff4573c060wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (curl) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* make a comparison to the cache */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe LDAP_CACHE_LOCK();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe curtime = apr_time_now();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
cf6ef072483172309861d06e85b1aeff4573c060wrowe the_compare_node.dn = (char *)dn;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe the_compare_node.attrib = (char *)attrib;
cf6ef072483172309861d06e85b1aeff4573c060wrowe the_compare_node.value = (char *)value;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar the_compare_node.result = 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe the_compare_node.sgl_processed = 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe the_compare_node.subgroupList = NULL;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar
c2cf53a40a9814eb91db2cdf820f97d943f21628coar compare_nodep = util_ald_cache_fetch(curl->compare_cache,
8aefbd756763807188d2e3ce336a8680e4893066wrowe &the_compare_node);
cf6ef072483172309861d06e85b1aeff4573c060wrowe
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (compare_nodep != NULL) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* found it... */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (curtime - compare_nodep->lastcompare > st->compare_cache_ttl) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* ...but it is too old */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe util_ald_cache_remove(curl->compare_cache, compare_nodep);
8aefbd756763807188d2e3ce336a8680e4893066wrowe }
8aefbd756763807188d2e3ce336a8680e4893066wrowe else {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* ...and it is good */
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (LDAP_COMPARE_TRUE == compare_nodep->result) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ldc->reason = "Comparison true (cached)";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe else if (LDAP_COMPARE_FALSE == compare_nodep->result) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "Comparison false (cached)";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe else if (LDAP_NO_SUCH_ATTRIBUTE == compare_nodep->result) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "Comparison no such attribute (cached)";
69adb3d949e3dd17c0492a01fc2cf298832c7eefwrowe }
69adb3d949e3dd17c0492a01fc2cf298832c7eefwrowe else {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "Comparison undefined (cached)";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* record the result code to return with the reason... */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe result = compare_nodep->result;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* and unlock this read lock */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker LDAP_CACHE_UNLOCK();
cf6ef072483172309861d06e85b1aeff4573c060wrowe return result;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
cadddb2c31d24d48f4017db4df0a29687432326cwrowe }
cadddb2c31d24d48f4017db4df0a29687432326cwrowe /* unlock this read lock */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe LDAP_CACHE_UNLOCK();
cf6ef072483172309861d06e85b1aeff4573c060wrowe }
0e58e92812f2f679d6bf2ff66cbcfa6c1d1e14bbjerenkrantz
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowestart_over:
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (failures++ > 10) {
cf6ef072483172309861d06e85b1aeff4573c060wrowe /* too many failures */
cf6ef072483172309861d06e85b1aeff4573c060wrowe return result;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick /* connect failed */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar return result;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe result = ldap_compare_s(ldc->ldap,
8aefbd756763807188d2e3ce336a8680e4893066wrowe (char *)dn,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe (char *)attrib,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe (char *)value);
cf6ef072483172309861d06e85b1aeff4573c060wrowe if (AP_LDAP_IS_SERVER_DOWN(result)) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe /* connection failed - try again */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "ldap_compare_s() failed with server down";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe uldap_connection_unbind(ldc);
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe goto start_over;
cf6ef072483172309861d06e85b1aeff4573c060wrowe }
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick if (result == LDAP_TIMEOUT && failures == 0) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /*
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * we are reusing a connection that doesn't seem to be active anymore
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * (firewall state drop?), let's try a new connection.
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe */
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "ldap_compare_s() failed with timeout";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe uldap_connection_unbind(ldc);
8aefbd756763807188d2e3ce336a8680e4893066wrowe goto start_over;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
cf6ef072483172309861d06e85b1aeff4573c060wrowe
cf6ef072483172309861d06e85b1aeff4573c060wrowe ldc->reason = "Comparison complete";
cf6ef072483172309861d06e85b1aeff4573c060wrowe if ((LDAP_COMPARE_TRUE == result) ||
cf6ef072483172309861d06e85b1aeff4573c060wrowe (LDAP_COMPARE_FALSE == result) ||
cf6ef072483172309861d06e85b1aeff4573c060wrowe (LDAP_NO_SUCH_ATTRIBUTE == result)) {
69adb3d949e3dd17c0492a01fc2cf298832c7eefwrowe if (curl) {
cf6ef072483172309861d06e85b1aeff4573c060wrowe /* compare completed; caching result */
cf6ef072483172309861d06e85b1aeff4573c060wrowe LDAP_CACHE_LOCK();
cf6ef072483172309861d06e85b1aeff4573c060wrowe the_compare_node.lastcompare = curtime;
cf6ef072483172309861d06e85b1aeff4573c060wrowe the_compare_node.result = result;
cf6ef072483172309861d06e85b1aeff4573c060wrowe the_compare_node.sgl_processed = 0;
cf6ef072483172309861d06e85b1aeff4573c060wrowe the_compare_node.subgroupList = NULL;
cf6ef072483172309861d06e85b1aeff4573c060wrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* If the node doesn't exist then insert it, otherwise just update
cf6ef072483172309861d06e85b1aeff4573c060wrowe * it with the last results
cf6ef072483172309861d06e85b1aeff4573c060wrowe */
cf6ef072483172309861d06e85b1aeff4573c060wrowe compare_nodep = util_ald_cache_fetch(curl->compare_cache,
cf6ef072483172309861d06e85b1aeff4573c060wrowe &the_compare_node);
cf6ef072483172309861d06e85b1aeff4573c060wrowe if ( (compare_nodep == NULL)
cf6ef072483172309861d06e85b1aeff4573c060wrowe || (strcmp(the_compare_node.dn, compare_nodep->dn) != 0)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe || (strcmp(the_compare_node.attrib,compare_nodep->attrib) != 0)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe || (strcmp(the_compare_node.value, compare_nodep->value) != 0))
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe void *junk;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe junk = util_ald_cache_insert(curl->compare_cache,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe &the_compare_node);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (junk == NULL) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe "cache_compare: Cache insertion failure.");
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar else {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe compare_nodep->lastcompare = curtime;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar compare_nodep->result = result;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar LDAP_CACHE_UNLOCK();
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (LDAP_COMPARE_TRUE == result) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "Comparison true (adding to cache)";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return LDAP_COMPARE_TRUE;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe else if (LDAP_COMPARE_FALSE == result) {
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe ldc->reason = "Comparison false (adding to cache)";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return LDAP_COMPARE_FALSE;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe else {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ldc->reason = "Comparison no such attribute (adding to cache)";
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return LDAP_NO_SUCH_ATTRIBUTE;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe return result;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe}
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoarstatic util_compare_subgroup_t* uldap_get_subgroups(request_rec *r,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker util_ldap_connection_t *ldc,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe const char *url,
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe const char *dn,
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar char **subgroupAttrs,
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar apr_array_header_t *subgroupclasses)
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe{
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar int failures = 0;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe int result = LDAP_COMPARE_FALSE;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe util_compare_subgroup_t *res = NULL;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe LDAPMessage *sga_res, *entry;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe struct mod_auth_ldap_groupattr_entry_t *sgc_ents;
8aefbd756763807188d2e3ce336a8680e4893066wrowe apr_array_header_t *subgroups = apr_array_make(r->pool, 20, sizeof(char *));
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe sgc_ents = (struct mod_auth_ldap_groupattr_entry_t *) subgroupclasses->elts;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe if (!subgroupAttrs) {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar return res;
e4a3f3c2f080cac75a15a6454cca429b8161c050wrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
8aefbd756763807188d2e3ce336a8680e4893066wrowestart_over:
8aefbd756763807188d2e3ce336a8680e4893066wrowe /*
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * 3.B. The cache didn't have any subgrouplist yet. Go check for subgroups.
c2cf53a40a9814eb91db2cdf820f97d943f21628coar */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar if (failures++ > 10) {
c2cf53a40a9814eb91db2cdf820f97d943f21628coar /* too many failures */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar return res;
8aefbd756763807188d2e3ce336a8680e4893066wrowe }
8aefbd756763807188d2e3ce336a8680e4893066wrowe
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* connect failed */
8aefbd756763807188d2e3ce336a8680e4893066wrowe return res;
8aefbd756763807188d2e3ce336a8680e4893066wrowe }
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* try to do the search */
8aefbd756763807188d2e3ce336a8680e4893066wrowe result = ldap_search_ext_s(ldc->ldap, (char *)dn, LDAP_SCOPE_BASE,
8aefbd756763807188d2e3ce336a8680e4893066wrowe (char *)"cn=*", subgroupAttrs, 0,
c2cf53a40a9814eb91db2cdf820f97d943f21628coar NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &sga_res);
c2cf53a40a9814eb91db2cdf820f97d943f21628coar if (AP_LDAP_IS_SERVER_DOWN(result)) {
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick ldc->reason = "ldap_search_ext_s() for subgroups failed with server"
c2cf53a40a9814eb91db2cdf820f97d943f21628coar " down";
8aefbd756763807188d2e3ce336a8680e4893066wrowe uldap_connection_unbind(ldc);
8aefbd756763807188d2e3ce336a8680e4893066wrowe goto start_over;
8aefbd756763807188d2e3ce336a8680e4893066wrowe }
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (result == LDAP_TIMEOUT && failures == 0) {
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe /*
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe * we are reusing a connection that doesn't seem to be active anymore
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe * (firewall state drop?), let's try a new connection.
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe */
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe ldc->reason = "ldap_search_ext_s() for subgroups failed with timeout";
1b315ee865b0f11e582beb64127ca3a99a319d2fwrowe uldap_connection_unbind(ldc);
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar goto start_over;
0540a0b469147b52e858587270dba31c2aaa9e09wrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar /* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */
0540a0b469147b52e858587270dba31c2aaa9e09wrowe if (result != LDAP_SUCCESS) {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ldc->reason = "ldap_search_ext_s() for subgroups failed";
0540a0b469147b52e858587270dba31c2aaa9e09wrowe return res;
0540a0b469147b52e858587270dba31c2aaa9e09wrowe }
a9a4544168a37b43bd180b3703ccee995f27a80awrowe
0540a0b469147b52e858587270dba31c2aaa9e09wrowe entry = ldap_first_entry(ldc->ldap, sga_res);
0540a0b469147b52e858587270dba31c2aaa9e09wrowe
0540a0b469147b52e858587270dba31c2aaa9e09wrowe /*
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe * Get values for the provided sub-group attributes.
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar */
0540a0b469147b52e858587270dba31c2aaa9e09wrowe if (subgroupAttrs) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe int indx = 0, tmp_sgcIndex;
0540a0b469147b52e858587270dba31c2aaa9e09wrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar while (subgroupAttrs[indx]) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe char **values;
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe int val_index = 0;
0540a0b469147b52e858587270dba31c2aaa9e09wrowe
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Get *all* matching "member" values from this group. */
8aefbd756763807188d2e3ce336a8680e4893066wrowe values = ldap_get_values(ldc->ldap, entry, subgroupAttrs[indx]);
0540a0b469147b52e858587270dba31c2aaa9e09wrowe
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe if (values) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb val_index = 0;
948096a99010fccf648814fecf38f75c689172d7wrowe /*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Now we are going to pare the subgroup members of this group
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * to *just* the subgroups, add them to the compare_nodep, and
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * then proceed to check the new level of subgroups.
0540a0b469147b52e858587270dba31c2aaa9e09wrowe */
948096a99010fccf648814fecf38f75c689172d7wrowe while (values[val_index]) {
948096a99010fccf648814fecf38f75c689172d7wrowe /* Check if this entry really is a group. */
948096a99010fccf648814fecf38f75c689172d7wrowe tmp_sgcIndex = 0;
948096a99010fccf648814fecf38f75c689172d7wrowe result = LDAP_COMPARE_FALSE;
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe while ((tmp_sgcIndex < subgroupclasses->nelts)
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe && (result != LDAP_COMPARE_TRUE)) {
053497224246c4dbef9af594cacf5c00ed271e6cwrowe result = uldap_cache_compare(r, ldc, url,
0540a0b469147b52e858587270dba31c2aaa9e09wrowe values[val_index],
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz "objectClass",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb sgc_ents[tmp_sgcIndex].name
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb );
42da244268b11ec661b528510f80a18b73c51727brianp
42da244268b11ec661b528510f80a18b73c51727brianp if (result != LDAP_COMPARE_TRUE) {
948096a99010fccf648814fecf38f75c689172d7wrowe tmp_sgcIndex++;
948096a99010fccf648814fecf38f75c689172d7wrowe }
948096a99010fccf648814fecf38f75c689172d7wrowe }
948096a99010fccf648814fecf38f75c689172d7wrowe /* It's a group, so add it to the array. */
948096a99010fccf648814fecf38f75c689172d7wrowe if (result == LDAP_COMPARE_TRUE) {
948096a99010fccf648814fecf38f75c689172d7wrowe char **newgrp = (char **) apr_array_push(subgroups);
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz *newgrp = apr_pstrdup(r->pool, values[val_index]);
948096a99010fccf648814fecf38f75c689172d7wrowe }
948096a99010fccf648814fecf38f75c689172d7wrowe val_index++;
948096a99010fccf648814fecf38f75c689172d7wrowe }
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz ldap_value_free(values);
948096a99010fccf648814fecf38f75c689172d7wrowe }
948096a99010fccf648814fecf38f75c689172d7wrowe indx++;
053497224246c4dbef9af594cacf5c00ed271e6cwrowe }
948096a99010fccf648814fecf38f75c689172d7wrowe }
948096a99010fccf648814fecf38f75c689172d7wrowe
948096a99010fccf648814fecf38f75c689172d7wrowe ldap_msgfree(sga_res);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
c2cf53a40a9814eb91db2cdf820f97d943f21628coar if (subgroups->nelts > 0) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* We need to fill in tmp_local_subgroups using the data from LDAP */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar int sgindex;
948096a99010fccf648814fecf38f75c689172d7wrowe char **group;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker res = apr_pcalloc(r->pool, sizeof(util_compare_subgroup_t));
948096a99010fccf648814fecf38f75c689172d7wrowe res->subgroupDNs = apr_pcalloc(r->pool,
948096a99010fccf648814fecf38f75c689172d7wrowe sizeof(char *) * (subgroups->nelts));
053497224246c4dbef9af594cacf5c00ed271e6cwrowe for (sgindex = 0; (group = apr_array_pop(subgroups)); sgindex++) {
a9a4544168a37b43bd180b3703ccee995f27a80awrowe res->subgroupDNs[sgindex] = apr_pstrdup(r->pool, *group);
948096a99010fccf648814fecf38f75c689172d7wrowe }
a9a4544168a37b43bd180b3703ccee995f27a80awrowe res->len = sgindex;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
a9a4544168a37b43bd180b3703ccee995f27a80awrowe
a9a4544168a37b43bd180b3703ccee995f27a80awrowe return res;
a9a4544168a37b43bd180b3703ccee995f27a80awrowe}
a9a4544168a37b43bd180b3703ccee995f27a80awrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar/*
948096a99010fccf648814fecf38f75c689172d7wrowe * Does a recursive lookup operation to try to find a user within (cached)
948096a99010fccf648814fecf38f75c689172d7wrowe * nested groups. It accepts a cache that it will use to lookup previous
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * compare attempts. We cache two kinds of compares (require group compares)
948096a99010fccf648814fecf38f75c689172d7wrowe * and (require user compares). Each compare has a different cache node:
948096a99010fccf648814fecf38f75c689172d7wrowe * require group includes the DN; require user does not because the require
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * user cache is owned by the
948096a99010fccf648814fecf38f75c689172d7wrowe *
948096a99010fccf648814fecf38f75c689172d7wrowe * DON'T CALL THIS UNLESS YOU CALLED uldap_cache_compare FIRST!!!!!
0540a0b469147b52e858587270dba31c2aaa9e09wrowe *
948096a99010fccf648814fecf38f75c689172d7wrowe *
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * 1. Call uldap_cache_compare for each subgroupclass value to check the
948096a99010fccf648814fecf38f75c689172d7wrowe * generic, user-agnostic, cached group entry. This will create a new generic
948096a99010fccf648814fecf38f75c689172d7wrowe * cache entry if there
948096a99010fccf648814fecf38f75c689172d7wrowe * wasn't one. If nothing returns LDAP_COMPARE_TRUE skip to step 5 since we
948096a99010fccf648814fecf38f75c689172d7wrowe * have no groups.
948096a99010fccf648814fecf38f75c689172d7wrowe * 2. Lock The cache and get the generic cache entry.
053497224246c4dbef9af594cacf5c00ed271e6cwrowe * 3. Check if there is already a subgrouplist in this generic group's cache
0540a0b469147b52e858587270dba31c2aaa9e09wrowe * entry.
053497224246c4dbef9af594cacf5c00ed271e6cwrowe * A. If there is, go to step 4.
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * B. If there isn't:
0540a0b469147b52e858587270dba31c2aaa9e09wrowe * i) Use ldap_search to get the full list
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * of subgroup "members" (which may include non-group "members").
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * ii) Use uldap_cache_compare to strip the list down to just groups.
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz * iii) Lock and add this stripped down list to the cache of the generic
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * group.
053497224246c4dbef9af594cacf5c00ed271e6cwrowe * 4. Loop through the sgl and call uldap_cache_compare (using the user info)
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * for each
053497224246c4dbef9af594cacf5c00ed271e6cwrowe * subgroup to see if the subgroup contains the user and to get the subgroups
053497224246c4dbef9af594cacf5c00ed271e6cwrowe * added to the
053497224246c4dbef9af594cacf5c00ed271e6cwrowe * cache (with user-afinity, if they aren't already there).
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * A. If the user is in the subgroup, then we'll be returning
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * LDAP_COMPARE_TRUE.
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * B. if the user isn't in the subgroup (LDAP_COMPARE_FALSE via
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * uldap_cache_compare) then recursively call this function to get the
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * sub-subgroups added...
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * 5. Cleanup local allocations.
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * 6. Return the final result.
4f9c22c4f27571d54197be9674e1fc0d528192aestriker */
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz
053497224246c4dbef9af594cacf5c00ed271e6cwrowestatic int uldap_cache_check_subgroups(request_rec *r,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb util_ldap_connection_t *ldc,
948096a99010fccf648814fecf38f75c689172d7wrowe const char *url, const char *dn,
948096a99010fccf648814fecf38f75c689172d7wrowe const char *attrib, const char *value,
948096a99010fccf648814fecf38f75c689172d7wrowe char **subgroupAttrs,
0540a0b469147b52e858587270dba31c2aaa9e09wrowe apr_array_header_t *subgroupclasses,
948096a99010fccf648814fecf38f75c689172d7wrowe int cur_subgroup_depth,
948096a99010fccf648814fecf38f75c689172d7wrowe int max_subgroup_depth)
948096a99010fccf648814fecf38f75c689172d7wrowe{
948096a99010fccf648814fecf38f75c689172d7wrowe int result = LDAP_COMPARE_FALSE;
948096a99010fccf648814fecf38f75c689172d7wrowe util_url_node_t *curl;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker util_url_node_t curnode;
948096a99010fccf648814fecf38f75c689172d7wrowe util_compare_node_t *compare_nodep;
948096a99010fccf648814fecf38f75c689172d7wrowe util_compare_node_t the_compare_node;
948096a99010fccf648814fecf38f75c689172d7wrowe util_compare_subgroup_t *tmp_local_sgl = NULL;
948096a99010fccf648814fecf38f75c689172d7wrowe int sgl_cached_empty = 0, sgindex = 0, base_sgcIndex = 0;
948096a99010fccf648814fecf38f75c689172d7wrowe struct mod_auth_ldap_groupattr_entry_t *sgc_ents =
948096a99010fccf648814fecf38f75c689172d7wrowe (struct mod_auth_ldap_groupattr_entry_t *) subgroupclasses->elts;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb util_ldap_state_t *st = (util_ldap_state_t *)
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ap_get_module_config(r->server->module_config,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker &ldap_module);
948096a99010fccf648814fecf38f75c689172d7wrowe
0540a0b469147b52e858587270dba31c2aaa9e09wrowe /*
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * Stop looking at deeper levels of nested groups if we have reached the
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * max. Since we already checked the top-level group in uldap_cache_compare,
0540a0b469147b52e858587270dba31c2aaa9e09wrowe * we don't need to check it again here - so if max_subgroup_depth is set
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * to 0, we won't check it (i.e. that is why we check < rather than <=).
696218c49632c863d18b25fa52ab63617088cb38wrowe * We'll be calling uldap_cache_compare from here to check if the user is
948096a99010fccf648814fecf38f75c689172d7wrowe * in the next level before we recurse into that next level looking for
0540a0b469147b52e858587270dba31c2aaa9e09wrowe * more subgroups.
948096a99010fccf648814fecf38f75c689172d7wrowe */
948096a99010fccf648814fecf38f75c689172d7wrowe if (cur_subgroup_depth >= max_subgroup_depth) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker return LDAP_COMPARE_FALSE;
948096a99010fccf648814fecf38f75c689172d7wrowe }
948096a99010fccf648814fecf38f75c689172d7wrowe
053497224246c4dbef9af594cacf5c00ed271e6cwrowe /*
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * 1. Check the "groupiness" of the specified basedn. Stopping at the first
948096a99010fccf648814fecf38f75c689172d7wrowe * TRUE return.
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar */
053497224246c4dbef9af594cacf5c00ed271e6cwrowe while ((base_sgcIndex < subgroupclasses->nelts)
053497224246c4dbef9af594cacf5c00ed271e6cwrowe && (result != LDAP_COMPARE_TRUE)) {
a9a4544168a37b43bd180b3703ccee995f27a80awrowe result = uldap_cache_compare(r, ldc, url, dn, "objectClass",
a9a4544168a37b43bd180b3703ccee995f27a80awrowe sgc_ents[base_sgcIndex].name);
a9a4544168a37b43bd180b3703ccee995f27a80awrowe if (result != LDAP_COMPARE_TRUE) {
948096a99010fccf648814fecf38f75c689172d7wrowe base_sgcIndex++;
948096a99010fccf648814fecf38f75c689172d7wrowe }
053497224246c4dbef9af594cacf5c00ed271e6cwrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
053497224246c4dbef9af594cacf5c00ed271e6cwrowe if (result != LDAP_COMPARE_TRUE) {
053497224246c4dbef9af594cacf5c00ed271e6cwrowe ldc->reason = "DN failed group verification.";
948096a99010fccf648814fecf38f75c689172d7wrowe return result;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
948096a99010fccf648814fecf38f75c689172d7wrowe
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 2. Find previously created cache entry and check if there is already a
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * subgrouplist.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe LDAP_CACHE_LOCK();
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb curnode.url = url;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);
aa047239dedf0d26e8efecfade32e7337f35df19wrowe LDAP_CACHE_UNLOCK();
aa047239dedf0d26e8efecfade32e7337f35df19wrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (curl && curl->compare_cache) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe /* make a comparison to the cache */
aa047239dedf0d26e8efecfade32e7337f35df19wrowe LDAP_CACHE_LOCK();
aa047239dedf0d26e8efecfade32e7337f35df19wrowe
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb the_compare_node.dn = (char *)dn;
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe the_compare_node.attrib = (char *)"objectClass";
4f9c22c4f27571d54197be9674e1fc0d528192aestriker the_compare_node.value = (char *)sgc_ents[base_sgcIndex].name;
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe the_compare_node.result = 0;
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe the_compare_node.sgl_processed = 0;
b5bd19d82874782007a2f9bcb19341a483c1270cwrowe the_compare_node.subgroupList = NULL;
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe compare_nodep = util_ald_cache_fetch(curl->compare_cache,
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe &the_compare_node);
a2b181763cb35fd899feb4a436aeadaa80bf91eabrianp
aa047239dedf0d26e8efecfade32e7337f35df19wrowe if (compare_nodep != NULL) {
aa047239dedf0d26e8efecfade32e7337f35df19wrowe /*
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * Found the generic group entry... but the user isn't in this
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * group or we wouldn't be here.
aa047239dedf0d26e8efecfade32e7337f35df19wrowe */
0540a0b469147b52e858587270dba31c2aaa9e09wrowe if (compare_nodep->sgl_processed) {
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (compare_nodep->subgroupList) {
aa047239dedf0d26e8efecfade32e7337f35df19wrowe /* Make a local copy of the subgroup list */
aa047239dedf0d26e8efecfade32e7337f35df19wrowe int i;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
aa047239dedf0d26e8efecfade32e7337f35df19wrowe "Making local copy of SGL for "
aa047239dedf0d26e8efecfade32e7337f35df19wrowe "group (%s)(objectClass=%s) ",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb dn, (char *)sgc_ents[base_sgcIndex].name);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb tmp_local_sgl = apr_pcalloc(r->pool,
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz sizeof(util_compare_subgroup_t));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb tmp_local_sgl->len = compare_nodep->subgroupList->len;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb tmp_local_sgl->subgroupDNs =
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz apr_pcalloc(r->pool,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb sizeof(char *) * compare_nodep->subgroupList->len);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb for (i = 0; i < compare_nodep->subgroupList->len; i++) {
aa047239dedf0d26e8efecfade32e7337f35df19wrowe tmp_local_sgl->subgroupDNs[i] =
4f9c22c4f27571d54197be9674e1fc0d528192aestriker apr_pstrdup(r->pool,
aa047239dedf0d26e8efecfade32e7337f35df19wrowe compare_nodep->subgroupList->subgroupDNs[i]);
aa047239dedf0d26e8efecfade32e7337f35df19wrowe }
c2cf53a40a9814eb91db2cdf820f97d943f21628coar }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker else {
c2cf53a40a9814eb91db2cdf820f97d943f21628coar sgl_cached_empty = 1;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
aa047239dedf0d26e8efecfade32e7337f35df19wrowe }
aa047239dedf0d26e8efecfade32e7337f35df19wrowe LDAP_CACHE_UNLOCK();
aa047239dedf0d26e8efecfade32e7337f35df19wrowe }
a9a4544168a37b43bd180b3703ccee995f27a80awrowe
a9a4544168a37b43bd180b3703ccee995f27a80awrowe if (!tmp_local_sgl && !sgl_cached_empty) {
a9a4544168a37b43bd180b3703ccee995f27a80awrowe /* No Cached SGL, retrieve from LDAP */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
a9a4544168a37b43bd180b3703ccee995f27a80awrowe "no cached SGL for %s, retrieving from LDAP", dn);
a9a4544168a37b43bd180b3703ccee995f27a80awrowe tmp_local_sgl = uldap_get_subgroups(r, ldc, url, dn, subgroupAttrs,
aa047239dedf0d26e8efecfade32e7337f35df19wrowe subgroupclasses);
a9a4544168a37b43bd180b3703ccee995f27a80awrowe if (!tmp_local_sgl) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* No SGL aailable via LDAP either */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "no subgroups for %s",
aa047239dedf0d26e8efecfade32e7337f35df19wrowe dn);
c2cf53a40a9814eb91db2cdf820f97d943f21628coar }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
aa047239dedf0d26e8efecfade32e7337f35df19wrowe if (curl && curl->compare_cache) {
aa047239dedf0d26e8efecfade32e7337f35df19wrowe /*
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * Find the generic group cache entry and add the sgl we just retrieved.
aa047239dedf0d26e8efecfade32e7337f35df19wrowe */
aa047239dedf0d26e8efecfade32e7337f35df19wrowe LDAP_CACHE_LOCK();
0540a0b469147b52e858587270dba31c2aaa9e09wrowe
aa047239dedf0d26e8efecfade32e7337f35df19wrowe the_compare_node.dn = (char *)dn;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe the_compare_node.attrib = (char *)"objectClass";
aa047239dedf0d26e8efecfade32e7337f35df19wrowe the_compare_node.value = (char *)sgc_ents[base_sgcIndex].name;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb the_compare_node.result = 0;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe the_compare_node.sgl_processed = 0;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe the_compare_node.subgroupList = NULL;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb compare_nodep = util_ald_cache_fetch(curl->compare_cache,
0540a0b469147b52e858587270dba31c2aaa9e09wrowe &the_compare_node);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
0540a0b469147b52e858587270dba31c2aaa9e09wrowe if (compare_nodep == NULL) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe /*
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * The group entry we want to attach our SGL to doesn't exist.
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * We only got here if we verified this DN was actually a group
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * based on the objectClass, but we can't call the compare function
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * while we already hold the cache lock -- only the insert.
c2cf53a40a9814eb91db2cdf820f97d943f21628coar */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
aa047239dedf0d26e8efecfade32e7337f35df19wrowe "Cache entry for %s doesn't exist", dn);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb the_compare_node.result = LDAP_COMPARE_TRUE;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe util_ald_cache_insert(curl->compare_cache, &the_compare_node);
aa047239dedf0d26e8efecfade32e7337f35df19wrowe compare_nodep = util_ald_cache_fetch(curl->compare_cache,
aa047239dedf0d26e8efecfade32e7337f35df19wrowe &the_compare_node);
aa047239dedf0d26e8efecfade32e7337f35df19wrowe if (compare_nodep == NULL) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
aa047239dedf0d26e8efecfade32e7337f35df19wrowe "util_ldap: Couldn't retrieve group entry "
aa047239dedf0d26e8efecfade32e7337f35df19wrowe "for %s from cache",
aa047239dedf0d26e8efecfade32e7337f35df19wrowe dn);
aa047239dedf0d26e8efecfade32e7337f35df19wrowe }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
aa047239dedf0d26e8efecfade32e7337f35df19wrowe /*
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * We have a valid cache entry and a locally generated SGL.
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * Attach the SGL to the cache entry
aa047239dedf0d26e8efecfade32e7337f35df19wrowe */
aa047239dedf0d26e8efecfade32e7337f35df19wrowe if (compare_nodep && !compare_nodep->sgl_processed) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (!tmp_local_sgl) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* We looked up an SGL for a group and found it to be empty */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar if (compare_nodep->subgroupList == NULL) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker compare_nodep->sgl_processed = 1;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe }
0540a0b469147b52e858587270dba31c2aaa9e09wrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar else {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar util_compare_subgroup_t *sgl_copy =
0540a0b469147b52e858587270dba31c2aaa9e09wrowe util_ald_sgl_dup(curl->compare_cache, tmp_local_sgl);
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
aa047239dedf0d26e8efecfade32e7337f35df19wrowe "Copying local SGL of len %d for group %s into cache",
aa047239dedf0d26e8efecfade32e7337f35df19wrowe tmp_local_sgl->len, dn);
0540a0b469147b52e858587270dba31c2aaa9e09wrowe if (sgl_copy) {
aa047239dedf0d26e8efecfade32e7337f35df19wrowe if (compare_nodep->subgroupList) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb util_ald_sgl_free(curl->compare_cache,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker &(compare_nodep->subgroupList));
aa047239dedf0d26e8efecfade32e7337f35df19wrowe }
aa047239dedf0d26e8efecfade32e7337f35df19wrowe compare_nodep->subgroupList = sgl_copy;
aa047239dedf0d26e8efecfade32e7337f35df19wrowe compare_nodep->sgl_processed = 1;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
aa047239dedf0d26e8efecfade32e7337f35df19wrowe else {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Copy of SGL failed to obtain shared memory, "
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe "couldn't update cache");
a9a4544168a37b43bd180b3703ccee995f27a80awrowe }
a9a4544168a37b43bd180b3703ccee995f27a80awrowe }
a9a4544168a37b43bd180b3703ccee995f27a80awrowe }
aa047239dedf0d26e8efecfade32e7337f35df19wrowe LDAP_CACHE_UNLOCK();
aa047239dedf0d26e8efecfade32e7337f35df19wrowe }
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
aa047239dedf0d26e8efecfade32e7337f35df19wrowe /*
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * tmp_local_sgl has either been created, or copied out of the cache
aa047239dedf0d26e8efecfade32e7337f35df19wrowe * If tmp_local_sgl is NULL, there are no subgroups to process and we'll
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * return false
aa047239dedf0d26e8efecfade32e7337f35df19wrowe */
dc8692c6c0ca616a09aa12dad005f2ef23baa1a0wrowe result = LDAP_COMPARE_FALSE;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (!tmp_local_sgl) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return result;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb while ((result != LDAP_COMPARE_TRUE) && (sgindex < tmp_local_sgl->len)) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb const char *group = NULL;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb group = tmp_local_sgl->subgroupDNs[sgindex];
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 4. Now loop through the subgroupList and call uldap_cache_compare
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * to check for the user.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb result = uldap_cache_compare(r, ldc, url, group, attrib, value);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (result == LDAP_COMPARE_TRUE) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 4.A. We found the user in the subgroup. Return
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * LDAP_COMPARE_TRUE.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Found user %s in a subgroup (%s) at level %d of %d.",
4f9c22c4f27571d54197be9674e1fc0d528192aestriker r->user, group, cur_subgroup_depth+1,
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe max_subgroup_depth);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb else {
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe /*
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * 4.B. We didn't find the user in this subgroup, so recurse into
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * it and keep looking.
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe */
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "User %s not found in subgroup (%s) at level %d of "
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe "%d.", r->user, group, cur_subgroup_depth+1,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe max_subgroup_depth);
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe result = uldap_cache_check_subgroups(r, ldc, url, group, attrib,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe value, subgroupAttrs,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe subgroupclasses,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe cur_subgroup_depth+1,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe max_subgroup_depth);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe }
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe sgindex++;
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe return result;
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe}
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe
4f9c22c4f27571d54197be9674e1fc0d528192aestrikerstatic int uldap_cache_checkuserid(request_rec *r, util_ldap_connection_t *ldc,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe const char *url, const char *basedn,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe int scope, char **attrs, const char *filter,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe const char *bindpw, const char **binddn,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe const char ***retvals)
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe{
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe const char **vals = NULL;
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe int numvals = 0;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb int result = 0;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb LDAPMessage *res, *entry;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb char *dn;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb int count;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker int failures = 0;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker util_url_node_t *curl; /* Cached URL node */
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe util_url_node_t curnode;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker util_search_node_t *search_nodep; /* Cached search node */
e57e920838f31508f1418aa4c25ce55b345b2cebrbb util_search_node_t the_search_node;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker apr_time_t curtime;
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe util_ldap_state_t *st =
e57e920838f31508f1418aa4c25ce55b345b2cebrbb (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
e57e920838f31508f1418aa4c25ce55b345b2cebrbb &ldap_module);
e57e920838f31508f1418aa4c25ce55b345b2cebrbb
e57e920838f31508f1418aa4c25ce55b345b2cebrbb /* Get the cache node for this url */
e57e920838f31508f1418aa4c25ce55b345b2cebrbb LDAP_CACHE_LOCK();
e57e920838f31508f1418aa4c25ce55b345b2cebrbb curnode.url = url;
e57e920838f31508f1418aa4c25ce55b345b2cebrbb curl = (util_url_node_t *)util_ald_cache_fetch(st->util_ldap_cache,
e57e920838f31508f1418aa4c25ce55b345b2cebrbb &curnode);
e57e920838f31508f1418aa4c25ce55b345b2cebrbb if (curl == NULL) {
e57e920838f31508f1418aa4c25ce55b345b2cebrbb curl = util_ald_create_caches(st, url);
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe }
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe LDAP_CACHE_UNLOCK();
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe if (curl) {
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe LDAP_CACHE_LOCK();
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe the_search_node.username = filter;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker search_nodep = util_ald_cache_fetch(curl->search_cache,
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe &the_search_node);
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe if (search_nodep != NULL) {
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe /* found entry in search cache... */
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe curtime = apr_time_now();
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe /*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Remove this item from the cache if its expired. If the sent
c2cf53a40a9814eb91db2cdf820f97d943f21628coar * password doesn't match the storepassword, the entry will
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * be removed and readded later if the credentials pass
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * authentication.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if ((curtime - search_nodep->lastbind) > st->search_cache_ttl) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ...but entry is too old */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb util_ald_cache_remove(curl->search_cache, search_nodep);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
68b29bcadd6c46aecdc9fe14c93555a2238ad2aagregames else if ( (search_nodep->bindpw)
68b29bcadd6c46aecdc9fe14c93555a2238ad2aagregames && (search_nodep->bindpw[0] != '\0')
68b29bcadd6c46aecdc9fe14c93555a2238ad2aagregames && (strcmp(search_nodep->bindpw, bindpw) == 0))
4f9c22c4f27571d54197be9674e1fc0d528192aestriker {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* ...and entry is valid */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *binddn = apr_pstrdup(r->pool, search_nodep->dn);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (attrs) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker int i;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *retvals = apr_pcalloc(r->pool, sizeof(char *) * search_nodep->numvals);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb for (i = 0; i < search_nodep->numvals; i++) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb (*retvals)[i] = apr_pstrdup(r->pool, search_nodep->vals[i]);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb LDAP_CACHE_UNLOCK();
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = "Authentication successful (cached)";
4f9c22c4f27571d54197be9674e1fc0d528192aestriker return LDAP_SUCCESS;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar /* unlock this read lock */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker LDAP_CACHE_UNLOCK();
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar /*
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar * At this point, there is no valid cached search, so lets do the search.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar /*
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * If LDAP operation fails due to LDAP_SERVER_DOWN, control returns here.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
4f9c22c4f27571d54197be9674e1fc0d528192aestrikerstart_over:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (failures++ > 10) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe return result;
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe }
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe return result;
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe /* try do the search */
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe result = ldap_search_ext_s(ldc->ldap,
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe (char *)basedn, scope,
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe (char *)filter, attrs, 0,
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe NULL, NULL, st->opTimeout, APR_LDAP_SIZELIMIT, &res);
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbb if (AP_LDAP_IS_SERVER_DOWN(result))
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = "ldap_search_ext_s() for user failed with server down";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb uldap_connection_unbind(ldc);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb goto start_over;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar /* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (result != LDAP_SUCCESS) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = "ldap_search_ext_s() for user failed";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return result;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard /*
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard * We should have found exactly one entry; to find a different
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard * number is an error.
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard */
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard count = ldap_count_entries(ldc->ldap, res);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (count != 1)
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard {
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard if (count == 0 )
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard ldc->reason = "User not found";
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard else
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard ldc->reason = "User is not unique (search found two "
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "or more matches)";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldap_msgfree(res);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return LDAP_NO_SUCH_OBJECT;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb entry = ldap_first_entry(ldc->ldap, res);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Grab the dn, copy it into the pool, and free it again */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb dn = ldap_get_dn(ldc->ldap, entry);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb *binddn = apr_pstrdup(r->pool, dn);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldap_memfree(dn);
efa1a34b0a7785fc72863eff175b0cfc1ecb0e38wrowe
117026201e6d8fe7d82416b8a7324830f5a87292wrowe /*
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe * A bind to the server with an empty password always succeeds, so
117026201e6d8fe7d82416b8a7324830f5a87292wrowe * we check to ensure that the password is not empty. This implies
117026201e6d8fe7d82416b8a7324830f5a87292wrowe * that users who actually do have empty passwords will never be
117026201e6d8fe7d82416b8a7324830f5a87292wrowe * able to authenticate with this module. I don't see this as a big
117026201e6d8fe7d82416b8a7324830f5a87292wrowe * problem.
117026201e6d8fe7d82416b8a7324830f5a87292wrowe */
6c24fd6cfe148639988d5b335185ffb215662801wrowe if (!bindpw || strlen(bindpw) <= 0) {
117026201e6d8fe7d82416b8a7324830f5a87292wrowe ldap_msgfree(res);
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe ldc->reason = "Empty password not allowed";
117026201e6d8fe7d82416b8a7324830f5a87292wrowe return LDAP_INVALID_CREDENTIALS;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
cadddb2c31d24d48f4017db4df0a29687432326cwrowe
117026201e6d8fe7d82416b8a7324830f5a87292wrowe /*
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames * Attempt to bind with the retrieved dn and the password. If the bind
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames * fails, it means that the password is wrong (the dn obviously
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe * exists, since we just retrieved it)
4f9c22c4f27571d54197be9674e1fc0d528192aestriker */
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe result = uldap_simple_bind(ldc, (char *)*binddn, (char *)bindpw,
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe st->opTimeout);
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe if (AP_LDAP_IS_SERVER_DOWN(result) ||
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames (result == LDAP_TIMEOUT && failures == 0)) {
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames if (AP_LDAP_IS_SERVER_DOWN(result))
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames ldc->reason = "ldap_simple_bind() to check user credentials "
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames "failed with server down";
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe else
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe ldc->reason = "ldap_simple_bind() to check user credentials "
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe "timed out";
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe ldap_msgfree(res);
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe uldap_connection_unbind(ldc);
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe goto start_over;
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames }
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames /* failure? if so - return */
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe if (result != LDAP_SUCCESS) {
f888346b48f5e5b5e3f0a47dedb8cefd2759a4e2gregames ldc->reason = "ldap_simple_bind() to check user credentials failed";
4f9c22c4f27571d54197be9674e1fc0d528192aestriker ldap_msgfree(res);
cadddb2c31d24d48f4017db4df0a29687432326cwrowe uldap_connection_unbind(ldc);
117026201e6d8fe7d82416b8a7324830f5a87292wrowe return result;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
e7505ba54ac56ae30e4e250f912f3dbaf92ca45fwrowe else {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar /*
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * We have just bound the connection to a different user and password
cadddb2c31d24d48f4017db4df0a29687432326cwrowe * combination, which might be reused unintentionally next time this
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * connection is used from the connection pool. To ensure no confusion,
4f9c22c4f27571d54197be9674e1fc0d528192aestriker * we mark the connection as unbound.
cadddb2c31d24d48f4017db4df0a29687432326cwrowe */
5b3abd2fecc712f08ad728114aa77137b9f67716wrowe ldc->bound = 0;
85bb5b92490e4f095aae394118fc588a8f4c486fwrowe }
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe
efa1a34b0a7785fc72863eff175b0cfc1ecb0e38wrowe /*
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * Get values for the provided attributes.
beda1fb2f11c52ca4612460a5d5ba47398143efbwrowe */
beda1fb2f11c52ca4612460a5d5ba47398143efbwrowe if (attrs) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker int k = 0;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker int i = 0;
beda1fb2f11c52ca4612460a5d5ba47398143efbwrowe while (attrs[k++]);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe vals = apr_pcalloc(r->pool, sizeof(char *) * (k+1));
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe numvals = k;
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe while (attrs[i]) {
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe char **values;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar int j = 0;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar char *str = NULL;
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* get values */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar values = ldap_get_values(ldc->ldap, entry, attrs[i]);
117026201e6d8fe7d82416b8a7324830f5a87292wrowe while (values && values[j]) {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar str = str ? apr_pstrcat(r->pool, str, "; ", values[j], NULL)
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe : apr_pstrdup(r->pool, values[j]);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe j++;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar }
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe ldap_value_free(values);
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar vals[i] = str;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar i++;
117026201e6d8fe7d82416b8a7324830f5a87292wrowe }
117026201e6d8fe7d82416b8a7324830f5a87292wrowe *retvals = vals;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar }
117026201e6d8fe7d82416b8a7324830f5a87292wrowe
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe /*
cadddb2c31d24d48f4017db4df0a29687432326cwrowe * Add the new username to the search cache.
cadddb2c31d24d48f4017db4df0a29687432326cwrowe */
cadddb2c31d24d48f4017db4df0a29687432326cwrowe if (curl) {
cadddb2c31d24d48f4017db4df0a29687432326cwrowe LDAP_CACHE_LOCK();
4f9c22c4f27571d54197be9674e1fc0d528192aestriker the_search_node.username = filter;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar the_search_node.dn = *binddn;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar the_search_node.bindpw = bindpw;
cadddb2c31d24d48f4017db4df0a29687432326cwrowe the_search_node.lastbind = apr_time_now();
cadddb2c31d24d48f4017db4df0a29687432326cwrowe the_search_node.vals = vals;
cadddb2c31d24d48f4017db4df0a29687432326cwrowe the_search_node.numvals = numvals;
cadddb2c31d24d48f4017db4df0a29687432326cwrowe
cadddb2c31d24d48f4017db4df0a29687432326cwrowe /* Search again to make sure that another thread didn't ready insert
cadddb2c31d24d48f4017db4df0a29687432326cwrowe * this node into the cache before we got here. If it does exist then
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe * update the lastbind
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe */
cadddb2c31d24d48f4017db4df0a29687432326cwrowe search_nodep = util_ald_cache_fetch(curl->search_cache,
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe &the_search_node);
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe if ((search_nodep == NULL) ||
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe (strcmp(*binddn, search_nodep->dn) != 0)) {
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar
cadddb2c31d24d48f4017db4df0a29687432326cwrowe /* Nothing in cache, insert new entry */
cadddb2c31d24d48f4017db4df0a29687432326cwrowe util_ald_cache_insert(curl->search_cache, &the_search_node);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe else if ((!search_nodep->bindpw) ||
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe (strcmp(bindpw, search_nodep->bindpw) != 0)) {
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* Entry in cache is invalid, remove it and insert new one */
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe util_ald_cache_remove(curl->search_cache, search_nodep);
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe util_ald_cache_insert(curl->search_cache, &the_search_node);
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe }
3cd826b00280881e5a2f03d8ec1f8d55802b93dewrowe else {
cadddb2c31d24d48f4017db4df0a29687432326cwrowe /* Cache entry is valid, update lastbind */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe search_nodep->lastbind = the_search_node.lastbind;
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe }
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe LDAP_CACHE_UNLOCK();
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe }
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe ldap_msgfree(res);
117026201e6d8fe7d82416b8a7324830f5a87292wrowe
117026201e6d8fe7d82416b8a7324830f5a87292wrowe ldc->reason = "Authentication successful";
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe return LDAP_SUCCESS;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar}
c2cf53a40a9814eb91db2cdf820f97d943f21628coar
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This function will return the DN of the entry matching userid.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * It is used to get the DN in case some other module than mod_auth_ldap
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * has authenticated the user.
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe * The function is basically a copy of uldap_cache_checkuserid
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * with password checking removed.
d2220a04f870f632b8cec1e6713dbb980ed5e386wrowe */
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbbstatic int uldap_cache_getuserdn(request_rec *r, util_ldap_connection_t *ldc,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb const char *url, const char *basedn,
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe int scope, char **attrs, const char *filter,
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe const char **binddn, const char ***retvals)
ecc4a080f07af3fbc1b91bbd00997ec1d592c6f9wrowe{
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe const char **vals = NULL;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar int numvals = 0;
2d2dadb81bf34e3bc9321eabcd971a738431b364wrowe int result = 0;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar LDAPMessage *res, *entry;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker char *dn;
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe int count;
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe int failures = 0;
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe util_url_node_t *curl; /* Cached URL node */
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe util_url_node_t curnode;
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe util_search_node_t *search_nodep; /* Cached search node */
4f9c22c4f27571d54197be9674e1fc0d528192aestriker util_search_node_t the_search_node;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar apr_time_t curtime;
ecc4a080f07af3fbc1b91bbd00997ec1d592c6f9wrowe
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar util_ldap_state_t *st =
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb &ldap_module);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
4f9c22c4f27571d54197be9674e1fc0d528192aestriker /* Get the cache node for this url */
5b3abd2fecc712f08ad728114aa77137b9f67716wrowe LDAP_CACHE_LOCK();
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb curnode.url = url;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb curl = (util_url_node_t *)util_ald_cache_fetch(st->util_ldap_cache,
af7e32b660b02a378e91d40987e59b28864db954jwoolley &curnode);
4f9c22c4f27571d54197be9674e1fc0d528192aestriker if (curl == NULL) {
c2cf53a40a9814eb91db2cdf820f97d943f21628coar curl = util_ald_create_caches(st, url);
0540a0b469147b52e858587270dba31c2aaa9e09wrowe }
0540a0b469147b52e858587270dba31c2aaa9e09wrowe LDAP_CACHE_UNLOCK();
0540a0b469147b52e858587270dba31c2aaa9e09wrowe
c2cf53a40a9814eb91db2cdf820f97d943f21628coar if (curl) {
c2cf53a40a9814eb91db2cdf820f97d943f21628coar LDAP_CACHE_LOCK();
0540a0b469147b52e858587270dba31c2aaa9e09wrowe the_search_node.username = filter;
c2cf53a40a9814eb91db2cdf820f97d943f21628coar search_nodep = util_ald_cache_fetch(curl->search_cache,
0540a0b469147b52e858587270dba31c2aaa9e09wrowe &the_search_node);
0540a0b469147b52e858587270dba31c2aaa9e09wrowe if (search_nodep != NULL) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe
0540a0b469147b52e858587270dba31c2aaa9e09wrowe /* found entry in search cache... */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar curtime = apr_time_now();
0540a0b469147b52e858587270dba31c2aaa9e09wrowe
c2cf53a40a9814eb91db2cdf820f97d943f21628coar /*
0540a0b469147b52e858587270dba31c2aaa9e09wrowe * Remove this item from the cache if its expired.
7763a4beb8afca9c8f93db0cb6836124901af52awrowe */
0540a0b469147b52e858587270dba31c2aaa9e09wrowe if ((curtime - search_nodep->lastbind) > st->search_cache_ttl) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe /* ...but entry is too old */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar util_ald_cache_remove(curl->search_cache, search_nodep);
c2cf53a40a9814eb91db2cdf820f97d943f21628coar }
0540a0b469147b52e858587270dba31c2aaa9e09wrowe else {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe /* ...and entry is valid */
0540a0b469147b52e858587270dba31c2aaa9e09wrowe *binddn = apr_pstrdup(r->pool, search_nodep->dn);
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (attrs) {
0540a0b469147b52e858587270dba31c2aaa9e09wrowe int i;
0540a0b469147b52e858587270dba31c2aaa9e09wrowe *retvals = apr_pcalloc(r->pool, sizeof(char *) * search_nodep->numvals);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb for (i = 0; i < search_nodep->numvals; i++) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb (*retvals)[i] = apr_pstrdup(r->pool, search_nodep->vals[i]);
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz }
5b3abd2fecc712f08ad728114aa77137b9f67716wrowe }
5b3abd2fecc712f08ad728114aa77137b9f67716wrowe LDAP_CACHE_UNLOCK();
5b3abd2fecc712f08ad728114aa77137b9f67716wrowe ldc->reason = "Search successful (cached)";
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz return LDAP_SUCCESS;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* unlock this read lock */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb LDAP_CACHE_UNLOCK();
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
58097d7d8d1a394092374b9f6ddf76b7993724a4rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * At this point, there is no valid cached search, so lets do the search.
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /*
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * If LDAP operation fails due to LDAP_SERVER_DOWN, control returns here.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstart_over:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (failures++ > 10) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return result;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard return result;
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard }
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard /* try do the search */
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard result = ldap_search_ext_s(ldc->ldap,
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard (char *)basedn, scope,
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard (char *)filter, attrs, 0,
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard NULL, NULL, st->opTimeout, APR_LDAP_SIZELIMIT, &res);
30b4a330a5f651eb5198fa93dbb9f3d3594564c9stoddard if (AP_LDAP_IS_SERVER_DOWN(result))
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = "ldap_search_ext_s() for user failed with server down";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb uldap_connection_unbind(ldc);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb goto start_over;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (result != LDAP_SUCCESS) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = "ldap_search_ext_s() for user failed";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return result;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb }
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * We should have found exactly one entry; to find a different
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * number is an error.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb count = ldap_count_entries(ldc->ldap, res);
d4abb06ac220bb280ae996b6d21bbd257db51bb1jerenkrantz if (count != 1)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if (count == 0 )
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = "User not found";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb else
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldc->reason = "User is not unique (search found two "
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "or more matches)";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ldap_msgfree(res);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return LDAP_NO_SUCH_OBJECT;
4f9c22c4f27571d54197be9674e1fc0d528192aestriker }
4f9c22c4f27571d54197be9674e1fc0d528192aestriker
4f9c22c4f27571d54197be9674e1fc0d528192aestriker entry = ldap_first_entry(ldc->ldap, res);
/* Grab the dn, copy it into the pool, and free it again */
dn = ldap_get_dn(ldc->ldap, entry);
*binddn = apr_pstrdup(r->pool, dn);
ldap_memfree(dn);
/*
* Get values for the provided attributes.
*/
if (attrs) {
int k = 0;
int i = 0;
while (attrs[k++]);
vals = apr_pcalloc(r->pool, sizeof(char *) * (k+1));
numvals = k;
while (attrs[i]) {
char **values;
int j = 0;
char *str = NULL;
/* get values */
values = ldap_get_values(ldc->ldap, entry, attrs[i]);
while (values && values[j]) {
str = str ? apr_pstrcat(r->pool, str, "; ", values[j], NULL)
: apr_pstrdup(r->pool, values[j]);
j++;
}
ldap_value_free(values);
vals[i] = str;
i++;
}
*retvals = vals;
}
/*
* Add the new username to the search cache.
*/
if (curl) {
LDAP_CACHE_LOCK();
the_search_node.username = filter;
the_search_node.dn = *binddn;
the_search_node.bindpw = NULL;
the_search_node.lastbind = apr_time_now();
the_search_node.vals = vals;
the_search_node.numvals = numvals;
/* 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
*/
search_nodep = util_ald_cache_fetch(curl->search_cache,
&the_search_node);
if ((search_nodep == NULL) ||
(strcmp(*binddn, search_nodep->dn) != 0)) {
/* Nothing in cache, insert new entry */
util_ald_cache_insert(curl->search_cache, &the_search_node);
}
/*
* 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 */
search_nodep->lastbind = the_search_node.lastbind;
}
LDAP_CACHE_UNLOCK();
}
ldap_msgfree(res);
ldc->reason = "Search successful";
return LDAP_SUCCESS;
}
/*
* Reports if ssl support is enabled
*
* 1 = enabled, 0 = not enabled
*/
static int uldap_ssl_supported(request_rec *r)
{
util_ldap_state_t *st = (util_ldap_state_t *)ap_get_module_config(
r->server->module_config, &ldap_module);
return(st->ssl_supported);
}
/* ---------------------------------------- */
/* config directives */
static const char *util_ldap_set_cache_bytes(cmd_parms *cmd, void *dummy,
const char *bytes)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
st->cache_bytes = atol(bytes);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"ldap cache: Setting shared memory cache size to "
"%" APR_SIZE_T_FMT " bytes.",
st->cache_bytes);
return NULL;
}
static const char *util_ldap_set_cache_file(cmd_parms *cmd, void *dummy,
const char *file)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
if (file) {
st->cache_file = ap_server_root_relative(st->pool, file);
}
else {
st->cache_file = NULL;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"LDAP cache: Setting shared memory cache file to %s bytes.",
st->cache_file);
return NULL;
}
static const char *util_ldap_set_cache_ttl(cmd_parms *cmd, void *dummy,
const char *ttl)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
st->search_cache_ttl = atol(ttl) * 1000000;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"ldap cache: Setting cache TTL to %ld microseconds.",
st->search_cache_ttl);
return NULL;
}
static const char *util_ldap_set_cache_entries(cmd_parms *cmd, void *dummy,
const char *size)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
st->search_cache_size = atol(size);
if (st->search_cache_size < 0) {
st->search_cache_size = 0;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"ldap cache: Setting search cache size to %ld entries.",
st->search_cache_size);
return NULL;
}
static const char *util_ldap_set_opcache_ttl(cmd_parms *cmd, void *dummy,
const char *ttl)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
st->compare_cache_ttl = atol(ttl) * 1000000;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"ldap cache: Setting operation cache TTL to %ld microseconds.",
st->compare_cache_ttl);
return NULL;
}
static const char *util_ldap_set_opcache_entries(cmd_parms *cmd, void *dummy,
const char *size)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
st->compare_cache_size = atol(size);
if (st->compare_cache_size < 0) {
st->compare_cache_size = 0;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"ldap cache: Setting operation cache size to %ld entries.",
st->compare_cache_size);
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 int util_ldap_parse_cert_type(const char *type)
{
/* Authority file in binary DER format */
if (0 == strcasecmp("CA_DER", type)) {
return APR_LDAP_CA_TYPE_DER;
}
/* Authority file in Base64 format */
else if (0 == strcasecmp("CA_BASE64", type)) {
return APR_LDAP_CA_TYPE_BASE64;
}
/* Netscape certificate database file/directory */
else if (0 == strcasecmp("CA_CERT7_DB", type)) {
return APR_LDAP_CA_TYPE_CERT7_DB;
}
/* Netscape secmod file/directory */
else if (0 == strcasecmp("CA_SECMOD", type)) {
return APR_LDAP_CA_TYPE_SECMOD;
}
/* Client cert file in DER format */
else if (0 == strcasecmp("CERT_DER", type)) {
return APR_LDAP_CERT_TYPE_DER;
}
/* Client cert file in Base64 format */
else if (0 == strcasecmp("CERT_BASE64", type)) {
return APR_LDAP_CERT_TYPE_BASE64;
}
/* Client cert file in PKCS#12 format */
else if (0 == strcasecmp("CERT_PFX", type)) {
return APR_LDAP_CERT_TYPE_PFX;
}
/* Netscape client cert database file/directory */
else if (0 == strcasecmp("CERT_KEY3_DB", type)) {
return APR_LDAP_CERT_TYPE_KEY3_DB;
}
/* Netscape client cert nickname */
else if (0 == strcasecmp("CERT_NICKNAME", type)) {
return APR_LDAP_CERT_TYPE_NICKNAME;
}
/* Client cert key file in DER format */
else if (0 == strcasecmp("KEY_DER", type)) {
return APR_LDAP_KEY_TYPE_DER;
}
/* Client cert key file in Base64 format */
else if (0 == strcasecmp("KEY_BASE64", type)) {
return APR_LDAP_KEY_TYPE_BASE64;
}
/* Client cert key file in PKCS#12 format */
else if (0 == strcasecmp("KEY_PFX", type)) {
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.
*/
static const char *util_ldap_set_trusted_global_cert(cmd_parms *cmd,
void *dummy,
const char *type,
const char *file,
const char *password)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
apr_finfo_t finfo;
apr_status_t rv;
int cert_type = 0;
apr_ldap_opt_tls_cert_t *cert;
if (err != NULL) {
return err;
}
/* handle the certificate type */
if (type) {
cert_type = util_ldap_parse_cert_type(type);
if (APR_LDAP_CA_TYPE_UNKNOWN == cert_type) {
return apr_psprintf(cmd->pool, "The certificate type %s is "
"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.";
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"LDAP: SSL trusted global cert - %s (type %s)",
file, type);
/* add the certificate to the global array */
cert = (apr_ldap_opt_tls_cert_t *)apr_array_push(st->global_certs);
cert->type = cert_type;
cert->path = file;
cert->password = password;
/* if file is a file or path, fix the path */
if (cert_type != APR_LDAP_CA_TYPE_UNKNOWN &&
cert_type != APR_LDAP_CERT_TYPE_NICKNAME) {
cert->path = ap_server_root_relative(cmd->pool, file);
if (cert->path &&
((rv = apr_stat (&finfo, cert->path, APR_FINFO_MIN, cmd->pool))
!= APR_SUCCESS))
{
ap_log_error(APLOG_MARK, APLOG_ERR, rv, cmd->server,
"LDAP: Could not open SSL trusted certificate "
"authority file - %s",
cert->path == NULL ? file : cert->path);
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)
*/
static const char *util_ldap_set_trusted_client_cert(cmd_parms *cmd,
void *config,
const char *type,
const char *file,
const char *password)
{
util_ldap_config_t *dc = config;
apr_finfo_t finfo;
apr_status_t rv;
int cert_type = 0;
apr_ldap_opt_tls_cert_t *cert;
/* handle the certificate type */
if (type) {
cert_type = util_ldap_parse_cert_type(type);
if (APR_LDAP_CA_TYPE_UNKNOWN == cert_type) {
return apr_psprintf(cmd->pool, "The certificate type \"%s\" is "
"not recognised. It should be one "
"of CA_DER, CA_BASE64, "
"CERT_DER, CERT_BASE64, "
"CERT_NICKNAME, CERT_PFX, "
"KEY_DER, KEY_BASE64, KEY_PFX",
type);
}
else if ( APR_LDAP_CA_TYPE_CERT7_DB == cert_type ||
APR_LDAP_CA_TYPE_SECMOD == cert_type ||
APR_LDAP_CERT_TYPE_PFX == cert_type ||
APR_LDAP_CERT_TYPE_KEY3_DB == cert_type) {
return apr_psprintf(cmd->pool, "The certificate type \"%s\" is "
"only valid within a "
"LDAPTrustedGlobalCert directive. "
"Only CA_DER, CA_BASE64, "
"CERT_DER, CERT_BASE64, "
"CERT_NICKNAME, KEY_DER, and "
"KEY_BASE64 may be used.", type);
}
}
else {
return "Certificate type was not specified.";
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"LDAP: SSL trusted client cert - %s (type %s)",
file, type);
/* add the certificate to the client array */
cert = (apr_ldap_opt_tls_cert_t *)apr_array_push(dc->client_certs);
cert->type = cert_type;
cert->path = file;
cert->password = password;
/* if file is a file or path, fix the path */
if (cert_type != APR_LDAP_CA_TYPE_UNKNOWN &&
cert_type != APR_LDAP_CERT_TYPE_NICKNAME) {
cert->path = ap_server_root_relative(cmd->pool, file);
if (cert->path &&
((rv = apr_stat (&finfo, cert->path, APR_FINFO_MIN, cmd->pool))
!= APR_SUCCESS))
{
ap_log_error(APLOG_MARK, APLOG_ERR, rv, cmd->server,
"LDAP: Could not open SSL client certificate "
"file - %s",
cert->path == NULL ? file : cert->path);
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)
*/
static const char *util_ldap_set_trusted_mode(cmd_parms *cmd, void *dummy,
const char *mode)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"LDAP: SSL trusted mode - %s",
mode);
if (0 == strcasecmp("NONE", mode)) {
st->secure = APR_LDAP_NONE;
}
else if (0 == strcasecmp("SSL", mode)) {
st->secure = APR_LDAP_SSL;
}
else if ( (0 == strcasecmp("TLS", mode))
|| (0 == strcasecmp("STARTTLS", mode))) {
st->secure = APR_LDAP_STARTTLS;
}
else {
return "Invalid LDAPTrustedMode setting: must be one of NONE, "
"SSL, or TLS/STARTTLS";
}
st->secure_set = 1;
return(NULL);
}
static const char *util_ldap_set_verify_srv_cert(cmd_parms *cmd,
void *dummy,
int mode)
{
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"LDAP: SSL verify server certificate - %s",
mode?"TRUE":"FALSE");
st->verify_svr_cert = mode;
return(NULL);
}
static const char *util_ldap_set_connection_timeout(cmd_parms *cmd,
void *dummy,
const char *ttl)
{
#ifdef LDAP_OPT_NETWORK_TIMEOUT
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
#endif
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
#ifdef LDAP_OPT_NETWORK_TIMEOUT
st->connectionTimeout = atol(ttl);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"ldap connection: Setting connection timeout to %ld seconds.",
st->connectionTimeout);
#else
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server,
"LDAP: Connection timeout option not supported by the "
"LDAP SDK in use." );
#endif
return NULL;
}
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 referral chasing %s",
(mode == AP_LDAP_CHASEREFERRALS_ON) ? "ON" : "OFF");
dc->ChaseReferrals = mode;
return(NULL);
}
static const char *util_ldap_set_debug_level(cmd_parms *cmd,
void *config,
const char *arg) {
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
#ifndef AP_LDAP_OPT_DEBUG
return "This directive is not supported with the currently linked LDAP library";
#endif
st->debug_level = atoi(arg);
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);
if (dc->ReferralHopLimit <= 0) {
return "LDAPReferralHopLimit must be greater than zero (Use 'LDAPReferrals Off' to disable referral chasing)";
}
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->client_certs = apr_array_make(p, 10, sizeof(apr_ldap_opt_tls_cert_t));
dc->ChaseReferrals = AP_LDAP_CHASEREFERRALS_ON;
dc->ReferralHopLimit = AP_LDAP_HOPLIMIT_UNSET;
return dc;
}
static const char *util_ldap_set_op_timeout(cmd_parms *cmd,
void *dummy,
const char *val)
{
long timeout;
char *endptr;
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
timeout = strtol(val, &endptr, 10);
if ((val == endptr) || (*endptr != '\0')) {
return "Timeout not numerical";
}
if (timeout < 0) {
return "Timeout must be non-negative";
}
if (timeout) {
if (!st->opTimeout) {
st->opTimeout = apr_pcalloc(cmd->pool, sizeof(struct timeval));
}
st->opTimeout->tv_sec = timeout;
}
else {
st->opTimeout = NULL;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"ldap connection: Setting op timeout to %ld seconds.",
timeout);
#ifndef LDAP_OPT_TIMEOUT
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
"LDAP: LDAP_OPT_TIMEOUT option not supported by the "
"LDAP library in use. Using LDAPTimeout value as search "
"timeout only." );
#endif
return NULL;
}
static const char *util_ldap_set_conn_ttl(cmd_parms *cmd,
void *dummy,
const char *val)
{
apr_interval_time_t timeout;
util_ldap_state_t *st =
(util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
&ldap_module);
if (ap_timeout_parameter_parse(val, &timeout, "s") != APR_SUCCESS) {
return "LDAPConnPoolTTL has wrong format";
}
if (timeout < 0) {
/* reserve -1 for default value */
timeout = AP_LDAP_CONNPOOL_INFINITE;
}
st->connection_pool_ttl = timeout;
return NULL;
}
static void *util_ldap_create_config(apr_pool_t *p, server_rec *s)
{
util_ldap_state_t *st =
(util_ldap_state_t *)apr_pcalloc(p, sizeof(util_ldap_state_t));
/* Create a per vhost pool for mod_ldap to use, serialized with
* st->mutex (also one per vhost). both are replicated by fork(),
* no shared memory managed by either.
*/
apr_pool_create(&st->pool, p);
#if APR_HAS_THREADS
apr_thread_mutex_create(&st->mutex, APR_THREAD_MUTEX_DEFAULT, st->pool);
#endif
st->cache_bytes = 500000;
st->search_cache_ttl = 600000000;
st->search_cache_size = 1024;
st->compare_cache_ttl = 600000000;
st->compare_cache_size = 1024;
st->connections = NULL;
st->ssl_supported = 0;
st->global_certs = apr_array_make(p, 10, sizeof(apr_ldap_opt_tls_cert_t));
st->secure = APR_LDAP_NONE;
st->secure_set = 0;
st->connectionTimeout = 10;
st->opTimeout = apr_pcalloc(p, sizeof(struct timeval));
st->opTimeout->tv_sec = 60;
st->verify_svr_cert = 1;
st->connection_pool_ttl = AP_LDAP_CONNPOOL_DEFAULT; /* no limit */
return st;
}
/* cache-related settings are not merged here, but in the post_config hook,
* since the cache has not yet sprung to life
*/
static void *util_ldap_merge_config(apr_pool_t *p, void *basev,
void *overridesv)
{
util_ldap_state_t *st = apr_pcalloc(p, sizeof(util_ldap_state_t));
util_ldap_state_t *base = (util_ldap_state_t *) basev;
util_ldap_state_t *overrides = (util_ldap_state_t *) overridesv;
st->pool = overrides->pool;
#if APR_HAS_THREADS
st->mutex = overrides->mutex;
#endif
/* The cache settings can not be modified in a
virtual host since all server use the same
shared memory cache. */
st->cache_bytes = base->cache_bytes;
st->search_cache_ttl = base->search_cache_ttl;
st->search_cache_size = base->search_cache_size;
st->compare_cache_ttl = base->compare_cache_ttl;
st->compare_cache_size = base->compare_cache_size;
st->util_ldap_cache_lock = base->util_ldap_cache_lock;
st->connections = NULL;
st->ssl_supported = 0;
st->global_certs = apr_array_append(p, base->global_certs,
overrides->global_certs);
st->secure = (overrides->secure_set == 0) ? base->secure
: overrides->secure;
/* These LDAP connection settings can not be overwritten in
a virtual host. Once set in the base server, they must
remain the same. None of the LDAP SDKs seem to be able
to handle setting the verify_svr_cert flag on a
per-connection basis. The OpenLDAP client appears to be
able to handle the connection timeout per-connection
but the Novell SDK cannot. Allowing the timeout to
be set by each vhost is of little value so rather than
trying to make special expections for one LDAP SDK, GLOBAL_ONLY
is being enforced on this setting as well. */
st->connectionTimeout = base->connectionTimeout;
st->opTimeout = base->opTimeout;
st->verify_svr_cert = base->verify_svr_cert;
st->debug_level = base->debug_level;
st->connection_pool_ttl = (overrides->connection_pool_ttl == AP_LDAP_CONNPOOL_DEFAULT) ?
base->connection_pool_ttl : overrides->connection_pool_ttl;
return st;
}
static apr_status_t util_ldap_cleanup_module(void *data)
{
server_rec *s = data;
util_ldap_state_t *st = (util_ldap_state_t *)ap_get_module_config(
s->module_config, &ldap_module);
if (st->ssl_supported) {
apr_ldap_ssl_deinit();
}
return APR_SUCCESS;
}
static int util_ldap_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp)
{
apr_status_t result;
result = ap_mutex_register(pconf, ldap_cache_mutex_type, NULL,
APR_LOCK_DEFAULT, 0);
if (result != APR_SUCCESS) {
return result;
}
return OK;
}
static int util_ldap_post_config(apr_pool_t *p, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s)
{
apr_status_t result;
server_rec *s_vhost;
util_ldap_state_t *st_vhost;
util_ldap_state_t *st = (util_ldap_state_t *)
ap_get_module_config(s->module_config,
&ldap_module);
apr_ldap_err_t *result_err = NULL;
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 (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) {
#if APR_HAS_SHARED_MEMORY
/* 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) {
char *lck_file = apr_pstrcat(ptemp, st->cache_file, ".lck",
NULL);
apr_file_remove(lck_file, ptemp);
}
#endif
return OK;
}
#if APR_HAS_SHARED_MEMORY
/* initializing cache if shared memory size is not zero and we already
* don't have shm address
*/
if (!st->cache_shm && st->cache_bytes > 0) {
#endif
result = util_ldap_cache_init(p, st);
if (result != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, result, s,
"LDAP cache: could not create shared memory segment");
return DONE;
}
result = ap_global_mutex_create(&st->util_ldap_cache_lock, NULL,
ldap_cache_mutex_type, NULL, s, p, 0);
if (result != APR_SUCCESS) {
return result;
}
/* merge config in all vhost */
s_vhost = s->next;
while (s_vhost) {
st_vhost = (util_ldap_state_t *)
ap_get_module_config(s_vhost->module_config,
&ldap_module);
#if APR_HAS_SHARED_MEMORY
st_vhost->cache_shm = st->cache_shm;
st_vhost->cache_rmm = st->cache_rmm;
st_vhost->cache_file = st->cache_file;
st_vhost->util_ldap_cache = st->util_ldap_cache;
ap_log_error(APLOG_MARK, APLOG_DEBUG, result, s,
"LDAP merging Shared Cache conf: shm=0x%pp rmm=0x%pp "
"for VHOST: %s", st->cache_shm, st->cache_rmm,
s_vhost->server_hostname);
#endif
s_vhost = s_vhost->next;
}
#if APR_HAS_SHARED_MEMORY
}
else {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"LDAP cache: LDAPSharedCacheSize is zero, disabling "
"shared memory cache");
}
#endif
/* log the LDAP SDK used
*/
{
apr_ldap_err_t *result = NULL;
apr_ldap_info(p, &(result));
if (result != NULL) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "%s", result->reason);
}
}
apr_pool_cleanup_register(p, s, util_ldap_cleanup_module,
util_ldap_cleanup_module);
/*
* 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) {
rc = apr_ldap_set_option(ptemp, NULL, APR_LDAP_OPT_TLS_CERT,
(void *)st->global_certs, &(result_err));
}
if (APR_SUCCESS == rc) {
st->ssl_supported = 1;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
"LDAP: SSL support available" );
}
else {
st->ssl_supported = 0;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
"LDAP: SSL support unavailable%s%s",
result_err ? ": " : "",
result_err ? result_err->reason : "");
}
/* Initialize the rebind callback's cross reference list. */
apr_ldap_rebind_init (p);
#ifdef AP_LDAP_OPT_DEBUG
if (st->debug_level > 0) {
result = ldap_set_option(NULL, AP_LDAP_OPT_DEBUG, &st->debug_level);
if (result != LDAP_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"LDAP: Could not set the LDAP library debug level to %d:(%d) %s",
st->debug_level, result, ldap_err2string(result));
}
}
#endif
return(OK);
}
static void util_ldap_child_init(apr_pool_t *p, server_rec *s)
{
apr_status_t sts;
util_ldap_state_t *st = ap_get_module_config(s->module_config,
&ldap_module);
if (!st->util_ldap_cache_lock) return;
sts = apr_global_mutex_child_init(&st->util_ldap_cache_lock,
apr_global_mutex_lockfile(st->util_ldap_cache_lock), p);
if (sts != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, sts, s,
"Failed to initialise global mutex %s in child process",
ldap_cache_mutex_type);
}
}
static const command_rec util_ldap_cmds[] = {
AP_INIT_TAKE1("LDAPSharedCacheSize", util_ldap_set_cache_bytes,
NULL, RSRC_CONF,
"Set the size of the shared memory cache (in bytes). Use "
"0 to disable the shared memory cache. (default: 100000)"),
AP_INIT_TAKE1("LDAPSharedCacheFile", util_ldap_set_cache_file,
NULL, RSRC_CONF,
"Set the file name for the shared memory cache."),
AP_INIT_TAKE1("LDAPCacheEntries", util_ldap_set_cache_entries,
NULL, RSRC_CONF,
"Set the maximum number of entries that are possible in the "
"LDAP search cache. Use 0 or -1 to disable the search cache "
"(default: 1024)"),
AP_INIT_TAKE1("LDAPCacheTTL", util_ldap_set_cache_ttl,
NULL, RSRC_CONF,
"Set the maximum time (in seconds) that an item can be "
"cached in the LDAP search cache. Use 0 for no limit. "
"(default 600)"),
AP_INIT_TAKE1("LDAPOpCacheEntries", util_ldap_set_opcache_entries,
NULL, RSRC_CONF,
"Set the maximum number of entries that are possible "
"in the LDAP compare cache. Use 0 or -1 to disable the compare cache "
"(default: 1024)"),
AP_INIT_TAKE1("LDAPOpCacheTTL", util_ldap_set_opcache_ttl,
NULL, RSRC_CONF,
"Set the maximum time (in seconds) that an item is cached "
"in the LDAP operation cache. Use 0 for no limit. "
"(default: 600)"),
AP_INIT_TAKE23("LDAPTrustedGlobalCert", util_ldap_set_trusted_global_cert,
NULL, RSRC_CONF,
"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, OR_AUTHCFG,
"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 type of security that should be applied to "
"an LDAP connection. One of; NONE, SSL or STARTTLS."),
AP_INIT_FLAG("LDAPVerifyServerCert", util_ldap_set_verify_srv_cert,
NULL, RSRC_CONF,
"Set to 'ON' requires that the server certificate be verified"
" before a secure LDAP connection can be establish. Default"
" 'ON'"),
AP_INIT_TAKE1("LDAPConnectionTimeout", util_ldap_set_connection_timeout,
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, Consult LDAP SDK documentation for applicability and defaults"),
AP_INIT_TAKE1("LDAPLibraryDebug", util_ldap_set_debug_level,
NULL, RSRC_CONF,
"Enable debugging in LDAP SDK (Default: off, values: SDK specific"),
AP_INIT_TAKE1("LDAPTimeout", util_ldap_set_op_timeout,
NULL, RSRC_CONF,
"Specify the LDAP bind/search timeout in seconds "
"(0 = no limit). Default: 60"),
AP_INIT_TAKE1("LDAPConnectionPoolTTL", util_ldap_set_conn_ttl,
NULL, RSRC_CONF,
"Specify the maximum amount of time a bound connection can sit "
"idle and still be considered valid for reuse"
"(0 = no pool, -1 = no limit, n = time in seconds). Default: -1"),
{NULL}
};
static void util_ldap_register_hooks(apr_pool_t *p)
{
APR_REGISTER_OPTIONAL_FN(uldap_connection_open);
APR_REGISTER_OPTIONAL_FN(uldap_connection_close);
APR_REGISTER_OPTIONAL_FN(uldap_connection_unbind);
APR_REGISTER_OPTIONAL_FN(uldap_connection_find);
APR_REGISTER_OPTIONAL_FN(uldap_cache_comparedn);
APR_REGISTER_OPTIONAL_FN(uldap_cache_compare);
APR_REGISTER_OPTIONAL_FN(uldap_cache_checkuserid);
APR_REGISTER_OPTIONAL_FN(uldap_cache_getuserdn);
APR_REGISTER_OPTIONAL_FN(uldap_ssl_supported);
APR_REGISTER_OPTIONAL_FN(uldap_cache_check_subgroups);
ap_hook_pre_config(util_ldap_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_post_config(util_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE);
ap_hook_handler(util_ldap_handler, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init(util_ldap_child_init, NULL, NULL, APR_HOOK_MIDDLE);
}
AP_DECLARE_MODULE(ldap) = {
STANDARD20_MODULE_STUFF,
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 */
util_ldap_cmds, /* command table */
util_ldap_register_hooks, /* set up request processing hooks */
};