bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen lookup_credentials_callback_t *lookup_credentials;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainenstatic void sql_query_save_results(struct sql_result *result,
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;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen fields_count = sql_result_get_fields_count(result);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen for (i = 0; i < fields_count; i++) {
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen value = sql_result_get_field_value(result, i);
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen auth_request_set_null_field(auth_request, name);
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen auth_request_set_field(auth_request, name, value,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void sql_query_callback(struct sql_result *result,
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;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen "Password query failed: %s",
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)",
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } else if (ret == 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_unknown_user(auth_request, AUTH_SUBSYS_DB);
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
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'");
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;
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);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* auth_request_set_field() sets scheme */
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen if (auth_request->credentials_scheme != NULL) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen passdb_handle_credentials(passdb_result, password, scheme,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* verify plain */
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen sql_request->callback.verify_plain(passdb_result, auth_request);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ret = auth_request_password_verify(auth_request,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen sql_request->callback.verify_plain(ret > 0 ? PASSDB_RESULT_OK :
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenstatic const char *
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenpassdb_sql_escape(const char *str, const struct auth_request *auth_request)
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen struct passdb_module *_module = auth_request->passdb->passdb;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen return sql_escape_string(module->conn->db, str);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void sql_lookup_pass(struct passdb_sql_request *sql_request)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (t_auth_request_var_expand(module->conn->set.password_query,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen auth_request_log_debug(sql_request->auth_request, AUTH_SUBSYS_DB,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Failed to expand password_query=%s: %s",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen sql_request->callback.verify_plain(PASSDB_RESULT_INTERNAL_FAILURE,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(sql_request->auth_request, AUTH_SUBSYS_DB,
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainenstatic void sql_verify_plain(struct auth_request *request,
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen sql_request = p_new(request->pool, struct passdb_sql_request, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request->callback.verify_plain = callback;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void sql_lookup_credentials(struct auth_request *request,
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen sql_request = p_new(request->pool, struct passdb_sql_request, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sql_request->callback.lookup_credentials = callback;
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainenstatic void sql_set_credentials_callback(const struct sql_commit_result *sql_result,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen struct sql_passdb_module *module = (struct sql_passdb_module *)_module;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(sql_request->auth_request,
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen "Set credentials query failed: %s", sql_result->error);
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(sql_request->auth_request,
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);
bb2b3656ef7635acc374f7fc19b25aeeb454ae95Timo Sirainen set_credentials(sql_result->error == NULL, sql_request->auth_request);
adea1e1e46ccb4ae107767fd930e3d1fb4f1d11dTimo Sirainenstatic void sql_set_credentials(struct auth_request *request,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen (struct sql_passdb_module *) request->passdb->passdb;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen request->mech_password = p_strdup(request->pool, new_credentials);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (t_auth_request_var_expand(module->conn->set.update_query,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen auth_request_log_error(request, AUTH_SUBSYS_DB,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Failed to expand update_query=%s: %s",
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_request = i_new(struct passdb_sql_request, 1);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sql_request->callback.set_credentials = callback;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen transaction = sql_transaction_begin(module->conn->db);
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainenpassdb_sql_preinit(pool_t pool, const char *args)
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen module = p_new(pool, struct sql_passdb_module, 1);
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen module->conn = conn = db_sql_init(args, FALSE);
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen auth_cache_parse_key(pool, conn->set.password_query);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen module->module.default_pass_scheme = conn->set.default_pass_scheme;
f3d506e525a720f214020ca0f989a1966b30edaeTimo Sirainenstatic void passdb_sql_init(struct passdb_module *_module)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen module->module.blocking = (flags & SQL_DB_FLAG_BLOCKING) != 0;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstatic void passdb_sql_deinit(struct passdb_module *_module)