passdb-dict.c revision 79042f8c2ec1778528584c064b164d1ebcdde16b
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include "auth-common.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include "passdb.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen#include "array.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include "str.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include "var-expand.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include "dict.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include "password-scheme.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include "auth-cache.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include "db-dict.h"
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include <stdlib.h>
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen#include <string.h>
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstruct dict_passdb_module {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct passdb_module module;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct dict_connection *conn;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen};
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstruct passdb_dict_request {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct auth_request *auth_request;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen union {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen verify_plain_callback_t *verify_plain;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen lookup_credentials_callback_t *lookup_credentials;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen } callback;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen};
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstatic int
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainendict_query_save_results(struct auth_request *auth_request,
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen struct dict_connection *conn,
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen struct db_dict_value_iter *iter)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen{
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen const char *key, *value, *error;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen while (db_dict_value_iter_next(iter, &key, &value)) {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen if (value != NULL) {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen auth_request_set_field(auth_request, key, value,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen conn->set.default_pass_scheme);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen if (db_dict_value_iter_deinit(&iter, &error) < 0) {
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen auth_request_log_error(auth_request, "dict", "%s", error);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen return -1;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen return 0;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen}
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstatic enum passdb_result
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenpassdb_dict_lookup_key(struct auth_request *auth_request,
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen struct dict_passdb_module *module)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen{
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen struct db_dict_value_iter *iter;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen int ret;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen ret = db_dict_value_iter_init(module->conn, auth_request,
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen &module->conn->set.passdb_fields,
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen &module->conn->set.parsed_passdb_objects,
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen &iter);
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen if (ret < 0)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen return PASSDB_RESULT_INTERNAL_FAILURE;
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen else if (ret == 0) {
ed3c4faf5ddf559818e4a3f7efc0f53f97396227Timo Sirainen auth_request_log_unknown_user(auth_request, "dict");
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen return PASSDB_RESULT_USER_UNKNOWN;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen } else {
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen if (dict_query_save_results(auth_request, module->conn, iter) < 0)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen return PASSDB_RESULT_INTERNAL_FAILURE;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen if (auth_request->passdb_password == NULL &&
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen !auth_fields_exists(auth_request->extra_fields, "nopassword")) {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen auth_request_log_info(auth_request, "dict",
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen "No password returned (and no nopassword)");
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen return PASSDB_RESULT_PASSWORD_MISMATCH;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen } else {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen return PASSDB_RESULT_OK;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen}
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstatic void passdb_dict_lookup_pass(struct passdb_dict_request *dict_request)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen{
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct auth_request *auth_request = dict_request->auth_request;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct passdb_module *_module = auth_request->passdb->passdb;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct dict_passdb_module *module =
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen (struct dict_passdb_module *)_module;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen const char *password = NULL, *scheme = NULL;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen enum passdb_result passdb_result;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen int ret;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen if (array_count(&module->conn->set.passdb_fields) == 0 &&
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen array_count(&module->conn->set.parsed_passdb_objects) == 0) {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen auth_request_log_error(auth_request, "dict",
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen "No passdb_objects or passdb_fields specified");
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen } else {
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen passdb_result = passdb_dict_lookup_key(auth_request, module);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen if (passdb_result == PASSDB_RESULT_OK) {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen /* passdb_password may change on the way,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen so we'll need to strdup. */
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen password = t_strdup(auth_request->passdb_password);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen scheme = password_get_scheme(&password);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen /* auth_request_set_field() sets scheme */
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen i_assert(password == NULL || scheme != NULL);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen if (auth_request->credentials_scheme != NULL) {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen passdb_handle_credentials(passdb_result, password, scheme,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_request->callback.lookup_credentials,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen auth_request);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen } else {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen if (password != NULL) {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen ret = auth_request_password_verify(auth_request,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen auth_request->mech_password,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen password, scheme, "dict");
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen passdb_result = ret > 0 ? PASSDB_RESULT_OK :
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen PASSDB_RESULT_PASSWORD_MISMATCH;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_request->callback.verify_plain(passdb_result,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen auth_request);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen }
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen}
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstatic void dict_verify_plain(struct auth_request *request,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen const char *password ATTR_UNUSED,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen verify_plain_callback_t *callback)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen{
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct passdb_dict_request *dict_request;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_request = p_new(request->pool, struct passdb_dict_request, 1);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_request->auth_request = request;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_request->callback.verify_plain = callback;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen passdb_dict_lookup_pass(dict_request);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen}
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstatic void dict_lookup_credentials(struct auth_request *request,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen lookup_credentials_callback_t *callback)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen{
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct passdb_dict_request *dict_request;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_request = p_new(request->pool, struct passdb_dict_request, 1);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_request->auth_request = request;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_request->callback.lookup_credentials = callback;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen passdb_dict_lookup_pass(dict_request);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen}
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstatic struct passdb_module *
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenpassdb_dict_preinit(pool_t pool, const char *args)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen{
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct dict_passdb_module *module;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct dict_connection *conn;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen module = p_new(pool, struct dict_passdb_module, 1);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen module->conn = conn = db_dict_init(args);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen module->module.blocking = TRUE;
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen module->module.cache_key = auth_cache_parse_key(pool,
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen db_dict_parse_cache_key(&conn->set.keys, &conn->set.passdb_fields,
79042f8c2ec1778528584c064b164d1ebcdde16bTimo Sirainen &conn->set.parsed_passdb_objects));
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen module->module.default_pass_scheme = conn->set.default_pass_scheme;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen return &module->module;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen}
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstatic void passdb_dict_deinit(struct passdb_module *_module)
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen{
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen struct dict_passdb_module *module =
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen (struct dict_passdb_module *)_module;
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen db_dict_unref(&module->conn);
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen}
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainenstruct passdb_module_interface passdb_dict = {
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen "dict",
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen passdb_dict_preinit,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen NULL,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen passdb_dict_deinit,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_verify_plain,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen dict_lookup_credentials,
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen NULL
2028d80c2704bbf62b29b2c624b0ee3c3a03c462Timo Sirainen};