db-dict.c revision a3783f8a3c9cd816b51e77a922f82301512fcf22
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const struct var_expand_table *var_expand_table;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen#define DEF_STR(name) DEF_STRUCT_STR(name, db_dict_settings)
51fb710488efa419a2964335c30451c62b9633b1Timo Sirainen#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, db_dict_settings)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic struct db_dict_settings default_dict_settings = {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen#define DEF_STR(name) DEF_STRUCT_STR(name, db_dict_key)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic struct setting_def key_setting_defs[] = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenstatic struct db_dict_key default_key_settings = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenstatic struct dict_connection *connections = NULL;
ba8498efbf886ca8b69fdb20c0ba2f5dba9416e3Timo Sirainenstatic struct dict_connection *dict_conn_find(const char *config_path)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen for (conn = connections; conn != NULL; conn = conn->next) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (strcmp(conn->config_path, config_path) == 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenparse_obsolete_setting(const char *key, const char *value,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char **error_r)
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen /* key passdb { key=<value> format=json }
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen passdb_objects = passdb */
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen ctx->cur_key = array_append_space(&ctx->conn->set.keys);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->cur_key->parsed_format = DB_DICT_VALUE_FORMAT_JSON;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->cur_key->key = p_strdup(ctx->conn->pool, value);
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen array_append(&ctx->conn->set.parsed_passdb_objects, &dbkey, 1);
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen /* key userdb { key=<value> format=json }
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen userdb_objects = userdb */
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen ctx->cur_key = array_append_space(&ctx->conn->set.keys);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen ctx->cur_key->parsed_format = DB_DICT_VALUE_FORMAT_JSON;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen ctx->cur_key->key = p_strdup(ctx->conn->pool, value);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen array_append(&ctx->conn->set.parsed_userdb_objects, &dbkey, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = "Deprecated value_format must be 'json'";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic const char *parse_setting(const char *key, const char *value,
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen if (parse_obsolete_setting(key, value, ctx, &error))
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return parse_setting_from_defs(ctx->conn->pool, setting_defs,
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen return parse_setting_from_defs(ctx->conn->pool, key_setting_defs,
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen field = array_append_space(&ctx->conn->set.passdb_fields);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen field->value = p_strdup(ctx->conn->pool, value);
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen field = array_append_space(&ctx->conn->set.userdb_fields);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen field->value = p_strdup(ctx->conn->pool, value);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return t_strconcat("Unknown setting: ", key, NULL);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainenstatic bool parse_section(const char *type, const char *name,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (strcmp(ctx->cur_key->format, "value") == 0) {
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen } else if (strcmp(ctx->cur_key->format, "json") == 0) {
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen *errormsg = t_strconcat("Unknown key format: ",
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ctx->section != DICT_SETTINGS_SECTION_ROOT) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *errormsg = "Key section names must not contain '.'";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->cur_key = array_append_space(&ctx->conn->set.keys);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->cur_key->name = p_strdup(ctx->conn->pool, name);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainendb_dict_settings_parse(struct db_dict_settings *set)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const char *const *tmp;
f2df3069766c747cbf020fea5d3a4261949064b0Timo Sirainen tmp = t_strsplit_spaces(set->passdb_objects, " ");
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_fatal("dict: passdb_objects refers to key %s, "
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (key->parsed_format == DB_DICT_VALUE_FORMAT_VALUE) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_fatal("dict: passdb_objects refers to key %s, "
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen array_append(&set->parsed_passdb_objects, &key, 1);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen tmp = t_strsplit_spaces(set->userdb_objects, " ");
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_fatal("dict: userdb_objects refers to key %s, "
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (key->parsed_format == DB_DICT_VALUE_FORMAT_VALUE) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_fatal("dict: userdb_objects refers to key %s, "
1da01eaa962be13cee75771064e2256b1a82d90aTimo Sirainen array_append(&set->parsed_userdb_objects, &key, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstruct dict_connection *db_dict_init(const char *config_path)
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen i_fatal("dict: Configuration file path not given");
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen pool = pool_alloconly_create("dict_connection", 1024);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen conn = p_new(pool, struct dict_connection, 1);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen conn->config_path = p_strdup(pool, config_path);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen p_array_init(&conn->set.passdb_fields, pool, 8);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen p_array_init(&conn->set.userdb_fields, pool, 8);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen p_array_init(&conn->set.parsed_passdb_objects, pool, 2);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen p_array_init(&conn->set.parsed_userdb_objects, pool, 2);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen if (!settings_read(config_path, NULL, parse_setting,
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen i_fatal("dict %s: Empty uri setting", config_path);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen dict_set.base_dir = global_auth_settings->base_dir;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen if (dict_init(conn->set.uri, &dict_set, &conn->dict, &error) < 0)
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen i_fatal("dict %s: Failed to init dict: %s", config_path, error);
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainenvoid db_dict_unref(struct dict_connection **_conn)
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainendb_dict_iter_find_key(struct db_dict_value_iter *iter, const char *name)
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainenstatic void db_dict_iter_find_used_keys(struct db_dict_value_iter *iter)
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen const char *p, *name;
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen if (*p != '%') {
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen /* broken %variable ending too early */
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainenstatic void db_dict_iter_find_used_objects(struct db_dict_value_iter *iter)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen key = db_dict_iter_find_key(iter, (*keyp)->name);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen i_assert(key->key->parsed_format != DB_DICT_VALUE_FORMAT_VALUE);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainendb_dict_iter_key_cmp(const struct db_dict_iter_key *k1,
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen return null_strcmp(k1->key->default_value, k2->key->default_value);
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainenstatic int db_dict_iter_lookup_key_values(struct db_dict_value_iter *iter)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* sort the keys so that we'll first lookup the keys without
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen default value. if their lookup fails, the user doesn't exist. */
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen array_sort(&iter->keys, db_dict_iter_key_cmp);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen var_expand(path, key->key->key, iter->var_expand_table);
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen ret = dict_lookup(iter->conn->dict, iter->pool,
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen auth_request_log_debug(iter->auth_request, AUTH_SUBSYS_DB,
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen } else if (ret < 0) {
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen auth_request_log_error(iter->auth_request, AUTH_SUBSYS_DB,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen "Failed to lookup key %s: %s", str_c(path), error);
int ret;
NULL);
T_BEGIN {
} T_END;
if (ret <= 0) {
return ret;
const char *value;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
return FALSE;
i_unreached();
i_unreached();
return NULL;
return NULL;
return ret;
i_unreached();
return TRUE;
const char **error_r)