mail-storage-service.c revision de0034cc6bb52585bc82289801435418a7ee7298
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "lib.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "ioloop.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "array.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "base64.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "hostpid.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "module-dir.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "restrict-access.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "eacces-error.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "ipwd.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "str.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "var-expand.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "dict.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "settings-parser.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "auth-master.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "master-service-private.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "master-service-settings.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "master-service-settings-cache.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "mail-user.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "mail-namespace.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "mail-storage.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include "mail-storage-service.h"
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/stat.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#ifdef HAVE_SYS_TIME_H
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu# include <sys/time.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#endif
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#ifdef HAVE_SYS_RESOURCE_H
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu# include <sys/resource.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#endif
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* If time moves backwards more than this, kill ourself instead of sleeping. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#define MAX_TIME_BACKWARDS_SLEEP 5
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#define MAX_NOWARN_FORWARD_SECS 10
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#define ERRSTR_INVALID_USER_SETTINGS \
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Invalid user settings. Refer to server log for more information."
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct mail_storage_service_privileges {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uid_t uid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu gid_t gid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *uid_source, *gid_source;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *home;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *chroot;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu};
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct mail_storage_service_ctx {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct master_service *service;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *default_log_prefix;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct auth_master_connection *conn, *iter_conn;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct auth_master_user_list_ctx *auth_list;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_info **set_roots;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum mail_storage_service_flags flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *set_cache_module, *set_cache_service;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct master_service_settings_cache *set_cache;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t userdb_next_pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *const **userdb_next_fieldsp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool debug:1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool log_initialized:1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool config_permission_denied:1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu};
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct mail_storage_service_user {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int refcount;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_ctx *service_ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_input input;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum mail_storage_service_flags flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct event *event;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ARRAY(struct event *) event_stack;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct ioloop_context *ioloop_ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *log_prefix, *auth_token, *auth_user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *system_groups_user, *uid_source, *gid_source;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe const char *chdir_path;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe const struct mail_user_settings *user_set;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe const struct setting_parser_info *user_info;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe struct setting_parser_context *set_parser;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe unsigned int session_id_counter;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe bool anonymous:1;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe bool admin:1;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe};
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestruct module *mail_storage_service_modules = NULL;
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic int
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowemail_storage_service_var_expand(struct mail_storage_service_ctx *ctx,
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe string_t *str, const char *format,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_privileges *priv,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic bool
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_user_set_get_mail_debug(const struct setting_parser_info *user_info,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_user_settings *user_set)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_settings *mail_set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_set = mail_user_set_get_driver_settings(user_info, user_set,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu MAIL_STORAGE_SET_DRIVER_NAME);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return mail_set->mail_debug;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void set_keyval(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *key, const char *value)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct setting_parser_context *set_parser = user->set_parser;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (master_service_set_has_config_override(ctx->service, key)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* this setting was already overridden with -o parameter */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_user_set_get_mail_debug(user->user_info,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_set)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_debug("Ignoring overridden (-o) userdb setting: %s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu key);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (settings_parse_keyvalue(set_parser, key, value) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("Invalid userdb input %s=%s: %s", key, value,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu settings_parser_get_error(set_parser));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int set_line(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *line)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct setting_parser_context *set_parser = user->set_parser;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool mail_debug;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *key, *orig_key, *append_value = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu size_t len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_debug = mail_user_set_get_mail_debug(user->user_info,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_set);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strchr(line, '=') == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu line = t_strconcat(line, "=yes", NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu orig_key = key = t_strcut(line, '=');
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu len = strlen(key);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len > 0 && key[len-1] == '+') {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* key+=value */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu append_value = line + len + 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu key = t_strndup(key, len-1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!settings_parse_is_valid_key(set_parser, key)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* assume it's a plugin setting */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu key = t_strconcat("plugin/", key, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu line = t_strconcat("plugin/", line, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (master_service_set_has_config_override(ctx->service, key)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* this setting was already overridden with -o parameter */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_debug) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_debug("Ignoring overridden (-o) userdb setting: %s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu key);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (append_value != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const void *value;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum setting_type type;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu value = settings_parse_get_value(set_parser, key, &type);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (value != NULL && type == SET_STR) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *const *strp = value;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu line = t_strdup_printf("%s=%s%s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu key, *strp, append_value);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_error("Ignoring %s userdb setting. "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "'+' can only be used for strings.", orig_key);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = settings_parse_line(set_parser, line);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_debug && ret >= 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strstr(key, "pass") != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* possibly a password field (e.g. imapc_password).
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu hide the value. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu line = t_strconcat(key, "=<hidden>", NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_debug(ret == 0 ?
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Unknown userdb setting: %s" :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Added userdb setting: %s", line);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic bool validate_chroot(const struct mail_user_settings *user_set,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *dir)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *const *chroot_dirs;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*dir == '\0')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*user_set->valid_chroot_dirs == '\0')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (*chroot_dirs != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (**chroot_dirs != '\0' &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu chroot_dirs++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuser_reply_handle(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct auth_user_reply *reply,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *home = reply->home;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *chroot = reply->chroot;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *const *str, *line, *p;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu unsigned int i, count;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (reply->uid != (uid_t)-1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (reply->uid == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = "userdb returned 0 as uid";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->uid_source = "userdb lookup";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_keyval(ctx, user, "mail_uid", dec2str(reply->uid));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (reply->gid != (uid_t)-1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->gid_source = "userdb lookup";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_keyval(ctx, user, "mail_gid", dec2str(reply->gid));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (home != NULL && chroot == NULL &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *user->user_set->valid_chroot_dirs != '\0' &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (p = strstr(home, "/./")) != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* wu-ftpd like <chroot>/./<home> - check only if there's even
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu a possibility of using them (non-empty valid_chroot_dirs) */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu chroot = t_strdup_until(home, p);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu home = p + 2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (home != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_keyval(ctx, user, "mail_home", home);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (chroot != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!validate_chroot(user->user_set, chroot)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "userdb returned invalid chroot directory: %s "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "(see valid_chroot_dirs setting)", chroot);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_keyval(ctx, user, "mail_chroot", chroot);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->anonymous = reply->anonymous;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu str = array_get(&reply->extra_fields, &count);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; i < count; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu line = str[i];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strncmp(line, "system_groups_user=", 19) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->system_groups_user =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p_strdup(user->pool, line + 19);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (strncmp(line, "chdir=", 6) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->chdir_path = p_strdup(user->pool, line+6);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (strncmp(line, "nice=", 5) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#ifdef HAVE_SETPRIORITY
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int n;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (str_to_int(line + 5, &n) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_error("userdb returned invalid nice value %s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu line + 5);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (n != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (setpriority(PRIO_PROCESS, 0, n) < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_error("setpriority(%d) failed: %m", n);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#endif
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (strncmp(line, "auth_token=", 11) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->auth_token = p_strdup(user->pool, line+11);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (strncmp(line, "auth_user=", 10) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->auth_user = p_strdup(user->pool, line+10);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (strncmp(line, "admin=", 6) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->admin = line[6] == 'y' || line[6] == 'Y' ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu line[6] == '1';
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else T_BEGIN {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = set_line(ctx, user, line);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } T_END;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ret < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ret < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu str[i], settings_parser_get_error(user->set_parser));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuservice_auth_userdb_lookup(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t pool, const char **user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *const **fields_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct auth_user_info info;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *new_username;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_zero(&info);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu info.service = input->service != NULL ? input->service :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->service->name;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu info.local_ip = input->local_ip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu info.remote_ip = input->remote_ip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu info.local_port = input->local_port;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu info.remote_port = input->remote_port;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu info.debug = input->debug;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = auth_master_user_lookup(ctx->conn, *user, &info, pool,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &new_username, fields_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ret > 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strcmp(*user, new_username) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->debug)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_debug("changed username to %s", new_username);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *user = t_strdup(new_username);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *user = new_username;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ret == 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = "Unknown user";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else if (**fields_r != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup(**fields_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = -2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = MAIL_ERRSTR_CRITICAL_MSG;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic bool parse_uid(const char *str, uid_t *uid_r, const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct passwd pw;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (str_to_uid(str, uid_r) == 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch (i_getpwnam(str, &pw)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case -1:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf("getpwnam(%s) failed: %m", str);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case 0:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strconcat("Unknown UNIX UID user: ", str, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu default:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *uid_r = pw.pw_uid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic bool parse_gid(const char *str, gid_t *gid_r, const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct group gr;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (str_to_gid(str, gid_r) == 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch (i_getgrnam(str, &gr)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case -1:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf("getgrnam(%s) failed: %m", str);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu case 0:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strconcat("Unknown UNIX GID group: ", str, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu default:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *gid_r = gr.gr_gid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic const struct var_expand_table *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuget_var_expand_table(struct master_service *service,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_privileges *priv)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *username = t_strcut(input->username, '@');
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *domain = i_strchr_to_next(input->username, '@');
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *uid = priv == NULL ? NULL :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *gid = priv == NULL ? NULL :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *auth_user, *auth_username, *auth_domain;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user == NULL || user->auth_user == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_user = input->username;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_username = username;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_domain = domain;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_user = user->auth_user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_username = t_strcut(user->auth_user, '@');
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_domain = i_strchr_to_next(user->auth_user, '@');
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct var_expand_table stack_tab[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { 'u', input->username, "user" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { 'n', username, "username" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { 'd', domain, "domain" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { 's', service->name, "service" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { 'l', net_ip2addr(&input->local_ip), "lip" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { 'r', net_ip2addr(&input->remote_ip), "rip" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { 'p', my_pid, "pid" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { 'i', uid, "uid" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { '\0', gid, "gid" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { '\0', input->session_id, "session" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { '\0', auth_user, "auth_user" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { '\0', auth_username, "auth_username" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { '\0', auth_domain, "auth_domain" },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { '\0', NULL, NULL }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu };
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct var_expand_table *tab;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu tab = t_malloc_no0(sizeof(stack_tab));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu memcpy(tab, stack_tab, sizeof(stack_tab));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return tab;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuconst struct var_expand_table *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_get_var_expand_table(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_input *input)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_privileges priv;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_zero(&priv);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.uid = (uid_t)-1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.gid = (gid_t)-1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return get_var_expand_table(ctx->service, NULL, input, &priv);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic bool
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuuser_expand_varstr(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_privileges *priv,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *str, const char **value_r, const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu string_t *value;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*str == SETTING_STRVAR_EXPANDED[0]) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *value_r = str + 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu value = t_str_new(256);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = mail_storage_service_var_expand(ctx, value, str + 1, user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &user->input, priv, error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *value_r = str_c(value);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret > 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuservice_parse_privileges(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_privileges *priv_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_user_settings *set = user->user_set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uid_t uid = (uid_t)-1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu gid_t gid = (gid_t)-1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *error;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_zero(priv_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*set->mail_uid != '\0') {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!parse_uid(set->mail_uid, &uid, error_r)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf("%s (from %s)", *error_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->uid_source);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (uid < (uid_t)set->first_valid_uid ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (set->last_valid_uid != 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uid > (uid_t)set->last_valid_uid)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Mail access for users with UID %s not permitted "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "(see first_valid_uid in config file, uid from %s).",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dec2str(uid), user->uid_source);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv_r->uid = uid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv_r->uid_source = user->uid_source;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*set->mail_gid != '\0') {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!parse_gid(set->mail_gid, &gid, error_r)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf("%s (from %s)", *error_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->gid_source);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (gid < (gid_t)set->first_valid_gid ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (set->last_valid_gid != 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu gid > (gid_t)set->last_valid_gid)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Mail access for users with GID %s not permitted "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "(see first_valid_gid in config file, gid from %s).",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dec2str(gid), user->gid_source);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv_r->gid = gid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv_r->gid_source = user->gid_source;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* variable strings are expanded in mail_user_init(),
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu but we need the home and chroot sooner so do them separately here. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!user_expand_varstr(ctx, user, priv_r, user->user_set->mail_home,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &priv_r->home, &error)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Failed to expand mail_home '%s': %s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_set->mail_home, error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!user_expand_varstr(ctx, user, priv_r, user->user_set->mail_chroot,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &priv_r->chroot, &error)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Failed to expand mail_chroot '%s': %s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_set->mail_chroot, error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void mail_storage_service_seteuid_root(void)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (seteuid(0) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("mail-storage-service: "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Failed to restore temporarily dropped root privileges: "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "seteuid(0) failed: %m");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuservice_drop_privileges(struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_privileges *priv,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool disallow_root, bool keep_setuid_root,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool setenv_only, const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_user_settings *set = user->user_set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct restrict_access_settings rset;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uid_t current_euid, setuid_uid = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *cur_chroot, *error;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu current_euid = geteuid();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu restrict_access_init(&rset);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu restrict_access_get_env(&rset);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.allow_setuid_root = keep_setuid_root;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (priv->uid != (uid_t)-1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.uid = priv->uid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.uid_source = priv->uid_source;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (rset.uid == (uid_t)-1 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu disallow_root && current_euid == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = "User is missing UID (see mail_uid setting)";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (priv->gid != (gid_t)-1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.gid = priv->gid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.gid_source = priv->gid_source;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (rset.gid == (gid_t)-1 && disallow_root &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set->first_valid_gid > 0 && getegid() == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = "User is missing GID (see mail_gid setting)";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*set->mail_privileged_group != '\0') {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!parse_gid(set->mail_privileged_group, &rset.privileged_gid,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &error)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "%s (in mail_privileged_group setting)", error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*set->mail_access_groups != '\0') {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.extra_groups = t_strconcat(set->mail_access_groups, ",",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.extra_groups, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.first_valid_gid = set->first_valid_gid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.last_valid_gid = set->last_valid_gid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.chroot_dir = *priv->chroot == '\0' ? NULL : priv->chroot;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.system_groups_user = user->system_groups_user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cur_chroot = restrict_access_get_current_chroot();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (cur_chroot != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* we're already chrooted. make sure the chroots are equal. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rset.chroot_dir == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = "Process is already chrooted, "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "can't un-chroot for this user";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strcmp(rset.chroot_dir, cur_chroot) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Process is already chrooted to %s, "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "can't chroot to %s", cur_chroot, priv->chroot);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* chrooting to same directory where we're already chrooted */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.chroot_dir = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (disallow_root &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = "Mail access not allowed for root";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (keep_setuid_root) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (current_euid != rset.uid && rset.uid != (uid_t)-1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (current_euid != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* we're changing the UID,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu switch back to root first */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_seteuid_root();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu setuid_uid = rset.uid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rset.uid = (uid_t)-1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu disallow_root = FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!setenv_only) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu restrict_access(&rset, *priv->home == '\0' ? NULL : priv->home,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu disallow_root);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu restrict_access_set_env(&rset);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (setuid_uid != 0 && !setenv_only) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (seteuid(setuid_uid) < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("mail-storage-service: seteuid(%s) failed: %m",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dec2str(setuid_uid));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_privileges *priv,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *session_id_suffix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_user **mail_user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_settings *mail_set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *home = priv->home;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_user_connection_data conn_data;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_user *mail_user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_zero(&conn_data);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu conn_data.local_ip = &user->input.local_ip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu conn_data.remote_ip = &user->input.remote_ip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu conn_data.local_port = user->input.local_port;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu conn_data.remote_port = user->input.remote_port;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu conn_data.secured = user->input.conn_secured;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu conn_data.ssl_secured = user->input.conn_ssl_secured;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* NOTE: if more user initialization is added, add it also to
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_dup() */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user = mail_user_alloc_nodup_set(user->event, user->input.username,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_info, user->user_set);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->_service_user = user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_user_ref(user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_set_vars(mail_user, ctx->service->name, &conn_data);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->uid = priv->uid == (uid_t)-1 ? geteuid() : priv->uid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->gid = priv->gid == (gid_t)-1 ? getegid() : priv->gid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->anonymous = user->anonymous;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->admin = user->admin;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->auth_token = p_strdup(mail_user->pool, user->auth_token);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->auth_user = p_strdup(mail_user->pool, user->auth_user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->input.session_create_time != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->session_create_time =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.session_create_time;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->session_restored = TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (session_id_suffix == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->session_id_counter++ == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->session_id =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p_strdup(mail_user->pool, user->input.session_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->session_id =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p_strdup_printf(mail_user->pool, "%s:%u",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.session_id,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->session_id_counter);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->session_id =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p_strdup_printf(mail_user->pool, "%s:%s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.session_id,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu session_id_suffix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_add_str(user->event, "session", mail_user->session_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user->userdb_fields = user->input.userdb_fields == NULL ? NULL :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p_strarray_dup(mail_user->pool, user->input.userdb_fields);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_set = mail_user_set_get_storage_set(mail_user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_set->mail_debug) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu string_t *str = t_str_new(64);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu str_printfa(str, "Effective uid=%s, gid=%s, home=%s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dec2str(geteuid()), dec2str(getegid()), home);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*priv->chroot != '\0')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu str_printfa(str, ", chroot=%s", priv->chroot);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_debug("%s", str_c(str));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* we don't want to write core files to any users' home
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu directories since they could contain information about other
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu users' mails as well. so do no chdiring to home. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* If possible chdir to home directory, so that core file
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu could be written in case we crash.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fallback to chdir()ing to root directory. this is needed
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu because the current directory may not be accessible after
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dropping privileges, and for example unlink_directory()
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu requires ability to open the current directory. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *chdir_path = user->chdir_path != NULL ?
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->chdir_path : home;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (chdir_path[0] == '\0') {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (chdir("/") < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_error("chdir(/) failed: %m");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (chdir(chdir_path) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (errno == EACCES) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_error("%s", eacces_error_get("chdir",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu t_strconcat(chdir_path, "/", NULL)));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (errno != ENOENT)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_error("chdir(%s) failed: %m", chdir_path);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else if (mail_set->mail_debug)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_debug("Home dir not found: %s", chdir_path);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (chdir("/") < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_error("chdir(/) failed: %m");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_user_init(mail_user, error_r) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_unref(&mail_user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_namespaces_init(mail_user, error_r) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_unref(&mail_user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *mail_user_r = mail_user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_io_activate_user(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu io_loop_context_activate(user->ioloop_ctx);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_io_deactivate_user(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu io_loop_context_deactivate(user->ioloop_ctx);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_io_activate_user_cb(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_push_global(user->event);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (array_is_created(&user->event_stack)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct event *const *events;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu unsigned int i, count;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* push the global events from stack in reverse order */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu events = array_get(&user->event_stack, &count);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = count; i > 0; i--)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_push_global(events[i-1]);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu array_clear(&user->event_stack);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->log_prefix != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_prefix("%s", user->log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_io_deactivate_user_cb(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct event *event;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* ioloop context is always global, so we can't push one ioloop context
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu on top of another one. We'll need to rewind the global event stack
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu until we've reached the event that started this context. We'll push
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu these global events back when the user's context is activated
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu again. (We'll assert-crash if the user is freed before these
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu global events have been popped.) */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while ((event = event_get_global()) != user->event) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(event != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!array_is_created(&user->event_stack))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_array_init(&user->event_stack, 4);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu array_append(&user->event_stack, &event, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_pop_global(event);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_pop_global(user->event);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->log_prefix != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_prefix("%s", user->service_ctx->default_log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic const char *field_get_default(const char *data)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *p;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p = strchr(data, ':');
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (p == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return "";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* default value given */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return p+1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuconst char *mail_storage_service_fields_var_expand(const char *data,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *const *fields)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *field_name = t_strcut(data, ':');
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu unsigned int i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu size_t field_name_len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (fields == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return field_get_default(data);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu field_name_len = strlen(field_name);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; fields[i] != NULL; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strncmp(fields[i], field_name, field_name_len) == 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fields[i][field_name_len] == '=')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return fields[i] + field_name_len+1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return field_get_default(data);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_input_var_userdb(const char *data, void *context,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **value_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r ATTR_UNUSED)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user = context;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *value_r = mail_storage_service_fields_var_expand(data,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user == NULL ? NULL : user->input.userdb_fields);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_var_expand(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu string_t *str, const char *format,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_privileges *priv,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu static const struct var_expand_func_table func_table[] = {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { "userdb", mail_storage_service_input_var_userdb },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { NULL, NULL }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu };
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return var_expand_with_funcs(str, format,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu get_var_expand_table(ctx->service, user, input, priv),
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu func_table, user, error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_privileges *priv)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *error;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->log_initialized = TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu T_BEGIN {
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek string_t *str;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu str = t_str_new(256);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void)mail_storage_service_var_expand(ctx, str,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_set->mail_log_prefix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user, &user->input, priv, &error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->log_prefix = p_strdup(user->pool, str_c(str));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } T_END;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu master_service_init_log(ctx->service, user->log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* replace the whole log prefix with mail_log_prefix */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_replace_log_prefix(user->event, user->log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (master_service_get_client_limit(master_service) == 1)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_send_prefix(user->log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void mail_storage_service_time_moved(time_t old_time, time_t new_time)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu long diff = new_time - old_time;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (diff > 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (diff > MAX_NOWARN_FORWARD_SECS)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_warning("Time jumped forwards %ld seconds", diff);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu diff = -diff;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (diff > MAX_TIME_BACKWARDS_SLEEP) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("Time just moved backwards by %ld seconds. "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "This might cause a lot of problems, "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "so I'll just kill myself now. "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_error("Time just moved backwards by %ld seconds. "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "I'll sleep now until we're back in present. "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Sleep extra second to make sure usecs also grows. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu diff++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (diff > 0 && sleep(diff) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* don't use sleep()'s return value, because
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu it could get us to a long loop in case
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu interrupts just keep coming */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu diff = old_time - time(NULL) + 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct mail_storage_service_ctx *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_init(struct master_service *service,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_info *set_roots[],
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum mail_storage_service_flags flags)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_ctx *ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *version;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu unsigned int count;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu version = master_service_get_version_string(service);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (version != NULL && strcmp(version, PACKAGE_VERSION) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("Version mismatch: libdovecot-storage.so is '%s', "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "while the running Dovecot binary is '%s'",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu PACKAGE_VERSION, version);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu getuid() != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* service { user } isn't root. the permission drop can't be
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu temporary. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags &= ~MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void)umask(0077);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu io_loop_set_time_moved_callback(current_ioloop,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_time_moved);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_init();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool = pool_alloconly_create("mail storage service", 2048);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx = p_new(pool, struct mail_storage_service_ctx, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->pool = pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->service = service;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->flags = flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* @UNSAFE */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (set_roots == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu count = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (count = 0; set_roots[count] != NULL; count++) ;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->set_roots =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p_new(pool, const struct setting_parser_info *, count + 2);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->set_roots[0] = &mail_user_setting_parser_info;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (set_roots != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu memcpy(ctx->set_roots + 1, set_roots,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sizeof(*ctx->set_roots) * count);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* do all the global initialization. delay initializing plugins until
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu we drop privileges the first time. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* note: we may not have read any settings yet, so this logging
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu may still be going to wrong location */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->default_log_prefix =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p_strconcat(pool, service->name, ": ", NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu master_service_init_log(service, ctx->default_log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dict_drivers_register_builtin();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct auth_master_connection *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_get_auth_conn(struct mail_storage_service_ctx *ctx)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(ctx->conn != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ctx->conn;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic enum mail_storage_service_flags
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_input_get_flags(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum mail_storage_service_flags flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags = (ctx->flags & ~input->flags_override_remove) |
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu input->flags_override_add;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (input->no_userdb_lookup) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* FIXME: for API backwards compatibility only */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags &= ~MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint mail_storage_service_read_settings(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t pool,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_info **user_info_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_context **parser_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct master_service_settings_input set_input;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_info *const *roots;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct master_service_settings_output set_output;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct dynamic_settings_parser *dyn_parsers;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum mail_storage_service_flags flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu unsigned int i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->config_permission_denied = FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags = input == NULL ? ctx->flags :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_input_get_flags(ctx, input);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_zero(&set_input);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.roots = ctx->set_roots;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.preserve_user = TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* settings reader may exec doveconf, which is going to clear
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu environment, and if we're not doing a userdb lookup we want to
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu use $HOME */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.preserve_home =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.use_sysexits =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (flags & MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS) != 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (input != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.module = input->module;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.service = input->service;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.username = input->username;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.local_ip = input->local_ip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.remote_ip = input->remote_ip;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (input == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* global settings read - don't create a cache for thi */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (ctx->set_cache == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->set_cache_module = p_strdup(ctx->pool, set_input.module);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->set_cache_service = p_strdup(ctx->pool, set_input.service);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->set_cache = master_service_settings_cache_init(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->service, set_input.module, set_input.service);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* already looked up settings at least once.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu we really shouldn't be execing anymore. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_input.never_exec = TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dyn_parsers = mail_storage_get_dynamic_parsers(pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (null_strcmp(set_input.module, ctx->set_cache_module) == 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu null_strcmp(set_input.service, ctx->set_cache_service) == 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->set_cache != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (master_service_settings_cache_read(ctx->set_cache,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &set_input, dyn_parsers,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu parser_r, error_r) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Error reading configuration: %s", *error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu settings_parser_dyn_update(pool, &set_input.roots, dyn_parsers);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (master_service_settings_read(ctx->service, &set_input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &set_output, error_r) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Error reading configuration: %s", *error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->config_permission_denied =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_output.permission_denied;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *parser_r = ctx->service->set_parser;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu roots = settings_parser_get_roots(*parser_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (i = 0; roots[i] != NULL; i++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strcmp(roots[i]->module_name,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_setting_parser_info.module_name) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *user_info_r = roots[i];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_unreached();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_set_auth_conn(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct auth_master_connection *conn)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(ctx->conn == NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(mail_user_auth_master_conn == NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->conn = conn;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_auth_master_conn = conn;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_first_init(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_info *user_info,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_user_settings *user_set)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum auth_master_flags flags = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->debug = mail_user_set_get_mail_debug(user_info, user_set);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->debug)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags |= AUTH_MASTER_FLAG_DEBUG;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_IDLE_TIMEOUT) != 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags |= AUTH_MASTER_FLAG_NO_IDLE_TIMEOUT;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_set_auth_conn(ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_master_init(user_set->auth_socket_path, flags));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_load_modules(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_info *user_info,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_user_settings *user_set,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct module_dir_load_settings mod_set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*user_set->mail_plugins == '\0')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS) != 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_zero(&mod_set);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mod_set.abi_version = DOVECOT_ABI_VERSION;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mod_set.binary_name = master_service_get_name(ctx->service);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mod_set.setting_name = "mail_plugins";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mod_set.require_init_funcs = TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mod_set.debug = mail_user_set_get_mail_debug(user_info, user_set);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return module_dir_try_load_missing(&mail_storage_service_modules,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user_set->mail_plugin_dir,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user_set->mail_plugins,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &mod_set, error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int extra_field_key_cmp_p(const char *const *s1, const char *const *s2)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *p1 = *s1, *p2 = *s2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (; *p1 == *p2; p1++, p2++) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*p1 == '\0')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*p1 == '=')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*p2 == '=')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return *p1 - *p2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_set_log_prefix(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_user_settings *user_set,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_privileges *priv)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu string_t *str;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *error;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu str = t_str_new(256);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void)mail_storage_service_var_expand(ctx, str, user_set->mail_log_prefix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user, input, priv, &error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_prefix("%s", str_c(str));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic const char *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_generate_session_id(pool_t pool, const char *prefix)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu guid_128_t guid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu string_t *str = str_new(pool, MAX_BASE64_ENCODED_SIZE(prefix_len + 1 + sizeof(guid)));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (prefix != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu str_printfa(str, "%s:", prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu guid_128_generate(guid);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu base64_encode(guid, sizeof(guid), str);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* remove the trailing "==" */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(str_data(str)[str_len(str)-2] == '=');
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu str_truncate(str, str_len(str)-2);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return str_c(str);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_lookup_real(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool update_log_prefix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user **user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum mail_storage_service_flags flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *username = input->username;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_info *user_info;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_user_settings *user_set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *const *userdb_fields, *error;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct auth_user_reply reply;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_context *set_parser;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu void **sets;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t user_pool, temp_pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user_pool = pool_alloconly_create(MEMPOOL_GROWING"mail storage service user", 1024*6);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags = mail_storage_service_input_get_flags(ctx, input);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu geteuid() != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* we dropped privileges only temporarily. switch back to root
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu before reading settings, so we'll definitely have enough
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu permissions to connect to the config socket. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_seteuid_root();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_storage_service_read_settings(ctx, input, user_pool,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &user_info, &set_parser,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu error_r) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->config_permission_denied) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* just restart and maybe next time we will open the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu config socket before dropping privileges */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("%s", *error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_unref(&user_pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu !ctx->log_initialized) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* initialize logging again, in case we only read the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu settings for the first above */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->log_initialized = TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu master_service_init_log(ctx->service,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu t_strconcat(ctx->service->name, ": ", NULL));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu update_log_prefix = TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sets = master_service_settings_parser_get_others(master_service,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_parser);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user_set = sets[0];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (update_log_prefix)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_set_log_prefix(ctx, user_set, NULL, input, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->conn == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_first_init(ctx, user_info, user_set);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* load global plugins */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_storage_service_load_modules(ctx, user_info, user_set, error_r) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_unref(&user_pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->userdb_next_pool == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu temp_pool = pool_alloconly_create("userdb lookup", 2048);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu temp_pool = ctx->userdb_next_pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->userdb_next_pool = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_ref(temp_pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = service_auth_userdb_lookup(ctx, input, temp_pool,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &username, &userdb_fields, error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ret <= 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_unref(&temp_pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_unref(&user_pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->userdb_next_fieldsp != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *ctx->userdb_next_fieldsp = userdb_fields;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu userdb_fields = input->userdb_fields;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user = p_new(user_pool, struct mail_storage_service_user, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->refcount = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->service_ctx = ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->pool = user_pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input = *input;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.userdb_fields = userdb_fields == NULL ? NULL :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu p_strarray_dup(user_pool, userdb_fields);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.username = p_strdup(user_pool, username);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.session_id = p_strdup(user_pool, input->session_id);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->input.session_id == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.session_id =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_generate_session_id(user_pool,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu input->session_id_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.session_create_time = input->session_create_time;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_info = user_info;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->flags = flags;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->set_parser = settings_parser_dup(set_parser, user_pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sets = master_service_settings_parser_get_others(master_service,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->set_parser);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_set = sets[0];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->gid_source = "mail_gid setting";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->uid_source = "mail_uid setting";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Create an event that will be used as the default event for logging.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu This event won't be a parent to any other events - mail_user.event
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu will be used for that. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->event = event_create(input->parent_event);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_add_fields(user->event, (const struct event_add_field []){
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { .key = "user", .value = user->input.username },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { .key = "service", .value = ctx->service->name },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { .key = "session", .value = user->input.session_id },
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu { .key = NULL }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu });
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->input.local_ip.family != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_add_str(user->event, "local_ip",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu net_ip2addr(&user->input.local_ip));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->input.local_port != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_add_int(user->event, "local_port",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.local_port);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->input.remote_ip.family != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_add_str(user->event, "remote_ip",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu net_ip2addr(&user->input.remote_ip));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->input.remote_port != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_add_int(user->event, "remote_port",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->input.remote_port);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void)settings_parse_line(user->set_parser, "mail_debug=yes");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *home = getenv("HOME");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (home != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_keyval(ctx, user, "mail_home", home);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (userdb_fields != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_user_fields_parse(userdb_fields, temp_pool, &reply);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu array_sort(&reply.extra_fields, extra_field_key_cmp_p);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user_reply_handle(ctx, user, &reply, &error) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Invalid settings in userdb: %s", error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = -2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ret > 0 && !settings_parser_check(user->set_parser, user_pool, &error)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Invalid settings (probably caused by userdb): %s", error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = -2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_unref(&temp_pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* load per-user plugins */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ret > 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_storage_service_load_modules(ctx, user_info,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_set,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu error_r) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = -2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS) != 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user_set->mail_plugins[0] != '\0') {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* mail_storage_service_load_modules() already avoids loading
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu plugins when the _NO_PLUGINS flag is set. However, it's
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu possible that the plugins are already loaded, because the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu plugin loading is a global state. This is especially true
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu with doveadm, which loads the mail_plugins immediately at
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu startup so it can find commands registered by plugins. It's
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fine that extra plugins are loaded - we'll just need to
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu prevent any of their hooks from being called. One easy way
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu to do this is just to clear out the mail_plugins setting: */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void)settings_parse_line(user->set_parser, "mail_plugins=");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *user_r = user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint mail_storage_service_lookup(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user **user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *old_log_prefix = i_strdup(i_get_failure_prefix());
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool update_log_prefix;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (io_loop_get_current_context(current_ioloop) == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* no user yet. log prefix should be just "imap:" or something
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu equally unhelpful. we don't know the proper log format yet,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu but initialize it to something better until we know it. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *session_id =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu input->session_id != NULL ? input->session_id :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (input->session_id_prefix != NULL ?
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu input->session_id_prefix : NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_prefix("%s(%s%s,%s)",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu master_service_get_name(ctx->service), input->username,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu session_id == NULL ? "" : t_strdup_printf(",%s", session_id),
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu input->remote_ip.family == 0 ? "" :
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu t_strdup_printf(",%s", net_ip2addr(&input->remote_ip)));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu update_log_prefix = TRUE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* we might be here because we're doing a user lookup for a
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu shared user. the log prefix is likely already usable, so
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu just append our own without replacing the whole thing. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_prefix("%suser-lookup(%s)",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu old_log_prefix, input->username);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu update_log_prefix = FALSE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = mail_storage_service_lookup_real(ctx, input, update_log_prefix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user_r, error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_prefix("%s", old_log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_free(old_log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_save_userdb_fields(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t pool, const char *const **userdb_fields_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(pool != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(userdb_fields_r != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->userdb_next_pool = pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->userdb_next_fieldsp = userdb_fields_r;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *userdb_fields_r = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_next_real(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *session_id_suffix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_user **mail_user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_privileges priv;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *error;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu size_t len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool disallow_root =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (user->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool temp_priv_drop =
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bool use_chroot;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (service_parse_privileges(ctx, user, &priv, error_r) < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*priv.home != '/' && *priv.home != '\0') {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Relative home directory paths not supported: %s",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.home);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* we can't chroot if we want to switch between users. there's
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu not much point either (from security point of view). but if we're
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu already chrooted, we'll just have to continue and hope that the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu current chroot is the same as the wanted chroot */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu use_chroot = !temp_priv_drop ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu restrict_access_get_current_chroot() != NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu len = strlen(priv.chroot);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len > 2 && strcmp(priv.chroot + len - 2, "/.") == 0 &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu strncmp(priv.home, priv.chroot, len - 2) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* mail_chroot = /chroot/. means that the home dir already
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu contains the chroot dir. remove it from home. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (use_chroot) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.home += len - 2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*priv.home == '\0')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.home = "/";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.chroot = t_strndup(priv.chroot, len - 2);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_keyval(ctx, user, "mail_home", priv.home);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_keyval(ctx, user, "mail_chroot", priv.chroot);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (len > 0 && !use_chroot) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* we're not going to chroot. fix home directory so we can
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu access it. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*priv.home == '\0' || strcmp(priv.home, "/") == 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.home = priv.chroot;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.home = t_strconcat(priv.chroot, priv.home, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu priv.chroot = "";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_keyval(ctx, user, "mail_home", priv.home);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* create ioloop context regardless of logging. it's also used by
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu stats plugin. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->ioloop_ctx = io_loop_context_new(current_ioloop);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu io_loop_context_add_callbacks(user->ioloop_ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_io_activate_user_cb,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_io_deactivate_user_cb,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_init_log(ctx, user, &priv);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (service_drop_privileges(user, &priv,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu disallow_root, temp_priv_drop,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu FALSE, &error) < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = t_strdup_printf(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "Couldn't drop privileges: %s", error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!temp_priv_drop ||
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) != 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu restrict_access_allow_coredumps(TRUE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* privileges are dropped. initialize plugins that haven't been
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu initialized yet. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu module_dir_init(mail_storage_service_modules);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_storage_service_init_post(ctx, user, &priv,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu session_id_suffix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_r, error_r) < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return -2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint mail_storage_service_next(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_user **mail_user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return mail_storage_service_next_with_session_suffix(ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu NULL,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint mail_storage_service_next_with_session_suffix(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *session_id_suffix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_user **mail_user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *old_log_prefix = i_strdup(i_get_failure_prefix());
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_set_log_prefix(ctx, user->user_set, user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &user->input, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_prefix("%s", old_log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = mail_storage_service_next_real(ctx, user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu session_id_suffix,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_r, error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) != 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_set_failure_prefix("%s", old_log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_free(old_log_prefix);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_restrict_setenv(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_privileges priv;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *error;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (service_parse_privileges(ctx, user, &priv, &error) < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("user %s: %s", user->input.username, error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (service_drop_privileges(user, &priv,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu FALSE, FALSE, TRUE, &error) < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("user %s: %s", user->input.username, error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint mail_storage_service_lookup_next(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user **user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_user **mail_user_r,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = mail_storage_service_lookup(ctx, input, &user, error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ret <= 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = mail_storage_service_next(ctx, user, mail_user_r, error_r);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ret < 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_user_unref(&user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *user_r = user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_user_ref(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(user->refcount > 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->refcount++;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_user_unref(struct mail_storage_service_user **_user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_user *user = *_user;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *_user = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(user->refcount > 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (--user->refcount > 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (user->ioloop_ctx != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (io_loop_get_current_context(current_ioloop) == user->ioloop_ctx)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_io_deactivate_user(user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu io_loop_context_remove_callbacks(user->ioloop_ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_io_activate_user_cb,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_io_deactivate_user_cb, user);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu io_loop_context_unref(&user->ioloop_ctx);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (array_is_created(&user->event_stack)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert(array_count(&user->event_stack) == 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu array_free(&user->event_stack);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu settings_parser_deinit(&user->set_parser);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu event_unref(&user->event);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_unref(&user->pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_init_settings(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_storage_service_input *input)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_info *user_info;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct mail_user_settings *user_set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const struct setting_parser_context *set_parser;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *error;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_t temp_pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu void **sets;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->conn != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu temp_pool = pool_alloconly_create("service all settings", 4096);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_storage_service_read_settings(ctx, input, temp_pool,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &user_info, &set_parser,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &error) < 0)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_fatal("%s", error);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sets = master_service_settings_parser_get_others(master_service,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set_parser);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user_set = sets[0];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_first_init(ctx, user_info, user_set);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_unref(&temp_pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustatic int
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_all_iter_deinit(struct mail_storage_service_ctx *ctx)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->auth_list != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ret = auth_master_user_list_deinit(&ctx->auth_list);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_master_deinit(&ctx->iter_conn);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_all_init_mask(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *user_mask_hint)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu enum auth_master_flags flags = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void)mail_storage_service_all_iter_deinit(ctx);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_service_init_settings(ctx, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* create a new connection, because the iteration might take a while
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu and we might want to do USER lookups during it, which don't mix
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu well in the same connection. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->debug)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags |= AUTH_MASTER_FLAG_DEBUG;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->iter_conn = auth_master_init(auth_master_get_socket_path(ctx->conn),
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ctx->auth_list = auth_master_user_list_init(ctx->iter_conn,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user_mask_hint, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint mail_storage_service_all_next(struct mail_storage_service_ctx *ctx,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **username_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu i_assert((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *username_r = auth_master_user_list_next(ctx->auth_list);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*username_r != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return mail_storage_service_all_iter_deinit(ctx);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid mail_storage_service_deinit(struct mail_storage_service_ctx **_ctx)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct mail_storage_service_ctx *ctx = *_ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *_ctx = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void)mail_storage_service_all_iter_deinit(ctx);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->conn != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mail_user_auth_master_conn == ctx->conn)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_user_auth_master_conn = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu auth_master_deinit(&ctx->conn);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ctx->set_cache != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu master_service_settings_cache_deinit(&ctx->set_cache);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu pool_unref(&ctx->pool);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu module_dir_unload(&mail_storage_service_modules);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mail_storage_deinit();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dict_drivers_unregister_builtin();
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid **mail_storage_service_user_get_set(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return master_service_settings_parser_get_others(master_service,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->set_parser);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuconst struct mail_storage_settings *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_user_get_mail_set(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return mail_user_set_get_driver_settings(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu user->user_info, user->user_set,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu MAIL_STORAGE_SET_DRIVER_NAME);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuconst struct mail_storage_service_input *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_user_get_input(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return &user->input;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct setting_parser_context *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_user_get_settings_parser(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return user->set_parser;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct mail_storage_service_ctx *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumail_storage_service_user_get_service_ctx(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return user->service_ctx;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liupool_t mail_storage_service_user_get_pool(struct mail_storage_service_user *user)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return user->pool;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid *mail_storage_service_get_settings(struct master_service *service)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu void **sets, *set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu T_BEGIN {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sets = master_service_settings_get_others(service);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu set = sets[1];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } T_END;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return set;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint mail_storage_service_user_set_setting(struct mail_storage_service_user *user,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *key,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char *value,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu const char **error_r)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int ret = settings_parse_keyvalue(user->set_parser, key, value);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *error_r = settings_parser_get_error(user->set_parser);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return ret;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu