mail-storage-service.c revision 8d5c97bf940e43e8ec6e9f1ec8655f3b20edafbe
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2009-2011 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen#include "ioloop.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hostpid.h"
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen#include "module-dir.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "restrict-access.h"
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen#include "eacces-error.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ipwd.h"
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen#include "str.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "var-expand.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "dict.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "settings-parser.h"
66ae183b6e895216037bd921367670f4b0665911Timo Sirainen#include "auth-master.h"
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#include "master-service-private.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "master-service-settings.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service-settings-cache.h"
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen#include "mail-user.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-namespace.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage-service.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include <stdlib.h>
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include <sys/stat.h>
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen#ifdef HAVE_SYS_TIME_H
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# include <sys/time.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef HAVE_SYS_RESOURCE_H
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# include <sys/resource.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* If time moves backwards more than this, kill ourself instead of sleeping. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MAX_TIME_BACKWARDS_SLEEP 5
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen#define MAX_NOWARN_FORWARD_SECS 10
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen#define ERRSTR_INVALID_USER_SETTINGS \
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen "Invalid user settings. Refer to server log for more information."
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainenstruct mail_storage_service_ctx {
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen pool_t pool;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct master_service *service;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_master_connection *conn;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_master_user_list_ctx *auth_list;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const struct setting_parser_info **set_roots;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen enum mail_storage_service_flags flags;
5aeb15e5817fbd4b1d8de540aa7673e3819a8030Timo Sirainen
5aeb15e5817fbd4b1d8de540aa7673e3819a8030Timo Sirainen const char *set_cache_module, *set_cache_service;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen struct master_service_settings_cache *set_cache;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen unsigned int debug:1;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen unsigned int log_initialized:1;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen};
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainenstruct mail_storage_service_user {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_t pool;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage_service_input input;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_storage_service_flags flags;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *system_groups_user, *uid_source, *gid_source;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen const struct mail_user_settings *user_set;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen const struct setting_parser_info *user_info;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct setting_parser_context *set_parser;
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen};
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstruct module *mail_storage_service_modules = NULL;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainenstatic bool
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainenmail_user_set_get_mail_debug(const struct setting_parser_info *user_info,
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen const struct mail_user_settings *user_set)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const struct mail_storage_settings *mail_set;
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_set = mail_user_set_get_driver_settings(user_info, user_set,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen MAIL_STORAGE_SET_DRIVER_NAME);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_set->mail_debug;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void set_keyval(struct mail_storage_service_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage_service_user *user,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *key, const char *value)
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen{
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen struct setting_parser_context *set_parser = user->set_parser;
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen const char *str;
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen if (master_service_set_has_config_override(ctx->service, key)) {
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen /* this setting was already overridden with -o parameter */
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (mail_user_set_get_mail_debug(user->user_info,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen user->user_set)) {
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen i_debug("Ignoring overridden (-o) userdb setting: %s",
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen key);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen }
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen return;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen }
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen str = t_strconcat(key, "=", value, NULL);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (settings_parse_line(set_parser, str) < 0) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen i_fatal("Invalid userdb input '%s': %s", str,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen settings_parser_get_error(set_parser));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainenstatic int set_line(struct mail_storage_service_ctx *ctx,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen struct mail_storage_service_user *user,
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen const char *line)
d161e3c2cde2bd8d5917840f68823a2259ed426eTimo Sirainen{
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen struct setting_parser_context *set_parser = user->set_parser;
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen bool mail_debug;
1e923fcf497665fe071a154c31fb452766b0b2deTimo Sirainen const char *key;
d161e3c2cde2bd8d5917840f68823a2259ed426eTimo Sirainen int ret;
1e923fcf497665fe071a154c31fb452766b0b2deTimo Sirainen
d161e3c2cde2bd8d5917840f68823a2259ed426eTimo Sirainen mail_debug = mail_user_set_get_mail_debug(user->user_info,
d161e3c2cde2bd8d5917840f68823a2259ed426eTimo Sirainen user->user_set);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen if (strchr(line, '=') == NULL)
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen line = t_strconcat(line, "=yes", NULL);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen key = t_strcut(line, '=');
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (!settings_parse_is_valid_key(set_parser, key)) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen /* assume it's a plugin setting */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen key = t_strconcat("plugin/", key, NULL);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen line = t_strconcat("plugin/", line, NULL);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (master_service_set_has_config_override(ctx->service, key)) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen /* this setting was already overridden with -o parameter */
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen if (mail_debug) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen i_debug("Ignoring overridden (-o) userdb setting: %s",
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen key);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen }
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen return 1;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen }
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen ret = settings_parse_line(set_parser, line);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen if (mail_debug && ret >= 0) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen i_debug(ret == 0 ?
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen "Unknown userdb setting: %s" :
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen "Added userdb setting: %s", line);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen }
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen return ret;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen}
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainenstatic bool validate_chroot(const struct mail_user_settings *user_set,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen const char *dir)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const char *const *chroot_dirs;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen if (*dir == '\0')
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return FALSE;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (*user_set->valid_chroot_dirs == '\0')
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen return FALSE;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen while (*chroot_dirs != NULL) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (**chroot_dirs != '\0' &&
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return TRUE;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen chroot_dirs++;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return FALSE;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen}
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenstatic int
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainenuser_reply_handle(struct mail_storage_service_ctx *ctx,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct mail_storage_service_user *user,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const struct auth_user_reply *reply,
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen const char **error_r)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen const char *home = reply->home;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const char *chroot = reply->chroot;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const char *const *str, *line, *p;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen unsigned int i, count;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen int ret = 0;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (reply->uid != (uid_t)-1) {
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (reply->uid == 0) {
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen *error_r = "userdb returned 0 as uid";
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen return -1;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen user->uid_source = "userdb lookup";
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen set_keyval(ctx, user, "mail_uid", dec2str(reply->uid));
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (reply->gid != (uid_t)-1) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen user->gid_source = "userdb lookup";
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen set_keyval(ctx, user, "mail_gid", dec2str(reply->gid));
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (home != NULL && chroot == NULL &&
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *user->user_set->valid_chroot_dirs != '\0' &&
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen (p = strstr(home, "/./")) != NULL) {
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* wu-ftpd like <chroot>/./<home> - check only if there's even
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen a possibility of using them (non-empty valid_chroot_dirs) */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen chroot = t_strdup_until(home, p);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen home = p + 2;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen if (home != NULL)
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen set_keyval(ctx, user, "mail_home", reply->home);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (chroot != NULL) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen if (!validate_chroot(user->user_set, chroot)) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen *error_r = t_strdup_printf(
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen "userdb returned invalid chroot directory: %s "
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen "(see valid_chroot_dirs setting)", chroot);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return -1;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen set_keyval(ctx, user, "mail_chroot", chroot);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen str = array_get(&reply->extra_fields, &count);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen for (i = 0; i < count && ret >= 0; i++) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen line = str[i];
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (strncmp(line, "system_groups_user=", 19) == 0) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen user->system_groups_user =
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen p_strdup(user->pool, line + 19);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen } else if (strncmp(line, "nice=", 5) == 0) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen#ifdef HAVE_SETPRIORITY
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen int n = atoi(line + 5);
6825360d446542046757b06064282301c4c6b27cTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (n != 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (setpriority(PRIO_PROCESS, 0, n) < 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_error("setpriority(%d) failed: %m", n);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen }
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen#endif
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen } else T_BEGIN {
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen ret = set_line(ctx, user, line);
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen } T_END;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ret < 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
6825360d446542046757b06064282301c4c6b27cTimo Sirainen str[i], settings_parser_get_error(user->set_parser));
6825360d446542046757b06064282301c4c6b27cTimo Sirainen }
6825360d446542046757b06064282301c4c6b27cTimo Sirainen return ret;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen}
6825360d446542046757b06064282301c4c6b27cTimo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainenstatic int
6825360d446542046757b06064282301c4c6b27cTimo Sirainenservice_auth_userdb_lookup(struct mail_storage_service_ctx *ctx,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen const struct mail_storage_service_input *input,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen pool_t pool, const char **user,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen const char *const **fields_r,
c8d093d149253fe8faec267c5057f45fe626f84cTimo Sirainen const char **error_r)
c8d093d149253fe8faec267c5057f45fe626f84cTimo Sirainen{
6825360d446542046757b06064282301c4c6b27cTimo Sirainen struct auth_user_info info;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen const char *new_username;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen int ret;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen memset(&info, 0, sizeof(info));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen info.service = ctx->service->name;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen info.local_ip = input->local_ip;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen info.remote_ip = input->remote_ip;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ret = auth_master_user_lookup(ctx->conn, *user, &info, pool,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen &new_username, fields_r);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (ret > 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (strcmp(*user, new_username) != 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ctx->debug)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_debug("changed username to %s", new_username);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen *user = t_strdup(new_username);
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen }
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen *user = new_username;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen } else if (ret == 0)
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen *error_r = "Unknown user";
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen else if (**fields_r != NULL) {
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen *error_r = t_strdup(**fields_r);
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen ret = -2;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen } else {
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen *error_r = MAIL_ERRSTR_CRITICAL_MSG;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen }
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen return ret;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen}
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainenstatic bool parse_uid(const char *str, uid_t *uid_r, const char **error_r)
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen{
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen struct passwd pw;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen if (str_to_uid(str, uid_r) == 0)
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen return TRUE;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen switch (i_getpwnam(str, &pw)) {
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen case -1:
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen *error_r = t_strdup_printf("getpwnam(%s) failed: %m", str);
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen return FALSE;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen case 0:
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen *error_r = t_strconcat("Unknown UNIX UID user: ", str, NULL);
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen return FALSE;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen default:
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen *uid_r = pw.pw_uid;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen return TRUE;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen }
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen}
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainenstatic bool parse_gid(const char *str, gid_t *gid_r, const char **error_r)
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen{
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen struct group gr;
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen
4a09c57f1c66b4a8880bcc12b567bb42c3549f52Timo Sirainen if (str_to_gid(str, gid_r) == 0)
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen return TRUE;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen switch (i_getgrnam(str, &gr)) {
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen case -1:
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen *error_r = t_strdup_printf("getgrnam(%s) failed: %m", str);
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen return FALSE;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen case 0:
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen *error_r = t_strconcat("Unknown UNIX GID group: ", str, NULL);
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen return FALSE;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen default:
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen *gid_r = gr.gr_gid;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen return TRUE;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen }
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen}
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainenstatic int
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainenservice_drop_privileges(struct mail_storage_service_user *user,
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen const struct mail_user_settings *set,
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen const char *home, const char *chroot,
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen bool disallow_root, bool keep_setuid_root,
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen bool setenv_only, const char **error_r)
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen{
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen struct restrict_access_settings rset;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen uid_t current_euid, setuid_uid = 0;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen const char *cur_chroot, *error;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen current_euid = geteuid();
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen restrict_access_init(&rset);
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen restrict_access_get_env(&rset);
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen if (*set->mail_uid != '\0') {
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen if (!parse_uid(set->mail_uid, &rset.uid, &error)) {
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen *error_r = t_strdup_printf("%s (from %s)", error,
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen user->uid_source);
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen return -1;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen }
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen if (rset.uid < (uid_t)set->first_valid_uid ||
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen (set->last_valid_uid != 0 &&
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen rset.uid > (uid_t)set->last_valid_uid)) {
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen *error_r = t_strdup_printf(
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen "Mail access for users with UID %s not permitted "
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen "(see first_valid_uid in config file, uid from %s).",
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen dec2str(rset.uid), user->uid_source);
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen return -1;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen }
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen rset.uid_source = user->uid_source;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen } else if (rset.uid == (uid_t)-1 &&
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen disallow_root && current_euid == 0) {
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen *error_r = "User is missing UID (see mail_uid setting)";
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen return -1;
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen }
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen if (*set->mail_gid != '\0') {
3f2ad7b8c3a243dabcba469c8a331423d036f3fcTimo Sirainen if (!parse_gid(set->mail_gid, &rset.gid, &error)) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen *error_r = t_strdup_printf("%s (from %s)", error,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen user->gid_source);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (rset.gid < (gid_t)set->first_valid_gid ||
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen (set->last_valid_gid != 0 &&
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen rset.gid > (gid_t)set->last_valid_gid)) {
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen *error_r = t_strdup_printf(
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen "Mail access for users with GID %s not permitted "
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen "(see first_valid_gid in config file, gid from %s).",
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen dec2str(rset.gid), user->gid_source);
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen return -1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen rset.gid_source = user->gid_source;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen } else if (rset.gid == (gid_t)-1 && disallow_root &&
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen set->first_valid_gid > 0 && getegid() == 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen *error_r = "User is missing GID (see mail_gid setting)";
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return -1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (*set->mail_privileged_group != '\0') {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (!parse_gid(set->mail_privileged_group, &rset.privileged_gid,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen &error)) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen *error_r = t_strdup_printf(
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "%s (in mail_privileged_group setting)", error);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return -1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (*set->mail_access_groups != '\0') {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen rset.extra_groups = t_strconcat(set->mail_access_groups, ",",
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen rset.extra_groups, NULL);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen rset.first_valid_gid = set->first_valid_gid;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen rset.last_valid_gid = set->last_valid_gid;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* we can't chroot if we want to switch between users. there's not
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen much point either (from security point of view) */
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen rset.chroot_dir = *chroot == '\0' || keep_setuid_root ? NULL : chroot;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen rset.system_groups_user = user->system_groups_user;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen cur_chroot = restrict_access_get_current_chroot();
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (cur_chroot != NULL) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (rset.chroot_dir == NULL) {
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen *error_r = "Process is already chrooted, "
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen "can't un-chroot for this user";
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen return -1;
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen }
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen if (strcmp(rset.chroot_dir, cur_chroot) != 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen *error_r = t_strdup_printf(
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "Process is already chrooted to %s, "
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "can't chroot to %s", cur_chroot, chroot);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* chrooting to same directory where we're already chrooted */
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen rset.chroot_dir = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (disallow_root &&
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0))) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen *error_r = "Mail access not allowed for root";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen if (keep_setuid_root) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (current_euid != rset.uid) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (current_euid != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we're changing the UID,
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen switch back to root first */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (seteuid(0) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("seteuid(0) failed: %m");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen setuid_uid = rset.uid;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rset.uid = (uid_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen disallow_root = FALSE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!setenv_only) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen restrict_access(&rset, *home == '\0' ? NULL : home,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen disallow_root);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } else {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen restrict_access_set_env(&rset);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen if (setuid_uid != 0 && !setenv_only) {
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen if (seteuid(setuid_uid) < 0)
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen i_fatal("seteuid(%s) failed: %m", dec2str(setuid_uid));
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen return 0;
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen}
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenstatic int
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainenmail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen struct mail_storage_service_user *user,
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen const char *home, struct mail_user **mail_user_r,
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen const char **error_r)
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen{
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen const struct mail_storage_settings *mail_set;
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen struct mail_user *mail_user;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen mail_user = mail_user_alloc(user->input.username, user->user_info,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen user->user_set);
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_user_set_vars(mail_user, geteuid(), ctx->service->name,
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen &user->input.local_ip, &user->input.remote_ip);
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen mail_set = mail_user_set_get_storage_set(mail_user);
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen if (mail_set->mail_debug) {
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen i_debug("Effective uid=%s, gid=%s, home=%s",
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen dec2str(geteuid()), dec2str(getegid()), home);
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen }
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) == 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* we don't want to write core files to any users' home
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen directories since they could contain information about other
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen users' mails as well. so do no chdiring to home. */
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen } else if (*home != '\0' &&
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen /* If possible chdir to home directory, so that core file
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen could be written in case we crash. */
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen if (chdir(home) < 0) {
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (errno == EACCES) {
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen i_error("%s", eacces_error_get("chdir",
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen t_strconcat(home, "/", NULL)));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } if (errno != ENOENT)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("chdir(%s) failed: %m", home);
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen else if (mail_set->mail_debug)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen i_debug("Home dir not found: %s", home);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen if (mail_user_init(mail_user, error_r) < 0) {
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen mail_user_unref(&mail_user);
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen return -1;
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen }
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES) == 0) {
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen if (mail_namespaces_init(mail_user, error_r) < 0) {
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen mail_user_unref(&mail_user);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
99e8698f598d2b83da7c581584a538c0713fd11dTimo Sirainen }
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen }
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen *mail_user_r = mail_user;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenstatic const struct var_expand_table *
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainenget_var_expand_table(struct master_service *service,
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen struct mail_storage_service_input *input)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen{
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen static struct var_expand_table static_tab[] = {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen { 'u', NULL, "user" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'n', NULL, "username" },
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen { 'd', NULL, "domain" },
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen { 's', NULL, "service" },
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen { 'l', NULL, "lip" },
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen { 'r', NULL, "rip" },
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen { 'p', NULL, "pid" },
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen { 'i', NULL, "uid" },
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen { '\0', NULL, NULL }
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen };
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen struct var_expand_table *tab;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen tab = t_malloc(sizeof(static_tab));
589a9c6e8ee22071c14171c04bfc6bfe17121871Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen tab[0].value = input->username;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen tab[1].value = t_strcut(input->username, '@');
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen tab[2].value = strchr(input->username, '@');
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen tab[3].value = service->name;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen tab[4].value = net_ip2addr(&input->local_ip);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen tab[5].value = net_ip2addr(&input->remote_ip);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen tab[6].value = my_pid;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen tab[7].value = dec2str(geteuid());
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen return tab;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainenstatic const char *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenuser_expand_varstr(struct master_service *service,
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen struct mail_storage_service_input *input, const char *str)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen{
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen string_t *ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*str == SETTING_STRVAR_EXPANDED[0])
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen return str + 1;
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen ret = t_str_new(256);
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen var_expand(ret, str + 1, get_var_expand_table(service, input));
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen return str_c(ret);
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen}
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainenstatic void
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainenmail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen struct mail_storage_service_user *user)
c2feb7d13482d0f60691cd71d06d42a80df99397Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->log_initialized = TRUE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen T_BEGIN {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen string_t *str;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen struct ioloop_log *log;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = t_str_new(256);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen var_expand(str, user->user_set->mail_log_prefix,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen get_var_expand_table(ctx->service, &user->input));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen master_service_init_log(ctx->service, str_c(str));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen log = io_loop_log_new(current_ioloop);
e670e1783fe4541dc3fc6109a181d45b0a9c2635Timo Sirainen io_loop_log_set_prefix(log, str_c(str));
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen io_loop_log_unref(&log);
e670e1783fe4541dc3fc6109a181d45b0a9c2635Timo Sirainen } T_END;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void mail_storage_service_time_moved(time_t old_time, time_t new_time)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen long diff = new_time - old_time;
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen if (diff > 0) {
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen if (diff > MAX_NOWARN_FORWARD_SECS)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_warning("Time jumped forwards %ld seconds", diff);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen diff = -diff;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (diff > MAX_TIME_BACKWARDS_SLEEP) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_fatal("Time just moved backwards by %ld seconds. "
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen "This might cause a lot of problems, "
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "so I'll just kill myself now. "
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen } else {
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen i_error("Time just moved backwards by %ld seconds. "
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen "I'll sleep now until we're back in present. "
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen /* Sleep extra second to make sure usecs also grows. */
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen diff++;
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen while (diff > 0 && sleep(diff) != 0) {
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen /* don't use sleep()'s return value, because
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen it could get us to a long loop in case
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen interrupts just keep coming */
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen diff = old_time - time(NULL) + 1;
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen }
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen }
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen}
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainenstruct mail_storage_service_ctx *
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainenmail_storage_service_init(struct master_service *service,
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen const struct setting_parser_info *set_roots[],
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen enum mail_storage_service_flags flags)
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen{
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen struct mail_storage_service_ctx *ctx;
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen pool_t pool;
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen unsigned int count;
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen (void)umask(0077);
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen io_loop_set_time_moved_callback(current_ioloop,
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen mail_storage_service_time_moved);
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen mail_storage_init();
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen mail_storage_register_all();
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen mailbox_list_register_all();
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen pool = pool_alloconly_create("mail storage service", 2048);
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen ctx = p_new(pool, struct mail_storage_service_ctx, 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ctx->pool = pool;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ctx->service = service;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ctx->flags = flags;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen /* @UNSAFE */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (set_roots == NULL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen count = 0;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen else
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen for (count = 0; set_roots[count] != NULL; count++) ;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen ctx->set_roots =
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen p_new(pool, const struct setting_parser_info *, count + 2);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ctx->set_roots[0] = &mail_user_setting_parser_info;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (set_roots != NULL) {
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen memcpy(ctx->set_roots + 1, set_roots,
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen sizeof(*ctx->set_roots) * count);
6143fece58262865ce89b5012b73ef08f2ad6abcTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* do all the global initialization. delay initializing plugins until
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen we drop privileges the first time. */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* note: we may not have read any settings yet, so this logging
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen may still be going to wrong location */
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen const char *log_prefix = t_strconcat(service->name, ": ", NULL);
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen
dec85d9856c33f427a06dda01e0e50de0bc8fa7dTimo Sirainen master_service_init_log(service, log_prefix);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen io_loop_set_default_log_prefix(current_ioloop, log_prefix);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen dict_drivers_register_builtin();
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return ctx;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstruct auth_master_connection *
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenmail_storage_service_get_auth_conn(struct mail_storage_service_ctx *ctx)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(ctx->conn != NULL);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return ctx->conn;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainenstatic enum mail_storage_service_flags
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainenmail_storage_service_input_get_flags(struct mail_storage_service_ctx *ctx,
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen const struct mail_storage_service_input *input)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen{
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen enum mail_storage_service_flags flags;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen flags = (ctx->flags & ~input->flags_override_remove) |
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen input->flags_override_add;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (input->no_userdb_lookup) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* FIXME: for API backwards compatibility only */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen flags &= ~MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_storage_service_read_settings(struct mail_storage_service_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_storage_service_input *input,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_t pool,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct setting_parser_info **user_info_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct setting_parser_context **parser_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct master_service_settings_input set_input;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct setting_parser_info *const *roots;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct master_service_settings_output set_output;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct dynamic_settings_parser *dyn_parsers;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_storage_service_flags flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen flags = input == NULL ? ctx->flags :
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_service_input_get_flags(ctx, input);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen memset(&set_input, 0, sizeof(set_input));
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen set_input.roots = ctx->set_roots;
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen set_input.preserve_user = TRUE;
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen /* settings reader may exec doveconf, which is going to clear
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen environment, and if we're not doing a userdb lookup we want to
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen use $HOME */
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen set_input.preserve_home =
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen set_input.use_sysexits =
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS) != 0;
2469ed8e17534f6cb5f41493df8c7e6f3b2c9b61Timo Sirainen
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen if (input != NULL) {
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen set_input.module = input->module;
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen set_input.service = input->service;
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen set_input.username = input->username;
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen set_input.local_ip = input->local_ip;
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen set_input.remote_ip = input->remote_ip;
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen }
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen if (ctx->set_cache == NULL) {
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen ctx->set_cache_module = p_strdup(ctx->pool, set_input.module);
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen ctx->set_cache_service = p_strdup(ctx->pool, set_input.service);
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen ctx->set_cache = master_service_settings_cache_init(
27db4ce5fe399c981e09dcf9e885a1546afd34f4Timo Sirainen ctx->service, set_input.module, set_input.service);
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen } else {
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen /* already looked up settings at least once.
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen we really shouldn't be execing anymore. */
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen set_input.never_exec = TRUE;
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen }
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen dyn_parsers = mail_storage_get_dynamic_parsers(pool);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (null_strcmp(set_input.module, ctx->set_cache_module) == 0 &&
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen null_strcmp(set_input.service, ctx->set_cache_service) == 0) {
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen if (master_service_settings_cache_read(ctx->set_cache,
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen &set_input, dyn_parsers,
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen parser_r, error_r) < 0) {
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen *error_r = t_strdup_printf(
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen "Error reading configuration: %s", *error_r);
902222fb0928d1701f20a384b73f327b1d9a15ddTimo Sirainen return -1;
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen }
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen } else {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen settings_parser_dyn_update(pool, &set_input.roots, dyn_parsers);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (master_service_settings_read(ctx->service, &set_input,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen &set_output, error_r) < 0) {
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen *error_r = t_strdup_printf(
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen "Error reading configuration: %s", *error_r);
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen return -1;
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen }
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen *parser_r = ctx->service->set_parser;
902222fb0928d1701f20a384b73f327b1d9a15ddTimo Sirainen }
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen roots = settings_parser_get_roots(*parser_r);
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen for (i = 0; roots[i] != NULL; i++) {
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen if (strcmp(roots[i]->module_name,
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen mail_user_setting_parser_info.module_name) == 0) {
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen *user_info_r = roots[i];
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen return 0;
bc1d1497d715cc5c820ff518f070f78c39ef6cdcTimo Sirainen }
bc1d1497d715cc5c820ff518f070f78c39ef6cdcTimo Sirainen }
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen i_unreached();
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen return -1;
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen}
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainenstatic void
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainenmail_storage_service_first_init(struct mail_storage_service_ctx *ctx,
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen const struct setting_parser_info *user_info,
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen const struct mail_user_settings *user_set)
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen{
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen enum auth_master_flags flags = 0;
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen i_assert(ctx->conn == NULL);
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen ctx->debug = mail_user_set_get_mail_debug(user_info, user_set);
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen if (ctx->debug)
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen flags |= AUTH_MASTER_FLAG_DEBUG;
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_IDLE_TIMEOUT) != 0)
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen flags |= AUTH_MASTER_FLAG_NO_IDLE_TIMEOUT;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen ctx->conn = auth_master_init(user_set->auth_socket_path, flags);
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen i_assert(mail_user_auth_master_conn == NULL);
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen mail_user_auth_master_conn = ctx->conn;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen}
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainenstatic void
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainenmail_storage_service_load_modules(struct mail_storage_service_ctx *ctx,
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen const struct setting_parser_info *user_info,
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen const struct mail_user_settings *user_set)
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen{
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen struct module_dir_load_settings mod_set;
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen if (*user_set->mail_plugins == '\0')
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen return;
1f80b32fc28f7a723ff07c1694230a090808b506Timo Sirainen if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(&mod_set, 0, sizeof(mod_set));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mod_set.version = master_service_get_version_string(ctx->service);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mod_set.binary_name = master_service_get_name(ctx->service);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mod_set.setting_name = "mail_plugins";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mod_set.require_init_funcs = TRUE;
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen mod_set.debug = mail_user_set_get_mail_debug(user_info, user_set);
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_service_modules =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen module_dir_load_missing(mail_storage_service_modules,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user_set->mail_plugin_dir,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user_set->mail_plugins, &mod_set);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_storage_service_lookup(struct mail_storage_service_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_storage_service_input *input,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage_service_user **user_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_storage_service_flags flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage_service_user *user;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *username = input->username;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct setting_parser_info *user_info;
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen const struct mail_user_settings *user_set;
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen const char *const *userdb_fields, *error;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_user_reply reply;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct setting_parser_context *set_parser;
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen pool_t user_pool, temp_pool;
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen int ret = 1;
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen user_pool = pool_alloconly_create("mail storage service user", 1024*5);
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen if (mail_storage_service_read_settings(ctx, input, user_pool,
1dd875d96ab5640f78250079961c10e99ed4aa79Timo Sirainen &user_info, &set_parser,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &error) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("user %s: %s", username, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(&user_pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = MAIL_ERRSTR_CRITICAL_MSG;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen flags = mail_storage_service_input_get_flags(ctx, input);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen !ctx->log_initialized) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* initialize logging again, in case we only read the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen settings for the first above */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->log_initialized = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen master_service_init_log(ctx->service,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_strconcat(ctx->service->name, ": ", NULL));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user_set = settings_parser_get_list(set_parser)[1];
if (ctx->conn == NULL)
mail_storage_service_first_init(ctx, user_info, user_set);
/* load global plugins */
mail_storage_service_load_modules(ctx, user_info, user_set);
temp_pool = pool_alloconly_create("userdb lookup", 2048);
if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
ret = service_auth_userdb_lookup(ctx, input, temp_pool,
&username, &userdb_fields,
error_r);
if (ret <= 0) {
pool_unref(&temp_pool);
pool_unref(&user_pool);
return ret;
}
} else {
userdb_fields = input->userdb_fields;
}
user = p_new(user_pool, struct mail_storage_service_user, 1);
memset(user_r, 0, sizeof(user_r));
user->pool = user_pool;
user->input = *input;
user->input.userdb_fields = NULL;
user->input.username = p_strdup(user_pool, username);
user->user_info = user_info;
user->flags = flags;
user->set_parser = settings_parser_dup(set_parser, user_pool);
if (!settings_parser_check(user->set_parser, user_pool, &error))
i_panic("settings_parser_check() failed: %s", error);
user->user_set = settings_parser_get_list(user->set_parser)[1];
user->gid_source = "mail_gid setting";
user->uid_source = "mail_uid setting";
if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
(void)settings_parse_line(user->set_parser, "mail_debug=yes");
if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0) {
const char *home = getenv("HOME");
if (home != NULL)
set_keyval(ctx, user, "mail_home", home);
}
if (userdb_fields != NULL) {
auth_user_fields_parse(userdb_fields, temp_pool, &reply);
if (user_reply_handle(ctx, user, &reply, &error) < 0) {
i_error("user %s: Invalid settings in userdb: %s",
username, error);
*error_r = ERRSTR_INVALID_USER_SETTINGS;
ret = -2;
}
}
pool_unref(&temp_pool);
/* load per-user plugins */
if (ret > 0) {
mail_storage_service_load_modules(ctx, user_info,
user->user_set);
}
*user_r = user;
return ret;
}
int mail_storage_service_next(struct mail_storage_service_ctx *ctx,
struct mail_storage_service_user *user,
struct mail_user **mail_user_r)
{
const struct mail_user_settings *user_set = user->user_set;
const char *home, *chroot, *error;
unsigned int len;
bool disallow_root =
(user->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0;
bool temp_priv_drop =
(user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0;
/* variable strings are expanded in mail_user_init(),
but we need the home and chroot sooner so do them separately here. */
home = user_expand_varstr(ctx->service, &user->input,
user_set->mail_home);
chroot = user_expand_varstr(ctx->service, &user->input,
user_set->mail_chroot);
if (*home != '/' && *home != '\0') {
i_error("user %s: "
"Relative home directory paths not supported: %s",
user->input.username, home);
return -2;
}
len = strlen(chroot);
if (len > 2 && strcmp(chroot + len - 2, "/.") == 0 &&
strncmp(home, chroot, len - 2) == 0) {
/* mail_chroot = /chroot/. means that the home dir already
contains the chroot dir. remove it from home. */
if (!temp_priv_drop) {
home += len - 2;
if (*home == '\0')
home = "/";
chroot = t_strndup(chroot, len - 2);
set_keyval(ctx, user, "mail_home", home);
set_keyval(ctx, user, "mail_chroot", chroot);
}
} else if (len > 0 && temp_priv_drop) {
/* we're dropping privileges only temporarily, so we can't
chroot. fix home directory so we can access it. */
if (*home == '\0' || strcmp(home, "/") == 0)
home = chroot;
else
home = t_strconcat(chroot, home, NULL);
chroot = "";
set_keyval(ctx, user, "mail_home", home);
}
if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0)
mail_storage_service_init_log(ctx, user);
if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
if (service_drop_privileges(user, user_set, home, chroot,
disallow_root, temp_priv_drop,
FALSE, &error) < 0) {
i_error("user %s: Couldn't drop privileges: %s",
user->input.username, error);
return -1;
}
if (!temp_priv_drop ||
(user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) != 0)
restrict_access_allow_coredumps(TRUE);
}
/* privileges are dropped. initialize plugins that haven't been
initialized yet. */
module_dir_init(mail_storage_service_modules);
if (mail_storage_service_init_post(ctx, user, home,
mail_user_r, &error) < 0) {
i_error("user %s: Initialization failed: %s",
user->input.username, error);
return -2;
}
return 0;
}
void mail_storage_service_restrict_setenv(struct mail_storage_service_ctx *ctx,
struct mail_storage_service_user *user)
{
const struct mail_user_settings *user_set = user->user_set;
const char *home, *chroot, *error;
home = user_expand_varstr(ctx->service, &user->input,
user_set->mail_home);
chroot = user_expand_varstr(ctx->service, &user->input,
user_set->mail_chroot);
if (service_drop_privileges(user, user_set, home, chroot,
FALSE, FALSE, TRUE,
&error) < 0)
i_fatal("%s", error);
}
int mail_storage_service_lookup_next(struct mail_storage_service_ctx *ctx,
const struct mail_storage_service_input *input,
struct mail_storage_service_user **user_r,
struct mail_user **mail_user_r,
const char **error_r)
{
struct mail_storage_service_user *user;
int ret;
ret = mail_storage_service_lookup(ctx, input, &user, error_r);
if (ret <= 0)
return ret;
ret = mail_storage_service_next(ctx, user, mail_user_r);
if (ret < 0) {
mail_storage_service_user_free(&user);
*error_r = ret == -2 ? ERRSTR_INVALID_USER_SETTINGS :
MAIL_ERRSTR_CRITICAL_MSG;
return ret;
}
*user_r = user;
return 1;
}
void mail_storage_service_user_free(struct mail_storage_service_user **_user)
{
struct mail_storage_service_user *user = *_user;
*_user = NULL;
settings_parser_deinit(&user->set_parser);
pool_unref(&user->pool);
}
void mail_storage_service_init_settings(struct mail_storage_service_ctx *ctx,
const struct mail_storage_service_input *input)
{
const struct setting_parser_info *user_info;
const struct mail_user_settings *user_set;
const struct setting_parser_context *set_parser;
const char *error;
pool_t temp_pool;
if (ctx->conn != NULL)
return;
temp_pool = pool_alloconly_create("service all settings", 4096);
if (mail_storage_service_read_settings(ctx, input, temp_pool,
&user_info, &set_parser,
&error) < 0)
i_fatal("%s", error);
user_set = settings_parser_get_list(set_parser)[1];
mail_storage_service_first_init(ctx, user_info, user_set);
pool_unref(&temp_pool);
}
unsigned int
mail_storage_service_all_init(struct mail_storage_service_ctx *ctx)
{
if (ctx->auth_list != NULL)
(void)auth_master_user_list_deinit(&ctx->auth_list);
mail_storage_service_init_settings(ctx, NULL);
ctx->auth_list = auth_master_user_list_init(ctx->conn);
return auth_master_user_list_count(ctx->auth_list);
}
int mail_storage_service_all_next(struct mail_storage_service_ctx *ctx,
const char **username_r)
{
i_assert((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0);
*username_r = auth_master_user_list_next(ctx->auth_list);
if (*username_r != NULL)
return 1;
return auth_master_user_list_deinit(&ctx->auth_list);
}
void mail_storage_service_deinit(struct mail_storage_service_ctx **_ctx)
{
struct mail_storage_service_ctx *ctx = *_ctx;
*_ctx = NULL;
if (ctx->auth_list != NULL)
(void)auth_master_user_list_deinit(&ctx->auth_list);
if (ctx->conn != NULL) {
if (mail_user_auth_master_conn == ctx->conn)
mail_user_auth_master_conn = NULL;
auth_master_deinit(&ctx->conn);
}
if (ctx->set_cache != NULL)
master_service_settings_cache_deinit(&ctx->set_cache);
pool_unref(&ctx->pool);
module_dir_unload(&mail_storage_service_modules);
mail_storage_deinit();
dict_drivers_unregister_builtin();
}
void **mail_storage_service_user_get_set(struct mail_storage_service_user *user)
{
return settings_parser_get_list(user->set_parser) + 1;
}
const struct mail_storage_service_input *
mail_storage_service_user_get_input(struct mail_storage_service_user *user)
{
return &user->input;
}
struct setting_parser_context *
mail_storage_service_user_get_settings_parser(struct mail_storage_service_user *user)
{
return user->set_parser;
}
void *mail_storage_service_get_settings(struct master_service *service)
{
void **sets, *set;
T_BEGIN {
sets = master_service_settings_get_others(service);
set = sets[1];
} T_END;
return set;
}