mail-user.c revision f182955da33263be83a8d45af4aab0253f8f274f
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2008-2014 Dovecot authors, see the included COPYING file */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "lib.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "array.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "hostpid.h"
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen#include "net.h"
65988f5a8abed57e9894fec77105941e046d3490Timo Sirainen#include "module-dir.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "home-expand.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "safe-mkstemp.h"
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen#include "str.h"
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen#include "strescape.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "var-expand.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "settings-parser.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "auth-master.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "master-service.h"
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen#include "mountpoint-list.h"
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen#include "dict.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "mail-storage-settings.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "mail-storage-private.h"
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen#include "mail-storage-service.h"
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen#include "mail-namespace.h"
f335accff54f408a8bbb328f8098ad458f2ff58eTimo Sirainen#include "mail-storage.h"
f335accff54f408a8bbb328f8098ad458f2ff58eTimo Sirainen#include "mail-user.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include <stdlib.h>
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainenstruct mail_user_module_register mail_user_module_register = { 0 };
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenstruct auth_master_connection *mail_user_auth_master_conn;
2c70dc3ca3f0e9e67b76065c4824aba6b2e4251cTimo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenstatic void mail_user_deinit_base(struct mail_user *user)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen if (user->_attr_dict != NULL) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen (void)dict_wait(user->_attr_dict);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen dict_deinit(&user->_attr_dict);
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mail_namespaces_deinit(&user->namespaces);
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen if (user->mountpoints != NULL)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mountpoint_list_deinit(&user->mountpoints);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainenstruct mail_user *mail_user_alloc(const char *username,
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen const struct setting_parser_info *set_info,
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen const struct mail_user_settings *set)
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen{
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen struct mail_user *user;
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen const char *error;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen pool_t pool;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_assert(username != NULL);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_assert(*username != '\0');
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"mail user", 16*1024);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user = p_new(pool, struct mail_user, 1);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->pool = pool;
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen user->refcount = 1;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->username = p_strdup(pool, username);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->set_info = set_info;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->unexpanded_set = settings_dup(set_info, set, pool);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->set = settings_dup(set_info, set, pool);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->service = master_service_get_name(master_service);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->default_normalizer = uni_utf8_to_decomposed_titlecase;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* check settings so that the duplicated structure will again
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen contain the parsed fields */
c69a255a68103a50fa3f04a527281a169075403fTimo Sirainen if (!settings_check(set_info, pool, user->set, &error))
c69a255a68103a50fa3f04a527281a169075403fTimo Sirainen i_panic("Settings check unexpectedly failed: %s", error);
c69a255a68103a50fa3f04a527281a169075403fTimo Sirainen
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen user->v.deinit = mail_user_deinit_base;
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen p_array_init(&user->module_contexts, user->pool, 5);
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen return user;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen}
c69a255a68103a50fa3f04a527281a169075403fTimo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenstatic void
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenmail_user_expand_plugins_envs(struct mail_user *user)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen const char **envs, *home;
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen string_t *str;
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen unsigned int i, count;
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen if (!array_is_created(&user->set->plugin_envs))
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen return;
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen str = t_str_new(256);
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen envs = array_get_modifiable(&user->set->plugin_envs, &count);
7e50cca6b1dab5a7e2a90a8949678c62f4a0958aTimo Sirainen i_assert((count % 2) == 0);
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen for (i = 0; i < count; i += 2) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (user->_home == NULL &&
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen var_has_key(envs[i+1], 'h', "home") &&
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen mail_user_get_home(user, &home) <= 0) {
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen user->error = p_strdup_printf(user->pool,
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen "userdb didn't return a home directory, "
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen "but plugin setting %s used it (%%h): %s",
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen envs[i], envs[i+1]);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return;
4e8d6d03c2ff85448df79b181a2ea850fb5d4199Timo Sirainen }
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen str_truncate(str, 0);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen var_expand(str, envs[i+1], mail_user_var_expand_table(user));
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen envs[i+1] = p_strdup(user->pool, str_c(str));
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainenint mail_user_init(struct mail_user *user, const char **error_r)
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const struct mail_storage_settings *mail_set;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const char *home, *key, *value;
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen bool need_home_dir;
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen need_home_dir = user->_home == NULL &&
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen settings_vars_have_key(user->set_info, user->set,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen 'h', "home", &key, &value);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen /* expand mail_home setting before calling mail_user_get_home() */
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen settings_var_expand(user->set_info, user->set,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->pool, mail_user_var_expand_table(user));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen if (need_home_dir && mail_user_get_home(user, &home) <= 0) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->error = p_strdup_printf(user->pool,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen "userdb didn't return a home directory, "
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen "but %s used it (%%h): %s", key, value);
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen }
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen mail_user_expand_plugins_envs(user);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen /* autocreated users for shared mailboxes need to be fully initialized
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen if they don't exist, since they're going to be used anyway */
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen if (user->error == NULL || user->nonexistent) {
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen mail_set = mail_user_set_get_storage_set(user);
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen user->mail_debug = mail_set->mail_debug;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen user->initialized = TRUE;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen hook_mail_user_created(user);
4e8d6d03c2ff85448df79b181a2ea850fb5d4199Timo Sirainen }
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (user->error != NULL) {
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen *error_r = t_strdup(user->error);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return -1;
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen }
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen return 0;
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen}
dabb4cec4cf9bdb34013de682b08f1284cfb670fTimo Sirainen
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainenvoid mail_user_ref(struct mail_user *user)
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_assert(user->refcount > 0);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->refcount++;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenvoid mail_user_unref(struct mail_user **_user)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen struct mail_user *user = *_user;
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_assert(user->refcount > 0);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen *_user = NULL;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (user->refcount > 1) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->refcount--;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen return;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen user->deinitializing = TRUE;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* call deinit() with refcount=1, otherwise we may assert-crash in
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen mail_user_ref() that is called by some deinit() handler. */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen user->v.deinit(user);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_assert(user->refcount == 1);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen pool_unref(&user->pool);
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen}
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainenstruct mail_user *mail_user_find(struct mail_user *user, const char *name)
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen{
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen struct mail_namespace *ns;
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
b516a7812b9acc04522869fead3aa6d2787dcdc6Timo Sirainen if (ns->owner != NULL && strcmp(ns->owner->username, name) == 0)
b516a7812b9acc04522869fead3aa6d2787dcdc6Timo Sirainen return ns->owner;
b516a7812b9acc04522869fead3aa6d2787dcdc6Timo Sirainen }
b516a7812b9acc04522869fead3aa6d2787dcdc6Timo Sirainen return NULL;
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenvoid mail_user_set_vars(struct mail_user *user, const char *service,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const struct ip_addr *local_ip,
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen const struct ip_addr *remote_ip)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
b516a7812b9acc04522869fead3aa6d2787dcdc6Timo Sirainen i_assert(service != NULL);
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen user->service = p_strdup(user->pool, service);
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen if (local_ip != NULL && local_ip->family != 0) {
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen user->local_ip = p_new(user->pool, struct ip_addr, 1);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen *user->local_ip = *local_ip;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (remote_ip != NULL && remote_ip->family != 0) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->remote_ip = p_new(user->pool, struct ip_addr, 1);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen *user->remote_ip = *remote_ip;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
2c70dc3ca3f0e9e67b76065c4824aba6b2e4251cTimo Sirainenconst struct var_expand_table *
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainenmail_user_var_expand_table(struct mail_user *user)
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen static struct var_expand_table static_tab[] = {
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { 'u', NULL, "user" },
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { 'n', NULL, "username" },
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { 'd', NULL, "domain" },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 's', NULL, "service" },
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { 'h', NULL, "home" },
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { 'l', NULL, "lip" },
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { 'r', NULL, "rip" },
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { 'p', NULL, "pid" },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 'i', NULL, "uid" },
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen { '\0', NULL, "gid" },
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { '\0', NULL, "session" },
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen { '\0', NULL, "auth_user" },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { '\0', NULL, "auth_username" },
3d92258c9897ffc9382c333964a1ab69cd1e5984Timo Sirainen { '\0', NULL, "auth_domain" },
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen { '\0', NULL, NULL }
2c70dc3ca3f0e9e67b76065c4824aba6b2e4251cTimo Sirainen };
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen struct var_expand_table *tab;
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen /* use a cached table, unless home directory has been set afterwards */
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen if (user->var_expand_table != NULL &&
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen user->var_expand_table[4].value == user->_home)
2e0fa95785f9b41c1c6aaf541245579a49f94841Timo Sirainen return user->var_expand_table;
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab = p_malloc(user->pool, sizeof(static_tab));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[0].value = user->username;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[1].value = p_strdup(user->pool, t_strcut(user->username, '@'));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[2].value = strchr(user->username, '@');
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[3].value = user->service;
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen tab[4].value = user->_home; /* don't look it up unless we need it */
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen tab[5].value = user->local_ip == NULL ? NULL :
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen p_strdup(user->pool, net_ip2addr(user->local_ip));
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen tab[6].value = user->remote_ip == NULL ? NULL :
87506860556bf42f656b13f4b14cf81b75261e95Timo Sirainen p_strdup(user->pool, net_ip2addr(user->remote_ip));
87506860556bf42f656b13f4b14cf81b75261e95Timo Sirainen tab[7].value = my_pid;
87506860556bf42f656b13f4b14cf81b75261e95Timo Sirainen tab[8].value = p_strdup(user->pool, dec2str(user->uid));
87506860556bf42f656b13f4b14cf81b75261e95Timo Sirainen tab[9].value = p_strdup(user->pool, dec2str(user->gid));
87506860556bf42f656b13f4b14cf81b75261e95Timo Sirainen tab[10].value = user->session_id;
47e90cc0da86de98a8923802a29d844ab5159834Timo Sirainen if (user->auth_user == NULL) {
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen tab[11].value = tab[0].value;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen tab[12].value = tab[1].value;
87506860556bf42f656b13f4b14cf81b75261e95Timo Sirainen tab[13].value = tab[2].value;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen } else {
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen tab[11].value = user->auth_user;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen tab[12].value = t_strcut(user->auth_user, '@');
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen tab[13].value = strchr(user->auth_user, '@');
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen }
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen user->var_expand_table = tab;
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen return user->var_expand_table;
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen}
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainenvoid mail_user_set_home(struct mail_user *user, const char *home)
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen{
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen user->_home = p_strdup(user->pool, home);
c389f8bf1340ca004f3a8f94b3f020bf47fd2610Timo Sirainen user->home_looked_up = TRUE;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen}
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenvoid mail_user_add_namespace(struct mail_user *user,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct mail_namespace **namespaces)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct mail_namespace **tmp, *next, *ns = *namespaces;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen for (; ns != NULL; ns = next) {
e619ecbbc00cba9e6e1e8322caa59776507fac02Timo Sirainen next = ns->next;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen tmp = &user->namespaces;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen for (; *tmp != NULL; tmp = &(*tmp)->next) {
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen if (strlen(ns->prefix) < strlen((*tmp)->prefix))
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen break;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen ns->next = *tmp;
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen *tmp = ns;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen *namespaces = user->namespaces;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen T_BEGIN {
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen hook_mail_namespaces_added(user->namespaces);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen } T_END;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainenvoid mail_user_drop_useless_namespaces(struct mail_user *user)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen struct mail_namespace *ns, *next;
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen /* drop all autocreated unusable (typically shared) namespaces.
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen don't drop the autocreated prefix="" namespace that we explicitly
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen created for being the fallback namespace. */
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen for (ns = user->namespaces; ns != NULL; ns = next) {
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen next = ns->next;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if ((ns->flags & NAMESPACE_FLAG_USABLE) == 0 &&
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen (ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0 &&
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen ns->prefix_len > 0)
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainen mail_namespace_destroy(ns);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen}
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainenconst char *mail_user_home_expand(struct mail_user *user, const char *path)
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen{
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen (void)mail_user_try_home_expand(user, &path);
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen return path;
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
e619ecbbc00cba9e6e1e8322caa59776507fac02Timo Sirainenstatic int mail_user_userdb_lookup_home(struct mail_user *user)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct auth_user_info info;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct auth_user_reply reply;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen pool_t userdb_pool;
e619ecbbc00cba9e6e1e8322caa59776507fac02Timo Sirainen const char *username, *const *fields;
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen int ret;
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen i_assert(!user->home_looked_up);
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen memset(&info, 0, sizeof(info));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen info.service = user->service;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (user->local_ip != NULL)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen info.local_ip = *user->local_ip;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (user->remote_ip != NULL)
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen info.remote_ip = *user->remote_ip;
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen userdb_pool = pool_alloconly_create("userdb lookup", 2048);
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen ret = auth_master_user_lookup(mail_user_auth_master_conn,
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen user->username, &info, userdb_pool,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen &username, &fields);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (ret > 0) {
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen auth_user_fields_parse(fields, userdb_pool, &reply);
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen user->_home = p_strdup(user->pool, reply.home);
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen pool_unref(&userdb_pool);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return ret;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenint mail_user_get_home(struct mail_user *user, const char **home_r)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
055f4599bba1874fa1148a8fa488517fa077619cTimo Sirainen int ret;
055f4599bba1874fa1148a8fa488517fa077619cTimo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (user->home_looked_up) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen *home_r = user->_home;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return user->_home != NULL ? 1 : 0;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (mail_user_auth_master_conn == NULL) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* no userdb connection. we can only use mail_home setting. */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->_home = user->set->mail_home;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen } else if ((ret = mail_user_userdb_lookup_home(user)) < 0) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* userdb lookup failed */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return -1;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen } else if (ret == 0) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* user doesn't exist */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->nonexistent = TRUE;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen } else if (user->_home == NULL && *user->set->mail_home != '\0') {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* no home returned by userdb lookup, fallback to mail_home
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen setting. */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen user->_home = user->set->mail_home;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
f335accff54f408a8bbb328f8098ad458f2ff58eTimo Sirainen user->home_looked_up = TRUE;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen *home_r = user->_home;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return user->_home != NULL ? 1 : 0;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
f335accff54f408a8bbb328f8098ad458f2ff58eTimo Sirainenbool mail_user_is_plugin_loaded(struct mail_user *user, struct module *module)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const char *const *plugins;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen bool ret;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen T_BEGIN {
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen plugins = t_strsplit_spaces(user->set->mail_plugins, ", ");
9ae664e94e6eeb5c1f900bb90642052633031832Timo Sirainen ret = str_array_find(plugins, module_get_plugin_name(module));
9ae664e94e6eeb5c1f900bb90642052633031832Timo Sirainen } T_END;
5cbefc6537aefbf1491416c433de00fc3e649a13Timo Sirainen return ret;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen}
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainenconst char *mail_user_plugin_getenv(struct mail_user *user, const char *name)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen{
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen return mail_user_set_plugin_getenv(user->set, name);
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen}
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
4e2d7dd2b201ae2083b6637d7ec0d37f49faca45Timo Sirainenconst char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
db24d60c306c9d477392ff5b61cb3fc95fef3bb7Timo Sirainen const char *name)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
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, '.');
}
const char *mail_user_get_anvil_userip_ident(struct mail_user *user)
{
if (user->remote_ip == NULL)
return NULL;
return t_strconcat(net_ip2addr(user->remote_ip), "/",
str_tabescape(user->username), NULL);
}
bool mail_user_is_path_mounted(struct mail_user *user, const char *path,
const char **error_r)
{
struct mountpoint_list_rec *rec;
const char *mounts_path;
*error_r = NULL;
if (user->mountpoints == NULL) {
mounts_path = t_strdup_printf("%s/"MOUNTPOINT_LIST_FNAME,
user->set->base_dir);
user->mountpoints = mountpoint_list_init_readonly(mounts_path);
} else {
(void)mountpoint_list_refresh(user->mountpoints);
}
rec = mountpoint_list_find(user->mountpoints, path);
if (rec == NULL || strcmp(rec->state, MOUNTPOINT_STATE_IGNORE) == 0) {
/* we don't have any knowledge of this path's mountpoint.
assume it's fine. */
return TRUE;
}
/* record exists for this mountpoint. see if it's mounted */
if (mountpoint_list_update_mounted(user->mountpoints) == 0 &&
!rec->mounted) {
*error_r = t_strdup_printf("Mountpoint %s isn't mounted. "
"Mount it or remove it with doveadm mount remove",
rec->mount_path);
return FALSE;
}
return TRUE;
}
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;
unsigned int name_len = strlen(name);
memset(&mod_set, 0, sizeof(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(user->username, user->set_info,
user->unexpanded_set);
if (user->_home != NULL)
mail_user_set_home(user2, user->_home);
mail_user_set_vars(user2, user->service,
user->local_ip, user->remote_ip);
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);
return user2;
}