userdb-sql.c revision 08d6658a4e2ec8104cd1307f6baa75fdb07a24f8
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "auth-common.h"
2423da95ee20fd4b3c260c1389cf2952d25f099cTimo Sirainen#include "userdb.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#ifdef USERDB_SQL
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#include "str.h"
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#include "strescape.h"
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#include "var-expand.h"
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#include "auth-cache.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "db-sql.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include <stdlib.h>
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen#include <string.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainenstruct sql_userdb_module {
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen struct userdb_module module;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen struct sql_connection *conn;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen};
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainenstruct userdb_sql_request {
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen struct auth_request *auth_request;
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen userdb_callback_t *callback;
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen};
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainenstatic void
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainensql_query_get_result(struct sql_result *result,
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen struct auth_request *auth_request)
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen{
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen const char *name, *value;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i, fields_count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen auth_request_init_userdb_reply(auth_request);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen fields_count = sql_result_get_fields_count(result);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (i = 0; i < fields_count; i++) {
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen name = sql_result_get_field_name(result, i);
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen value = sql_result_get_field_value(result, i);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*name != '\0' && value != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen auth_request_set_userdb_field(auth_request,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen name, value);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic void sql_query_callback(struct sql_result *sql_result,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct userdb_sql_request *sql_request)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct auth_request *auth_request = sql_request->auth_request;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum userdb_result result = USERDB_RESULT_INTERNAL_FAILURE;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen int ret;
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen ret = sql_result_next_row(sql_result);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (ret < 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen auth_request_log_error(auth_request, "sql",
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen "User query failed: %s",
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen sql_result_get_error(sql_result));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else if (ret == 0) {
61e84692827b6a64912343f515c984853021483aTimo Sirainen result = USERDB_RESULT_USER_UNKNOWN;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen auth_request_log_info(auth_request, "sql", "Unknown user");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen sql_query_get_result(sql_result, auth_request);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen result = USERDB_RESULT_OK;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen }
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen sql_request->callback(result, auth_request);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen auth_request_unref(&auth_request);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen i_free(sql_request);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic const char *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenuserdb_sql_escape(const char *str, const struct auth_request *auth_request)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen struct sql_userdb_module *module =
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen (struct sql_userdb_module *)_module;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen return sql_escape_string(module->conn->db, str);
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen}
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void userdb_sql_lookup(struct auth_request *auth_request,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen userdb_callback_t *callback)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct sql_userdb_module *module =
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen (struct sql_userdb_module *)_module;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct userdb_sql_request *sql_request;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen string_t *query;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen query = t_str_new(512);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen var_expand(query, module->conn->set.user_query,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen auth_request_get_var_expand_table(auth_request,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen userdb_sql_escape));
bbd0a870f8639767e4e4011d2aedadac08d5c66fTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen auth_request_ref(auth_request);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen sql_request = i_new(struct userdb_sql_request, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen sql_request->callback = callback;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen sql_request->auth_request = auth_request;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen auth_request_log_debug(auth_request, "sql", "%s", str_c(query));
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen sql_query(module->conn->db, str_c(query),
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sql_query_callback, sql_request);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainenstatic struct userdb_module *
106b804c819443791f1324f8bbe34429eeea6a13Timo Sirainenuserdb_sql_preinit(struct auth_userdb *auth_userdb, const char *args)
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen{
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen struct sql_userdb_module *module;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen module = p_new(auth_userdb->auth->pool, struct sql_userdb_module, 1);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen module->conn = db_sql_init(args);
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen module->module.cache_key =
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen auth_cache_parse_key(auth_userdb->auth->pool,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen module->conn->set.user_query);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return &module->module;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainenstatic void userdb_sql_init(struct userdb_module *_module,
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen const char *args ATTR_UNUSED)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct sql_userdb_module *module =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (struct sql_userdb_module *)_module;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum sql_db_flags flags;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen flags = sql_get_flags(module->conn->db);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen _module->blocking = (flags & SQL_DB_FLAG_BLOCKING) != 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen if (!_module->blocking || worker)
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen sql_connect(module->conn->db);
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen}
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainenstatic void userdb_sql_deinit(struct userdb_module *_module)
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen{
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen struct sql_userdb_module *module =
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen (struct sql_userdb_module *)_module;
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen db_sql_unref(&module->conn);
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct userdb_module_interface userdb_sql = {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "sql",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen userdb_sql_preinit,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen userdb_sql_init,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen userdb_sql_deinit,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen userdb_sql_lookup
4645cc6c911a95991d7af43b40f88e99506ea5e9Timo Sirainen};
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen#else
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstruct userdb_module_interface userdb_sql = {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen MEMBER(name) "sql"
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen};
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen#endif
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen