mail-user.c revision 74943466e541d8bfe3916bb0eb9fb9cb0599dfe7
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen#include "array.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "hostpid.h"
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen#include "ioloop.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "net.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "module-dir.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "home-expand.h"
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen#include "file-create-locked.h"
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen#include "safe-mkstemp.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "str.h"
18565c69efcd7db003dbf27cf625ed822e889fb1Timo Sirainen#include "strescape.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "var-expand.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "settings-parser.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "iostream-ssl.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "fs-api.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "auth-master.h"
d22301419109ed4a38351715e6760011421dadecTimo Sirainen#include "master-service.h"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#include "dict.h"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#include "mail-storage-settings.h"
d22301419109ed4a38351715e6760011421dadecTimo Sirainen#include "mail-storage-private.h"
d22301419109ed4a38351715e6760011421dadecTimo Sirainen#include "mail-storage-service.h"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#include "mail-namespace.h"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#include "mail-storage.h"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#include "mailbox-list-private.h"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#include "mail-autoexpunge.h"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen#include "mail-user.h"
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstruct mail_user_module_register mail_user_module_register = { 0 };
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstruct auth_master_connection *mail_user_auth_master_conn;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic void mail_user_deinit_base(struct mail_user *user)
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainen{
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainen if (user->_attr_dict != NULL) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen dict_wait(user->_attr_dict);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen dict_deinit(&user->_attr_dict);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen mail_namespaces_deinit(&user->namespaces);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (user->_service_user != NULL)
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen mail_storage_service_user_unref(&user->_service_user);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen}
4b41116563110d00330896a568eff1078c382827Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainenstatic void mail_user_deinit_pre_base(struct mail_user *user ATTR_UNUSED)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen}
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainenstatic void mail_user_stats_fill_base(struct mail_user *user ATTR_UNUSED,
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen struct stats *stats ATTR_UNUSED)
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen{
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen}
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainenstatic struct mail_user *
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenmail_user_alloc_int(struct event *parent_event,
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen const char *username,
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen const struct setting_parser_info *set_info,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const struct mail_user_settings *set, pool_t pool)
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen{
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen struct mail_user *user;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen const char *error;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen i_assert(username != NULL);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen i_assert(*username != '\0');
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen user = p_new(pool, struct mail_user, 1);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen user->pool = pool;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen user->refcount = 1;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen user->username = p_strdup(pool, username);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen user->set_info = set_info;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen user->unexpanded_set = set;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen user->set = settings_dup_with_pointers(set_info, user->unexpanded_set, pool);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen user->service = master_service_get_name(master_service);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen user->default_normalizer = uni_utf8_to_decomposed_titlecase;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen user->session_create_time = ioloop_time;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen user->event = event_create(parent_event);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen event_add_category(user->event, &event_category_storage);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen event_add_str(user->event, "user", username);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen /* check settings so that the duplicated structure will again
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen contain the parsed fields */
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (!settings_check(set_info, pool, user->set, &error))
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen i_panic("Settings check unexpectedly failed: %s", error);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
597dce34068d603fb759b4dff404b34049213e51Timo Sirainen user->v.deinit = mail_user_deinit_base;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen user->v.deinit_pre = mail_user_deinit_pre_base;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen user->v.stats_fill = mail_user_stats_fill_base;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen p_array_init(&user->module_contexts, user->pool, 5);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return user;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen}
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenstruct mail_user *
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenmail_user_alloc_nodup_set(struct event *parent_event,
4b41116563110d00330896a568eff1078c382827Timo Sirainen const char *username,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const struct setting_parser_info *set_info,
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen const struct mail_user_settings *set)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen pool_t pool;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"mail user", 16*1024);
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen return mail_user_alloc_int(parent_event, username, set_info, set, pool);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen}
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenstruct mail_user *mail_user_alloc(struct event *parent_event,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *username,
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen const struct setting_parser_info *set_info,
4b41116563110d00330896a568eff1078c382827Timo Sirainen const struct mail_user_settings *set)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen pool_t pool;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"mail user", 16*1024);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return mail_user_alloc_int(parent_event, username, set_info,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen settings_dup(set_info, set, pool), pool);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenstatic void
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenmail_user_expand_plugins_envs(struct mail_user *user)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
4b41116563110d00330896a568eff1078c382827Timo Sirainen const char **envs, *home, *error;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen string_t *str;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen unsigned int i, count;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (!array_is_created(&user->set->plugin_envs))
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen return;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen str = t_str_new(256);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen envs = array_get_modifiable(&user->set->plugin_envs, &count);
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen i_assert((count % 2) == 0);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen for (i = 0; i < count; i += 2) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (user->_home == NULL &&
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen var_has_key(envs[i+1], 'h', "home") &&
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mail_user_get_home(user, &home) <= 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen user->error = p_strdup_printf(user->pool,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen "userdb didn't return a home directory, "
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen "but plugin setting %s used it (%%h): %s",
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen envs[i], envs[i+1]);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen str_truncate(str, 0);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (var_expand_with_funcs(str, envs[i+1],
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen mail_user_var_expand_table(user),
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen mail_user_var_expand_func_table, user,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen &error) <= 0) {
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen user->error = p_strdup_printf(user->pool,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "Failed to expand plugin setting %s = '%s': %s",
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen envs[i], envs[i+1], error);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen envs[i+1] = p_strdup(user->pool, str_c(str));
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen }
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen}
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenint mail_user_init(struct mail_user *user, const char **error_r)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen const struct mail_storage_settings *mail_set;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen const char *home, *key, *value, *error;
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen bool need_home_dir;
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen need_home_dir = user->_home == NULL &&
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen settings_vars_have_key(user->set_info, user->set,
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen 'h', "home", &key, &value);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen if (need_home_dir && mail_user_get_home(user, &home) <= 0) {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen user->error = p_strdup_printf(user->pool,
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen "userdb didn't return a home directory, "
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen "but %s used it (%%h): %s", key, value);
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen }
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen /* expand settings after we can expand %h */
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen if (settings_var_expand_with_funcs(user->set_info, user->set,
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen user->pool, mail_user_var_expand_table(user),
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen mail_user_var_expand_func_table, user,
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen &error) <= 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen user->error = p_strdup_printf(user->pool,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "Failed to expand settings: %s", error);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen user->settings_expanded = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mail_user_expand_plugins_envs(user);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen /* autocreated users for shared mailboxes need to be fully initialized
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if they don't exist, since they're going to be used anyway */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (user->error == NULL || user->nonexistent) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen mail_set = mail_user_set_get_storage_set(user);
4b41116563110d00330896a568eff1078c382827Timo Sirainen user->mail_debug = mail_set->mail_debug;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen user->initialized = TRUE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen hook_mail_user_created(user);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
ee3e01f75b1db691bf20dd4e2558965421b8f937Timo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (user->error != NULL) {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen *error_r = t_strdup(user->error);
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen return -1;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen return 0;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen}
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainenvoid mail_user_ref(struct mail_user *user)
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen{
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen i_assert(user->refcount > 0);
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen user->refcount++;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen}
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainenvoid mail_user_unref(struct mail_user **_user)
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen{
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen struct mail_user *user = *_user;
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen i_assert(user->refcount > 0);
cbcde6379f1b0b27bdefc4b11eec93ad69e459d4Timo Sirainen
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen *_user = NULL;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen if (user->refcount > 1) {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen user->refcount--;
e48c10b9db945fd72e2315e3ec343174fa55c7c7Timo Sirainen return;
e48c10b9db945fd72e2315e3ec343174fa55c7c7Timo Sirainen }
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen user->deinitializing = TRUE;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen /* call deinit() and deinit_pre() with refcount=1, otherwise we may
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen assert-crash in mail_user_ref() that is called by some handlers. */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen user->v.deinit_pre(user);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen user->v.deinit(user);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen event_unref(&user->event);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_assert(user->refcount == 1);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen pool_unref(&user->pool);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen}
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainenstruct mail_user *mail_user_find(struct mail_user *user, const char *name)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen struct mail_namespace *ns;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen if (ns->owner != NULL && strcmp(ns->owner->username, name) == 0)
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen return ns->owner;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen return NULL;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen}
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainenstatic void
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainenmail_user_connection_init_from(struct mail_user_connection_data *conn,
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen pool_t pool, const struct mail_user_connection_data *src)
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen{
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen *conn = *src;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (src->local_ip != NULL && src->local_ip->family != 0) {
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen conn->local_ip = p_new(pool, struct ip_addr, 1);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen *conn->local_ip = *src->local_ip;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (src->remote_ip != NULL && src->remote_ip->family != 0) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen conn->remote_ip = p_new(pool, struct ip_addr, 1);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen *conn->remote_ip = *src->remote_ip;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen }
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen}
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainenvoid mail_user_set_vars(struct mail_user *user, const char *service,
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen const struct mail_user_connection_data *conn)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_assert(service != NULL);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen user->service = p_strdup(user->pool, service);
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen event_add_str(user->event, "service", service);
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen mail_user_connection_init_from(&user->conn, user->pool, conn);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (user->conn.local_ip != NULL)
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen event_add_str(user->event, "local_ip",
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen net_ip2addr(user->conn.local_ip));
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (user->conn.remote_ip != NULL)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen event_add_str(user->event, "remote_ip",
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen net_ip2addr(user->conn.remote_ip));
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen}
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainenconst struct var_expand_table *
d22301419109ed4a38351715e6760011421dadecTimo Sirainenmail_user_var_expand_table(struct mail_user *user)
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen{
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen /* use a cached table, unless home directory has been set afterwards */
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen if (user->var_expand_table != NULL &&
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen user->var_expand_table[4].value == user->_home)
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen return user->var_expand_table;
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen const char *username =
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen p_strdup(user->pool, t_strcut(user->username, '@'));
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen const char *domain = i_strchr_to_next(user->username, '@');
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen const char *local_ip = user->conn.local_ip == NULL ? NULL :
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen p_strdup(user->pool, net_ip2addr(user->conn.local_ip));
a1808be0774cbcb28fec45341aabf803ec44bae5Timo Sirainen const char *remote_ip = user->conn.remote_ip == NULL ? NULL :
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen p_strdup(user->pool, net_ip2addr(user->conn.remote_ip));
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen const char *auth_user, *auth_username, *auth_domain;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (user->auth_user == NULL) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen auth_user = user->username;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen auth_username = username;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen auth_domain = domain;
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen } else {
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen auth_user = user->auth_user;
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen auth_username =
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen p_strdup(user->pool, t_strcut(user->auth_user, '@'));
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen auth_domain = i_strchr_to_next(user->auth_user, '@');
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen const struct var_expand_table stack_tab[] = {
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen { 'u', user->username, "user" },
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen { 'n', username, "username" },
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen { 'd', domain, "domain" },
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen { 's', user->service, "service" },
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen { 'h', user->_home /* don't look it up unless we need it */, "home" },
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen { 'l', local_ip, "lip" },
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen { 'r', remote_ip, "rip" },
a5c8dc283ef673fcdae158513b8032e74b45f59aTimo Sirainen { 'p', my_pid, "pid" },
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen { 'i', p_strdup(user->pool, dec2str(user->uid)), "uid" },
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen { '\0', p_strdup(user->pool, dec2str(user->gid)), "gid" },
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen { '\0', user->session_id, "session" },
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen { '\0', auth_user, "auth_user" },
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen { '\0', auth_username, "auth_username" },
d22301419109ed4a38351715e6760011421dadecTimo Sirainen { '\0', auth_domain, "auth_domain" },
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* NOTE: keep this synced with imap-hibernate's
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen imap_client_var_expand_table() */
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen { '\0', NULL, NULL }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen };
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen struct var_expand_table *tab;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen tab = p_malloc(user->pool, sizeof(stack_tab));
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen memcpy(tab, stack_tab, sizeof(stack_tab));
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen
4b41116563110d00330896a568eff1078c382827Timo Sirainen user->var_expand_table = tab;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return user->var_expand_table;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen}
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen
f480b30abdddf6f1beb8a2c5b1ce4bf8999400dbTimo Sirainenstatic int
f480b30abdddf6f1beb8a2c5b1ce4bf8999400dbTimo Sirainenmail_user_var_expand_func_userdb(const char *data, void *context,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char **value_r,
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen const char **error_r ATTR_UNUSED)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen{
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen struct mail_user *user = context;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen *value_r = mail_storage_service_fields_var_expand(data, user->userdb_fields);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen return 1;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen}
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenvoid mail_user_set_home(struct mail_user *user, const char *home)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen{
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen user->_home = p_strdup(user->pool, home);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen user->home_looked_up = TRUE;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen}
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainenvoid mail_user_add_namespace(struct mail_user *user,
8f017a40470ef2f4b530000d947a8bce44350a5eTimo Sirainen struct mail_namespace **namespaces)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen{
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen struct mail_namespace **tmp, *next, *ns = *namespaces;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen for (; ns != NULL; ns = next) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen next = ns->next;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen tmp = &user->namespaces;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen for (; *tmp != NULL; tmp = &(*tmp)->next) {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen i_assert(*tmp != ns);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (strlen(ns->prefix) < strlen((*tmp)->prefix))
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen break;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen ns->next = *tmp;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen *tmp = ns;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen }
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen *namespaces = user->namespaces;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen T_BEGIN {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen hook_mail_namespaces_added(user->namespaces);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } T_END;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenvoid mail_user_drop_useless_namespaces(struct mail_user *user)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen{
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct mail_namespace *ns, *next;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen /* drop all autocreated unusable (typically shared) namespaces.
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen don't drop the autocreated prefix="" namespace that we explicitly
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen created for being the fallback namespace. */
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen for (ns = user->namespaces; ns != NULL; ns = next) {
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen next = ns->next;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if ((ns->flags & NAMESPACE_FLAG_USABLE) == 0 &&
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen (ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0 &&
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen ns->prefix_len > 0)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen mail_namespace_destroy(ns);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen }
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenconst char *mail_user_home_expand(struct mail_user *user, const char *path)
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen (void)mail_user_try_home_expand(user, &path);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return path;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
aa247243412a49f9bdebf7255e131dc6ece4ed46Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic int mail_user_userdb_lookup_home(struct mail_user *user)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct auth_user_info info;
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen struct auth_user_reply reply;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen pool_t userdb_pool;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char *username, *const *fields;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen int ret;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen i_assert(!user->home_looked_up);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen i_zero(&info);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen info.service = user->service;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (user->conn.local_ip != NULL)
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen info.local_ip = *user->conn.local_ip;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (user->conn.remote_ip != NULL)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen info.remote_ip = *user->conn.remote_ip;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen userdb_pool = pool_alloconly_create("userdb lookup", 2048);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen ret = auth_master_user_lookup(mail_user_auth_master_conn,
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen user->username, &info, userdb_pool,
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen &username, &fields);
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen if (ret > 0) {
01404d41657a104c5ea1c12bb87f9c321e9c1ac4Timo Sirainen auth_user_fields_parse(fields, userdb_pool, &reply);
01404d41657a104c5ea1c12bb87f9c321e9c1ac4Timo Sirainen user->_home = p_strdup(user->pool, reply.home);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
pool_unref(&userdb_pool);
return ret;
}
static bool mail_user_get_mail_home(struct mail_user *user)
{
const char *error, *home = user->set->mail_home;
string_t *str;
if (user->settings_expanded) {
user->_home = home[0] != '\0' ? home : NULL;
return TRUE;
}
/* we're still initializing user. need to do the expansion ourself. */
i_assert(home[0] == SETTING_STRVAR_UNEXPANDED[0]);
home++;
if (home[0] == '\0')
return TRUE;
str = t_str_new(128);
if (var_expand_with_funcs(str, home,
mail_user_var_expand_table(user),
mail_user_var_expand_func_table, user,
&error) <= 0) {
i_error("Failed to expand mail_home=%s: %s", home, error);
return FALSE;
}
user->_home = p_strdup(user->pool, str_c(str));
return TRUE;
}
int mail_user_get_home(struct mail_user *user, const char **home_r)
{
int ret;
if (user->home_looked_up) {
*home_r = user->_home;
return user->_home != NULL ? 1 : 0;
}
if (mail_user_auth_master_conn == NULL) {
/* no userdb connection. we can only use mail_home setting. */
if (!mail_user_get_mail_home(user))
return -1;
} else if ((ret = mail_user_userdb_lookup_home(user)) < 0) {
/* userdb lookup failed */
return -1;
} else if (ret == 0) {
/* user doesn't exist */
user->nonexistent = TRUE;
} else if (user->_home == NULL) {
/* no home returned by userdb lookup, fallback to
mail_home setting. */
if (!mail_user_get_mail_home(user))
return -1;
}
user->home_looked_up = TRUE;
*home_r = user->_home;
return user->_home != NULL ? 1 : 0;
}
bool mail_user_is_plugin_loaded(struct mail_user *user, struct module *module)
{
const char *const *plugins;
bool ret;
T_BEGIN {
plugins = t_strsplit_spaces(user->set->mail_plugins, ", ");
ret = str_array_find(plugins, module_get_plugin_name(module));
} T_END;
return ret;
}
bool mail_user_plugin_getenv_bool(struct mail_user *user, const char *name)
{
return mail_user_set_plugin_getenv_bool(user->set, name);
}
bool mail_user_set_plugin_getenv_bool(const struct mail_user_settings *set,
const char *name)
{
const char *env = mail_user_set_plugin_getenv(set, name);
if (env == NULL)
return FALSE;
switch (env[0]) {
case 'n':
case 'N':
case '0':
case 'f':
case 'F':
return FALSE;
}
//any other value including empty string will be treated as TRUE.
return TRUE;
}
const char *mail_user_plugin_getenv(struct mail_user *user, const char *name)
{
return mail_user_set_plugin_getenv(user->set, name);
}
const char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
const char *name)
{
const char *const *envs;
unsigned int i, count;
if (!array_is_created(&set->plugin_envs))
return NULL;
envs = array_get(&set->plugin_envs, &count);
for (i = 0; i < count; i += 2) {
if (strcmp(envs[i], name) == 0)
return envs[i+1];
}
return NULL;
}
int mail_user_try_home_expand(struct mail_user *user, const char **pathp)
{
const char *home, *path = *pathp;
if (*path != '~') {
/* no need to expand home */
return 0;
}
if (mail_user_get_home(user, &home) <= 0)
return -1;
path = home_expand_tilde(path, home);
if (path == NULL)
return -1;
*pathp = path;
return 0;
}
void mail_user_set_get_temp_prefix(string_t *dest,
const struct mail_user_settings *set)
{
str_append(dest, set->mail_temp_dir);
str_append(dest, "/dovecot.");
str_append(dest, master_service_get_name(master_service));
str_append_c(dest, '.');
}
int mail_user_lock_file_create(struct mail_user *user, const char *lock_fname,
unsigned int lock_secs,
struct file_lock **lock_r, const char **error_r)
{
const char *home, *path;
int ret;
if ((ret = mail_user_get_home(user, &home)) < 0) {
/* home lookup failed - shouldn't really happen */
*error_r = "Failed to lookup home directory";
errno = EINVAL;
return -1;
}
if (ret == 0) {
*error_r = "User has no home directory";
errno = EINVAL;
return -1;
}
const struct mail_storage_settings *mail_set =
mail_user_set_get_storage_set(user);
struct file_create_settings lock_set = {
.lock_timeout_secs = lock_secs,
.lock_method = mail_set->parsed_lock_method,
};
struct mailbox_list *inbox_list =
mail_namespace_find_inbox(user->namespaces)->list;
if (inbox_list->set.volatile_dir == NULL)
path = t_strdup_printf("%s/%s", home, lock_fname);
else {
path = t_strdup_printf("%s/%s", inbox_list->set.volatile_dir,
lock_fname);
lock_set.mkdir_mode = 0700;
}
return mail_storage_lock_create(path, &lock_set, mail_set, lock_r, error_r);
}
const char *mail_user_get_anvil_userip_ident(struct mail_user *user)
{
if (user->conn.remote_ip == NULL)
return NULL;
return t_strconcat(net_ip2addr(user->conn.remote_ip), "/",
str_tabescape(user->username), NULL);
}
static void
mail_user_try_load_class_plugin(struct mail_user *user, const char *name)
{
struct module_dir_load_settings mod_set;
struct module *module;
size_t name_len = strlen(name);
i_zero(&mod_set);
mod_set.abi_version = DOVECOT_ABI_VERSION;
mod_set.binary_name = master_service_get_name(master_service);
mod_set.setting_name = "<built-in storage lookup>";
mod_set.require_init_funcs = TRUE;
mod_set.debug = user->mail_debug;
mail_storage_service_modules =
module_dir_load_missing(mail_storage_service_modules,
user->set->mail_plugin_dir,
name, &mod_set);
/* initialize the module (and only this module!) immediately so that
the class gets registered */
for (module = mail_storage_service_modules; module != NULL; module = module->next) {
if (strncmp(module->name, name, name_len) == 0 &&
strcmp(module->name + name_len, "_plugin") == 0) {
if (!module->initialized) {
module->initialized = TRUE;
module->init(module);
}
break;
}
}
}
struct mail_storage *
mail_user_get_storage_class(struct mail_user *user, const char *name)
{
struct mail_storage *storage;
storage = mail_storage_find_class(name);
if (storage == NULL || storage->v.alloc != NULL)
return storage;
/* it's implemented by a plugin. load it and check again. */
mail_user_try_load_class_plugin(user, name);
storage = mail_storage_find_class(name);
if (storage != NULL && storage->v.alloc == NULL) {
i_error("Storage driver '%s' exists as a stub, "
"but its plugin couldn't be loaded", name);
return NULL;
}
return storage;
}
struct mail_user *mail_user_dup(struct mail_user *user)
{
struct mail_user *user2;
user2 = mail_user_alloc(event_get_parent(user->event), user->username,
user->set_info, user->unexpanded_set);
if (user2->_service_user != NULL) {
user2->_service_user = user->_service_user;
mail_storage_service_user_ref(user2->_service_user);
}
if (user->_home != NULL)
mail_user_set_home(user2, user->_home);
mail_user_set_vars(user2, user->service, &user->conn);
user2->uid = user->uid;
user2->gid = user->gid;
user2->anonymous = user->anonymous;
user2->admin = user->admin;
user2->auth_token = p_strdup(user2->pool, user->auth_token);
user2->auth_user = p_strdup(user2->pool, user->auth_user);
user2->session_id = p_strdup(user2->pool, user->session_id);
user2->session_create_time = user->session_create_time;
user2->userdb_fields = user->userdb_fields == NULL ? NULL :
p_strarray_dup(user2->pool, user->userdb_fields);
return user2;
}
void mail_user_init_ssl_client_settings(struct mail_user *user,
struct ssl_iostream_settings *ssl_set)
{
const struct mail_storage_settings *mail_set =
mail_user_set_get_storage_set(user);
ssl_set->ca_dir = mail_set->ssl_client_ca_dir;
ssl_set->ca_file = mail_set->ssl_client_ca_file;
}
void mail_user_init_fs_settings(struct mail_user *user,
struct fs_settings *fs_set,
struct ssl_iostream_settings *ssl_set)
{
fs_set->username = user->username;
fs_set->session_id = user->session_id;
fs_set->base_dir = user->set->base_dir;
fs_set->temp_dir = user->set->mail_temp_dir;
fs_set->debug = user->mail_debug;
fs_set->enable_timing = user->stats_enabled;
fs_set->ssl_client_set = ssl_set;
mail_user_init_ssl_client_settings(user, ssl_set);
}
void mail_user_stats_fill(struct mail_user *user, struct stats *stats)
{
user->v.stats_fill(user, stats);
}
static const struct var_expand_func_table mail_user_var_expand_func_table_arr[] = {
{ "userdb", mail_user_var_expand_func_userdb },
{ NULL, NULL }
};
const struct var_expand_func_table *mail_user_var_expand_func_table =
mail_user_var_expand_func_table_arr;