mail-storage-service.c revision d6601a0bc4fd60e58bedbddf2481abd82cba76d7
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Copyright (c) 2009-2015 Dovecot authors, see the included COPYING file */
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen/* If time moves backwards more than this, kill ourself instead of sleeping. */
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen "Invalid user settings. Refer to server log for more information."
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen struct auth_master_connection *conn, *iter_conn;
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen const char *set_cache_module, *set_cache_service;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct master_service_settings_cache *set_cache;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *const **userdb_next_fieldsp;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *log_prefix, *auth_token, *auth_user;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *system_groups_user, *uid_source, *gid_source;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct module *mail_storage_service_modules = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmail_user_set_get_mail_debug(const struct setting_parser_info *user_info,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_set = mail_user_set_get_driver_settings(user_info, user_set,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void set_keyval(struct mail_storage_service_ctx *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct setting_parser_context *set_parser = user->set_parser;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen const char *str;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (master_service_set_has_config_override(ctx->service, key)) {
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen /* this setting was already overridden with -o parameter */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_user_set_get_mail_debug(user->user_info,
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen i_debug("Ignoring overridden (-o) userdb setting: %s",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (settings_parse_line(set_parser, str) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int set_line(struct mail_storage_service_ctx *ctx,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen struct setting_parser_context *set_parser = user->set_parser;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen const char *key, *orig_key, *append_value = NULL;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen unsigned int len;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen mail_debug = mail_user_set_get_mail_debug(user->user_info,
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen /* key+=value */
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen if (!settings_parse_is_valid_key(set_parser, key)) {
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen /* assume it's a plugin setting */
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen if (master_service_set_has_config_override(ctx->service, key)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* this setting was already overridden with -o parameter */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_debug("Ignoring overridden (-o) userdb setting: %s",
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen value = settings_parse_get_value(set_parser, key, &type);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "'+' can only be used for strings.", orig_key);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* possibly a password field (e.g. imapc_password).
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen hide the value. */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen "Unknown userdb setting: %s" :
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic bool validate_chroot(const struct mail_user_settings *user_set,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *dir)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *const *chroot_dirs;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenuser_reply_handle(struct mail_storage_service_ctx *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char **error_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen set_keyval(ctx, user, "mail_uid", dec2str(reply->uid));
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen set_keyval(ctx, user, "mail_gid", dec2str(reply->gid));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* wu-ftpd like <chroot>/./<home> - check only if there's even
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen a possibility of using them (non-empty valid_chroot_dirs) */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!validate_chroot(user->user_set, chroot)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "userdb returned invalid chroot directory: %s "
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str = array_get(&reply->extra_fields, &count);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < count; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strncmp(line, "system_groups_user=", 19) == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (n != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (strncmp(line, "auth_token=", 11) == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen user->auth_token = p_strdup(user->pool, line+11);
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen } else if (strncmp(line, "auth_user=", 10) == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen user->auth_user = p_strdup(user->pool, line+10);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen user->admin = line[6] == 'y' || line[6] == 'Y' ||
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen str[i], settings_parser_get_error(user->set_parser));
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainenservice_auth_userdb_lookup(struct mail_storage_service_ctx *ctx,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen const struct mail_storage_service_input *input,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen const char *const **fields_r,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen const char **error_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen info.service = input->service != NULL ? input->service :
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = auth_master_user_lookup(ctx->conn, *user, &info, pool,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen i_debug("changed username to %s", new_username);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen } else if (ret == 0)
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainenstatic bool parse_uid(const char *str, uid_t *uid_r, const char **error_r)
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen *error_r = t_strdup_printf("getpwnam(%s) failed: %m", str);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk *error_r = t_strconcat("Unknown UNIX UID user: ", str, NULL);
1b04762685272a53643ac2179939537a44c7c044Timo Sirainenstatic bool parse_gid(const char *str, gid_t *gid_r, const char **error_r)
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen *error_r = t_strdup_printf("getgrnam(%s) failed: %m", str);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen *error_r = t_strconcat("Unknown UNIX GID group: ", str, NULL);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainenstatic const struct var_expand_table *
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainenget_var_expand_table(struct master_service *service,
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen const struct mail_storage_service_input *input,
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen const struct mail_storage_service_privileges *priv)
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen static struct var_expand_table static_tab[] = {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen tab[1].value = t_strcut(input->username, '@');
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen tab[5].value = net_ip2addr(&input->remote_ip);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (user == NULL || user->auth_user == NULL) {
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen tab[11].value = t_strcut(user->auth_user, '@');
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainenmail_storage_service_get_var_expand_table(struct mail_storage_service_ctx *ctx,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return get_var_expand_table(ctx->service, NULL, input, &priv);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic const char *
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenuser_expand_varstr(struct master_service *service,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen const char *str)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen get_var_expand_table(service, user, &user->input, priv));
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenservice_parse_privileges(struct mail_storage_service_ctx *ctx,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen struct mail_storage_service_privileges *priv_r,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const char **error_r)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const struct mail_user_settings *set = user->user_set;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!parse_uid(set->mail_uid, &uid, error_r)) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen *error_r = t_strdup_printf("%s (from %s)", *error_r,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "Mail access for users with UID %s not permitted "
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "(see first_valid_uid in config file, uid from %s).",
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (!parse_gid(set->mail_gid, &gid, error_r)) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen *error_r = t_strdup_printf("%s (from %s)", *error_r,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "Mail access for users with GID %s not permitted "
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "(see first_valid_gid in config file, gid from %s).",
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen /* variable strings are expanded in mail_user_init(),
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen but we need the home and chroot sooner so do them separately here. */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen priv_r->home = user_expand_varstr(ctx->service, user, priv_r,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen priv_r->chroot = user_expand_varstr(ctx->service, user, priv_r,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenstatic void mail_storage_service_seteuid_root(void)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (seteuid(0) < 0) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen "Failed to restore temporarily dropped root privileges: "
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen "seteuid(0) failed: %m");
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenservice_drop_privileges(struct mail_storage_service_user *user,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen const struct mail_user_settings *set = user->user_set;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen *error_r = "User is missing UID (see mail_uid setting)";
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen } else if (rset.gid == (gid_t)-1 && disallow_root &&
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen *error_r = "User is missing GID (see mail_gid setting)";
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (!parse_gid(set->mail_privileged_group, &rset.privileged_gid,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen "%s (in mail_privileged_group setting)", error);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen rset.extra_groups = t_strconcat(set->mail_access_groups, ",",
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen rset.chroot_dir = *priv->chroot == '\0' ? NULL : priv->chroot;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen rset.system_groups_user = user->system_groups_user;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen cur_chroot = restrict_access_get_current_chroot();
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen /* we're already chrooted. make sure the chroots are equal. */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen "can't un-chroot for this user";
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (strcmp(rset.chroot_dir, cur_chroot) != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "Process is already chrooted to %s, "
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "can't chroot to %s", cur_chroot, priv->chroot);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* chrooting to same directory where we're already chrooted */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0))) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen *error_r = "Mail access not allowed for root";
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* we're changing the UID,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen switch back to root first */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen restrict_access(&rset, *priv->home == '\0' ? NULL : priv->home,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen i_fatal("mail-storage-service: seteuid(%s) failed: %m",
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenmail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen const char **error_r)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen /* NOTE: if more user initialization is added, add it also to
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_user_dup() */
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen mail_user = mail_user_alloc(user->input.username, user->user_info,
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen mail_user_set_vars(mail_user, ctx->service->name,
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen &user->input.local_ip, &user->input.remote_ip);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_user->uid = priv->uid == (uid_t)-1 ? geteuid() : priv->uid;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_user->gid = priv->gid == (gid_t)-1 ? getegid() : priv->gid;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen mail_user->auth_token = p_strdup(mail_user->pool, user->auth_token);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen mail_user->auth_user = p_strdup(mail_user->pool, user->auth_user);
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen p_strdup(mail_user->pool, user->input.session_id);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen mail_set = mail_user_set_get_storage_set(mail_user);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen str_printfa(str, "Effective uid=%s, gid=%s, home=%s",
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainen dec2str(geteuid()), dec2str(getegid()), home);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen str_printfa(str, ", chroot=%s", priv->chroot);
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) == 0) {
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen /* we don't want to write core files to any users' home
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen directories since they could contain information about other
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen users' mails as well. so do no chdiring to home. */
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen /* If possible chdir to home directory, so that core file
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen could be written in case we crash. */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES) == 0) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (mail_namespaces_init(mail_user, error_r) < 0) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid mail_storage_service_io_activate_user(struct mail_storage_service_user *user)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid mail_storage_service_io_deactivate_user(struct mail_storage_service_user *user)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_set_failure_prefix("%s", user->service_ctx->default_log_prefix);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid mail_storage_service_io_deactivate(struct mail_storage_service_ctx *ctx)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen i_set_failure_prefix("%s", ctx->default_log_prefix);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenmail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen var_expand(str, user->user_set->mail_log_prefix,
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen get_var_expand_table(ctx->service, user, &user->input, priv));
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen user->log_prefix = p_strdup(user->pool, str_c(str));
abb9b8f14e83baca887cf12210bfe480f6cde7a6Timo Sirainen master_service_init_log(ctx->service, user->log_prefix);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen if (master_service_get_client_limit(master_service) == 1)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen user->ioloop_ctx = io_loop_context_new(current_ioloop);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen io_loop_context_add_callbacks(user->ioloop_ctx,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstatic void mail_storage_service_time_moved(time_t old_time, time_t new_time)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_warning("Time jumped forwards %ld seconds", diff);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen i_fatal("Time just moved backwards by %ld seconds. "
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen "This might cause a lot of problems, "
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "so I'll just kill myself now. "
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_error("Time just moved backwards by %ld seconds. "
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen "I'll sleep now until we're back in present. "
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen /* Sleep extra second to make sure usecs also grows. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* don't use sleep()'s return value, because
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen it could get us to a long loop in case
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen interrupts just keep coming */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenmail_storage_service_init(struct master_service *service,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const struct setting_parser_info *set_roots[],
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen unsigned int count;
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen version = master_service_get_version_string(service);
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen if (version != NULL && strcmp(version, PACKAGE_VERSION) != 0) {
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen i_fatal("Version mismatch: libdovecot-storage.so is '%s', "
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen "while the running Dovecot binary is '%s'",
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen /* service { user } isn't root. the permission drop can't be
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen temporary. */
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen flags &= ~MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen io_loop_set_time_moved_callback(current_ioloop,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen pool = pool_alloconly_create("mail storage service", 2048);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx = p_new(pool, struct mail_storage_service_ctx, 1);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen /* @UNSAFE */
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen for (count = 0; set_roots[count] != NULL; count++) ;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen p_new(pool, const struct setting_parser_info *, count + 2);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->set_roots[0] = &mail_user_setting_parser_info;
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen /* do all the global initialization. delay initializing plugins until
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen we drop privileges the first time. */
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) {
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen /* note: we may not have read any settings yet, so this logging
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen may still be going to wrong location */
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen master_service_init_log(service, ctx->default_log_prefix);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenmail_storage_service_get_auth_conn(struct mail_storage_service_ctx *ctx)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenmail_storage_service_input_get_flags(struct mail_storage_service_ctx *ctx,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const struct mail_storage_service_input *input)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen flags = (ctx->flags & ~input->flags_override_remove) |
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* FIXME: for API backwards compatibility only */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen flags &= ~MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenint mail_storage_service_read_settings(struct mail_storage_service_ctx *ctx,
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen const struct mail_storage_service_input *input,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const struct setting_parser_info **user_info_r,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const struct setting_parser_context **parser_r,
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen const char **error_r)
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen struct master_service_settings_input set_input;
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen const struct setting_parser_info *const *roots;
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen struct master_service_settings_output set_output;
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen const struct dynamic_settings_parser *dyn_parsers;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen unsigned int i;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen mail_storage_service_input_get_flags(ctx, input);
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen /* settings reader may exec doveconf, which is going to clear
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen environment, and if we're not doing a userdb lookup we want to
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS) != 0;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen /* global settings read - don't create a cache for thi */
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen ctx->set_cache_module = p_strdup(ctx->pool, set_input.module);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen ctx->set_cache_service = p_strdup(ctx->pool, set_input.service);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen ctx->set_cache = master_service_settings_cache_init(
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx->service, set_input.module, set_input.service);
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen /* already looked up settings at least once.
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen we really shouldn't be execing anymore. */
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen dyn_parsers = mail_storage_get_dynamic_parsers(pool);
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen if (null_strcmp(set_input.module, ctx->set_cache_module) == 0 &&
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen null_strcmp(set_input.service, ctx->set_cache_service) == 0 &&
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (master_service_settings_cache_read(ctx->set_cache,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen settings_parser_dyn_update(pool, &set_input.roots, dyn_parsers);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (master_service_settings_read(ctx->service, &set_input,
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen mail_user_setting_parser_info.module_name) == 0) {
608bdb7f008cd5cd332d727018a9e8173abec998Timo Sirainenvoid mail_storage_service_set_auth_conn(struct mail_storage_service_ctx *ctx,
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainenmail_storage_service_first_init(struct mail_storage_service_ctx *ctx,
const char **error_r)
bool update_log_prefix,
const char **error_r)
void **sets;
geteuid() != 0) {
&error) < 0) {
if (update_log_prefix)
error_r);
if (ret <= 0) {
return ret;
if (ret > 0) {
&error) < 0) {
return ret;
const char **error_r)
bool update_log_prefix;
int ret;
return ret;
const char *error;
unsigned int len;
bool disallow_root =
bool temp_priv_drop =
bool use_chroot;
if (use_chroot) {
if (!temp_priv_drop ||
int ret;
return ret;
const char *error;
const char **error_r)
int ret;
if (ret <= 0)
return ret;
if (ret < 0) {
return ret;
const char *error;
void **sets;
&error) < 0)
int ret = 0;
return ret;
flags);
const char **username_r)
const struct mail_storage_settings *
const struct mail_storage_service_input *
struct setting_parser_context *
T_BEGIN {
} T_END;
return set;