bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2008-2018 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)
d1bf4ae66b8bf3b9e28df1823d6d4adda2b923b6Timo Sirainen mail_storage_service_user_unref(&user->_service_user);
5231ae561283595a73e9d838bdf4eb5d1b074679Josef 'Jeff' Sipekstatic void mail_user_deinit_pre_base(struct mail_user *user ATTR_UNUSED)
379175cfba8150d481d9898b78330b719d128d84Timo Sirainenstatic void mail_user_stats_fill_base(struct mail_user *user ATTR_UNUSED,
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainenstatic struct mail_user *
677cc0d62b41c7506246bf1b992a400a11896474Timo Sirainenmail_user_alloc_int(struct event *parent_event,
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen const struct mail_user_settings *set, pool_t pool)
3c2e763ab035567b2081a805648537b27e7cbbcfTimo Sirainen user->set = settings_dup_with_pointers(set_info, user->unexpanded_set, pool);
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen user->service = master_service_get_name(master_service);
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen user->default_normalizer = uni_utf8_to_decomposed_titlecase;
677cc0d62b41c7506246bf1b992a400a11896474Timo Sirainen event_add_category(user->event, &event_category_storage);
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);
5231ae561283595a73e9d838bdf4eb5d1b074679Josef 'Jeff' Sipek user->v.deinit_pre = mail_user_deinit_pre_base;
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen user->v.stats_fill = mail_user_stats_fill_base;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen p_array_init(&user->module_contexts, user->pool, 5);
677cc0d62b41c7506246bf1b992a400a11896474Timo Sirainenmail_user_alloc_nodup_set(struct event *parent_event,
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"mail user", 16*1024);
677cc0d62b41c7506246bf1b992a400a11896474Timo Sirainen return mail_user_alloc_int(parent_event, username, set_info, set, pool);
677cc0d62b41c7506246bf1b992a400a11896474Timo Sirainenstruct mail_user *mail_user_alloc(struct event *parent_event,
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"mail user", 16*1024);
677cc0d62b41c7506246bf1b992a400a11896474Timo Sirainen return mail_user_alloc_int(parent_event, username, set_info,
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainenmail_user_expand_plugins_envs(struct mail_user *user)
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",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Failed to expand plugin setting %s = '%s': %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 */
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (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);
5231ae561283595a73e9d838bdf4eb5d1b074679Josef 'Jeff' Sipek /* call deinit() and deinit_pre() with refcount=1, otherwise we may
5231ae561283595a73e9d838bdf4eb5d1b074679Josef 'Jeff' Sipek assert-crash in mail_user_ref() that is called by some handlers. */
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)
ff4ba036fcdf28d4a1a7e3c1c6c0c71793547bd6Stephan Boschmail_user_connection_init_from(struct mail_user_connection_data *conn,
ff4ba036fcdf28d4a1a7e3c1c6c0c71793547bd6Stephan Bosch pool_t pool, const struct mail_user_connection_data *src)
ff4ba036fcdf28d4a1a7e3c1c6c0c71793547bd6Stephan Bosch if (src->local_ip != NULL && src->local_ip->family != 0) {
ff4ba036fcdf28d4a1a7e3c1c6c0c71793547bd6Stephan Bosch conn->local_ip = p_new(pool, struct ip_addr, 1);
ff4ba036fcdf28d4a1a7e3c1c6c0c71793547bd6Stephan Bosch if (src->remote_ip != NULL && src->remote_ip->family != 0) {
ff4ba036fcdf28d4a1a7e3c1c6c0c71793547bd6Stephan Bosch conn->remote_ip = p_new(pool, struct ip_addr, 1);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenvoid mail_user_set_vars(struct mail_user *user, const char *service,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen user->service = p_strdup(user->pool, service);
677cc0d62b41c7506246bf1b992a400a11896474Timo Sirainen event_add_str(user->event, "service", service);
ff4ba036fcdf28d4a1a7e3c1c6c0c71793547bd6Stephan Bosch mail_user_connection_init_from(&user->conn, user->pool, conn);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenmail_user_var_expand_table(struct mail_user *user)
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen /* use a cached table, unless home directory has been set afterwards */
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen user->var_expand_table[4].value == user->_home)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen p_strdup(user->pool, t_strcut(user->username, '@'));
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen const char *domain = i_strchr_to_next(user->username, '@');
60670187b0dd0e7f23f99a58feab11b862ad77acStephan Bosch const char *local_ip = user->conn.local_ip == NULL ? NULL :
60670187b0dd0e7f23f99a58feab11b862ad77acStephan Bosch p_strdup(user->pool, net_ip2addr(user->conn.local_ip));
60670187b0dd0e7f23f99a58feab11b862ad77acStephan Bosch const char *remote_ip = user->conn.remote_ip == NULL ? NULL :
60670187b0dd0e7f23f99a58feab11b862ad77acStephan Bosch p_strdup(user->pool, net_ip2addr(user->conn.remote_ip));
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen const char *auth_user, *auth_username, *auth_domain;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen p_strdup(user->pool, t_strcut(user->auth_user, '@'));
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen auth_domain = i_strchr_to_next(user->auth_user, '@');
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen { 'h', user->_home /* don't look it up unless we need it */, "home" },
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen { 'i', p_strdup(user->pool, dec2str(user->uid)), "uid" },
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen { '\0', p_strdup(user->pool, dec2str(user->gid)), "gid" },
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen /* NOTE: keep this synced with imap-hibernate's
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen imap_client_var_expand_table() */
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen tab = p_malloc(user->pool, sizeof(stack_tab));
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainenmail_user_var_expand_func_userdb(const char *data, void *context,
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen const char **value_r,
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen *value_r = 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);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenstatic bool mail_user_get_mail_home(struct mail_user *user)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const char *error, *home = user->set->mail_home;
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen /* we're still initializing user. need to do the expansion ourself. */
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen i_assert(home[0] == SETTING_STRVAR_UNEXPANDED[0]);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen i_error("Failed to expand mail_home=%s: %s", home, error);
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 plugins = t_strsplit_spaces(user->set->mail_plugins, ", ");
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen ret = str_array_find(plugins, module_get_plugin_name(module));
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wangbool mail_user_plugin_getenv_bool(struct mail_user *user, const char *name)
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen return mail_user_set_plugin_getenv_bool(user->set, name);
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainenbool mail_user_set_plugin_getenv_bool(const struct mail_user_settings *set,
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen const char *env = mail_user_set_plugin_getenv(set, name);
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang switch (env[0]) {
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang //any other value including empty string will be treated as TRUE.
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,
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));
55cec51dba1352482e93db30d7ced6bc4fe15f3aTimo Sirainenint mail_user_lock_file_create(struct mail_user *user, const char *lock_fname,
55cec51dba1352482e93db30d7ced6bc4fe15f3aTimo Sirainen struct file_lock **lock_r, const char **error_r)
55cec51dba1352482e93db30d7ced6bc4fe15f3aTimo Sirainen if ((ret = mail_user_get_home(user, &home)) < 0) {
55cec51dba1352482e93db30d7ced6bc4fe15f3aTimo Sirainen /* home lookup failed - shouldn't really happen */
55cec51dba1352482e93db30d7ced6bc4fe15f3aTimo Sirainen const struct mail_storage_settings *mail_set =
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen mail_namespace_find_inbox(user->namespaces)->list;
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen path = t_strdup_printf("%s/%s", home, lock_fname);
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen path = t_strdup_printf("%s/%s", inbox_list->set.volatile_dir,
74943466e541d8bfe3916bb0eb9fb9cb0599dfe7Timo Sirainen return mail_storage_lock_create(path, &lock_set, mail_set, lock_r, error_r);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenconst char *mail_user_get_anvil_userip_ident(struct mail_user *user)
60670187b0dd0e7f23f99a58feab11b862ad77acStephan Bosch return t_strconcat(net_ip2addr(user->conn.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)
677cc0d62b41c7506246bf1b992a400a11896474Timo Sirainen user2 = mail_user_alloc(event_get_parent(user->event), user->username,
d1bf4ae66b8bf3b9e28df1823d6d4adda2b923b6Timo Sirainen mail_storage_service_user_ref(user2->_service_user);
ff4ba036fcdf28d4a1a7e3c1c6c0c71793547bd6Stephan Bosch mail_user_set_vars(user2, user->service, &user->conn);
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);
a020eb653b2620a989e4795adceb6136037327b2Timo Sirainen user2->session_create_time = user->session_create_time;
9f7441a47863d44ec303c7980b499b46b3d1671bTimo Sirainen user2->userdb_fields = user->userdb_fields == NULL ? NULL :
9f7441a47863d44ec303c7980b499b46b3d1671bTimo Sirainen p_strarray_dup(user2->pool, user->userdb_fields);
26bdbffc35ee46779f15a537a757ed937a4d1c91Stephan Boschvoid mail_user_init_ssl_client_settings(struct mail_user *user,
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen const struct mail_storage_settings *mail_set =
26bdbffc35ee46779f15a537a757ed937a4d1c91Stephan Bosch ssl_set->ca_dir = mail_set->ssl_client_ca_dir;
26bdbffc35ee46779f15a537a757ed937a4d1c91Stephan Bosch ssl_set->ca_file = mail_set->ssl_client_ca_file;
26bdbffc35ee46779f15a537a757ed937a4d1c91Stephan Boschvoid mail_user_init_fs_settings(struct mail_user *user,
26bdbffc35ee46779f15a537a757ed937a4d1c91Stephan Bosch mail_user_init_ssl_client_settings(user, ssl_set);
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 },