mail-storage-service.c revision 367e28a16854ee9f7247b2518f36f5e9163fcc10
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "array.h"
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "hostpid.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "module-dir.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "restrict-access.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "str.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "var-expand.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "dict.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "settings-parser.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "auth-master.h"
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen#include "master-service-private.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "master-service-settings.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "mail-user.h"
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen#include "mail-namespace.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "mail-storage.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "mail-storage-service.h"
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <stdlib.h>
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen#include <sys/stat.h>
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include <pwd.h>
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include <grp.h>
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstruct mail_storage_service_multi_ctx {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct master_service *service;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen enum mail_storage_service_flags flags;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int modules_initialized:1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen};
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct mail_storage_service_multi_user {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen pool_t pool;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *user;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *system_groups_user;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct mail_user_settings *user_set;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct setting_parser_context *set_parser;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen};
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic struct module *modules = NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void set_keyval(struct setting_parser_context *set_parser,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *key, const char *value)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *str;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen str = t_strconcat(key, "=", value, NULL);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (settings_parse_line(set_parser, str) < 0) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen i_fatal("Invalid userdb input '%s': %s", str,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen settings_parser_get_error(set_parser));
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic bool validate_chroot(const struct mail_user_settings *user_set,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *dir)
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *const *chroot_dirs;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (*dir == '\0')
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (*user_set->valid_chroot_dirs == '\0')
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen while (*chroot_dirs != NULL) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (**chroot_dirs != '\0' &&
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen chroot_dirs++;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainenstatic int
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenuser_reply_handle(struct setting_parser_context *set_parser,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct mail_user_settings *user_set,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const struct auth_user_reply *reply,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const char **system_groups_user_r, const char **error_r)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen const char *const *str, *p, *line, *key;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int i, count;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int ret = 0;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *system_groups_user_r = NULL;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (reply->uid != (uid_t)-1) {
35df1dd606c5ef21068ab4fe4be305859d4fad4bTimo Sirainen if (reply->uid == 0) {
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen *error_r = "userdb returned 0 as uid";
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen return -1;
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen }
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen set_keyval(set_parser, "mail_uid", dec2str(reply->uid));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (reply->gid != (uid_t)-1)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen set_keyval(set_parser, "mail_gid", dec2str(reply->gid));
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (reply->home != NULL)
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen set_keyval(set_parser, "mail_home", reply->home);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (reply->chroot != NULL) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (!validate_chroot(user_set, reply->chroot)) {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen *error_r = t_strdup_printf(
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen "userdb returned invalid chroot directory: %s "
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen "(see valid_chroot_dirs setting)",
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen reply->chroot);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen return -1;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen }
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen set_keyval(set_parser, "mail_chroot", reply->chroot);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen str = array_get(&reply->extra_fields, &count);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (i = 0; i < count && ret == 0; i++) T_BEGIN {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen line = str[i];
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (strncmp(line, "system_groups_user=", 19) == 0) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen *system_groups_user_r = line + 19;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen continue;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (strncmp(line, "mail=", 5) == 0)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen line = t_strconcat("mail_location=", line + 5, NULL);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen else if ((p = strchr(str[i], '=')) == NULL)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen line = t_strconcat(str[i], "=yes", NULL);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen else
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen line = str[i];
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen key = t_strcut(line, '=');
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen if (!settings_parse_is_valid_key(set_parser, key)) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* assume it's a plugin setting */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen line = t_strconcat("plugin/", line, NULL);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen ret = settings_parse_line(set_parser, line);
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen } T_END;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen if (ret < 0) {
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen str[i], settings_parser_get_error(set_parser));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return ret;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenstatic int
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenservice_auth_userdb_lookup(struct setting_parser_context *set_parser,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen const char *name,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen const struct mail_user_settings *user_set,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen const char **user, const char **system_groups_user_r,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen const char **error_r)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen const struct mail_storage_settings *mail_set;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct auth_master_connection *conn;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct auth_user_reply reply;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen const char *system_groups_user, *orig_user = *user;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen unsigned int len;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen pool_t pool;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen int ret;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen mail_set = mail_user_set_get_storage_set(user_set);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen pool = pool_alloconly_create("userdb lookup", 1024);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen conn = auth_master_init(user_set->auth_socket_path,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen mail_set->mail_debug);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen ret = auth_master_user_lookup(conn, *user, name, pool, &reply);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (ret > 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen len = reply.chroot == NULL ? 0 : strlen(reply.chroot);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen *user = t_strdup(reply.user);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (user_reply_handle(set_parser, user_set, &reply,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen &system_groups_user, error_r) < 0)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen ret = -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *system_groups_user_r = t_strdup(system_groups_user);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ret == 0)
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen *error_r = "unknown user";
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen else
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *error_r = "userdb lookup failed";
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen *system_groups_user_r = NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (ret > 0 && strcmp(*user, orig_user) != 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (mail_user_set_get_storage_set(user_set)->mail_debug)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_info("changed username to %s", *user);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_set_failure_prefix(t_strdup_printf("%s(%s): ", name, *user));
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
3e25b17126e9536736d5da03697613e4c3af5f76Timo Sirainen auth_master_deinit(&conn);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pool_unref(&pool);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return ret;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic bool parse_uid(const char *str, uid_t *uid_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct passwd *pw;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char *p;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (*str >= '0' && *str <= '9') {
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen *uid_r = (uid_t)strtoul(str, &p, 10);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen if (*p == '\0')
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen return TRUE;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen }
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen pw = getpwnam(str);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen if (pw == NULL)
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen return FALSE;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen *uid_r = pw->pw_uid;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen return TRUE;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen}
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainenstatic bool parse_gid(const char *str, gid_t *gid_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct group *gr;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char *p;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (*str >= '0' && *str <= '9') {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *gid_r = (gid_t)strtoul(str, &p, 10);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (*p == '\0')
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return TRUE;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen gr = getgrnam(str);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (gr == NULL)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen return FALSE;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *gid_r = gr->gr_gid;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen return TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainenstatic void
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenservice_drop_privileges(const struct mail_user_settings *set,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *system_groups_user, const char *home,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen bool disallow_root, bool keep_setuid_root)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct restrict_access_settings rset;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uid_t current_euid, setuid_uid = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen current_euid = geteuid();
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen restrict_access_init(&rset);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (*set->mail_uid != '\0') {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!parse_uid(set->mail_uid, &rset.uid))
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen i_fatal("Unknown mail_uid user: %s", set->mail_uid);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (rset.uid < (uid_t)set->first_valid_uid ||
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen (set->last_valid_uid != 0 &&
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen rset.uid > (uid_t)set->last_valid_uid)) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_fatal("Mail access for users with UID %s "
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen "not permitted (see first_valid_uid in config file).",
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen dec2str(rset.uid));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
f4bbeadda12fbd7c219063db68f3e78646d83c2cTimo Sirainen }
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen if (*set->mail_gid != '\0') {
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen if (!parse_gid(set->mail_gid, &rset.gid))
abe8754852e70763e92f74caabbcc13d0917714cTimo Sirainen i_fatal("Unknown mail_gid group: %s", set->mail_gid);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (rset.gid < (gid_t)set->first_valid_gid ||
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen (set->last_valid_gid != 0 &&
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen rset.gid > (gid_t)set->last_valid_gid)) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_fatal("Mail access for users with GID %s "
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen "not permitted (see first_valid_gid in config file).",
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen dec2str(rset.gid));
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (*set->mail_privileged_group != '\0') {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (!parse_uid(set->mail_privileged_group, &rset.privileged_gid))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_fatal("Unknown mail_gid group: %s", set->mail_gid);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (*set->mail_access_groups != '\0')
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen rset.extra_groups = set->mail_access_groups;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen rset.first_valid_gid = set->first_valid_gid;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen rset.last_valid_gid = set->last_valid_gid;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen /* we can't chroot if we want to switch between users. there's not
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen much point either (from security point of view) */
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen rset.chroot_dir = *set->mail_chroot == '\0' || keep_setuid_root ?
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen NULL : set->mail_chroot;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen rset.system_groups_user = system_groups_user;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (disallow_root &&
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0)))
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen i_fatal("Mail access not allowed for root");
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (keep_setuid_root && current_euid != rset.uid) {
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (current_euid != 0) {
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen /* we're changing the UID, switch back to root first */
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen if (seteuid(0) < 0)
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen i_fatal("seteuid(0) failed: %m");
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen }
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen setuid_uid = rset.uid;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen rset.uid = (uid_t)-1;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen }
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen restrict_access(&rset, *home == '\0' ? NULL : home, disallow_root);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (keep_setuid_root) {
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen if (seteuid(setuid_uid) < 0)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen i_fatal("seteuid(%s) failed: %m", dec2str(setuid_uid));
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen }
14175321ddb88619015866978c05a27786ca4814Timo Sirainen}
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainenstatic void
14175321ddb88619015866978c05a27786ca4814Timo Sirainenmail_storage_service_init_settings(struct master_service *service,
14175321ddb88619015866978c05a27786ca4814Timo Sirainen const struct setting_parser_info *set_roots[],
14175321ddb88619015866978c05a27786ca4814Timo Sirainen bool preserve_home)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen{
14175321ddb88619015866978c05a27786ca4814Timo Sirainen ARRAY_DEFINE(all_set_roots, const struct setting_parser_info *);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen const struct setting_parser_info *info = &mail_user_setting_parser_info;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen const char *error;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen unsigned int i;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainen (void)umask(0077);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainen mail_storage_init();
14175321ddb88619015866978c05a27786ca4814Timo Sirainen mail_storage_register_all();
14175321ddb88619015866978c05a27786ca4814Timo Sirainen mailbox_list_register_all();
14175321ddb88619015866978c05a27786ca4814Timo Sirainen
14175321ddb88619015866978c05a27786ca4814Timo Sirainen t_array_init(&all_set_roots, 5);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen array_append(&all_set_roots, &info, 1);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (set_roots != NULL) {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen for (i = 0; set_roots[i] != NULL; i++)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen array_append(&all_set_roots, &set_roots[i], 1);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen }
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen (void)array_append_space(&all_set_roots);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen /* read settings after registering storages so they can have their
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen own setting definitions too */
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen set_roots = array_idx_modifiable(&all_set_roots, 0);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (master_service_settings_read(service, set_roots,
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen mail_storage_get_dynamic_parsers(),
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen preserve_home, &error) < 0)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen i_fatal("Error reading configuration: %s", error);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen}
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainenstatic int
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainenmail_storage_service_init_post(struct master_service *service,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen const char *user, const char *home,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen const struct mail_user_settings *user_set,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_user **mail_user_r,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char **error_r)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct mail_storage_settings *mail_set;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_user *mail_user;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen mail_set = mail_user_set_get_storage_set(user_set);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (mail_set->mail_debug) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen i_info("Effective uid=%s, gid=%s, home=%s",
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen dec2str(geteuid()), dec2str(getegid()),
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen home != NULL ? home : "(none)");
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* If possible chdir to home directory, so that core file
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen could be written in case we crash. */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (*home != '\0') {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (chdir(home) < 0) {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (errno != ENOENT)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("chdir(%s) failed: %m", home);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen else if (mail_set->mail_debug)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_info("Home dir not found: %s", home);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_user = mail_user_alloc(user, user_set);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_user_set_vars(mail_user, geteuid(), service->name, NULL, NULL);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mail_user_init(mail_user, error_r) < 0) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_user_unref(&mail_user);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return -1;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mail_namespaces_init(mail_user, error_r) < 0) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_user_unref(&mail_user);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return -1;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen *mail_user_r = mail_user;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return 0;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic const struct var_expand_table *
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenget_var_expand_table(struct master_service *service, const char *user)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen static struct var_expand_table static_tab[] = {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen { 'u', NULL, "user" },
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen { 'n', NULL, "username" },
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen { 'd', NULL, "domain" },
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen { 's', NULL, "service" },
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen { 'p', NULL, "pid" },
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen { 'i', NULL, "uid" },
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen { '\0', NULL, NULL }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen };
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct var_expand_table *tab;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen tab = t_malloc(sizeof(static_tab));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen tab[0].value = user;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen tab[1].value = t_strcut(user, '@');
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen tab[2].value = strchr(user, '@');
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen tab[3].value = service->name;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen tab[4].value = my_pid;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen tab[5].value = dec2str(geteuid());
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen return tab;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic const char *
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenuser_expand_varstr(struct master_service *service, const char *user,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const char *str)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen string_t *ret;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (*str == SETTING_STRVAR_EXPANDED[0])
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return str + 1;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen ret = t_str_new(256);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen var_expand(ret, str + 1, get_var_expand_table(service, user));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return str_c(ret);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstruct mail_user *
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenmail_storage_service_init_user(struct master_service *service, const char *user,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const struct setting_parser_info *set_roots[],
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen enum mail_storage_service_flags flags)
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen{
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen const struct master_service_settings *set;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const struct mail_user_settings *user_set;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const struct mail_storage_settings *mail_set;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mail_user *mail_user;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen void **sets;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const char *orig_user, *home, *system_groups_user, *error;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen unsigned int len;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen bool userdb_lookup;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen userdb_lookup = (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_storage_service_init_settings(service, set_roots, !userdb_lookup);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen set_keyval(service->set_parser, "mail_debug", "yes");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen /* now that we've read settings, we can set up logging */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen master_service_init_log(service,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen t_strdup_printf("%s(%s): ", service->name, user));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen set = master_service_settings_get(service);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen sets = master_service_settings_get_others(service);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen user_set = sets[0];
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_set = mail_user_set_get_storage_set(user_set);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (userdb_lookup) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* userdb lookup may change settings, do it as soon as
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen possible. */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen orig_user = user;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (service_auth_userdb_lookup(service->set_parser,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen service->name, user_set, &user,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen &system_groups_user,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen &error) <= 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_fatal("%s", error);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* variable strings are expanded in mail_user_init(),
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen but we need the home sooner so do it separately here. */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen home = user_expand_varstr(service, user, user_set->mail_home);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (!userdb_lookup) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen system_groups_user = NULL;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (*home == '\0' && getenv("HOME") != NULL) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen home = getenv("HOME");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen set_keyval(service->set_parser, "mail_home", home);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen len = strlen(user_set->mail_chroot);
if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
strncmp(home, user_set->mail_chroot, len - 2) == 0) {
/* If chroot ends with "/.", strip chroot dir from home dir */
home += len - 2;
set_keyval(service->set_parser, "mail_home", home);
}
modules = *user_set->mail_plugins == '\0' ? NULL :
module_dir_load(user_set->mail_plugin_dir,
user_set->mail_plugins, TRUE,
master_service_get_version_string(service));
if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
service_drop_privileges(user_set, system_groups_user, home,
(flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0,
FALSE);
}
/* privileges are now dropped */
dict_drivers_register_builtin();
module_dir_init(modules);
mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
if (mail_storage_service_init_post(service, user, home, user_set,
&mail_user, &error) < 0)
i_fatal("%s", error);
return mail_user;
}
void mail_storage_service_deinit_user(void)
{
module_dir_unload(&modules);
mail_storage_deinit();
mail_users_deinit();
dict_drivers_unregister_builtin();
}
struct mail_storage_service_multi_ctx *
mail_storage_service_multi_init(struct master_service *service,
const struct setting_parser_info *set_roots[],
enum mail_storage_service_flags flags)
{
struct mail_storage_service_multi_ctx *ctx;
const struct master_service_settings *set;
const struct mail_user_settings *user_set;
const struct mail_storage_settings *mail_set;
void **sets;
ctx = i_new(struct mail_storage_service_multi_ctx, 1);
ctx->service = service;
ctx->flags = flags;
mail_storage_service_init_settings(service, set_roots, FALSE);
/* do all the global initialization. delay initializing plugins until
we drop privileges the first time. */
master_service_init_log(service,
t_strdup_printf("%s: ", service->name));
set = master_service_settings_get(service);
sets = master_service_settings_get_others(service);
user_set = sets[0];
mail_set = mail_user_set_get_storage_set(user_set);
modules = *user_set->mail_plugins == '\0' ? NULL :
module_dir_load(user_set->mail_plugin_dir,
user_set->mail_plugins, TRUE,
master_service_get_version_string(service));
dict_drivers_register_builtin();
mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
return ctx;
}
int mail_storage_service_multi_lookup(struct mail_storage_service_multi_ctx *ctx,
const char *username, pool_t pool,
struct mail_storage_service_multi_user **user_r,
const char **error_r)
{
struct mail_storage_service_multi_user *user;
const char *orig_user;
void **sets;
int ret;
user = p_new(pool, struct mail_storage_service_multi_user, 1);
memset(user_r, 0, sizeof(user_r));
user->pool = pool;
user->user = username;
user->set_parser = settings_parser_dup(ctx->service->set_parser, pool);
sets = settings_parser_get_list(user->set_parser);
user->user_set = sets[1];
if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
orig_user = user->user;
ret = service_auth_userdb_lookup(user->set_parser,
ctx->service->name,
user->user_set,
&user->user,
&user->system_groups_user,
error_r);
if (ret <= 0)
return ret;
}
*user_r = user;
return 1;
}
int mail_storage_service_multi_next(struct mail_storage_service_multi_ctx *ctx,
struct mail_storage_service_multi_user *user,
struct mail_user **mail_user_r,
const char **error_r)
{
const struct mail_user_settings *user_set = user->user_set;
const char *home;
unsigned int len;
/* variable strings are expanded in mail_user_init(),
but we need the home sooner so do it separately here. */
home = user_expand_varstr(ctx->service, user->user,
user_set->mail_home);
if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
service_drop_privileges(user_set, user->system_groups_user, home,
(ctx->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0,
TRUE);
}
if (!ctx->modules_initialized) {
/* privileges dropped for the first time. initialize the
modules now to avoid code running as root. */
module_dir_init(modules);
ctx->modules_initialized = TRUE;
}
/* we couldn't do chrooting, so if chrooting was enabled fix
the home directory */
len = strlen(user_set->mail_chroot);
if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
strncmp(home, user_set->mail_chroot, len - 2) == 0) {
/* home dir already contains the chroot dir */
} else if (len > 0) {
set_keyval(user->set_parser, "mail_home",
t_strconcat(user_set->mail_chroot, "/", home, NULL));
}
if (mail_storage_service_init_post(ctx->service, user->user, home,
user_set, mail_user_r, error_r) < 0)
return -1;
return 0;
}
void mail_storage_service_multi_deinit(struct mail_storage_service_multi_ctx **_ctx)
{
struct mail_storage_service_multi_ctx *ctx = *_ctx;
*_ctx = NULL;
i_free(ctx);
mail_storage_service_deinit_user();
}
void *mail_storage_service_get_settings(struct master_service *service)
{
void **sets;
sets = master_service_settings_get_others(service);
return sets[1];
}