mail-user.c revision 74943466e541d8bfe3916bb0eb9fb9cb0599dfe7
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstruct mail_user_module_register mail_user_module_register = { 0 };
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstruct auth_master_connection *mail_user_auth_master_conn;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic void mail_user_deinit_base(struct mail_user *user)
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen mail_storage_service_user_unref(&user->_service_user);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainenstatic void mail_user_deinit_pre_base(struct mail_user *user ATTR_UNUSED)
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainenstatic void mail_user_stats_fill_base(struct mail_user *user ATTR_UNUSED,
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainenstatic struct mail_user *
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenmail_user_alloc_int(struct event *parent_event,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const struct mail_user_settings *set, pool_t pool)
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 event_add_category(user->event, &event_category_storage);
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);
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 Sirainenmail_user_alloc_nodup_set(struct event *parent_event,
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 Sirainenstruct mail_user *mail_user_alloc(struct event *parent_event,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"mail user", 16*1024);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return mail_user_alloc_int(parent_event, username, set_info,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenmail_user_expand_plugins_envs(struct mail_user *user)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen unsigned int i, count;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (!array_is_created(&user->set->plugin_envs))
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen envs = array_get_modifiable(&user->set->plugin_envs, &count);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen "userdb didn't return a home directory, "
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen "but plugin setting %s used it (%%h): %s",
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "Failed to expand plugin setting %s = '%s': %s",
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenint mail_user_init(struct mail_user *user, const char **error_r)
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen settings_vars_have_key(user->set_info, user->set,
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen if (need_home_dir && mail_user_get_home(user, &home) <= 0) {
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen "userdb didn't return a home directory, "
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen /* expand settings after we can expand %h */
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen if (settings_var_expand_with_funcs(user->set_info, user->set,
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);
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. */
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainenstruct mail_user *mail_user_find(struct mail_user *user, const char *name)
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen if (ns->owner != NULL && strcmp(ns->owner->username, name) == 0)
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainenmail_user_connection_init_from(struct mail_user_connection_data *conn,
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen pool_t pool, const struct mail_user_connection_data *src)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (src->local_ip != NULL && src->local_ip->family != 0) {
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen conn->local_ip = p_new(pool, struct ip_addr, 1);
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 Sirainenvoid mail_user_set_vars(struct mail_user *user, const char *service,
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen user->service = p_strdup(user->pool, service);
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen event_add_str(user->event, "service", service);
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen mail_user_connection_init_from(&user->conn, user->pool, conn);
d22301419109ed4a38351715e6760011421dadecTimo Sirainenmail_user_var_expand_table(struct mail_user *user)
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen /* use a cached table, unless home directory has been set afterwards */
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen user->var_expand_table[4].value == user->_home)
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));
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen const char *auth_user, *auth_username, *auth_domain;
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen p_strdup(user->pool, t_strcut(user->auth_user, '@'));
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen auth_domain = i_strchr_to_next(user->auth_user, '@');
aa215ab623706463cea1d047f975ffe51d3f0c05Timo Sirainen { 'h', user->_home /* don't look it up unless we need it */, "home" },
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen { 'i', p_strdup(user->pool, dec2str(user->uid)), "uid" },
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen { '\0', p_strdup(user->pool, dec2str(user->gid)), "gid" },
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* NOTE: keep this synced with imap-hibernate's
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen imap_client_var_expand_table() */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen tab = p_malloc(user->pool, sizeof(stack_tab));
f480b30abdddf6f1beb8a2c5b1ce4bf8999400dbTimo Sirainenmail_user_var_expand_func_userdb(const char *data, void *context,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char **value_r,
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen *value_r = mail_storage_service_fields_var_expand(data, user->userdb_fields);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenvoid mail_user_set_home(struct mail_user *user, const char *home)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainenvoid mail_user_add_namespace(struct mail_user *user,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen struct mail_namespace **tmp, *next, *ns = *namespaces;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (strlen(ns->prefix) < strlen((*tmp)->prefix))
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenvoid mail_user_drop_useless_namespaces(struct mail_user *user)
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 if ((ns->flags & NAMESPACE_FLAG_USABLE) == 0 &&
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen (ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0 &&
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenconst char *mail_user_home_expand(struct mail_user *user, const char *path)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic int mail_user_userdb_lookup_home(struct mail_user *user)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen userdb_pool = pool_alloconly_create("userdb lookup", 2048);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen ret = auth_master_user_lookup(mail_user_auth_master_conn,
01404d41657a104c5ea1c12bb87f9c321e9c1ac4Timo Sirainen auth_user_fields_parse(fields, userdb_pool, &reply);
01404d41657a104c5ea1c12bb87f9c321e9c1ac4Timo Sirainen user->_home = p_strdup(user->pool, reply.home);
return ret;
return TRUE;
home++;
return TRUE;
&error) <= 0) {
return FALSE;
return TRUE;
int ret;
} else if (ret == 0) {
const char *const *plugins;
bool ret;
T_BEGIN {
} T_END;
return ret;
const char *name)
return FALSE;
switch (env[0]) {
return FALSE;
return TRUE;
const char *name)
const char *const *envs;
unsigned int i, count;
return NULL;
return NULL;
unsigned int lock_secs,
int ret;
if (ret == 0) {
return NULL;
struct mail_storage *
return storage;
return NULL;
return storage;
return user2;