mail-storage-service.c revision 18c209a06941ef583b08b173dadfbe4571995bf9
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
80c1d98d3638b71e57a39cafa88b9122bf8169c6Timo Sirainen#include "ioloop.h"
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen#include "array.h"
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen#include "hostpid.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "module-dir.h"
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen#include "restrict-access.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include "var-expand.h"
795aeec896095aa8f08cc5d3282c88cc0921bff6Timo Sirainen#include "dict.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "settings-parser.h"
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#include "auth-master.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service-settings.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-user.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-namespace.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "mail-storage-service.h"
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen#include <stdlib.h>
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen#include <sys/stat.h>
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen#include <pwd.h>
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen#include <grp.h>
589a9c6e8ee22071c14171c04bfc6bfe17121871Timo Sirainen
589a9c6e8ee22071c14171c04bfc6bfe17121871Timo Sirainen/* If time moves backwards more than this, kill ourself instead of sleeping. */
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen#define MAX_TIME_BACKWARDS_SLEEP 5
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen#define MAX_NOWARN_FORWARD_SECS 10
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen
18d92dbbb752c79dc461514e52f7ef11847e636bTimo Sirainenstruct mail_storage_service_multi_ctx {
18d92dbbb752c79dc461514e52f7ef11847e636bTimo Sirainen struct master_service *service;
18d92dbbb752c79dc461514e52f7ef11847e636bTimo Sirainen struct auth_master_connection *conn;
18d92dbbb752c79dc461514e52f7ef11847e636bTimo Sirainen struct auth_master_user_list_ctx *auth_list;
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen enum mail_storage_service_flags flags;
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int modules_initialized:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_storage_service_multi_user {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_t pool;
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen struct mail_storage_service_input input;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen
6ec7cf71ccd0eed1f9cc1b0bda8960796b04160bTimo Sirainen const char *system_groups_user;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_user_settings *user_set;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct setting_parser_context *set_parser;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen};
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic struct module *modules = NULL;
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic void set_keyval(struct setting_parser_context *set_parser,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen const char *key, const char *value)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = t_strconcat(key, "=", value, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (settings_parse_line(set_parser, str) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("Invalid userdb input '%s': %s", str,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen settings_parser_get_error(set_parser));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool validate_chroot(const struct mail_user_settings *user_set,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *dir)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen{
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen const char *const *chroot_dirs;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (*dir == '\0')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen if (*user_set->valid_chroot_dirs == '\0')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (*chroot_dirs != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (**chroot_dirs != '\0' &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen chroot_dirs++;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainenstatic int
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainenuser_reply_handle(struct setting_parser_context *set_parser,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_user_settings *user_set,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct auth_user_reply *reply,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **system_groups_user_r, const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen const char *const *str, *p, *line, *key;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen unsigned int i, count;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen int ret = 0;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *system_groups_user_r = NULL;
b84451fa6ada675ae504725702e0815967124cbbTimo Sirainen
b84451fa6ada675ae504725702e0815967124cbbTimo Sirainen if (reply->uid != (uid_t)-1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (reply->uid == 0) {
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen *error_r = "userdb returned 0 as uid";
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return -1;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen set_keyval(set_parser, "mail_uid", dec2str(reply->uid));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (reply->gid != (uid_t)-1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen set_keyval(set_parser, "mail_gid", dec2str(reply->gid));
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (reply->home != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen set_keyval(set_parser, "mail_home", reply->home);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (reply->chroot != NULL) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (!validate_chroot(user_set, reply->chroot)) {
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen *error_r = t_strdup_printf(
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen "userdb returned invalid chroot directory: %s "
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen "(see valid_chroot_dirs setting)",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen reply->chroot);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return -1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen set_keyval(set_parser, "mail_chroot", reply->chroot);
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen }
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen str = array_get(&reply->extra_fields, &count);
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen for (i = 0; i < count && ret == 0; i++) {
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen line = str[i];
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen if (strncmp(line, "system_groups_user=", 19) == 0)
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen *system_groups_user_r = line + 19;
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen else T_BEGIN {
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen if (strncmp(line, "mail=", 5) == 0) {
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen line = t_strconcat("mail_location=",
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen line + 5, NULL);
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen } else if ((p = strchr(str[i], '=')) == NULL)
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen line = t_strconcat(str[i], "=yes", NULL);
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen else
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen line = str[i];
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen key = t_strcut(line, '=');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!settings_parse_is_valid_key(set_parser, key)) {
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen /* assume it's a plugin setting */
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen line = t_strconcat("plugin/", line, NULL);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen }
250105a1440167ef000323cdb2721cd2a3688e1eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = settings_parse_line(set_parser, line);
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen } T_END;
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen }
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen if (ret < 0) {
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen str[i], settings_parser_get_error(set_parser));
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen }
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen return ret;
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen}
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainenstatic int
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainenservice_auth_userdb_lookup(struct auth_master_connection *conn,
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen struct setting_parser_context *set_parser,
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen const char *service_name,
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen const struct mail_storage_service_input *input,
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen const struct mail_user_settings *user_set,
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen const char **user, const char **system_groups_user_r,
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen const char **error_r)
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen{
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen struct auth_user_info info;
cfbacf6ea5fb39ae5304e4d95a78d9d4751bdfe1Timo Sirainen struct auth_user_reply reply;
dc912088f84c263db1609435c2f5d7cb29bf1a33Timo Sirainen const char *system_groups_user, *orig_user = *user;
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen unsigned int len;
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen pool_t pool;
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen int ret;
7761758f43d6150be4b07f4c54457ce662f78c4cTimo Sirainen
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen memset(&info, 0, sizeof(info));
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen info.service = service_name;
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen info.local_ip = input->local_ip;
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen info.remote_ip = input->remote_ip;
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen pool = pool_alloconly_create("userdb lookup", 1024);
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen ret = auth_master_user_lookup(conn, *user, &info, pool, &reply);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen len = reply.chroot == NULL ? 0 : strlen(reply.chroot);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *user = t_strdup(reply.user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (user_reply_handle(set_parser, user_set, &reply,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &system_groups_user, error_r) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *system_groups_user_r = t_strdup(system_groups_user);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen } else {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ret == 0)
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen *error_r = "unknown user";
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen else
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen *error_r = "userdb lookup failed";
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen *system_groups_user_r = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen if (ret > 0 && strcmp(*user, orig_user) != 0) {
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen if (mail_user_set_get_storage_set(user_set)->mail_debug)
e68fc7dc8c8a75842f1e39deb49d196d1cfdb3b3Timo Sirainen i_info("changed username to %s", *user);
e68fc7dc8c8a75842f1e39deb49d196d1cfdb3b3Timo Sirainen }
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen pool_unref(&pool);
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen return ret;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen}
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainenstatic bool parse_uid(const char *str, uid_t *uid_r)
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen{
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen struct passwd *pw;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen char *p;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (*str >= '0' && *str <= '9') {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen *uid_r = (uid_t)strtoul(str, &p, 10);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (*p == '\0')
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return TRUE;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen pw = getpwnam(str);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (pw == NULL)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return FALSE;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen *uid_r = pw->pw_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool parse_gid(const char *str, gid_t *gid_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct group *gr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *p;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (*str >= '0' && *str <= '9') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *gid_r = (gid_t)strtoul(str, &p, 10);
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen if (*p == '\0')
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen return TRUE;
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen }
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen gr = getgrnam(str);
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen if (gr == NULL)
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen return FALSE;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen *gid_r = gr->gr_gid;
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen return TRUE;
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen}
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainenstatic void
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainenservice_drop_privileges(const struct mail_user_settings *set,
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen const char *system_groups_user, const char *home,
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen bool disallow_root, bool keep_setuid_root)
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen{
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen struct restrict_access_settings rset;
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen uid_t current_euid, setuid_uid = 0;
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen current_euid = geteuid();
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen restrict_access_init(&rset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*set->mail_uid != '\0') {
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen if (!parse_uid(set->mail_uid, &rset.uid))
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen i_fatal("Unknown mail_uid user: %s", set->mail_uid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (rset.uid < (uid_t)set->first_valid_uid ||
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen (set->last_valid_uid != 0 &&
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen rset.uid > (uid_t)set->last_valid_uid)) {
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen i_fatal("Mail access for users with UID %s "
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen "not permitted (see first_valid_uid in config file).",
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen dec2str(rset.uid));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (*set->mail_gid != '\0') {
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (!parse_gid(set->mail_gid, &rset.gid))
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen i_fatal("Unknown mail_gid group: %s", set->mail_gid);
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen if (rset.gid < (gid_t)set->first_valid_gid ||
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen (set->last_valid_gid != 0 &&
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen rset.gid > (gid_t)set->last_valid_gid)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("Mail access for users with GID %s "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "not permitted (see first_valid_gid in config file).",
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen dec2str(rset.gid));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*set->mail_privileged_group != '\0') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!parse_uid(set->mail_privileged_group, &rset.privileged_gid))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("Unknown mail_gid group: %s", set->mail_gid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen if (*set->mail_access_groups != '\0')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rset.extra_groups = set->mail_access_groups;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen rset.first_valid_gid = set->first_valid_gid;
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen rset.last_valid_gid = set->last_valid_gid;
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen /* we can't chroot if we want to switch between users. there's not
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen much point either (from security point of view) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rset.chroot_dir = *set->mail_chroot == '\0' || keep_setuid_root ?
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen NULL : set->mail_chroot;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen rset.system_groups_user = system_groups_user;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (disallow_root &&
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0)))
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen i_fatal("Mail access not allowed for root");
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (keep_setuid_root) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (current_euid != rset.uid) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (current_euid != 0) {
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen /* we're changing the UID,
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen switch back to root first */
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen if (seteuid(0) < 0)
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen i_fatal("seteuid(0) failed: %m");
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen }
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen setuid_uid = rset.uid;
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen }
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen rset.uid = (uid_t)-1;
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen disallow_root = FALSE;
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen }
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen restrict_access(&rset, *home == '\0' ? NULL : home, disallow_root);
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen if (setuid_uid != 0) {
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen if (seteuid(setuid_uid) < 0)
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen i_fatal("seteuid(%s) failed: %m", dec2str(setuid_uid));
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (rset.chroot_dir == NULL) {
97735b96d442568f65efa20f8c292a496498c17bTimo Sirainen /* enable core dumps only when we can be sure that the core
97735b96d442568f65efa20f8c292a496498c17bTimo Sirainen file is written to a safe directory. with chrooting we're
97735b96d442568f65efa20f8c292a496498c17bTimo Sirainen chrooting to user's home dir. */
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen restrict_access_allow_coredumps(TRUE);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen }
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen}
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainenstatic void
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainenmail_storage_service_init_settings(struct master_service *service,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_storage_service_input *input,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct setting_parser_info *set_roots[],
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool preserve_home)
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen{
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen ARRAY_DEFINE(all_set_roots, const struct setting_parser_info *);
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen const struct setting_parser_info *info = &mail_user_setting_parser_info;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct master_service_settings_input set_input;
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen const char *error;
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen (void)umask(0077);
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen mail_storage_init();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_register_all();
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen mailbox_list_register_all();
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen t_array_init(&all_set_roots, 5);
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen array_append(&all_set_roots, &info, 1);
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen if (set_roots != NULL) {
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen for (i = 0; set_roots[i] != NULL; i++)
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen array_append(&all_set_roots, &set_roots[i], 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)array_append_space(&all_set_roots);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen /* read settings after registering storages so they can have their
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen own setting definitions too */
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen memset(&set_input, 0, sizeof(set_input));
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen set_input.roots = array_idx_modifiable(&all_set_roots, 0);
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen set_input.dyn_parsers = mail_storage_get_dynamic_parsers();
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen set_input.preserve_home = preserve_home;
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen if (input != NULL) {
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen set_input.module = input->module;
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen set_input.service = input->service;
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen set_input.username = input->username;
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen set_input.local_ip = input->local_ip;
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen set_input.remote_ip = input->remote_ip;
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen }
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen if (master_service_settings_read(service, &set_input, &error) < 0)
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen i_fatal("Error reading configuration: %s", error);
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen}
079f54c97145a0a5daa36c37eead3eae91b67a1eTimo Sirainen
079f54c97145a0a5daa36c37eead3eae91b67a1eTimo Sirainenstatic int
079f54c97145a0a5daa36c37eead3eae91b67a1eTimo Sirainenmail_storage_service_init_post(struct master_service *service,
079f54c97145a0a5daa36c37eead3eae91b67a1eTimo Sirainen const struct mail_storage_service_input *input,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *home,
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen const struct mail_user_settings *user_set,
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen bool setuid_root,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen enum mail_storage_service_flags flags,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen struct mail_user **mail_user_r,
3955d6726c939b3b30527c22b70c879fbe78692eTimo Sirainen const char **error_r)
3955d6726c939b3b30527c22b70c879fbe78692eTimo Sirainen{
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen const struct mail_storage_settings *mail_set;
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen struct mail_user *mail_user;
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen mail_set = mail_user_set_get_storage_set(user_set);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (mail_set->mail_debug) {
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen i_info("Effective uid=%s, gid=%s, home=%s",
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen dec2str(geteuid()), dec2str(getegid()),
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen home != NULL ? home : "(none)");
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (setuid_root) {
685393de106e55b61f754d420e378d05bd462ebbTimo Sirainen /* we don't want to write core files to any users' home
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen directories since they could contain information about other
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen users' mails as well. so do no chdiring to home. */
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen } else if (*home != '\0' &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
8a3f549a3cb1d6dd980a4fa3db284653e256dae7Timo Sirainen /* If possible chdir to home directory, so that core file
8a3f549a3cb1d6dd980a4fa3db284653e256dae7Timo Sirainen could be written in case we crash. */
8a3f549a3cb1d6dd980a4fa3db284653e256dae7Timo Sirainen if (chdir(home) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (errno != ENOENT)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("chdir(%s) failed: %m", home);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (mail_set->mail_debug)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_info("Home dir not found: %s", home);
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen }
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen }
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen mail_user = mail_user_alloc(input->username, user_set);
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen mail_user_set_vars(mail_user, geteuid(), service->name,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &input->local_ip, &input->remote_ip);
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen if (mail_user_init(mail_user, error_r) < 0) {
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen mail_user_unref(&mail_user);
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_namespaces_init(mail_user, error_r) < 0) {
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen mail_user_unref(&mail_user);
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen return -1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen *mail_user_r = mail_user;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return 0;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic const struct var_expand_table *
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenget_var_expand_table(struct master_service *service,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct mail_storage_service_input *input)
bb26f09873c18f342cd1ab2d0ee0b9018e6546d9Timo Sirainen{
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen static struct var_expand_table static_tab[] = {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen { 'u', NULL, "user" },
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen { 'n', NULL, "username" },
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen { 'd', NULL, "domain" },
c4db5f0fb7cea8160dc10b5f0ab57ab7c02bf8a5Timo Sirainen { 's', NULL, "service" },
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen { 'l', NULL, "lip" },
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen { 'r', NULL, "rip" },
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen { 'p', NULL, "pid" },
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen { 'i', NULL, "uid" },
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen { '\0', NULL, NULL }
dd9712b013e5a14939deed84b2e391d89897d2cfTimo Sirainen };
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct var_expand_table *tab;
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen tab = t_malloc(sizeof(static_tab));
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen tab[0].value = input->username;
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen tab[1].value = t_strcut(input->username, '@');
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen tab[2].value = strchr(input->username, '@');
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen tab[3].value = service->name;
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen tab[4].value = net_ip2addr(&input->local_ip);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen tab[5].value = net_ip2addr(&input->remote_ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[6].value = my_pid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[7].value = dec2str(geteuid());
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return tab;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen}
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic const char *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenuser_expand_varstr(struct master_service *service,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage_service_input *input, const char *str)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d48860922190d08427ceaf30475994017ef09e2bTimo Sirainen string_t *ret;
d48860922190d08427ceaf30475994017ef09e2bTimo Sirainen
d48860922190d08427ceaf30475994017ef09e2bTimo Sirainen if (*str == SETTING_STRVAR_EXPANDED[0])
d48860922190d08427ceaf30475994017ef09e2bTimo Sirainen return str + 1;
d48860922190d08427ceaf30475994017ef09e2bTimo Sirainen
8cf32443413f811d514123c5c74c95c87594b0e3Timo Sirainen i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
8cf32443413f811d514123c5c74c95c87594b0e3Timo Sirainen
8cf32443413f811d514123c5c74c95c87594b0e3Timo Sirainen ret = t_str_new(256);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen var_expand(ret, str + 1, get_var_expand_table(service, input));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return str_c(ret);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic void
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainenmail_storage_service_init_log(struct master_service *service,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage_service_input *input)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_user_settings *user_set;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen void **sets;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen sets = master_service_settings_get_others(service);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen user_set = sets[0];
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen T_BEGIN {
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen string_t *str;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen str = t_str_new(256);
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen var_expand(str, user_set->mail_log_prefix,
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen get_var_expand_table(service, input));
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen master_service_init_log(service, str_c(str));
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen } T_END;
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenstatic void mail_storage_service_time_moved(time_t old_time, time_t new_time)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen{
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen long diff = new_time - old_time;
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen if (diff > 0) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (diff > MAX_NOWARN_FORWARD_SECS)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_warning("Time jumped forwards %ld seconds", diff);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return;
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen }
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen diff = -diff;
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (diff > MAX_TIME_BACKWARDS_SLEEP) {
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen i_fatal("Time just moved backwards by %ld seconds. "
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen "This might cause a lot of problems, "
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen "so I'll just kill myself now. "
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen "http://wiki.dovecot.org/TimeMovedBackwards", diff);
6c2ddb9f586e6392552ddfb82ab55e57fcfc4110Timo Sirainen } else {
6c2ddb9f586e6392552ddfb82ab55e57fcfc4110Timo Sirainen i_error("Time just moved backwards by %ld seconds. "
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen "I'll sleep now until we're back in present. "
6825360d446542046757b06064282301c4c6b27cTimo Sirainen "http://wiki.dovecot.org/TimeMovedBackwards", diff);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* Sleep extra second to make sure usecs also grows. */
6825360d446542046757b06064282301c4c6b27cTimo Sirainen diff++;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainen while (diff > 0 && sleep(diff) != 0) {
6825360d446542046757b06064282301c4c6b27cTimo Sirainen /* don't use sleep()'s return value, because
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen it could get us to a long loop in case
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen interrupts just keep coming */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen diff = old_time - time(NULL) + 1;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic struct mail_user *
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Siraineninit_user_real(struct master_service *service,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen const struct mail_storage_service_input *_input,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const struct setting_parser_info *set_roots[],
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen enum mail_storage_service_flags flags)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen{
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen struct mail_storage_service_input input = *_input;
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen const struct master_service_settings *set;
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen const struct mail_user_settings *user_set;
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen const struct mail_storage_settings *mail_set;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct mail_user *mail_user;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct auth_master_connection *conn;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen void **sets;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen const char *user, *orig_user, *home, *system_groups_user, *error;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen unsigned int len;
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen bool userdb_lookup;
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen io_loop_set_time_moved_callback(current_ioloop,
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen mail_storage_service_time_moved);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen master_service_init_finish(service);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen userdb_lookup = (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_service_init_settings(service, &input, set_roots,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen !userdb_lookup);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen set_keyval(service->set_parser, "mail_debug", "yes");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_storage_service_init_log(service, &input);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen set = master_service_settings_get(service);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen sets = master_service_settings_get_others(service);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen user_set = sets[0];
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_set = mail_user_set_get_storage_set(user_set);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (userdb_lookup) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* userdb lookup may change settings, do it as soon as
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen possible. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen orig_user = user = input.username;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen conn = auth_master_init(user_set->auth_socket_path,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen mail_set->mail_debug);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (service_auth_userdb_lookup(conn, service->set_parser,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen service->name, &input,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen user_set, &user,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen &system_groups_user,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen &error) <= 0)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_fatal("%s", error);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen auth_master_deinit(&conn);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen input.username = user;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* set up logging again in case username changed */
c7fc0431b23dc8d29e12e09c8120e223fbee116bTimo Sirainen mail_storage_service_init_log(service, &input);
c7fc0431b23dc8d29e12e09c8120e223fbee116bTimo Sirainen }
c7fc0431b23dc8d29e12e09c8120e223fbee116bTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* variable strings are expanded in mail_user_init(),
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen but we need the home sooner so do it separately here. */
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen home = user_expand_varstr(service, &input, user_set->mail_home);
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen if (!userdb_lookup) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen system_groups_user = NULL;
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen if (*home == '\0' && getenv("HOME") != NULL) {
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen home = getenv("HOME");
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen set_keyval(service->set_parser, "mail_home", home);
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen }
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen }
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen len = strlen(user_set->mail_chroot);
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen strncmp(home, user_set->mail_chroot, len - 2) == 0) {
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen /* If chroot ends with "/.", strip chroot dir from home dir */
893e5bbd5184ec5c21f47c67c8ea6efbea41f7d0Timo Sirainen home += len - 2;
893e5bbd5184ec5c21f47c67c8ea6efbea41f7d0Timo Sirainen set_keyval(service->set_parser, "mail_home", home);
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen }
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen
44c5e644cb413a6559bf2d4179cbe48f9a82f366Timo Sirainen modules = *user_set->mail_plugins == '\0' ? NULL :
5278c93bd7105c32ac7ec37f36015d5950f6cbcaTimo Sirainen module_dir_load(user_set->mail_plugin_dir,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen user_set->mail_plugins, TRUE,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen master_service_get_version_string(service));
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen service_drop_privileges(user_set, system_groups_user, home,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen FALSE);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* privileges are now dropped */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen dict_drivers_register_builtin();
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen module_dir_init(modules);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (mail_storage_service_init_post(service, &input, home, user_set,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen FALSE, flags,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen &mail_user, &error) < 0)
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen i_fatal("%s", error);
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen return mail_user;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen}
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstruct mail_user *
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenmail_storage_service_init_user(struct master_service *service,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const struct mail_storage_service_input *_input,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const struct setting_parser_info *set_roots[],
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen enum mail_storage_service_flags flags)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_user *user;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen T_BEGIN {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen user = init_user_real(service, _input, set_roots, flags);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen } T_END;
b7a5580abb62dd82e82e58ed81dcb307ed338144Timo Sirainen return user;
b7a5580abb62dd82e82e58ed81dcb307ed338144Timo Sirainen}
b7a5580abb62dd82e82e58ed81dcb307ed338144Timo Sirainen
b7a5580abb62dd82e82e58ed81dcb307ed338144Timo Sirainenvoid mail_storage_service_deinit_user(void)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen 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;
io_loop_set_time_moved_callback(current_ioloop,
mail_storage_service_time_moved);
master_service_init_finish(service);
ctx = i_new(struct mail_storage_service_multi_ctx, 1);
ctx->service = service;
ctx->flags = flags;
mail_storage_service_init_settings(service, NULL, set_roots, FALSE);
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);
/* do all the global initialization. delay initializing plugins until
we drop privileges the first time. */
master_service_init_log(service, t_strconcat(service->name, ": ", NULL));
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 ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
ctx->conn = auth_master_init(user_set->auth_socket_path,
mail_set->mail_debug);
}
dict_drivers_register_builtin();
mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
return ctx;
}
struct auth_master_connection *
mail_storage_service_multi_get_auth_conn(struct mail_storage_service_multi_ctx *ctx)
{
return ctx->conn;
}
int mail_storage_service_multi_lookup(struct mail_storage_service_multi_ctx *ctx,
const struct mail_storage_service_input *input,
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, *username;
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->input = *input;
user->input.username = p_strdup(pool, input->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 = username = user->input.username;
ret = service_auth_userdb_lookup(ctx->conn, user->set_parser,
ctx->service->name, input,
user->user_set, &username,
&user->system_groups_user,
error_r);
if (ret <= 0)
return ret;
user->input.username = p_strdup(pool, username);
}
*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->input,
user_set->mail_home);
mail_storage_service_init_log(ctx->service, &user->input);
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->input,
home, user_set, TRUE, ctx->flags,
mail_user_r, error_r) < 0)
return -1;
return 0;
}
void mail_storage_service_multi_user_free(struct mail_storage_service_multi_user *user)
{
settings_parser_deinit(&user->set_parser);
}
unsigned int
mail_storage_service_multi_all_init(struct mail_storage_service_multi_ctx *ctx)
{
if (ctx->auth_list != NULL)
(void)auth_master_user_list_deinit(&ctx->auth_list);
ctx->auth_list = auth_master_user_list_init(ctx->conn);
return auth_master_user_list_count(ctx->auth_list);
}
int mail_storage_service_multi_all_next(struct mail_storage_service_multi_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_multi_deinit(struct mail_storage_service_multi_ctx **_ctx)
{
struct mail_storage_service_multi_ctx *ctx = *_ctx;
*_ctx = NULL;
if (ctx->auth_list != NULL)
(void)auth_master_user_list_deinit(&ctx->auth_list);
if (ctx->conn != NULL)
auth_master_deinit(&ctx->conn);
i_free(ctx);
mail_storage_service_deinit_user();
}
void *mail_storage_service_multi_user_get_set(struct mail_storage_service_multi_user *user)
{
return settings_parser_get_list(user->set_parser) + 1;
}
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;
}