mail-user.c revision 87ca4b209c10954826b878da165d303d9b4dc5a2
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Copyright (c) 2008-2012 Dovecot authors, see the included COPYING file */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "lib.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "array.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "hostpid.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "net.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "module-dir.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "home-expand.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "safe-mkstemp.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "str.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "strescape.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "var-expand.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "settings-parser.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "auth-master.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "master-service.h"
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk#include "mountpoint-list.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "mail-storage-settings.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "mail-storage-private.h"
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk#include "mail-storage-service.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "mail-namespace.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "mail-storage.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "mail-user.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <stdlib.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstruct mail_user_module_register mail_user_module_register = { 0 };
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstruct auth_master_connection *mail_user_auth_master_conn;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void mail_user_deinit_base(struct mail_user *user)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk mail_namespaces_deinit(&user->namespaces);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->mountpoints != NULL)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk mountpoint_list_deinit(&user->mountpoints);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstruct mail_user *mail_user_alloc(const char *username,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const struct setting_parser_info *set_info,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const struct mail_user_settings *set)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct mail_user *user;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const char *error;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pool_t pool;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk i_assert(username != NULL);
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk i_assert(*username != '\0');
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pool = pool_alloconly_create("mail user", 16*1024);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user = p_new(pool, struct mail_user, 1);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->pool = pool;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->refcount = 1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->username = p_strdup(pool, username);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->set_info = set_info;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->unexpanded_set = settings_dup(set_info, set, pool);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->set = settings_dup(set_info, set, pool);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->service = master_service_get_name(master_service);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->default_normalizer = uni_utf8_to_decomposed_titlecase;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* check settings so that the duplicated structure will again
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk contain the parsed fields */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (!settings_check(set_info, pool, user->set, &error))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk i_panic("Settings check unexpectedly failed: %s", error);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->v.deinit = mail_user_deinit_base;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk p_array_init(&user->module_contexts, user->pool, 5);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return user;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkmail_user_expand_plugins_envs(struct mail_user *user, const char **error_r)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const char **envs, *home;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk string_t *str;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk unsigned int i, count;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (!array_is_created(&user->set->plugin_envs))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk str = t_str_new(256);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk envs = array_get_modifiable(&user->set->plugin_envs, &count);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk i_assert((count % 2) == 0);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (i = 0; i < count; i += 2) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->_home == NULL &&
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk var_has_key(envs[i+1], 'h', "home") &&
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk mail_user_get_home(user, &home) <= 0) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *error_r = t_strdup_printf(
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk "userdb didn't return a home directory, "
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk "but plugin setting %s used it (%%h): %s",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk envs[i], envs[i+1]);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return -1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk str_truncate(str, 0);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk var_expand(str, envs[i+1], mail_user_var_expand_table(user));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk envs[i+1] = p_strdup(user->pool, str_c(str));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkint mail_user_init(struct mail_user *user, const char **error_r)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const struct mail_storage_settings *mail_set;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const char *home, *key, *value;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk bool need_home_dir;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk need_home_dir = user->_home == NULL &&
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk settings_vars_have_key(user->set_info, user->set,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk 'h', "home", &key, &value);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* expand mail_home setting before calling mail_user_get_home() */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk settings_var_expand(user->set_info, user->set,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->pool, mail_user_var_expand_table(user));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (need_home_dir && mail_user_get_home(user, &home) <= 0) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *error_r = t_strdup_printf(
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk "userdb didn't return a home directory, "
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk "but %s used it (%%h): %s", key, value);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return -1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (mail_user_expand_plugins_envs(user, error_r) < 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return -1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk mail_set = mail_user_set_get_storage_set(user);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->mail_debug = mail_set->mail_debug;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->initialized = TRUE;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk hook_mail_user_created(user);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->error != NULL) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *error_r = t_strdup(user->error);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return -1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkvoid mail_user_ref(struct mail_user *user)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk i_assert(user->refcount > 0);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->refcount++;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkvoid mail_user_unref(struct mail_user **_user)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct mail_user *user = *_user;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk i_assert(user->refcount > 0);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *_user = NULL;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->refcount > 1) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->refcount--;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* call deinit() with refcount=1, otherwise we may assert-crash in
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk mail_user_ref() that is called by some deinit() handler. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->v.deinit(user);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk i_assert(user->refcount == 1);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pool_unref(&user->pool);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstruct mail_user *mail_user_find(struct mail_user *user, const char *name)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct mail_namespace *ns;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (ns = user->namespaces; ns != NULL; ns = ns->next) {
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk if (ns->owner != NULL && strcmp(ns->owner->username, name) == 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return ns->owner;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return NULL;
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkvoid mail_user_set_vars(struct mail_user *user, const char *service,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const struct ip_addr *local_ip,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const struct ip_addr *remote_ip)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk i_assert(service != NULL);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->service = p_strdup(user->pool, service);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (local_ip != NULL && local_ip->family != 0) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->local_ip = p_new(user->pool, struct ip_addr, 1);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *user->local_ip = *local_ip;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (remote_ip != NULL && remote_ip->family != 0) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->remote_ip = p_new(user->pool, struct ip_addr, 1);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *user->remote_ip = *remote_ip;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkconst struct var_expand_table *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkmail_user_var_expand_table(struct mail_user *user)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk static struct var_expand_table static_tab[] = {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 'u', NULL, "user" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 'n', NULL, "username" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 'd', NULL, "domain" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 's', NULL, "service" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 'h', NULL, "home" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 'l', NULL, "lip" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 'r', NULL, "rip" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 'p', NULL, "pid" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 'i', NULL, "uid" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { '\0', NULL, "gid" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { '\0', NULL, NULL }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk };
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct var_expand_table *tab;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* use a cached table, unless home directory has been set afterwards */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->var_expand_table != NULL &&
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->var_expand_table[4].value == user->_home)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return user->var_expand_table;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab = p_malloc(user->pool, sizeof(static_tab));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk memcpy(tab, static_tab, sizeof(static_tab));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[0].value = user->username;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[1].value = p_strdup(user->pool, t_strcut(user->username, '@'));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[2].value = strchr(user->username, '@');
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk if (tab[2].value != NULL) tab[2].value++;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[3].value = user->service;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[4].value = user->_home; /* don't look it up unless we need it */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[5].value = user->local_ip == NULL ? NULL :
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk p_strdup(user->pool, net_ip2addr(user->local_ip));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[6].value = user->remote_ip == NULL ? NULL :
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk p_strdup(user->pool, net_ip2addr(user->remote_ip));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[7].value = my_pid;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[8].value = p_strdup(user->pool, dec2str(user->uid));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tab[9].value = p_strdup(user->pool, dec2str(user->gid));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->var_expand_table = tab;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return user->var_expand_table;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkvoid mail_user_set_home(struct mail_user *user, const char *home)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->_home = p_strdup(user->pool, home);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->home_looked_up = TRUE;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkvoid mail_user_add_namespace(struct mail_user *user,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct mail_namespace **namespaces)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct mail_namespace **tmp, *next, *ns = *namespaces;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (; ns != NULL; ns = next) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk next = ns->next;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk tmp = &user->namespaces;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (; *tmp != NULL; tmp = &(*tmp)->next) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (strlen(ns->prefix) < strlen((*tmp)->prefix))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk break;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk ns->next = *tmp;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *tmp = ns;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *namespaces = user->namespaces;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkvoid mail_user_drop_useless_namespaces(struct mail_user *user)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct mail_namespace *ns, *next;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (ns = user->namespaces; ns != NULL; ns = next) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk next = ns->next;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if ((ns->flags & NAMESPACE_FLAG_USABLE) == 0 &&
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk (ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk mail_namespace_destroy(ns);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkconst char *mail_user_home_expand(struct mail_user *user, const char *path)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk (void)mail_user_try_home_expand(user, &path);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return path;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int mail_user_userdb_lookup_home(struct mail_user *user)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct auth_user_info info;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct auth_user_reply reply;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pool_t userdb_pool;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const char *username, *const *fields;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int ret;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk i_assert(!user->home_looked_up);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk memset(&info, 0, sizeof(info));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk info.service = user->service;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->local_ip != NULL)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk info.local_ip = *user->local_ip;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->remote_ip != NULL)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk info.remote_ip = *user->remote_ip;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (mail_user_auth_master_conn == NULL)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk userdb_pool = pool_alloconly_create("userdb lookup", 2048);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk ret = auth_master_user_lookup(mail_user_auth_master_conn,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->username, &info, userdb_pool,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk &username, &fields);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (ret > 0) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk auth_user_fields_parse(fields, userdb_pool, &reply);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->_home = p_strdup(user->pool, reply.home);
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pool_unref(&userdb_pool);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return ret;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkint mail_user_get_home(struct mail_user *user, const char **home_r)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int ret;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->home_looked_up) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *home_r = user->_home;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return user->_home != NULL ? 1 : 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk ret = mail_user_userdb_lookup_home(user);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (ret < 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return -1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (ret > 0 && user->_home == NULL && *user->set->mail_home != '\0') {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* no home in userdb, fallback to mail_home setting */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->_home = user->set->mail_home;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk user->home_looked_up = TRUE;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *home_r = user->_home;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return user->_home != NULL ? 1 : 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkbool mail_user_is_plugin_loaded(struct mail_user *user, struct module *module)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const char *const *plugins;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk bool ret;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk T_BEGIN {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk plugins = t_strsplit_spaces(user->set->mail_plugins, ", ");
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk ret = str_array_find(plugins, module_get_plugin_name(module));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk } T_END;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return ret;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkconst char *mail_user_plugin_getenv(struct mail_user *user, const char *name)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return mail_user_set_plugin_getenv(user->set, name);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkconst char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const char *name)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk const char *const *envs;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk unsigned int i, count;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (!array_is_created(&set->plugin_envs))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return NULL;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk envs = array_get(&set->plugin_envs, &count);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (i = 0; i < count; i += 2) {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (strcmp(envs[i], name) == 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return envs[i+1];
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return NULL;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkint mail_user_try_home_expand(struct mail_user *user, const char **pathp)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const char *home, *path = *pathp;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (*path != '~') {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* no need to expand home */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (mail_user_get_home(user, &home) <= 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return -1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk path = home_expand_tilde(path, home);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (path == NULL)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return -1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *pathp = path;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkvoid mail_user_set_get_temp_prefix(string_t *dest,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const struct mail_user_settings *set)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk str_append(dest, set->mail_temp_dir);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk str_append(dest, "/dovecot.");
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk str_append(dest, master_service_get_name(master_service));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk str_append_c(dest, '.');
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkconst char *mail_user_get_anvil_userip_ident(struct mail_user *user)
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (user->remote_ip == NULL)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return NULL;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return t_strconcat(net_ip2addr(user->remote_ip), "/",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk str_tabescape(user->username), NULL);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkbool mail_user_is_path_mounted(struct mail_user *user, const char *path,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk const char **error_r)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
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;
}