Mercurial > dovecot > original-hg > dovecot-1.2
view src/auth/passdb-sql.c @ 2798:54b29901a793 HEAD
Added simple LRU cache for auth requests. Currently only for sql passdb.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 21 Oct 2004 05:23:09 +0300 |
parents | 0058f0b70402 |
children | 4481384a4fba |
line wrap: on
line source
/* Copyright (C) 2004 Timo Sirainen, Alex Howansky */ #include "config.h" #undef HAVE_CONFIG_H #ifdef PASSDB_SQL #include "common.h" #include "str.h" #include "strescape.h" #include "var-expand.h" #include "password-scheme.h" #include "db-sql.h" #include "passdb.h" #include "passdb-cache.h" #include <stdlib.h> #include <string.h> struct passdb_sql_request { struct auth_request *auth_request; enum passdb_credentials credentials; union { verify_plain_callback_t *verify_plain; lookup_credentials_callback_t *lookup_credentials; } callback; char password[1]; }; static struct sql_connection *passdb_sql_conn; static char *passdb_sql_cache_key; static void result_save_extra_fields(struct sql_result *result, struct passdb_sql_request *sql_request, struct auth_request *auth_request) { struct auth_request_extra *extra; unsigned int i, fields_count; const char *name, *value; extra = auth_request_extra_begin(auth_request, sql_request->password); fields_count = sql_result_get_fields_count(result); for (i = 0; i < fields_count; i++) { name = sql_result_get_field_name(result, i); value = sql_result_get_field_value(result, i); if (value != NULL) auth_request_extra_next(extra, name, value); } auth_request_extra_finish(extra, passdb_sql_cache_key); } static void sql_query_callback(struct sql_result *result, void *context) { struct passdb_sql_request *sql_request = context; struct auth_request *auth_request = sql_request->auth_request; const char *user, *password, *scheme; int ret, idx; user = auth_request->user; password = NULL; ret = sql_result_next_row(result); if (ret < 0) { i_error("sql(%s): Password query failed: %s", get_log_prefix(auth_request), sql_result_get_error(result)); } else if (ret == 0) { if (verbose) { i_info("sql(%s): Unknown user", get_log_prefix(auth_request)); } if (passdb_cache != NULL) { auth_cache_insert(passdb_cache, auth_request, passdb_sql_cache_key, ""); } } else if ((idx = sql_result_find_field(result, "password")) < 0) { i_error("sql(%s): Password query didn't return password", get_log_prefix(auth_request)); } else { password = t_strdup(sql_result_get_field_value(result, idx)); result_save_extra_fields(result, sql_request, auth_request); } if (ret > 0) { /* make sure there was only one row returned */ if (sql_result_next_row(result) > 0) { i_error("sql(%s): Password query returned multiple " "matches", get_log_prefix(auth_request)); password = NULL; } } scheme = password_get_scheme(&password); if (scheme == NULL) { scheme = passdb_sql_conn->set.default_pass_scheme; i_assert(scheme != NULL); } if (sql_request->credentials != -1) { passdb_handle_credentials(sql_request->credentials, password, scheme, sql_request->callback.lookup_credentials, auth_request); return; } /* verify plain */ if (password == NULL) { sql_request->callback.verify_plain(PASSDB_RESULT_USER_UNKNOWN, auth_request); return; } ret = password_verify(sql_request->password, password, scheme, user); if (ret < 0) { i_error("sql(%s): Unknown password scheme %s", get_log_prefix(auth_request), scheme); } else if (ret == 0) { if (verbose) { i_info("sql(%s): Password mismatch", get_log_prefix(auth_request)); } } sql_request->callback.verify_plain(ret > 0 ? PASSDB_RESULT_OK : PASSDB_RESULT_PASSWORD_MISMATCH, auth_request); } static void sql_lookup_pass(struct passdb_sql_request *sql_request) { string_t *query; query = t_str_new(512); var_expand(query, passdb_sql_conn->set.password_query, auth_request_get_var_expand_table(sql_request->auth_request, str_escape)); sql_query(passdb_sql_conn->db, str_c(query), sql_query_callback, sql_request); } static void sql_verify_plain(struct auth_request *request, const char *password, verify_plain_callback_t *callback) { struct passdb_sql_request *sql_request; enum passdb_result result; if (passdb_cache_verify_plain(request, passdb_sql_cache_key, password, passdb_sql_conn->set.default_pass_scheme, &result)) { callback(result, request); return; } sql_request = i_malloc(sizeof(struct passdb_sql_request) + strlen(password)); sql_request->auth_request = request; sql_request->credentials = -1; sql_request->callback.verify_plain = callback; strcpy(sql_request->password, password); sql_lookup_pass(sql_request); } static void sql_lookup_credentials(struct auth_request *request, enum passdb_credentials credentials, lookup_credentials_callback_t *callback) { struct passdb_sql_request *sql_request; const char *result, *scheme; if (passdb_cache_lookup_credentials(request, passdb_sql_cache_key, &result, &scheme)) { if (scheme == NULL) scheme = passdb_sql_conn->set.default_pass_scheme; passdb_handle_credentials(credentials, result, scheme, callback, request); return; } sql_request = i_new(struct passdb_sql_request, 1); sql_request->auth_request = request; sql_request->credentials = credentials; sql_request->callback.lookup_credentials = callback; sql_lookup_pass(sql_request); } static void passdb_sql_preinit(const char *args) { passdb_sql_conn = db_sql_init(args); passdb_sql_cache_key = auth_cache_parse_key(passdb_sql_conn->set.password_query); } static void passdb_sql_init(const char *args __attr_unused__) { db_sql_connect(passdb_sql_conn); } static void passdb_sql_deinit(void) { db_sql_unref(passdb_sql_conn); i_free(passdb_sql_cache_key); } struct passdb_module passdb_sql = { passdb_sql_preinit, passdb_sql_init, passdb_sql_deinit, sql_verify_plain, sql_lookup_credentials }; #endif