⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util_ldap.c

📁 linux网络服务器工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * util_ldap.c: LDAP things * * Original code from auth_ldap module for Apache v1.3: * Copyright 1998, 1999 Enbridge Pipelines Inc. * Copyright 1999-2001 Dave Carrigan */#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_log.h"#include "http_protocol.h"#include "http_request.h"#include "util_ldap.h"#include "util_ldap_cache.h"#include <apr_strings.h>#if APR_HAVE_UNISTD_H#include <unistd.h>#endif#if !APR_HAS_LDAP#error mod_ldap requires APR-util to have LDAP support built in#endif#ifdef AP_NEED_SET_MUTEX_PERMS#include "unixd.h"#endif    /* defines for certificate file types    */#define LDAP_CA_TYPE_UNKNOWN            0#define LDAP_CA_TYPE_DER                1#define LDAP_CA_TYPE_BASE64             2#define LDAP_CA_TYPE_CERT7_DB           3/* Default define for ldap functions that need a SIZELIMIT but * do not have the define * XXX This should be removed once a supporting #define is  *  released through APR-Util. */#ifndef APR_LDAP_SIZELIMIT#define APR_LDAP_SIZELIMIT -1#endifmodule AP_MODULE_DECLARE_DATA ldap_module;#define LDAP_CACHE_LOCK() do {                                  \    if (st->util_ldap_cache_lock)                               \        apr_global_mutex_lock(st->util_ldap_cache_lock);        \} while (0)#define LDAP_CACHE_UNLOCK() do {                                \    if (st->util_ldap_cache_lock)                               \        apr_global_mutex_unlock(st->util_ldap_cache_lock);      \} while (0)static void util_ldap_strdup (char **str, const char *newstr){    if (*str) {        free(*str);        *str = NULL;    }    if (newstr) {        *str = strdup(newstr);    }}/* * Status Handler * -------------- * * This handler generates a status page about the current performance of * the LDAP cache. It is enabled as follows: * * <Location /ldap-status> *   SetHandler ldap-status * </Location> * */static int util_ldap_handler(request_rec *r){    util_ldap_state_t *st = (util_ldap_state_t *)                            ap_get_module_config(r->server->module_config,                                                 &ldap_module);    r->allowed |= (1 << M_GET);    if (r->method_number != M_GET)        return DECLINED;    if (strcmp(r->handler, "ldap-status")) {        return DECLINED;    }    r->content_type = "text/html; charset=ISO-8859-1";    if (r->header_only)        return OK;    ap_rputs(DOCTYPE_HTML_3_2             "<html><head><title>LDAP Cache Information</title></head>\n", r);    ap_rputs("<body bgcolor='#ffffff'><h1 align=center>LDAP Cache Information"             "</h1>\n", r);    util_ald_cache_display(r, st);    return OK;}/* ------------------------------------------------------------------ *//* * Closes an LDAP connection by unlocking it. The next time * uldap_connection_find() is called this connection will be * available for reuse. */static void uldap_connection_close(util_ldap_connection_t *ldc){    /*     * QUESTION:     *     * Is it safe leaving bound connections floating around between the     * different modules? Keeping the user bound is a performance boost,     * but it is also a potential security problem - maybe.     *     * For now we unbind the user when we finish with a connection, but     * we don't have to...     */    /* mark our connection as available for reuse */#if APR_HAS_THREADS    apr_thread_mutex_unlock(ldc->lock);#endif}/* * Destroys an LDAP connection by unbinding and closing the connection to * the LDAP server. It is used to bring the connection back to a known * state after an error, and during pool cleanup. */static apr_status_t uldap_connection_unbind(void *param){    util_ldap_connection_t *ldc = param;    if (ldc) {        if (ldc->ldap) {            ldap_unbind_s(ldc->ldap);            ldc->ldap = NULL;        }        ldc->bound = 0;    }    return APR_SUCCESS;}/* * Clean up an LDAP connection by unbinding and unlocking the connection. * This function is registered with the pool cleanup function - causing * the LDAP connections to be shut down cleanly on graceful restart. */static apr_status_t uldap_connection_cleanup(void *param){    util_ldap_connection_t *ldc = param;    if (ldc) {        /* unbind and disconnect from the LDAP server */        uldap_connection_unbind(ldc);        /* free the username and password */        if (ldc->bindpw) {            free((void*)ldc->bindpw);        }        if (ldc->binddn) {            free((void*)ldc->binddn);        }        /* unlock this entry */        uldap_connection_close(ldc);    }    return APR_SUCCESS;}static int uldap_connection_init(request_rec *r,                                 util_ldap_connection_t *ldc ){    int rc = 0, ldap_option = 0;    int version  = LDAP_VERSION3;    apr_ldap_err_t *result = NULL;#ifdef LDAP_OPT_NETWORK_TIMEOUT    struct timeval timeOut = {10,0};    /* 10 second connection timeout */#endif    util_ldap_state_t *st =        (util_ldap_state_t *)ap_get_module_config(r->server->module_config,        &ldap_module);    /* Since the host will include a port if the default port is not used,     * always specify the default ports for the port parameter.  This will     * allow a host string that contains multiple hosts the ability to mix     * some hosts with ports and some without. All hosts which do not     * specify a port will use the default port.     */    apr_ldap_init(r->pool, &(ldc->ldap),                  ldc->host,                  APR_LDAP_SSL == ldc->secure ? LDAPS_PORT : LDAP_PORT,                  APR_LDAP_NONE,                  &(result));    if (result != NULL && result->rc) {        ldc->reason = result->reason;    }    if (NULL == ldc->ldap)    {        ldc->bound = 0;        if (NULL == ldc->reason) {            ldc->reason = "LDAP: ldap initialization failed";        }        else {            ldc->reason = result->reason;        }        return(result->rc);    }    /* always default to LDAP V3 */    ldap_set_option(ldc->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);    /* set client certificates */    if (!apr_is_empty_array(ldc->client_certs)) {        apr_ldap_set_option(r->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT,                            ldc->client_certs, &(result));        if (LDAP_SUCCESS != result->rc) {            uldap_connection_unbind( ldc );            ldc->reason = result->reason;            return(result->rc);        }    }    /* switch on SSL/TLS */    if (APR_LDAP_NONE != ldc->secure) {        apr_ldap_set_option(r->pool, ldc->ldap,                            APR_LDAP_OPT_TLS, &ldc->secure, &(result));        if (LDAP_SUCCESS != result->rc) {            uldap_connection_unbind( ldc );            ldc->reason = result->reason;            return(result->rc);        }    }    /* Set the alias dereferencing option */    ldap_option = ldc->deref;    ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &ldap_option);/*XXX All of the #ifdef's need to be removed once apr-util 1.2 is released */#ifdef APR_LDAP_OPT_VERIFY_CERT    apr_ldap_set_option(r->pool, ldc->ldap,                        APR_LDAP_OPT_VERIFY_CERT, &(st->verify_svr_cert), &(result));#else#if defined(LDAPSSL_VERIFY_SERVER)    if (st->verify_svr_cert) {        result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_SERVER);    }    else {        result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_NONE);    }#elif defined(LDAP_OPT_X_TLS_REQUIRE_CERT)    /* This is not a per-connection setting so just pass NULL for the       Ldap connection handle */    if (st->verify_svr_cert) {        int i = LDAP_OPT_X_TLS_DEMAND;        result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);    }    else {        int i = LDAP_OPT_X_TLS_NEVER;        result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);    }#endif#endif#ifdef LDAP_OPT_NETWORK_TIMEOUT    if (st->connectionTimeout > 0) {        timeOut.tv_sec = st->connectionTimeout;    }    if (st->connectionTimeout >= 0) {        rc = apr_ldap_set_option(r->pool, ldc->ldap, LDAP_OPT_NETWORK_TIMEOUT,                                 (void *)&timeOut, &(result));        if (APR_SUCCESS != rc) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                             "LDAP: Could not set the connection timeout");        }    }#endif    return(rc);}/* * Connect to the LDAP server and binds. Does not connect if already * connected (i.e. ldc->ldap is non-NULL.) Does not bind if already bound. * * Returns LDAP_SUCCESS on success; and an error code on failure */static int uldap_connection_open(request_rec *r,                                 util_ldap_connection_t *ldc){    int rc = 0;    int failures = 0;    /* sanity check for NULL */    if (!ldc) {        return -1;    }    /* If the connection is already bound, return    */    if (ldc->bound)    {        ldc->reason = "LDAP: connection open successful (already bound)";        return LDAP_SUCCESS;    }    /* create the ldap session handle    */    if (NULL == ldc->ldap)    {       rc = uldap_connection_init( r, ldc );       if (LDAP_SUCCESS != rc)       {           return rc;       }    }    /* loop trying to bind up to 10 times if LDAP_SERVER_DOWN error is     * returned.  Break out of the loop on Success or any other error.     *     * NOTE: Looping is probably not a great idea. If the server isn't     * responding the chances it will respond after a few tries are poor.     * However, the original code looped and it only happens on     * the error condition.      */    for (failures=0; failures<10; failures++)    {        rc = ldap_simple_bind_s(ldc->ldap,                                (char *)ldc->binddn,                                (char *)ldc->bindpw);        if (!AP_LDAP_IS_SERVER_DOWN(rc)) {            break;        } else if (failures == 5) {           /* attempt to init the connection once again */           uldap_connection_unbind( ldc );           rc = uldap_connection_init( r, ldc );           if (LDAP_SUCCESS != rc)           {               break;           }       }    }    /* free the handle if there was an error    */    if (LDAP_SUCCESS != rc)    {       uldap_connection_unbind(ldc);        ldc->reason = "LDAP: ldap_simple_bind_s() failed";    }    else {        ldc->bound = 1;        ldc->reason = "LDAP: connection open successful";    }    return(rc);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -