userdb-sql.c revision 45312f52ff3a3d4c137447be4c7556500c2f8bf2
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
2fbc2a7c65d30e46803195ebb4547176b85c22c7Timo Sirainen#include "common.h"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#include "userdb.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#ifdef USERDB_SQL
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "str.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "strescape.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "var-expand.h"
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen#include "auth-cache.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "db-sql.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <stdlib.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <string.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenstruct sql_userdb_module {
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen struct userdb_module module;
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen struct sql_connection *conn;
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen};
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct userdb_sql_request {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct auth_request *auth_request;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen userdb_callback_t *callback;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainenstatic void
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainensql_query_get_result(struct sql_result *result,
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen struct auth_request *auth_request)
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen{
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen const char *name, *value;
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen unsigned int i, fields_count;
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen auth_request_init_userdb_reply(auth_request);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen fields_count = sql_result_get_fields_count(result);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen for (i = 0; i < fields_count; i++) {
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen name = sql_result_get_field_name(result, i);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen value = sql_result_get_field_value(result, i);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen if (*name != '\0' && value != NULL) {
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen auth_request_set_userdb_field(auth_request,
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen name, value);
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen }
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen }
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen}
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void sql_query_callback(struct sql_result *sql_result,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen struct userdb_sql_request *sql_request)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct auth_request *auth_request = sql_request->auth_request;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen enum userdb_result result = USERDB_RESULT_INTERNAL_FAILURE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen ret = sql_result_next_row(sql_result);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret < 0) {
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen auth_request_log_error(auth_request, "sql",
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen "User query failed: %s",
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen sql_result_get_error(sql_result));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else if (ret == 0) {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen result = USERDB_RESULT_USER_UNKNOWN;
b323e76cf555fa6031f3dbbdedeac0df2fff3778Timo Sirainen auth_request_log_info(auth_request, "sql", "Unknown user");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen sql_query_get_result(sql_result, auth_request);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen result = USERDB_RESULT_OK;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen sql_request->callback(result, auth_request);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&auth_request);
a30b52af112bc98b74b8624e9a5d20cb754b2ab7Timo Sirainen i_free(sql_request);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenstatic const char *
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenuserdb_sql_escape(const char *str, const struct auth_request *auth_request)
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen{
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen struct sql_userdb_module *module =
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen (struct sql_userdb_module *)_module;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen return sql_escape_string(module->conn->db, str);
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen}
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void userdb_sql_lookup(struct auth_request *auth_request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen userdb_callback_t *callback)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen struct sql_userdb_module *module =
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen (struct sql_userdb_module *)_module;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct userdb_sql_request *sql_request;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen string_t *query;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen query = t_str_new(512);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen var_expand(query, module->conn->set.user_query,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen auth_request_get_var_expand_table(auth_request,
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen userdb_sql_escape));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_ref(auth_request);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request = i_new(struct userdb_sql_request, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request->callback = callback;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request->auth_request = auth_request;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen auth_request_log_debug(auth_request, "sql", "%s", str_c(query));
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen sql_query(module->conn->db, str_c(query),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_query_callback, sql_request);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenstatic struct userdb_module *
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenuserdb_sql_preinit(struct auth_userdb *auth_userdb, const char *args)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen struct sql_userdb_module *module;
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen module = p_new(auth_userdb->auth->pool, struct sql_userdb_module, 1);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen module->conn = db_sql_init(args);
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen module->module.cache_key =
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen auth_cache_parse_key(auth_userdb->auth->pool,
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen module->conn->set.user_query);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen return &module->module;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenstatic void userdb_sql_init(struct userdb_module *_module,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen const char *args ATTR_UNUSED)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen struct sql_userdb_module *module =
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen (struct sql_userdb_module *)_module;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen enum sql_db_flags flags;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen flags = sql_get_flags(module->conn->db);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen _module->blocking = (flags & SQL_DB_FLAG_BLOCKING) != 0;
f8a86fdfb0048f9c87bf223373b35416ceb5856bTimo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen if (!_module->blocking || worker)
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen sql_connect(module->conn->db);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenstatic void userdb_sql_deinit(struct userdb_module *_module)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen struct sql_userdb_module *module =
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen (struct sql_userdb_module *)_module;
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen db_sql_unref(&module->conn);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenstruct userdb_module_interface userdb_sql = {
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen "sql",
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen userdb_sql_preinit,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen userdb_sql_init,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen userdb_sql_deinit,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen userdb_sql_lookup
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#else
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainenstruct userdb_module_interface userdb_sql = {
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen MEMBER(name) "sql"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#endif