passdb-cache.c revision 8759adc67109b5a12a7af3ed717c7040622a0a04
2035N/A/* Copyright (C) 2004 Timo Sirainen */
2035N/A
2035N/A#include "common.h"
2035N/A#include "password-scheme.h"
2035N/A#include "passdb.h"
2035N/A#include "passdb-cache.h"
2035N/A
2035N/A#include <stdlib.h>
2035N/A
2035N/Astruct auth_cache *passdb_cache = NULL;
2035N/A
2035N/Astatic void list_save(struct auth_request *request, const char *const *list)
2035N/A{
2035N/A const char *name, *value;
2035N/A
2035N/A if (*list == NULL)
2035N/A return;
2035N/A
2035N/A for (; *list != NULL; list++) {
2035N/A t_push();
2842N/A value = strchr(*list, '=');
2035N/A if (value == NULL) {
2035N/A name = *list;
2035N/A value = "";
2035N/A } else {
2842N/A name = t_strcut(*list, '=');
2035N/A value++;
2035N/A }
2035N/A
2842N/A auth_request_set_field(request, name, value, NULL);
2035N/A t_pop();
2035N/A }
2035N/A}
2035N/A
2899N/Abool passdb_cache_verify_plain(struct auth_request *request, const char *key,
2899N/A const char *password,
2035N/A enum passdb_result *result_r, int use_expired)
2035N/A{
2035N/A const char *value, *cached_pw, *scheme, *const *list;
2035N/A struct auth_cache_node *node;
2035N/A int ret;
2035N/A bool expired;
2035N/A
2035N/A if (passdb_cache == NULL || key == NULL)
3372N/A return FALSE;
2035N/A
2035N/A /* value = password \t ... */
2035N/A value = auth_cache_lookup(passdb_cache, request, key, &node, &expired);
2035N/A if (value == NULL || (expired && !use_expired))
2035N/A return FALSE;
2035N/A
3372N/A if (*value == '\0') {
2035N/A /* negative cache entry */
2035N/A auth_request_log_info(request, "cache", "User unknown");
2035N/A *result_r = PASSDB_RESULT_USER_UNKNOWN;
2035N/A return TRUE;
}
list = t_strsplit(value, "\t");
list_save(request, list + 1);
cached_pw = list[0];
if (*cached_pw == '\0') {
/* NULL password */
auth_request_log_info(request, "cache", "NULL password access");
*result_r = PASSDB_RESULT_OK;
return TRUE;
}
scheme = password_get_scheme(&cached_pw);
i_assert(scheme != NULL);
ret = auth_request_password_verify(request, password, cached_pw,
scheme, "cache");
if (ret == 0 && node->last_success) {
/* the last authentication was successful. assume that the
password was changed and cache is expired. */
node->last_success = FALSE;
return FALSE;
}
node->last_success = ret > 0;
*result_r = ret > 0 ? PASSDB_RESULT_OK :
PASSDB_RESULT_PASSWORD_MISMATCH;
return TRUE;
}
bool passdb_cache_lookup_credentials(struct auth_request *request,
const char *key, const char **password_r,
const char **scheme_r,
enum passdb_result *result_r,
bool use_expired)
{
const char *value, *const *list;
struct auth_cache_node *node;
bool expired;
if (passdb_cache == NULL)
return FALSE;
value = auth_cache_lookup(passdb_cache, request, key, &node, &expired);
if (value == NULL || (expired && !use_expired))
return FALSE;
if (*value == '\0') {
/* negative cache entry */
*result_r = PASSDB_RESULT_USER_UNKNOWN;
*password_r = NULL;
*scheme_r = NULL;
return TRUE;
}
list = t_strsplit(value, "\t");
list_save(request, list + 1);
*result_r = PASSDB_RESULT_OK;
*password_r = list[0];
*scheme_r = password_get_scheme(password_r);
i_assert(*scheme_r != NULL);
return TRUE;
}
void passdb_cache_init(void)
{
const char *env;
size_t max_size;
unsigned int cache_ttl;
env = getenv("CACHE_SIZE");
if (env == NULL)
return;
max_size = (size_t)strtoul(env, NULL, 10) * 1024;
if (max_size == 0)
return;
env = getenv("CACHE_TTL");
if (env == NULL)
return;
cache_ttl = (unsigned int)strtoul(env, NULL, 10);
if (cache_ttl == 0)
return;
passdb_cache = auth_cache_new(max_size, cache_ttl);
}
void passdb_cache_deinit(void)
{
if (passdb_cache != NULL)
auth_cache_free(&passdb_cache);
}