mail-storage-service.c revision abf015c9682f0f723db87a7c97bc284ef814818f
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi/* If time moves backwards more than this, kill ourself instead of sleeping. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void set_keyval(struct setting_parser_context *set_parser,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char *str;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic bool validate_chroot(const struct mail_user_settings *user_set,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char *dir)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char *const *chroot_dirs;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiuser_reply_handle(struct mail_storage_service_user *user,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char **error_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct setting_parser_context *set_parser = user->set_parser;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi unsigned int i, count;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi set_keyval(set_parser, "mail_uid", dec2str(reply->uid));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi set_keyval(set_parser, "mail_gid", dec2str(reply->gid));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (!validate_chroot(user->user_set, reply->chroot)) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "userdb returned invalid chroot directory: %s "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "(see valid_chroot_dirs setting)",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi set_keyval(set_parser, "mail_chroot", reply->chroot);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (strncmp(line, "system_groups_user=", 19) == 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (n != 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (!settings_parse_is_valid_key(set_parser, key)) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* assume it's a plugin setting */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiservice_auth_userdb_lookup(struct mail_storage_service_ctx *ctx,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char *const **fields_r,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char **error_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi ret = auth_master_user_lookup(ctx->conn, *user, &info, pool,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi } else if (ret == 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic bool parse_uid(const char *str, uid_t *uid_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (*p == '\0')
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic bool parse_gid(const char *str, gid_t *gid_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (*p == '\0')
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiservice_drop_privileges(const struct mail_user_settings *set,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_fatal("Unknown mail_uid user: %s", set->mail_uid);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "not permitted (see first_valid_uid in config file).",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_fatal("Unknown mail_gid group: %s", set->mail_gid);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "not permitted (see first_valid_gid in config file).",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (!parse_uid(set->mail_privileged_group, &rset.privileged_gid))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_fatal("Unknown mail_gid group: %s", set->mail_gid);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* we can't chroot if we want to switch between users. there's not
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi much point either (from security point of view) */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi rset.chroot_dir = *chroot == '\0' || keep_setuid_root ? NULL : chroot;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0)))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* we're changing the UID,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi switch back to root first */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi restrict_access(&rset, *home == '\0' ? NULL : home, disallow_root);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_fatal("seteuid(%s) failed: %m", dec2str(setuid_uid));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char **error_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_user = mail_user_alloc(user->input.username, user->user_info,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_user_set_vars(mail_user, geteuid(), ctx->service->name,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_set = mail_user_set_get_storage_set(mail_user);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (ctx->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) == 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* we don't want to write core files to any users' home
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi directories since they could contain information about other
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi users' mails as well. so do no chdiring to home. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* If possible chdir to home directory, so that core file
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi could be written in case we crash. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (mail_namespaces_init(mail_user, error_r) < 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic const struct var_expand_table *
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiget_var_expand_table(struct master_service *service,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic const char *
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mail_storage_service_input *input, const char *str)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi var_expand(ret, str + 1, get_var_expand_table(service, input));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimail_storage_service_init_log(struct master_service *service,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi sets = master_service_settings_get_others(service);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void mail_storage_service_time_moved(time_t old_time, time_t new_time)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_warning("Time jumped forwards %ld seconds", diff);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_fatal("Time just moved backwards by %ld seconds. "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "This might cause a lot of problems, "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "so I'll just kill myself now. "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "http://wiki.dovecot.org/TimeMovedBackwards", diff);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_error("Time just moved backwards by %ld seconds. "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "I'll sleep now until we're back in present. "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "http://wiki.dovecot.org/TimeMovedBackwards", diff);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* Sleep extra second to make sure usecs also grows. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* don't use sleep()'s return value, because
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi it could get us to a long loop in case
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi interrupts just keep coming */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimail_storage_service_init(struct master_service *service,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi unsigned int count;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* @UNSAFE */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi for (count = 0; set_roots[count] != NULL; count++) ;
return ctx;
struct auth_master_connection *
unsigned int i, count;
for (i = 0; i < count; i++) {
static struct setting_parser_info *
unsigned int i, count;
for (i = 0; i < count; i++) {
for (i = 0; i < count; i++) {
return new_parent;
const char **error_r)
error_r) < 0) {
*error_r);
i_unreached();
const char **error_r)
const char *const *userdb_fields;
void **sets;
error_r);
if (ret <= 0) {
return ret;
return ret;
const char **error_r)
unsigned int len;
bool temp_priv_drop =
if (!temp_priv_drop ||
if (!temp_priv_drop) {
const char **error_r)
const char *error;
int ret;
if (ret <= 0) {
return ret;
const char *error;
void **sets;
const char **username_r)
const struct mail_storage_service_input *
struct setting_parser_context *
T_BEGIN {
} T_END;
return set;