mail-user.c revision fc4e528886f47bf4d2dd0276fb8705c085c3b9ae
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2016 Dovecot authors, see the included COPYING file */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenstruct mail_user_module_register mail_user_module_register = { 0 };
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstruct auth_master_connection *mail_user_auth_master_conn;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenstatic void mail_user_deinit_base(struct mail_user *user)
379175cfba8150d481d9898b78330b719d128d84Timo Sirainenstatic void mail_user_stats_fill_base(struct mail_user *user ATTR_UNUSED,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstruct mail_user *mail_user_alloc(const char *username,
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"mail user", 16*1024);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen user->unexpanded_set = settings_dup(set_info, set, pool);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen user->set = settings_dup(set_info, set, pool);
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen user->service = master_service_get_name(master_service);
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen user->default_normalizer = uni_utf8_to_decomposed_titlecase;
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen /* check settings so that the duplicated structure will again
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen contain the parsed fields */
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen if (!settings_check(set_info, pool, user->set, &error))
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen i_panic("Settings check unexpectedly failed: %s", error);
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen user->v.stats_fill = mail_user_stats_fill_base;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen p_array_init(&user->module_contexts, user->pool, 5);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainenmail_user_expand_plugins_envs(struct mail_user *user)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen unsigned int i, count;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (!array_is_created(&user->set->plugin_envs))
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen envs = array_get_modifiable(&user->set->plugin_envs, &count);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen "userdb didn't return a home directory, "
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen "but plugin setting %s used it (%%h): %s",
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint mail_user_init(struct mail_user *user, const char **error_r)
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen settings_vars_have_key(user->set_info, user->set,
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen if (need_home_dir && mail_user_get_home(user, &home) <= 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "userdb didn't return a home directory, "
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen /* expand settings after we can expand %h */
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen settings_var_expand_with_funcs(user->set_info, user->set,
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* autocreated users for shared mailboxes need to be fully initialized
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen if they don't exist, since they're going to be used anyway */
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen if (user->error == NULL || user->nonexistent) {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen mail_set = mail_user_set_get_storage_set(user);
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen /* call deinit() with refcount=1, otherwise we may assert-crash in
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen mail_user_ref() that is called by some deinit() handler. */
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenstruct mail_user *mail_user_find(struct mail_user *user, const char *name)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen if (ns->owner != NULL && strcmp(ns->owner->username, name) == 0)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenvoid mail_user_set_vars(struct mail_user *user, const char *service,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen user->service = p_strdup(user->pool, service);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (local_ip != NULL && local_ip->family != 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen user->local_ip = p_new(user->pool, struct ip_addr, 1);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (remote_ip != NULL && remote_ip->family != 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen user->remote_ip = p_new(user->pool, struct ip_addr, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenmail_user_var_expand_table(struct mail_user *user)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen static struct var_expand_table static_tab[] = {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* NOTE: keep this synced with imap-hibernate's
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen imap_client_var_expand_table() */
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen /* use a cached table, unless home directory has been set afterwards */
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen user->var_expand_table[4].value == user->_home)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tab = p_malloc(user->pool, sizeof(static_tab));
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tab[1].value = p_strdup(user->pool, t_strcut(user->username, '@'));
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tab[4].value = user->_home; /* don't look it up unless we need it */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tab[5].value = user->local_ip == NULL ? NULL :
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen p_strdup(user->pool, net_ip2addr(user->local_ip));
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tab[6].value = user->remote_ip == NULL ? NULL :
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen p_strdup(user->pool, net_ip2addr(user->remote_ip));
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tab[8].value = p_strdup(user->pool, dec2str(user->uid));
88b0427d90f1d3c2c5fb3171e53a505c46e2c39dTimo Sirainen tab[9].value = p_strdup(user->pool, dec2str(user->gid));
872876c29ab50b4d3b4aeaac65546f21bfaa71f4Timo Sirainen tab[12].value = p_strdup(user->pool, t_strcut(user->auth_user, '@'));
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenstatic const char *
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenmail_user_var_expand_func_userdb(const char *data, void *context)
d23dfc385f22d7a2c466d29501c9e0ce5a243deeTimo Sirainen return mail_storage_service_fields_var_expand(data, user->userdb_fields);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenvoid mail_user_set_home(struct mail_user *user, const char *home)
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainenvoid mail_user_add_namespace(struct mail_user *user,
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen struct mail_namespace **tmp, *next, *ns = *namespaces;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (strlen(ns->prefix) < strlen((*tmp)->prefix))
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainenvoid mail_user_drop_useless_namespaces(struct mail_user *user)
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen /* drop all autocreated unusable (typically shared) namespaces.
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen don't drop the autocreated prefix="" namespace that we explicitly
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen created for being the fallback namespace. */
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = next) {
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen if ((ns->flags & NAMESPACE_FLAG_USABLE) == 0 &&
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen (ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0 &&
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenconst char *mail_user_home_expand(struct mail_user *user, const char *path)
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainenstatic int mail_user_userdb_lookup_home(struct mail_user *user)
5e751dbaecf7c337abc149f328c4a13ee5c15134Timo Sirainen userdb_pool = pool_alloconly_create("userdb lookup", 2048);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ret = auth_master_user_lookup(mail_user_auth_master_conn,
9f10cc61ec303351b43e54155c86699ef53cb8beTimo Sirainen auth_user_fields_parse(fields, userdb_pool, &reply);
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen user->_home = p_strdup(user->pool, reply.home);
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainenstatic void mail_user_get_mail_home(struct mail_user *user)
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen /* we're still initializing user. need to do the expansion ourself. */
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen i_assert(home[0] == SETTING_STRVAR_UNEXPANDED[0]);
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen user->_home = p_strdup(user->pool, str_c(str));
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainenint mail_user_get_home(struct mail_user *user, const char **home_r)
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen /* no userdb connection. we can only use mail_home setting. */
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen } else if ((ret = mail_user_userdb_lookup_home(user)) < 0) {
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen /* userdb lookup failed */
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen } else if (ret == 0) {
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen /* user doesn't exist */
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen /* no home returned by userdb lookup, fallback to
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen mail_home setting. */
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainenbool mail_user_is_plugin_loaded(struct mail_user *user, struct module *module)
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen const char *const *plugins;
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen plugins = t_strsplit_spaces(user->set->mail_plugins, ", ");
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen ret = str_array_find(plugins, module_get_plugin_name(module));
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenconst char *mail_user_plugin_getenv(struct mail_user *user, const char *name)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return mail_user_set_plugin_getenv(user->set, name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const char *const *envs;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, count;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenint mail_user_try_home_expand(struct mail_user *user, const char **pathp)
cb17980a661554ebb3fd099c77e92a5be4d304ecTimo Sirainen /* no need to expand home */
55a14bce15b9f44441b5f56616d73651a294d770Timo Sirainenvoid mail_user_set_get_temp_prefix(string_t *dest,
55a14bce15b9f44441b5f56616d73651a294d770Timo Sirainen str_append(dest, master_service_get_name(master_service));
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenconst char *mail_user_get_anvil_userip_ident(struct mail_user *user)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return t_strconcat(net_ip2addr(user->remote_ip), "/",
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainenmail_user_try_load_class_plugin(struct mail_user *user, const char *name)
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen mod_set.binary_name = master_service_get_name(master_service);
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen mod_set.setting_name = "<built-in storage lookup>";
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen module_dir_load_missing(mail_storage_service_modules,
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen /* initialize the module (and only this module!) immediately so that
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen the class gets registered */
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen for (module = mail_storage_service_modules; module != NULL; module = module->next) {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen if (strncmp(module->name, name, name_len) == 0 &&
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen strcmp(module->name + name_len, "_plugin") == 0) {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainenmail_user_get_storage_class(struct mail_user *user, const char *name)
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen if (storage == NULL || storage->v.alloc != NULL)
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen /* it's implemented by a plugin. load it and check again. */
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen if (storage != NULL && storage->v.alloc == NULL) {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen i_error("Storage driver '%s' exists as a stub, "
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainenstruct mail_user *mail_user_dup(struct mail_user *user)
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen user2 = mail_user_alloc(user->username, user->set_info,
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen user2->auth_token = p_strdup(user2->pool, user->auth_token);
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen user2->auth_user = p_strdup(user2->pool, user->auth_user);
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen user2->session_id = p_strdup(user2->pool, user->session_id);
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainenvoid mail_user_init_fs_settings(struct mail_user *user,
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen const struct mail_storage_settings *mail_set =
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen ssl_set->ca_dir = mail_set->ssl_client_ca_dir;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen ssl_set->ca_file = mail_set->ssl_client_ca_file;
379175cfba8150d481d9898b78330b719d128d84Timo Sirainenvoid mail_user_stats_fill(struct mail_user *user, struct stats *stats)
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenstatic const struct var_expand_func_table mail_user_var_expand_func_table_arr[] = {
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen { "userdb", mail_user_var_expand_func_userdb },