mail-user.c revision bdd36cfdba3ff66d25570a9ff568d69e1eb543cf
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2008-2012 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "array.h"
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen#include "hostpid.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "net.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include "module-dir.h"
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen#include "home-expand.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "safe-mkstemp.h"
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "strescape.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "var-expand.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "settings-parser.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "auth-master.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mountpoint-list.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage-settings.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "mail-storage-private.h"
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen#include "mail-namespace.h"
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen#include "mail-storage.h"
369a1084c500a9df7448ffa9409ce32e42060bc2Timo Sirainen#include "mail-user.h"
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen#include <stdlib.h>
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_user_module_register mail_user_module_register = { 0 };
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct auth_master_connection *mail_user_auth_master_conn;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_user_deinit_base(struct mail_user *user)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen mail_namespaces_deinit(&user->namespaces);
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen if (user->mountpoints != NULL)
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen mountpoint_list_deinit(&user->mountpoints);
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen}
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_user *mail_user_alloc(const char *username,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct setting_parser_info *set_info,
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen const struct mail_user_settings *set)
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_user *user;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *error;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_t pool;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(username != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(*username != '\0');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool = pool_alloconly_create("mail user", 16*1024);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user = p_new(pool, struct mail_user, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->pool = pool;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->refcount = 1;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen user->username = p_strdup(pool, username);
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen user->set_info = set_info;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen user->unexpanded_set = settings_dup(set_info, set, pool);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen user->set = settings_dup(set_info, set, pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->service = master_service_get_name(master_service);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen user->default_normalizer = uni_utf8_to_decomposed_titlecase;
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* check settings so that the duplicated structure will again
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen contain the parsed fields */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!settings_check(set_info, pool, user->set, &error))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_panic("Settings check unexpectedly failed: %s", error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->v.deinit = mail_user_deinit_base;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_array_init(&user->module_contexts, user->pool, 5);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return user;
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_user_expand_plugins_envs(struct mail_user *user, const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **envs, *home;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen string_t *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!array_is_created(&user->set->plugin_envs))
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = t_str_new(256);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen envs = array_get_modifiable(&user->set->plugin_envs, &count);
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen i_assert((count % 2) == 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i += 2) {
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (user->_home == NULL &&
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen var_has_key(envs[i+1], 'h', "home") &&
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen mail_user_get_home(user, &home) <= 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen *error_r = t_strdup_printf(
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen "userdb didn't return a home directory, "
d2475500ee2a5f3c07eb22886797cef0e11ce7c4Timo Sirainen "but plugin setting %s used it (%%h): %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen envs[i], envs[i+1]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_truncate(str, 0);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen var_expand(str, envs[i+1], mail_user_var_expand_table(user));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen envs[i+1] = p_strdup(user->pool, str_c(str));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return 0;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenint mail_user_init(struct mail_user *user, const char **error_r)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const struct mail_storage_settings *mail_set;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *home, *key, *value;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen bool need_home_dir;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen need_home_dir = user->_home == NULL &&
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen settings_vars_have_key(user->set_info, user->set,
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen 'h', "home", &key, &value);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen /* expand mail_home setting before calling mail_user_get_home() */
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen settings_var_expand(user->set_info, user->set,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->pool, mail_user_var_expand_table(user));
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen if (need_home_dir && mail_user_get_home(user, &home) <= 0) {
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen *error_r = t_strdup_printf(
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen "userdb didn't return a home directory, "
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen "but %s used it (%%h): %s", key, value);
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen return -1;
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen }
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen if (mail_user_expand_plugins_envs(user, error_r) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen mail_set = mail_user_set_get_storage_set(user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->mail_debug = mail_set->mail_debug;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->initialized = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hook_mail_user_created(user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen if (user->error != NULL) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *error_r = t_strdup(user->error);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen}
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainenvoid mail_user_ref(struct mail_user *user)
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen{
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen i_assert(user->refcount > 0);
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen user->refcount++;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_user_unref(struct mail_user **_user)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_user *user = *_user;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(user->refcount > 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *_user = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (user->refcount > 1) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen user->refcount--;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen }
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen /* call deinit() with refcount=1, otherwise we may assert-crash in
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen mail_user_ref() that is called by some deinit() handler. */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen user->v.deinit(user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(user->refcount == 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(&user->pool);
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen}
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainenstruct mail_user *mail_user_find(struct mail_user *user, const char *name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_namespace *ns;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (ns->owner != NULL && strcmp(ns->owner->username, name) == 0)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return ns->owner;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_user_set_vars(struct mail_user *user, const char *service,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen const struct ip_addr *local_ip,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct ip_addr *remote_ip)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(service != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->service = p_strdup(user->pool, service);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (local_ip != NULL && local_ip->family != 0) {
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen user->local_ip = p_new(user->pool, struct ip_addr, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *user->local_ip = *local_ip;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (remote_ip != NULL && remote_ip->family != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->remote_ip = p_new(user->pool, struct ip_addr, 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen *user->remote_ip = *remote_ip;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenconst struct var_expand_table *
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenmail_user_var_expand_table(struct mail_user *user)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen{
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen static struct var_expand_table static_tab[] = {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen { 'u', NULL, "user" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'n', NULL, "username" },
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen { 'd', NULL, "domain" },
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen { 's', NULL, "service" },
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen { 'h', NULL, "home" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'l', NULL, "lip" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'r', NULL, "rip" },
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen { 'p', NULL, "pid" },
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen { 'i', NULL, "uid" },
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen { '\0', NULL, "gid" },
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen { '\0', NULL, NULL }
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen };
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen struct var_expand_table *tab;
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen /* use a cached table, unless home directory has been set afterwards */
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen if (user->var_expand_table != NULL &&
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen user->var_expand_table[4].value == user->_home)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return user->var_expand_table;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen tab = p_malloc(user->pool, sizeof(static_tab));
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen tab[0].value = user->username;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen tab[1].value = p_strdup(user->pool, t_strcut(user->username, '@'));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen tab[2].value = strchr(user->username, '@');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[3].value = user->service;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen tab[4].value = user->_home; /* don't look it up unless we need it */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen tab[5].value = user->local_ip == NULL ? NULL :
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_strdup(user->pool, net_ip2addr(user->local_ip));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[6].value = user->remote_ip == NULL ? NULL :
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_strdup(user->pool, net_ip2addr(user->remote_ip));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[7].value = my_pid;
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen tab[8].value = p_strdup(user->pool, dec2str(user->uid));
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen tab[9].value = p_strdup(user->pool, dec2str(user->gid));
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->var_expand_table = tab;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return user->var_expand_table;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_user_set_home(struct mail_user *user, const char *home)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->_home = p_strdup(user->pool, home);
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen user->home_looked_up = TRUE;
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_user_add_namespace(struct mail_user *user,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_namespace **namespaces)
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen{
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen struct mail_namespace **tmp, *next, *ns = *namespaces;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (; ns != NULL; ns = next) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen next = ns->next;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen tmp = &user->namespaces;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen for (; *tmp != NULL; tmp = &(*tmp)->next) {
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen if (strlen(ns->prefix) < strlen((*tmp)->prefix))
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen break;
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen }
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen ns->next = *tmp;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *tmp = ns;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen }
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen *namespaces = user->namespaces;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
685393de106e55b61f754d420e378d05bd462ebbTimo Sirainenvoid mail_user_drop_useless_namespaces(struct mail_user *user)
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen{
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen struct mail_namespace *ns, *next;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = next) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen next = ns->next;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((ns->flags & NAMESPACE_FLAG_USABLE) == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_namespace_destroy(ns);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *mail_user_home_expand(struct mail_user *user, const char *path)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen (void)mail_user_try_home_expand(user, &path);
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen return path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic int mail_user_userdb_lookup_home(struct mail_user *user)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_user_info info;
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen struct auth_user_reply reply;
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen pool_t userdb_pool;
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen const char *username, *const *fields;
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(!user->home_looked_up);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen memset(&info, 0, sizeof(info));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen info.service = user->service;
bb26f09873c18f342cd1ab2d0ee0b9018e6546d9Timo Sirainen if (user->local_ip != NULL)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen info.local_ip = *user->local_ip;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (user->remote_ip != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen info.remote_ip = *user->remote_ip;
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_user_auth_master_conn == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen userdb_pool = pool_alloconly_create("userdb lookup", 2048);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = auth_master_user_lookup(mail_user_auth_master_conn,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->username, &info, userdb_pool,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &username, &fields);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_user_fields_parse(fields, userdb_pool, &reply);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user->_home = p_strdup(user->pool, reply.home);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(&userdb_pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_user_get_home(struct mail_user *user, const char **home_r)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen{
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen int ret;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen if (user->home_looked_up) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *home_r = user->_home;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return user->_home != NULL ? 1 : 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = mail_user_userdb_lookup_home(user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return -1;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (ret > 0 && user->_home == NULL && *user->set->mail_home != '\0') {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* no home in userdb, fallback to mail_home setting */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen user->_home = user->set->mail_home;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen user->home_looked_up = TRUE;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen *home_r = user->_home;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return user->_home != NULL ? 1 : 0;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenbool mail_user_is_plugin_loaded(struct mail_user *user, struct module *module)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const char *const *plugins;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen bool ret;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen T_BEGIN {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen plugins = t_strsplit_spaces(user->set->mail_plugins, ", ");
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ret = str_array_find(plugins, module_get_plugin_name(module));
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen } T_END;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return ret;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenconst char *mail_user_plugin_getenv(struct mail_user *user, const char *name)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return mail_user_set_plugin_getenv(user->set, name);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenconst char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen const char *name)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen const char *const *envs;
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen unsigned int i, count;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen if (!array_is_created(&set->plugin_envs))
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen envs = array_get(&set->plugin_envs, &count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i += 2) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strcmp(envs[i], name) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return envs[i+1];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_user_try_home_expand(struct mail_user *user, const char **pathp)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *home, *path = *pathp;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (*path != '~') {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen /* no need to expand home */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (mail_user_get_home(user, &home) <= 0)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return -1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen path = home_expand_tilde(path, home);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (path == NULL)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return -1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *pathp = path;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid mail_user_set_get_temp_prefix(string_t *dest,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_user_settings *set)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen str_append(dest, set->mail_temp_dir);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen str_append(dest, "/dovecot.");
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen str_append(dest, master_service_get_name(master_service));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen str_append_c(dest, '.');
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenconst char *mail_user_get_anvil_userip_ident(struct mail_user *user)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (user->remote_ip == NULL)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return NULL;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return t_strconcat(net_ip2addr(user->remote_ip), "/",
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen str_tabescape(user->username), NULL);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenbool mail_user_is_path_mounted(struct mail_user *user, const char *path,
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen const char **error_r)
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen{
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen struct mountpoint_list_rec *rec;
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen const char *mounts_path;
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen *error_r = NULL;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (user->mountpoints == NULL) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen mounts_path = t_strdup_printf("%s/"MOUNTPOINT_LIST_FNAME,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen user->set->base_dir);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen user->mountpoints = mountpoint_list_init_readonly(mounts_path);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen } else {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen (void)mountpoint_list_refresh(user->mountpoints);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen rec = mountpoint_list_find(user->mountpoints, path);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (rec == NULL || strcmp(rec->state, MOUNTPOINT_STATE_IGNORE) == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* 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;
}