bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "auth-common.h"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#include "passdb.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#ifdef PASSDB_SQL
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen#include "safe-memset.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "password-scheme.h"
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen#include "auth-cache.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "db-sql.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <string.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstruct sql_passdb_module {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct passdb_module module;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct sql_connection *conn;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen};
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct passdb_sql_request {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct auth_request *auth_request;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen union {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen verify_plain_callback_t *verify_plain;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen lookup_credentials_callback_t *lookup_credentials;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen set_credentials_callback_t *set_credentials;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } callback;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainenstatic void sql_query_save_results(struct sql_result *result,
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen struct passdb_sql_request *sql_request)
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen{
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen struct auth_request *auth_request = sql_request->auth_request;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct passdb_module *_module = auth_request->passdb->passdb;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen unsigned int i, fields_count;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen const char *name, *value;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen fields_count = sql_result_get_fields_count(result);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen for (i = 0; i < fields_count; i++) {
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen name = sql_result_get_field_name(result, i);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen value = sql_result_get_field_value(result, i);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen if (*name == '\0')
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen ;
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen else if (value == NULL)
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen auth_request_set_null_field(auth_request, name);
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen else {
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen auth_request_set_field(auth_request, name, value,
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen module->conn->set.default_pass_scheme);
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen }
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen }
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen}
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void sql_query_callback(struct sql_result *result,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen struct passdb_sql_request *sql_request)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct auth_request *auth_request = sql_request->auth_request;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen struct passdb_module *_module = auth_request->passdb->passdb;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen enum passdb_result passdb_result;
a9c8c1f74e5d2911d3c15657727a30b649d3bbc4Timo Sirainen const char *password, *scheme;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen int ret;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen password = NULL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ret = sql_result_next_row(result);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (ret >= 0)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen db_sql_success(module->conn);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (ret < 0) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (!module->conn->default_password_query) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen "Password query failed: %s",
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen sql_result_get_error(result));
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen } else {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen "Password query failed: %s "
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen "(using built-in default password_query: %s)",
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen sql_result_get_error(result),
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen module->conn->set.password_query);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } else if (ret == 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_unknown_user(auth_request, AUTH_SUBSYS_DB);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen passdb_result = PASSDB_RESULT_USER_UNKNOWN;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } else {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen sql_query_save_results(result, sql_request);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* Note that we really want to check if the password field is
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen found. Just checking if password is set isn't enough,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen because with proxies we might want to return NULL as
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen password. */
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen if (sql_result_find_field(result, "password") < 0 &&
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen sql_result_find_field(result, "password_noscheme") < 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen "Password query must return a field named "
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen "'password'");
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } else if (sql_result_next_row(result) > 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen "Password query returned multiple matches");
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen } else if (auth_request->passdb_password == NULL &&
749b9176d6d1da2f0cbdeea5377ff7a8c77fc7e3Timo Sirainen !auth_fields_exists(auth_request->extra_fields, "nopassword")) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_DB,
5af8ea0a24c5930a8e310ebc4f33fba1d084217cTimo Sirainen "Empty password returned without nopassword");
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen passdb_result = PASSDB_RESULT_PASSWORD_MISMATCH;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } else {
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen /* passdb_password may change on the way,
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen so we'll need to strdup. */
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen password = t_strdup(auth_request->passdb_password);
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen passdb_result = PASSDB_RESULT_OK;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen scheme = password_get_scheme(&password);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* auth_request_set_field() sets scheme */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen i_assert(password == NULL || scheme != NULL);
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen if (auth_request->credentials_scheme != NULL) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen passdb_handle_credentials(passdb_result, password, scheme,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen sql_request->callback.lookup_credentials,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen auth_request);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen auth_request_unref(&auth_request);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* verify plain */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (password == NULL) {
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen sql_request->callback.verify_plain(passdb_result, auth_request);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen auth_request_unref(&auth_request);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return;
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ret = auth_request_password_verify(auth_request,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen auth_request->mech_password,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen password, scheme, AUTH_SUBSYS_DB);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen sql_request->callback.verify_plain(ret > 0 ? PASSDB_RESULT_OK :
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen PASSDB_RESULT_PASSWORD_MISMATCH,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen auth_request);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&auth_request);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenstatic const char *
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenpassdb_sql_escape(const char *str, const struct auth_request *auth_request)
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen{
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen struct passdb_module *_module = auth_request->passdb->passdb;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen return sql_escape_string(module->conn->db, str);
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen}
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void sql_lookup_pass(struct passdb_sql_request *sql_request)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct passdb_module *_module =
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen sql_request->auth_request->passdb->passdb;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const char *query, *error;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (t_auth_request_var_expand(module->conn->set.password_query,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen sql_request->auth_request,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen passdb_sql_escape, &query, &error) <= 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen auth_request_log_debug(sql_request->auth_request, AUTH_SUBSYS_DB,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Failed to expand password_query=%s: %s",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen module->conn->set.password_query, error);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen sql_request->callback.verify_plain(PASSDB_RESULT_INTERNAL_FAILURE,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen sql_request->auth_request);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(sql_request->auth_request, AUTH_SUBSYS_DB,
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen "query: %s", query);
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_ref(sql_request->auth_request);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen sql_query(module->conn->db, query,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_query_callback, sql_request);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainenstatic void sql_verify_plain(struct auth_request *request,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen const char *password ATTR_UNUSED,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen verify_plain_callback_t *callback)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct passdb_sql_request *sql_request;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen sql_request = p_new(request->pool, struct passdb_sql_request, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request->auth_request = request;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request->callback.verify_plain = callback;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_lookup_pass(sql_request);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void sql_lookup_credentials(struct auth_request *request,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen lookup_credentials_callback_t *callback)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct passdb_sql_request *sql_request;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen sql_request = p_new(request->pool, struct passdb_sql_request, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request->auth_request = request;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request->callback.lookup_credentials = callback;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_lookup_pass(sql_request);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainenstatic void sql_set_credentials_callback(const struct sql_commit_result *sql_result,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen struct passdb_sql_request *sql_request)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen struct passdb_module *_module =
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen sql_request->auth_request->passdb->passdb;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen if (sql_result->error != NULL) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (!module->conn->default_update_query) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(sql_request->auth_request,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen AUTH_SUBSYS_DB,
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen "Set credentials query failed: %s", sql_result->error);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen } else {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(sql_request->auth_request,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen AUTH_SUBSYS_DB,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen "Set credentials query failed: %s"
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen "(using built-in default update_query: %s)",
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen sql_result->error, module->conn->set.update_query);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen sql_request->callback.
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen set_credentials(sql_result->error == NULL, sql_request->auth_request);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_free(sql_request);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
adea1e1e46ccb4ae107767fd930e3d1fb4f1d11dTimo Sirainenstatic void sql_set_credentials(struct auth_request *request,
adea1e1e46ccb4ae107767fd930e3d1fb4f1d11dTimo Sirainen const char *new_credentials,
adea1e1e46ccb4ae107767fd930e3d1fb4f1d11dTimo Sirainen set_credentials_callback_t *callback)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct sql_passdb_module *module =
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen (struct sql_passdb_module *) request->passdb->passdb;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct sql_transaction_context *transaction;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct passdb_sql_request *sql_request;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const char *query, *error;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen request->mech_password = p_strdup(request->pool, new_credentials);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (t_auth_request_var_expand(module->conn->set.update_query,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen request, passdb_sql_escape,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen &query, &error) <= 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen auth_request_log_error(request, AUTH_SUBSYS_DB,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Failed to expand update_query=%s: %s",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen module->conn->set.update_query, error);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen callback(FALSE, request);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_request = i_new(struct passdb_sql_request, 1);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_request->auth_request = request;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_request->callback.set_credentials = callback;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen transaction = sql_transaction_begin(module->conn->db);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen sql_update(transaction, query);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_transaction_commit(&transaction,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_set_credentials_callback, sql_request);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstatic struct passdb_module *
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainenpassdb_sql_preinit(pool_t pool, const char *args)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct sql_passdb_module *module;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct sql_connection *conn;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen module = p_new(pool, struct sql_passdb_module, 1);
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen module->conn = conn = db_sql_init(args, FALSE);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
74674a53a72dab535c61f455b2246ef2797844eaTimo Sirainen module->module.default_cache_key =
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen auth_cache_parse_key(pool, conn->set.password_query);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen module->module.default_pass_scheme = conn->set.default_pass_scheme;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen return &module->module;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
f3d506e525a720f214020ca0f989a1966b30edaeTimo Sirainenstatic void passdb_sql_init(struct passdb_module *_module)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct sql_passdb_module *module =
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen (struct sql_passdb_module *)_module;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen enum sql_db_flags flags;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen flags = sql_get_flags(module->conn->db);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen module->module.blocking = (flags & SQL_DB_FLAG_BLOCKING) != 0;
f8a86fdfb0048f9c87bf223373b35416ceb5856bTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (!module->module.blocking || worker)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen db_sql_connect(module->conn);
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen db_sql_check_userdb_warning(module->conn);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstatic void passdb_sql_deinit(struct passdb_module *_module)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct sql_passdb_module *module =
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen (struct sql_passdb_module *)_module;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen db_sql_unref(&module->conn);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstruct passdb_module_interface passdb_sql = {
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen "sql",
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen passdb_sql_preinit,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen passdb_sql_init,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen passdb_sql_deinit,
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_verify_plain,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_lookup_credentials,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_set_credentials
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen};
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#else
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainenstruct passdb_module_interface passdb_sql = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .name = "sql"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen};
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#endif