userdb-sql.c revision f8a86fdfb0048f9c87bf223373b35416ceb5856b
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2004 Timo Sirainen, Alex Howansky */
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen#include "config.h"
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen#undef HAVE_CONFIG_H
86441ffc028f11857152c15fe7b0d24ff0874504Timo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#ifdef USERDB_SQL
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "common.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "str.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "strescape.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "var-expand.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "db-sql.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include "userdb.h"
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include <stdlib.h>
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#include <string.h>
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenstruct userdb_sql_request {
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen struct auth_request *auth_request;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen userdb_callback_t *callback;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen};
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenextern struct userdb_module userdb_sql;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenstatic struct sql_connection *userdb_sql_conn;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenstatic const char *sql_query_get_result(struct sql_result *result,
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen struct auth_request *auth_request)
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen{
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen string_t *str;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen uid_t uid, gid;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen const char *name, *value;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen unsigned int i, fields_count;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen uid = (uid_t)-1;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen gid = (gid_t)-1;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen str = t_str_new(256);
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen str_append(str, auth_request->user);
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen fields_count = sql_result_get_fields_count(result);
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen for (i = 0; i < fields_count; i++) {
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen name = sql_result_get_field_name(result, i);
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen value = sql_result_get_field_value(result, i);
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen if (value == NULL)
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen continue;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen str_append_c(str, '\t');
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen str_append(str, name);
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen str_append_c(str, '=');
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen /* some special handling for UID and GID. */
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen if (strcmp(name, "uid") == 0) {
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen uid = userdb_parse_uid(auth_request, value);
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen if (uid == (uid_t)-1)
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen return NULL;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen value = dec2str(uid);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen } else if (strcmp(name, "gid") == 0) {
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen gid = userdb_parse_gid(auth_request, value);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen if (gid == (gid_t)-1)
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen return NULL;
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen value = dec2str(gid);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen }
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen str_append(str, value);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen }
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen if (uid == (uid_t)-1) {
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen auth_request_log_error(auth_request, "sql",
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen "Password query didn't return uid, or it was NULL");
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen }
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen if (gid == (gid_t)-1) {
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen auth_request_log_error(auth_request, "sql",
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen "Password query didn't return gid, or it was NULL");
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen }
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen return str_c(str);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen}
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainenstatic void sql_query_callback(struct sql_result *result, void *context)
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen{
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen struct userdb_sql_request *sql_request = context;
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen struct auth_request *auth_request = sql_request->auth_request;
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen const char *user_result = NULL;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen int ret;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen ret = sql_result_next_row(result);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen if (ret < 0) {
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen auth_request_log_error(auth_request, "sql",
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen "User query failed: %s", sql_result_get_error(result));
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen } else if (ret == 0) {
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen auth_request_log_info(auth_request, "sql", "User not found");
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen } else {
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen user_result = sql_query_get_result(result, auth_request);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen }
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen sql_request->callback(user_result, auth_request);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen i_free(sql_request);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen}
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstatic void userdb_sql_lookup(struct auth_request *auth_request,
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen userdb_callback_t *callback)
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen{
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen struct userdb_sql_request *sql_request;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen string_t *query;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen query = t_str_new(512);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen var_expand(query, userdb_sql_conn->set.user_query,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen auth_request_get_var_expand_table(auth_request,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen str_escape));
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen sql_request = i_new(struct userdb_sql_request, 1);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen sql_request->callback = callback;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen sql_request->auth_request = auth_request;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen auth_request_log_debug(auth_request, "sql", "%s", str_c(query));
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen sql_query(userdb_sql_conn->db, str_c(query),
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen sql_query_callback, sql_request);
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen}
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstatic void userdb_sql_preinit(const char *args)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen{
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen userdb_sql_conn = db_sql_init(args);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen}
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstatic void userdb_sql_init(const char *args __attr_unused__)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen{
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen enum sql_db_flags flags;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen flags = sql_get_flags(userdb_sql_conn->db);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen userdb_sql.blocking = (flags & SQL_DB_FLAG_BLOCKING) != 0;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen if (!userdb_sql.blocking || worker)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen sql_connect(userdb_sql_conn->db);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen}
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainenstatic void userdb_sql_deinit(void)
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen{
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen db_sql_unref(userdb_sql_conn);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen}
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstruct userdb_module userdb_sql = {
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen "sql",
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen FALSE,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen userdb_sql_preinit,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen userdb_sql_init,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen userdb_sql_deinit,
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen userdb_sql_lookup
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen};
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen#endif
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen