mail-storage-service.c revision b9b841558c5f91db7f5fc71c0ac62aad1bbf6418
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2009-2011 Dovecot authors, see the included COPYING file */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen/* If time moves backwards more than this, kill ourself instead of sleeping. */
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen "Invalid user settings. Refer to server log for more information."
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *set_cache_module, *set_cache_service;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct master_service_settings_cache *set_cache;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *system_groups_user, *uid_source, *gid_source;
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainenstruct module *mail_storage_service_modules = NULL;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainenmail_user_set_get_mail_debug(const struct setting_parser_info *user_info,
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen mail_set = mail_user_set_get_driver_settings(user_info, user_set,
2f94ca6b0f70641fe31c8e1f93404ca0df8bb289Timo Sirainenstatic void set_keyval(struct mail_storage_service_ctx *ctx,
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen struct setting_parser_context *set_parser = user->set_parser;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen const char *str;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (master_service_set_has_config_override(ctx->service, key)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* this setting was already overridden with -o parameter */
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen if (mail_user_set_get_mail_debug(user->user_info,
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen i_debug("Ignoring overridden (-o) userdb setting: %s",
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen if (settings_parse_line(set_parser, str) < 0) {
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainenstatic int set_line(struct mail_storage_service_ctx *ctx,
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen struct setting_parser_context *set_parser = user->set_parser;
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen const char *key;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen mail_debug = mail_user_set_get_mail_debug(user->user_info,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (!settings_parse_is_valid_key(set_parser, key)) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* assume it's a plugin setting */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (master_service_set_has_config_override(ctx->service, key)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* this setting was already overridden with -o parameter */
7fe37c2b0e4cd2a39896ab16e47eb418a59e3934Timo Sirainen i_debug("Ignoring overridden (-o) userdb setting: %s",
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen "Unknown userdb setting: %s" :
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainenstatic bool validate_chroot(const struct mail_user_settings *user_set,
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen const char *dir)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen const char *const *chroot_dirs;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainenuser_reply_handle(struct mail_storage_service_ctx *ctx,
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen const char **error_r)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen unsigned int i, count;
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi set_keyval(ctx, user, "mail_uid", dec2str(reply->uid));
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen set_keyval(ctx, user, "mail_gid", dec2str(reply->gid));
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen /* wu-ftpd like <chroot>/./<home> - check only if there's even
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen a possibility of using them (non-empty valid_chroot_dirs) */
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen set_keyval(ctx, user, "mail_home", reply->home);
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen if (!validate_chroot(user->user_set, chroot)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "userdb returned invalid chroot directory: %s "
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen str = array_get(&reply->extra_fields, &count);
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen if (strncmp(line, "system_groups_user=", 19) == 0) {
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen if (n != 0) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen str[i], settings_parser_get_error(user->set_parser));
28bf8f762fcd21c57bf71822cf818447babce9a0Timo Sirainenservice_auth_userdb_lookup(struct mail_storage_service_ctx *ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_storage_service_input *input,
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen const char *const **fields_r,
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen const char **error_r)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen ret = auth_master_user_lookup(ctx->conn, *user, &info, pool,
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen i_debug("changed username to %s", new_username);
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi } else if (ret == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic bool parse_uid(const char *str, uid_t *uid_r, const char **error_r)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen *error_r = t_strdup_printf("getpwnam(%s) failed: %m", str);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen *error_r = t_strconcat("Unknown UNIX UID user: ", str, NULL);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainenstatic bool parse_gid(const char *str, gid_t *gid_r, const char **error_r)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen *error_r = t_strdup_printf("getgrnam(%s) failed: %m", str);
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen *error_r = t_strconcat("Unknown UNIX GID group: ", str, NULL);
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainenservice_drop_privileges(struct mail_storage_service_user *user,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen if (!parse_uid(set->mail_uid, &rset.uid, &error)) {
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen *error_r = t_strdup_printf("%s (from %s)", error,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen "Mail access for users with UID %s not permitted "
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen "(see first_valid_uid in config file, uid from %s).",
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen *error_r = "User is missing UID (see mail_uid setting)";
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen if (!parse_gid(set->mail_gid, &rset.gid, &error)) {
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen *error_r = t_strdup_printf("%s (from %s)", error,
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen "Mail access for users with GID %s not permitted "
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "(see first_valid_gid in config file, gid from %s).",
e52f55c08f6f1b4fbc5765bf6aa9c7daee0785c3Timo Sirainen } else if (rset.gid == (gid_t)-1 && disallow_root &&
e52f55c08f6f1b4fbc5765bf6aa9c7daee0785c3Timo Sirainen *error_r = "User is missing GID (see mail_gid setting)";
719abeb2088987f213a33a7dd1fe78958beaef03Timo Sirainen if (!parse_gid(set->mail_privileged_group, &rset.privileged_gid,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "%s (in mail_privileged_group setting)", error);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rset.extra_groups = t_strconcat(set->mail_access_groups, ",",
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen /* we can't chroot if we want to switch between users. there's not
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen much point either (from security point of view) */
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen rset.chroot_dir = *chroot == '\0' || keep_setuid_root ? NULL : chroot;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen rset.system_groups_user = user->system_groups_user;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen cur_chroot = restrict_access_get_current_chroot();
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen "can't un-chroot for this user";
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(rset.chroot_dir, cur_chroot) != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "Process is already chrooted to %s, "
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen /* chrooting to same directory where we're already chrooted */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0))) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *error_r = "Mail access not allowed for root";
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen /* we're changing the UID,
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen switch back to root first */
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen restrict_access(&rset, *home == '\0' ? NULL : home,
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen i_fatal("seteuid(%s) failed: %m", dec2str(setuid_uid));
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainenmail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen const char *home, struct mail_user **mail_user_r,
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen const char **error_r)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen mail_user = mail_user_alloc(user->input.username, user->user_info,
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen mail_user_set_vars(mail_user, geteuid(), ctx->service->name,
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen &user->input.local_ip, &user->input.remote_ip);
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen mail_set = mail_user_set_get_storage_set(mail_user);
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen dec2str(geteuid()), dec2str(getegid()), home);
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) == 0) {
d9515a2eaa94c8287188c38fc28028727671e729Timo Sirainen /* we don't want to write core files to any users' home
d9515a2eaa94c8287188c38fc28028727671e729Timo Sirainen directories since they could contain information about other
d9515a2eaa94c8287188c38fc28028727671e729Timo Sirainen users' mails as well. so do no chdiring to home. */
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen /* If possible chdir to home directory, so that core file
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen could be written in case we crash. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES) == 0) {
85b4143f07c504294dd4e5b168e9bfb293515c31Josef 'Jeff' Sipek if (mail_namespaces_init(mail_user, error_r) < 0) {
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainenstatic const struct var_expand_table *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenget_var_expand_table(struct master_service *service,
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen static struct var_expand_table static_tab[] = {
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen tab[1].value = t_strcut(input->username, '@');
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen tab[5].value = net_ip2addr(&input->remote_ip);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainenstatic const char *
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainenuser_expand_varstr(struct master_service *service,
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen struct mail_storage_service_input *input, const char *str)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen var_expand(ret, str + 1, get_var_expand_table(service, input));
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainenmail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen var_expand(str, user->user_set->mail_log_prefix,
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen get_var_expand_table(ctx->service, &user->input));
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen master_service_init_log(ctx->service, str_c(str));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void mail_storage_service_time_moved(time_t old_time, time_t new_time)
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen i_warning("Time jumped forwards %ld seconds", diff);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_fatal("Time just moved backwards by %ld seconds. "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "This might cause a lot of problems, "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "so I'll just kill myself now. "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("Time just moved backwards by %ld seconds. "
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen "I'll sleep now until we're back in present. "
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
28bf8f762fcd21c57bf71822cf818447babce9a0Timo Sirainen /* Sleep extra second to make sure usecs also grows. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* don't use sleep()'s return value, because
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen it could get us to a long loop in case
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen interrupts just keep coming */
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainenmail_storage_service_init(struct master_service *service,
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen const struct setting_parser_info *set_roots[],
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen unsigned int count;
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen io_loop_set_time_moved_callback(current_ioloop,
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen pool = pool_alloconly_create("mail storage service", 2048);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen ctx = p_new(pool, struct mail_storage_service_ctx, 1);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen /* @UNSAFE */
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen for (count = 0; set_roots[count] != NULL; count++) ;
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen p_new(pool, const struct setting_parser_info *, count + 2);
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen ctx->set_roots[0] = &mail_user_setting_parser_info;
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen /* do all the global initialization. delay initializing plugins until
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen we drop privileges the first time. */
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) {
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen /* note: we may not have read any settings yet, so this logging
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen may still be going to wrong location */
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen const char *log_prefix = t_strconcat(service->name, ": ", NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_loop_set_default_log_prefix(current_ioloop, log_prefix);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_storage_service_get_auth_conn(struct mail_storage_service_ctx *ctx)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_storage_service_input_get_flags(struct mail_storage_service_ctx *ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_storage_service_input *input)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen flags = (ctx->flags & ~input->flags_override_remove) |
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen /* FIXME: for API backwards compatibility only */
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen flags &= ~MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainenint mail_storage_service_read_settings(struct mail_storage_service_ctx *ctx,
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen const struct mail_storage_service_input *input,
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen const struct setting_parser_info **user_info_r,
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen const struct setting_parser_context **parser_r,
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen const char **error_r)
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen struct master_service_settings_input set_input;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct setting_parser_info *const *roots;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct master_service_settings_output set_output;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct dynamic_settings_parser *dyn_parsers;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen flags = mail_storage_service_input_get_flags(ctx, input);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* settings reader may exec doveconf, which is going to clear
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen environment, and if we're not doing a userdb lookup we want to
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS) != 0;
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen ctx->set_cache_module = p_strdup(ctx->pool, set_input.module);
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen ctx->set_cache_service = p_strdup(ctx->pool, set_input.service);
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen ctx->set_cache = master_service_settings_cache_init(
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen ctx->service, set_input.module, set_input.service);
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen /* already looked up settings at least once.
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen we really shouldn't be execing anymore. */
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen dyn_parsers = mail_storage_get_dynamic_parsers(pool);
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen if (null_strcmp(set_input.module, ctx->set_cache_module) == 0 &&
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen null_strcmp(set_input.service, ctx->set_cache_service) == 0) {
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen if (master_service_settings_cache_read(ctx->set_cache,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen settings_parser_dyn_update(pool, &set_input.roots, dyn_parsers);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (master_service_settings_read(ctx->service, &set_input,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_user_setting_parser_info.module_name) == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmail_storage_service_first_init(struct mail_storage_service_ctx *ctx,
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen ctx->debug = mail_user_set_get_mail_debug(user_info, user_set);
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_IDLE_TIMEOUT) != 0)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen ctx->conn = auth_master_init(user_set->auth_socket_path, flags);
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainenmail_storage_service_load_modules(struct mail_storage_service_ctx *ctx,
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS) != 0)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mod_set.version = master_service_get_version_string(ctx->service);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mod_set.binary_name = master_service_get_name(ctx->service);
57397188558fcd1a9e24dbbbd2952eac9c45c20dTimo Sirainen mod_set.debug = mail_user_set_get_mail_debug(user_info, user_set);
03baa1c4c51f7b08fb285e82b528fcb00ac09ebfTimo Sirainen module_dir_load_missing(mail_storage_service_modules,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenint mail_storage_service_lookup(struct mail_storage_service_ctx *ctx,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const struct mail_storage_service_input *input,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const char **error_r)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const struct setting_parser_context *set_parser;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen user_pool = pool_alloconly_create("mail storage service user", 1024*5);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (mail_storage_service_read_settings(ctx, input, user_pool,
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen flags = mail_storage_service_input_get_flags(ctx, input);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0 &&
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen /* initialize logging again, in case we only read the
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen settings for the first above */
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen user_set = settings_parser_get_list(set_parser)[1];
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen mail_storage_service_first_init(ctx, user_info, user_set);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen /* load global plugins */
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen mail_storage_service_load_modules(ctx, user_info, user_set);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen temp_pool = pool_alloconly_create("userdb lookup", 2048);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen ret = service_auth_userdb_lookup(ctx, input, temp_pool,
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen user = p_new(user_pool, struct mail_storage_service_user, 1);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen user->input.username = p_strdup(user_pool, username);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen user->set_parser = settings_parser_dup(set_parser, user_pool);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen if (!settings_parser_check(user->set_parser, user_pool, &error))
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen i_panic("settings_parser_check() failed: %s", error);
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen user->user_set = settings_parser_get_list(user->set_parser)[1];
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen (void)settings_parse_line(user->set_parser, "mail_debug=yes");
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0) {
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen auth_user_fields_parse(userdb_fields, temp_pool, &reply);
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen if (user_reply_handle(ctx, user, &reply, &error) < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("user %s: Invalid settings in userdb: %s",
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen /* load per-user plugins */
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen mail_storage_service_load_modules(ctx, user_info,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_storage_service_next(struct mail_storage_service_ctx *ctx,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen const struct mail_user_settings *user_set = user->user_set;
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen unsigned int len;
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0;
c668292359474a4aa8c608b30a858337fa3fc813Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0;
c668292359474a4aa8c608b30a858337fa3fc813Timo Sirainen /* variable strings are expanded in mail_user_init(),
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen but we need the home and chroot sooner so do them separately here. */
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen home = user_expand_varstr(ctx->service, &user->input,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen chroot = user_expand_varstr(ctx->service, &user->input,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen "Relative home directory paths not supported: %s",
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (len > 2 && strcmp(chroot + len - 2, "/.") == 0 &&
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* mail_chroot = /chroot/. means that the home dir already
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen contains the chroot dir. remove it from home. */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* we're dropping privileges only temporarily, so we can't
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen chroot. fix home directory so we can access it. */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (service_drop_privileges(user, user_set, home, chroot,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_error("user %s: Couldn't drop privileges: %s",
6a6e3c2538a08cc4880a8db7e0a9a3392122ea04Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) != 0)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen /* privileges are dropped. initialize plugins that haven't been
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen initialized yet. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen module_dir_init(mail_storage_service_modules);
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen if (mail_storage_service_init_post(ctx, user, home,
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipekvoid mail_storage_service_restrict_setenv(struct mail_storage_service_ctx *ctx,
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen const struct mail_user_settings *user_set = user->user_set;
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen home = user_expand_varstr(ctx->service, &user->input,
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen chroot = user_expand_varstr(ctx->service, &user->input,
41789540204ce091b2c06629d9a31788082e5da8Timo Sirainen if (service_drop_privileges(user, user_set, home, chroot,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainenint mail_storage_service_lookup_next(struct mail_storage_service_ctx *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_storage_service_input *input,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char **error_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = mail_storage_service_lookup(ctx, input, &user, error_r);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen ret = mail_storage_service_next(ctx, user, mail_user_r);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen *error_r = ret == -2 ? ERRSTR_INVALID_USER_SETTINGS :
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_storage_service_user_free(struct mail_storage_service_user **_user)
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch struct mail_storage_service_user *user = *_user;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_storage_service_init_settings(struct mail_storage_service_ctx *ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_storage_service_input *input)
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen const struct setting_parser_context *set_parser;
5ff22d69989a3ccc2d947164e47996f720d493d8Timo Sirainen temp_pool = pool_alloconly_create("service all settings", 4096);
5ff22d69989a3ccc2d947164e47996f720d493d8Timo Sirainen if (mail_storage_service_read_settings(ctx, input, temp_pool,
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen user_set = settings_parser_get_list(set_parser)[1];
e3540e734a79fd4f971652925079c2e26a4b5524Timo Sirainen mail_storage_service_first_init(ctx, user_info, user_set);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_storage_service_all_init(struct mail_storage_service_ctx *ctx)
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch (void)auth_master_user_list_deinit(&ctx->auth_list);
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch mail_storage_service_init_settings(ctx, NULL);
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch ctx->auth_list = auth_master_user_list_init(ctx->conn);
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch return auth_master_user_list_count(ctx->auth_list);
e4eb49e29197c6783ec93b868100394e189f4e0cTimo Sirainenint mail_storage_service_all_next(struct mail_storage_service_ctx *ctx,
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen i_assert((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0);
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen *username_r = auth_master_user_list_next(ctx->auth_list);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return auth_master_user_list_deinit(&ctx->auth_list);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainenvoid mail_storage_service_deinit(struct mail_storage_service_ctx **_ctx)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen (void)auth_master_user_list_deinit(&ctx->auth_list);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen master_service_settings_cache_deinit(&ctx->set_cache);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen module_dir_unload(&mail_storage_service_modules);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid **mail_storage_service_user_get_set(struct mail_storage_service_user *user)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return settings_parser_get_list(user->set_parser) + 1;
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainenmail_storage_service_user_get_input(struct mail_storage_service_user *user)
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainenmail_storage_service_user_get_settings_parser(struct mail_storage_service_user *user)
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainenvoid *mail_storage_service_get_settings(struct master_service *service)