📄 util_ldap.c
字号:
/* 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); /* * A bind to the server with an empty password always succeeds, so * we check to ensure that the password is not empty. This implies * that users who actually do have empty passwords will never be * able to authenticate with this module. I don't see this as a big * problem. */ if (!bindpw || strlen(bindpw) <= 0) { ldap_msgfree(res); ldc->reason = "Empty password not allowed"; return LDAP_INVALID_CREDENTIALS; } /* * Attempt to bind with the retrieved dn and the password. If the bind * fails, it means that the password is wrong (the dn obviously * exists, since we just retrieved it) */ if ((result = ldap_simple_bind_s(ldc->ldap, const_cast(*binddn), const_cast(bindpw))) == LDAP_SERVER_DOWN) { ldc->reason = "ldap_simple_bind_s() to check user credentials failed with server down"; ldap_msgfree(res); util_ldap_connection_unbind(ldc); goto start_over; } /* failure? if so - return */ if (result != LDAP_SUCCESS) { ldc->reason = "ldap_simple_bind_s() to check user credentials failed"; ldap_msgfree(res); util_ldap_connection_unbind(ldc); return result; } else { /* * We have just bound the connection to a different user and password * combination, which might be reused unintentionally next time this * connection is used from the connection pool. To ensure no confusion, * we mark the connection as unbound. */ ldc->bound = 0; } /* * 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 = bindpw; 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); } else if ((!search_nodep->bindpw) || (strcmp(bindpw, search_nodep->bindpw) != 0)) { /* Entry in cache is invalid, remove it and insert new one */ util_ald_cache_remove(curl->search_cache, search_nodep); util_ald_cache_insert(curl->search_cache, &the_search_node); } else { /* Cache entry is valid, update lastbind */ search_nodep->lastbind = the_search_node.lastbind; } LDAP_CACHE_UNLOCK(); } ldap_msgfree(res); ldc->reason = "Authentication successful"; return LDAP_SUCCESS;}/* * This function will return the DN of the entry matching userid. * It is used to get the DN in case some other module than mod_auth_ldap * has authenticated the user. * The function is basically a copy of util_ldap_cache_checkuserid * with password checking removed. */LDAP_DECLARE(int) util_ldap_cache_getuserdn(request_rec *r, util_ldap_connection_t *ldc, const char *url, const char *basedn, int scope, char **attrs, const char *filter, const char **binddn, const char ***retvals){ const char **vals = NULL; int numvals = 0; int result = 0; LDAPMessage *res, *entry; char *dn; int count; int failures = 0; util_url_node_t *curl; /* Cached URL node */ util_url_node_t curnode; util_search_node_t *search_nodep; /* Cached search node */ util_search_node_t the_search_node; apr_time_t curtime; util_ldap_state_t *st = (util_ldap_state_t *)ap_get_module_config(r->server->module_config, &ldap_module); /* Get the cache node for this url */ LDAP_CACHE_LOCK(); curnode.url = url; curl = (util_url_node_t *)util_ald_cache_fetch(st->util_ldap_cache, &curnode); if (curl == NULL) { curl = util_ald_create_caches(st, url); } LDAP_CACHE_UNLOCK(); if (curl) { LDAP_CACHE_LOCK(); the_search_node.username = filter; search_nodep = util_ald_cache_fetch(curl->search_cache, &the_search_node); if (search_nodep != NULL) { /* found entry in search cache... */ curtime = apr_time_now(); /* * Remove this item from the cache if its expired. */ if ((curtime - search_nodep->lastbind) > st->search_cache_ttl) { /* ...but entry is too old */ util_ald_cache_remove(curl->search_cache, search_nodep); } else { /* ...and entry is valid */ *binddn = search_nodep->dn; *retvals = search_nodep->vals; LDAP_CACHE_UNLOCK(); ldc->reason = "Search successful (cached)"; return LDAP_SUCCESS; } } /* unlock this read lock */ LDAP_CACHE_UNLOCK(); } /* * At this point, there is no valid cached search, so lets do the search. */ /* * If any LDAP operation fails due to LDAP_SERVER_DOWN, control returns here. */start_over: if (failures++ > 10) { return result; } if (LDAP_SUCCESS != (result = util_ldap_connection_open(r, ldc))) { return result; } /* try do the search */ if ((result = ldap_search_ext_s(ldc->ldap, const_cast(basedn), scope, const_cast(filter), attrs, 0, NULL, NULL, NULL, -1, &res)) == LDAP_SERVER_DOWN) { ldc->reason = "ldap_search_ext_s() for user failed with server down"; util_ldap_connection_unbind(ldc); goto start_over; } /* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */ if (result != LDAP_SUCCESS) { ldc->reason = "ldap_search_ext_s() for user failed"; return result; } /* * We should have found exactly one entry; to find a different * number is an error. */ count = ldap_count_entries(ldc->ldap, res); if (count != 1) { if (count == 0 ) ldc->reason = "User not found"; else ldc->reason = "User is not unique (search found two or more matches)"; ldap_msgfree(res); return LDAP_NO_SUCH_OBJECT; } 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 */LDAP_DECLARE(int) util_ldap_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_support);}/* ---------------------------------------- *//* 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); st->cache_bytes = atol(bytes); ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, "[%" APR_PID_T_FMT "] ldap cache: Setting shared memory " " cache size to %" APR_SIZE_T_FMT " bytes.", getpid(), 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); if (file) { st->cache_file = ap_server_root_relative(st->pool, file); } else { st->cache_file = NULL; } ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 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); st->search_cache_ttl = atol(ttl) * 1000000; ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, "[%d] ldap cache: Setting cache TTL to %ld microseconds.", getpid(), 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); st->search_cache_size = atol(size); if (st->search_cache_size < 0) { st->search_cache_size = 0; } ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, "[%d] ldap cache: Setting search cache size to %ld entries.", getpid(), 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); st->compare_cache_ttl = atol(ttl) * 1000000; ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, "[%d] ldap cache: Setting operation cache TTL to %ld microseconds.", getpid(), 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); st->compare_cache_size = atol(size); if (st->compare_cache_size < 0) { st->compare_cache_size = 0; } ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, "[%d] ldap cache: Setting operation cache size to %ld entries.", getpid(), st->compare_cache_size); return NULL;}static const char *util_ldap_set_cert_auth(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); apr_finfo_t finfo; apr_status_t rv; if (err != NULL) { return err; } ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->server, "LDAP: SSL trusted certificate authority file - %s", file); st->cert_auth_file = ap_server_root_relative(cmd->pool, file);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -