From: Siavash Tavakoli Date: Fri, 4 Jun 2021 22:00:21 +0000 (+0100) Subject: dict-file: Make sure home_dir doesn't change during operations X-Git-Tag: 2.3.17~350 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=60cbb2959c614ac9777bb9511bc6f4e0f81aeb90;p=thirdparty%2Fdovecot%2Fcore.git dict-file: Make sure home_dir doesn't change during operations file_dict is initialized for a specific user. Keep record of the user's home_dir and check for all dict operations that the user did not change. --- diff --git a/src/lib-dict/dict-file.c b/src/lib-dict/dict-file.c index b101871be7..8a3942fec3 100644 --- a/src/lib-dict/dict-file.c +++ b/src/lib-dict/dict-file.c @@ -27,6 +27,8 @@ struct file_dict { enum file_lock_method lock_method; char *path; + char *home_dir; + bool dict_path_checked; HASH_TABLE(char *, char *) hash; int fd; @@ -52,6 +54,28 @@ static struct dotlock_settings file_dict_dotlock_settings = { .use_io_notify = TRUE }; +static int +file_dict_ensure_path_home_dir(struct file_dict *dict, const char *home_dir, + const char **error_r) +{ + if (null_strcmp(dict->home_dir, home_dir) == 0) + return 0; + + if (dict->dict_path_checked) { + *error_r = t_strdup_printf("home_dir changed from %s to %s " + "(requested dict was: %s)", dict->home_dir, + home_dir, dict->path); + return -1; + } + + char *_p = dict->path; + dict->path = i_strdup(home_expand_tilde(dict->path, home_dir)); + dict->home_dir = i_strdup(home_dir); + i_free(_p); + dict->dict_path_checked = TRUE; + return 0; +} + static int file_dict_init(struct dict *driver, const char *uri, const struct dict_settings *set ATTR_UNUSED, @@ -79,6 +103,11 @@ file_dict_init(struct dict *driver, const char *uri, return -1; } } + + /* keep the path for now, later in dict operations check if home_dir + should be prepended. */ + dict->path = i_strdup(path); + dict->dict = *driver; dict->hash_pool = pool_alloconly_create("file dict", 1024); hash_table_create(&dict->hash, dict->hash_pool, 0, str_hash, strcmp); @@ -95,6 +124,7 @@ static void file_dict_deinit(struct dict *_dict) hash_table_destroy(&dict->hash); pool_unref(&dict->hash_pool); i_free(dict->path); + i_free(dict->home_dir); i_free(dict); } @@ -192,12 +222,15 @@ static int file_dict_refresh(struct file_dict *dict, const char **error_r) } static int file_dict_lookup(struct dict *_dict, - const struct dict_op_settings *set ATTR_UNUSED, + const struct dict_op_settings *set, pool_t pool, const char *key, const char **value_r, const char **error_r) { struct file_dict *dict = (struct file_dict *)_dict; + if (file_dict_ensure_path_home_dir(dict, set->home_dir, error_r) < 0) + return -1; + if (file_dict_refresh(dict, error_r) < 0) return -1; @@ -224,7 +257,8 @@ file_dict_iterate_init(struct dict *_dict, ctx->path_len = strlen(path); ctx->flags = flags; - if (file_dict_refresh(dict, &error) < 0) + if (file_dict_ensure_path_home_dir(dict, set->home_dir, &error) < 0 || + file_dict_refresh(dict, &error) < 0) ctx->error = p_strdup(pool, error); ctx->iter = hash_table_iterate_init(dict->hash); @@ -520,6 +554,9 @@ file_dict_write_changes(struct dict_transaction_memory_context *ctx, *atomic_inc_not_found_r = FALSE; + if (file_dict_ensure_path_home_dir(dict, ctx->ctx.set.home_dir, error_r) < 0) + return -1; + switch (dict->lock_method) { case FILE_LOCK_METHOD_FCNTL: case FILE_LOCK_METHOD_FLOCK: