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

📄 util_ldap.c

📁 linux网络服务器工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Compare client certificate arrays. * * Returns 1 on compare failure, 0 otherwise. */static int compare_client_certs(apr_array_header_t *srcs,                                apr_array_header_t *dests){    int i = 0;    struct apr_ldap_opt_tls_cert_t *src, *dest;    /* arrays both NULL? if so, then equal */    if (srcs == NULL && dests == NULL) {        return 0;    }    /* arrays different length or either NULL? If so, then not equal */    if (srcs == NULL || dests == NULL || srcs->nelts != dests->nelts) {        return 1;    }    /* run an actual comparison */    src = (struct apr_ldap_opt_tls_cert_t *)srcs->elts;    dest = (struct apr_ldap_opt_tls_cert_t *)dests->elts;    for (i = 0; i < srcs->nelts; i++) {        if (strcmp(src[i].path, dest[i].path) ||            strcmp(src[i].password, dest[i].password) ||            src[i].type != dest[i].type) {            return 1;        }    }    /* if we got here, the cert arrays were identical */    return 0;}/* * Find an existing ldap connection struct that matches the * provided ldap connection parameters. * * If not found in the cache, a new ldc structure will be allocated * from st->pool and returned to the caller.  If found in the cache, * a pointer to the existing ldc structure will be returned. */static util_ldap_connection_t *            uldap_connection_find(request_rec *r,                                  const char *host, int port,                                  const char *binddn, const char *bindpw,                                  deref_options deref, int secure){    struct util_ldap_connection_t *l, *p; /* To traverse the linked list */    int secureflag = secure;    util_ldap_state_t *st =        (util_ldap_state_t *)ap_get_module_config(r->server->module_config,        &ldap_module);#if APR_HAS_THREADS    /* mutex lock this function */    apr_thread_mutex_lock(st->mutex);#endif    if (secure < APR_LDAP_NONE) {        secureflag = st->secure;    }    /* Search for an exact connection match in the list that is not     * being used.     */    for (l=st->connections,p=NULL; l; l=l->next) {#if APR_HAS_THREADS        if (APR_SUCCESS == apr_thread_mutex_trylock(l->lock)) {#endif        if (   (l->port == port) && (strcmp(l->host, host) == 0)            && ((!l->binddn && !binddn) || (l->binddn && binddn                                             && !strcmp(l->binddn, binddn)))            && ((!l->bindpw && !bindpw) || (l->bindpw && bindpw                                             && !strcmp(l->bindpw, bindpw)))            && (l->deref == deref) && (l->secure == secureflag)            && !compare_client_certs(st->client_certs, l->client_certs))        {            break;        }#if APR_HAS_THREADS            /* If this connection didn't match the criteria, then we             * need to unlock the mutex so it is available to be reused.             */            apr_thread_mutex_unlock(l->lock);        }#endif        p = l;    }    /* If nothing found, search again, but we don't care about the     * binddn and bindpw this time.     */    if (!l) {        for (l=st->connections,p=NULL; l; l=l->next) {#if APR_HAS_THREADS            if (APR_SUCCESS == apr_thread_mutex_trylock(l->lock)) {#endif            if ((l->port == port) && (strcmp(l->host, host) == 0) &&                (l->deref == deref) && (l->secure == secureflag) &&                !compare_client_certs(st->client_certs, l->client_certs))            {                /* the bind credentials have changed */                l->bound = 0;                util_ldap_strdup((char**)&(l->binddn), binddn);                util_ldap_strdup((char**)&(l->bindpw), bindpw);                break;            }#if APR_HAS_THREADS                /* If this connection didn't match the criteria, then we                 * need to unlock the mutex so it is available to be reused.                 */                apr_thread_mutex_unlock(l->lock);            }#endif            p = l;        }    }/* artificially disable cache *//* l = NULL; */    /* If no connection what found after the second search, we     * must create one.     */    if (!l) {        /*         * Add the new connection entry to the linked list. Note that we         * don't actually establish an LDAP connection yet; that happens         * the first time authentication is requested.         */        /* create the details to the pool in st */        l = apr_pcalloc(st->pool, sizeof(util_ldap_connection_t));        if (apr_pool_create(&l->pool, st->pool) != APR_SUCCESS) {             ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,                          "util_ldap: Failed to create memory pool");#if APR_HAS_THREADS            apr_thread_mutex_unlock(st->mutex);#endif            return NULL;            }#if APR_HAS_THREADS        apr_thread_mutex_create(&l->lock, APR_THREAD_MUTEX_DEFAULT, st->pool);        apr_thread_mutex_lock(l->lock);#endif        l->bound = 0;        l->host = apr_pstrdup(st->pool, host);        l->port = port;        l->deref = deref;        util_ldap_strdup((char**)&(l->binddn), binddn);        util_ldap_strdup((char**)&(l->bindpw), bindpw);        /* The security mode after parsing the URL will always be either         * APR_LDAP_NONE (ldap://) or APR_LDAP_SSL (ldaps://).         * If the security setting is NONE, override it to the security         * setting optionally supplied by the admin using LDAPTrustedMode         */        l->secure = secureflag;        /* save away a copy of the client cert list that is presently valid */        l->client_certs = apr_array_copy_hdr(l->pool, st->client_certs);        /* add the cleanup to the pool */        apr_pool_cleanup_register(l->pool, l,                                  uldap_connection_cleanup,                                  apr_pool_cleanup_null);        if (p) {            p->next = l;        }        else {            st->connections = l;        }    }#if APR_HAS_THREADS    apr_thread_mutex_unlock(st->mutex);#endif    return l;}/* ------------------------------------------------------------------ *//* * Compares two DNs to see if they're equal. The only way to do this correctly * is to search for the dn and then do ldap_get_dn() on the result. This should * match the initial dn, since it would have been also retrieved with * ldap_get_dn(). This is expensive, so if the configuration value * compare_dn_on_server is false, just does an ordinary strcmp. * * The lock for the ldap cache should already be acquired. */static int uldap_cache_comparedn(request_rec *r, util_ldap_connection_t *ldc,                                 const char *url, const char *dn,                                 const char *reqdn, int compare_dn_on_server){    int result = 0;    util_url_node_t *curl;    util_url_node_t curnode;    util_dn_compare_node_t *node;    util_dn_compare_node_t newnode;    int failures = 0;    LDAPMessage *res, *entry;    char *searchdn;    util_ldap_state_t *st = (util_ldap_state_t *)                            ap_get_module_config(r->server->module_config,                                                 &ldap_module);    /* get cache entry (or create one) */    LDAP_CACHE_LOCK();    curnode.url = url;    curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);    if (curl == NULL) {        curl = util_ald_create_caches(st, url);    }    LDAP_CACHE_UNLOCK();    /* a simple compare? */    if (!compare_dn_on_server) {        /* unlock this read lock */        if (strcmp(dn, reqdn)) {            ldc->reason = "DN Comparison FALSE (direct strcmp())";            return LDAP_COMPARE_FALSE;        }        else {            ldc->reason = "DN Comparison TRUE (direct strcmp())";            return LDAP_COMPARE_TRUE;        }    }    if (curl) {        /* no - it's a server side compare */        LDAP_CACHE_LOCK();        /* is it in the compare cache? */        newnode.reqdn = (char *)reqdn;        node = util_ald_cache_fetch(curl->dn_compare_cache, &newnode);        if (node != NULL) {            /* If it's in the cache, it's good */            /* unlock this read lock */            LDAP_CACHE_UNLOCK();            ldc->reason = "DN Comparison TRUE (cached)";            return LDAP_COMPARE_TRUE;        }        /* unlock this read lock */        LDAP_CACHE_UNLOCK();    }start_over:    if (failures++ > 10) {        /* too many failures */        return result;    }    /* make a server connection */    if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {        /* connect to server failed */        return result;    }    /* search for reqdn */    result = ldap_search_ext_s(ldc->ldap, (char *)reqdn, LDAP_SCOPE_BASE,                               "(objectclass=*)", NULL, 1,                               NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &res);    if (AP_LDAP_IS_SERVER_DOWN(result))    {        ldc->reason = "DN Comparison ldap_search_ext_s() "                      "failed with server down";        uldap_connection_unbind(ldc);        goto start_over;    }    if (result != LDAP_SUCCESS) {        /* search for reqdn failed - no match */        ldc->reason = "DN Comparison ldap_search_ext_s() failed";        return result;    }    entry = ldap_first_entry(ldc->ldap, res);    searchdn = ldap_get_dn(ldc->ldap, entry);    ldap_msgfree(res);    if (strcmp(dn, searchdn) != 0) {        /* compare unsuccessful */        ldc->reason = "DN Comparison FALSE (checked on server)";        result = LDAP_COMPARE_FALSE;    }    else {        if (curl) {            /* compare successful - add to the compare cache */            LDAP_CACHE_LOCK();            newnode.reqdn = (char *)reqdn;            newnode.dn = (char *)dn;            node = util_ald_cache_fetch(curl->dn_compare_cache, &newnode);            if (   (node == NULL)                || (strcmp(reqdn, node->reqdn) != 0)                || (strcmp(dn, node->dn) != 0))            {                util_ald_cache_insert(curl->dn_compare_cache, &newnode);            }            LDAP_CACHE_UNLOCK();        }        ldc->reason = "DN Comparison TRUE (checked on server)";        result = LDAP_COMPARE_TRUE;    }    ldap_memfree(searchdn);    return result;}/* * Does an generic ldap_compare operation. It accepts a cache that it will use * to lookup the compare in the cache. We cache two kinds of compares * (require group compares) and (require user compares). Each compare has a different * cache node: require group includes the DN; require user does not because the * require user cache is owned by the * */static int uldap_cache_compare(request_rec *r, util_ldap_connection_t *ldc,                               const char *url, const char *dn,                               const char *attrib, const char *value){    int result = 0;    util_url_node_t *curl;    util_url_node_t curnode;    util_compare_node_t *compare_nodep;    util_compare_node_t the_compare_node;    apr_time_t curtime = 0; /* silence gcc -Wall */    int failures = 0;    util_ldap_state_t *st = (util_ldap_state_t *)                            ap_get_module_config(r->server->module_config,                                                 &ldap_module);    /* get cache entry (or create one) */    LDAP_CACHE_LOCK();    curnode.url = url;    curl = util_ald_cache_fetch(st->util_ldap_cache, &curnode);    if (curl == NULL) {        curl = util_ald_create_caches(st, url);    }    LDAP_CACHE_UNLOCK();    if (curl) {        /* make a comparison to the cache */        LDAP_CACHE_LOCK();        curtime = apr_time_now();        the_compare_node.dn = (char *)dn;        the_compare_node.attrib = (char *)attrib;        the_compare_node.value = (char *)value;        the_compare_node.result = 0;        compare_nodep = util_ald_cache_fetch(curl->compare_cache,                                             &the_compare_node);        if (compare_nodep != NULL) {            /* found it... */            if (curtime - compare_nodep->lastcompare > st->compare_cache_ttl) {                /* ...but it is too old */                util_ald_cache_remove(curl->compare_cache, compare_nodep);            }            else {                /* ...and it is good */                /* unlock this read lock */                LDAP_CACHE_UNLOCK();                if (LDAP_COMPARE_TRUE == compare_nodep->result) {                    ldc->reason = "Comparison true (cached)";                    return compare_nodep->result;                }                else if (LDAP_COMPARE_FALSE == compare_nodep->result) {                    ldc->reason = "Comparison false (cached)";                    return compare_nodep->result;                }                else if (LDAP_NO_SUCH_ATTRIBUTE == compare_nodep->result) {                    ldc->reason = "Comparison no such attribute (cached)";                    return compare_nodep->result;                }                else {                    ldc->reason = "Comparison undefined (cached)";                    return compare_nodep->result;                }            }        }        /* unlock this read lock */        LDAP_CACHE_UNLOCK();    }start_over:    if (failures++ > 10) {

⌨️ 快捷键说明

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