mail-storage-service.c revision 23152672e3ad7f3512c11df43e8dabba4fe6407d
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* 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. */
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen "Invalid user settings. Refer to server log for more information."
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen struct auth_master_connection *conn, *iter_conn;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const char *set_cache_module, *set_cache_service;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_cache *set_cache;
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen const char *const **userdb_next_fieldsp;
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen const char *log_prefix, *auth_token, *auth_user;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen const char *system_groups_user, *uid_source, *gid_source;
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainenstruct module *mail_storage_service_modules = NULL;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenmail_user_set_get_mail_debug(const struct setting_parser_info *user_info,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mail_set = mail_user_set_get_driver_settings(user_info, user_set,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void set_keyval(struct mail_storage_service_ctx *ctx,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct setting_parser_context *set_parser = user->set_parser;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *str;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (master_service_set_has_config_override(ctx->service, key)) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* this setting was already overridden with -o parameter */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (mail_user_set_get_mail_debug(user->user_info,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen i_debug("Ignoring overridden (-o) userdb setting: %s",
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen if (settings_parse_line(set_parser, str) < 0) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic int set_line(struct mail_storage_service_ctx *ctx,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct setting_parser_context *set_parser = user->set_parser;
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen const char *key, *orig_key, *append_value = NULL;
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen unsigned int len;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mail_debug = mail_user_set_get_mail_debug(user->user_info,
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen /* key+=value */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (!settings_parse_is_valid_key(set_parser, key)) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* assume it's a plugin setting */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (master_service_set_has_config_override(ctx->service, key)) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* this setting was already overridden with -o parameter */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen i_debug("Ignoring overridden (-o) userdb setting: %s",
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen value = settings_parse_get_value(set_parser, key, &type);
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen "'+' can only be used for strings.", orig_key);
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen /* possibly a password field (e.g. imapc_password).
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen hide the value. */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo 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)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenuser_reply_handle(struct mail_storage_service_ctx *ctx,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const char **error_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, count;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen set_keyval(ctx, user, "mail_uid", dec2str(reply->uid));
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen set_keyval(ctx, user, "mail_gid", dec2str(reply->gid));
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen /* wu-ftpd like <chroot>/./<home> - check only if there's even
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen a possibility of using them (non-empty valid_chroot_dirs) */
002179a890bf4f1942cad6463787719eaa9fd6c0Timo 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);
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen for (i = 0; i < count; i++) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (strncmp(line, "system_groups_user=", 19) == 0) {
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen if (n != 0) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch } else if (strncmp(line, "auth_token=", 11) == 0) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch user->auth_token = p_strdup(user->pool, line+11);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen } else if (strncmp(line, "auth_user=", 10) == 0) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen user->auth_user = p_strdup(user->pool, line+10);
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen user->admin = line[6] == 'y' || line[6] == 'Y' ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen str[i], settings_parser_get_error(user->set_parser));
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenservice_auth_userdb_lookup(struct mail_storage_service_ctx *ctx,
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen const struct mail_storage_service_input *input,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen const char *const **fields_r,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char **error_r)
b9dc21a94401638c00e40b695998875e1563ce77Timo Sirainen info.service = input->service != NULL ? input->service :
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ret = auth_master_user_lookup(ctx->conn, *user, &info, pool,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_debug("changed username to %s", new_username);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen } else if (ret == 0)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenstatic bool parse_uid(const char *str, uid_t *uid_r, const char **error_r)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen *error_r = t_strdup_printf("getpwnam(%s) failed: %m", str);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen *error_r = t_strconcat("Unknown UNIX UID user: ", str, NULL);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenstatic bool parse_gid(const char *str, gid_t *gid_r, const char **error_r)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen *error_r = t_strdup_printf("getgrnam(%s) failed: %m", str);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen *error_r = t_strconcat("Unknown UNIX GID group: ", str, NULL);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic const struct var_expand_table *
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenget_var_expand_table(struct master_service *service,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen const struct mail_storage_service_input *input,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen const struct mail_storage_service_privileges *priv)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen static struct var_expand_table static_tab[] = {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen tab[1].value = t_strcut(input->username, '@');
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen tab[5].value = net_ip2addr(&input->remote_ip);
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid);
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (user == NULL || user->auth_user == NULL) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen tab[11].value = t_strcut(user->auth_user, '@');
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainenmail_storage_service_get_var_expand_table(struct mail_storage_service_ctx *ctx,
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen return get_var_expand_table(ctx->service, NULL, input, &priv);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic const char *
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenuser_expand_varstr(struct master_service *service,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const char *str)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen get_var_expand_table(service, user, &user->input, priv));
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenservice_parse_privileges(struct mail_storage_service_ctx *ctx,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct mail_storage_service_privileges *priv_r,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const char **error_r)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const struct mail_user_settings *set = user->user_set;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (!parse_uid(set->mail_uid, &uid, error_r)) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen *error_r = t_strdup_printf("%s (from %s)", *error_r,
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen "Mail access for users with UID %s not permitted "
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen "(see first_valid_uid in config file, uid from %s).",
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (!parse_gid(set->mail_gid, &gid, error_r)) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen *error_r = t_strdup_printf("%s (from %s)", *error_r,
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen "Mail access for users with GID %s not permitted "
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen "(see first_valid_gid in config file, gid from %s).",
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* variable strings are expanded in mail_user_init(),
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen but we need the home and chroot sooner so do them separately here. */
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen priv_r->home = user_expand_varstr(ctx->service, user, priv_r,
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen priv_r->chroot = user_expand_varstr(ctx->service, user, priv_r,
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainenstatic void mail_storage_service_seteuid_root(void)
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen if (seteuid(0) < 0) {
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen "Failed to restore temporarily dropped root privileges: "
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen "seteuid(0) failed: %m");
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenservice_drop_privileges(struct mail_storage_service_user *user,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const struct mail_user_settings *set = user->user_set;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen *error_r = "User is missing UID (see mail_uid setting)";
7f472e15b5f19a3536634863950c80a88079da23Timo Sirainen } else if (rset.gid == (gid_t)-1 && disallow_root &&
0139fcb57a88f6ed27a1bb4a1bd537b04fd2b5d6Timo Sirainen *error_r = "User is missing GID (see mail_gid setting)";
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (!parse_gid(set->mail_privileged_group, &rset.privileged_gid,
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen "%s (in mail_privileged_group setting)", error);
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen rset.extra_groups = t_strconcat(set->mail_access_groups, ",",
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen rset.chroot_dir = *priv->chroot == '\0' ? NULL : priv->chroot;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen rset.system_groups_user = user->system_groups_user;
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen cur_chroot = restrict_access_get_current_chroot();
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen /* we're already chrooted. make sure the chroots are equal. */
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen "can't un-chroot for this user";
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen if (strcmp(rset.chroot_dir, cur_chroot) != 0) {
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen "Process is already chrooted to %s, "
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen "can't chroot to %s", cur_chroot, priv->chroot);
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen /* chrooting to same directory where we're already chrooted */
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0))) {
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen *error_r = "Mail access not allowed for root";
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen /* we're changing the UID,
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen switch back to root first */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen restrict_access(&rset, *priv->home == '\0' ? NULL : priv->home,
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen i_fatal("mail-storage-service: seteuid(%s) failed: %m",
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenmail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char **error_r)
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen /* NOTE: if more user initialization is added, add it also to
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen mail_user_dup() */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_user = mail_user_alloc(user->input.username, user->user_info,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_user_set_vars(mail_user, ctx->service->name,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen &user->input.local_ip, &user->input.remote_ip);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_user->uid = priv->uid == (uid_t)-1 ? geteuid() : priv->uid;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_user->gid = priv->gid == (gid_t)-1 ? getegid() : priv->gid;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch mail_user->auth_token = p_strdup(mail_user->pool, user->auth_token);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen mail_user->auth_user = p_strdup(mail_user->pool, user->auth_user);
330096f204a221d8b8beb7f408a03d28c7572537Timo Sirainen p_strdup(mail_user->pool, user->input.session_id);
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen mail_user->userdb_fields = user->input.userdb_fields == NULL ? NULL :
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen p_strarray_dup(mail_user->pool, user->input.userdb_fields);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_set = mail_user_set_get_storage_set(mail_user);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen str_printfa(str, "Effective uid=%s, gid=%s, home=%s",
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen dec2str(geteuid()), dec2str(getegid()), home);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen str_printfa(str, ", chroot=%s", priv->chroot);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) == 0) {
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen /* we don't want to write core files to any users' home
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen directories since they could contain information about other
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen users' mails as well. so do no chdiring to home. */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen /* If possible chdir to home directory, so that core file
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen could be written in case we crash. */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES) == 0) {
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen if (mail_namespaces_init(mail_user, error_r) < 0) {
85779ec11f23eb8efeb8993b1e0b9aad62c4122aTimo Sirainenvoid mail_storage_service_io_activate_user(struct mail_storage_service_user *user)
85779ec11f23eb8efeb8993b1e0b9aad62c4122aTimo Sirainenvoid mail_storage_service_io_deactivate_user(struct mail_storage_service_user *user)
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("%s", user->service_ctx->default_log_prefix);
85779ec11f23eb8efeb8993b1e0b9aad62c4122aTimo Sirainenvoid mail_storage_service_io_deactivate(struct mail_storage_service_ctx *ctx)
85779ec11f23eb8efeb8993b1e0b9aad62c4122aTimo Sirainen i_set_failure_prefix("%s", ctx->default_log_prefix);
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenstatic const char *
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenmail_storage_service_input_var_userdb(const char *data, void *context)
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen struct mail_storage_service_user *user = context;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen unsigned int i, field_name_len;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen if (user == NULL || user->input.userdb_fields == NULL)
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen for (i = 0; user->input.userdb_fields[i] != NULL; i++) {
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen if (strncmp(user->input.userdb_fields[i], field_name,
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen user->input.userdb_fields[i][field_name_len] == '=')
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen return user->input.userdb_fields[i] + field_name_len+1;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenmail_storage_service_var_expand(struct mail_storage_service_ctx *ctx,
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen const struct mail_storage_service_input *input,
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen const struct mail_storage_service_privileges *priv)
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen static const struct var_expand_func_table func_table[] = {
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen { "userdb", mail_storage_service_input_var_userdb },
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen get_var_expand_table(ctx->service, user, input, priv),
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainenmail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen user->log_prefix = p_strdup(user->pool, str_c(str));
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen master_service_init_log(ctx->service, user->log_prefix);
8abe071cb14a622b9d84b00a9269f96d01a576f6Timo Sirainen if (master_service_get_client_limit(master_service) == 1)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen user->ioloop_ctx = io_loop_context_new(current_ioloop);
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen io_loop_context_add_callbacks(user->ioloop_ctx,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic void mail_storage_service_time_moved(time_t old_time, time_t new_time)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_warning("Time jumped forwards %ld seconds", diff);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_fatal("Time just moved backwards by %ld seconds. "
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen "This might cause a lot of problems, "
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen "so I'll just kill myself now. "
0992011130e9d0a498ca860ddbe4028398a530c5Timo Sirainen "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_error("Time just moved backwards by %ld seconds. "
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen "I'll sleep now until we're back in present. "
0992011130e9d0a498ca860ddbe4028398a530c5Timo Sirainen "http://wiki2.dovecot.org/TimeMovedBackwards", diff);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen /* Sleep extra second to make sure usecs also grows. */
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen /* don't use sleep()'s return value, because
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen it could get us to a long loop in case
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen interrupts just keep coming */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenmail_storage_service_init(struct master_service *service,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const struct setting_parser_info *set_roots[],
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen unsigned int count;
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen version = master_service_get_version_string(service);
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen if (version != NULL && strcmp(version, PACKAGE_VERSION) != 0) {
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen i_fatal("Version mismatch: libdovecot-storage.so is '%s', "
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen "while the running Dovecot binary is '%s'",
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen /* service { user } isn't root. the permission drop can't be
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen temporary. */
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen flags &= ~MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen io_loop_set_time_moved_callback(current_ioloop,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool = pool_alloconly_create("mail storage service", 2048);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ctx = p_new(pool, struct mail_storage_service_ctx, 1);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* @UNSAFE */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen for (count = 0; set_roots[count] != NULL; count++) ;
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen p_new(pool, const struct setting_parser_info *, count + 2);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx->set_roots[0] = &mail_user_setting_parser_info;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* do all the global initialization. delay initializing plugins until
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen we drop privileges the first time. */
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) {
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen /* note: we may not have read any settings yet, so this logging
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen may still be going to wrong location */
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen master_service_init_log(service, ctx->default_log_prefix);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenmail_storage_service_get_auth_conn(struct mail_storage_service_ctx *ctx)
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainenmail_storage_service_input_get_flags(struct mail_storage_service_ctx *ctx,
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen const struct mail_storage_service_input *input)
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen flags = (ctx->flags & ~input->flags_override_remove) |
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen /* FIXME: for API backwards compatibility only */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen flags &= ~MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenint mail_storage_service_read_settings(struct mail_storage_service_ctx *ctx,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen const struct mail_storage_service_input *input,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen const struct setting_parser_info **user_info_r,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct setting_parser_context **parser_r,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen const char **error_r)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen struct master_service_settings_input set_input;
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen const struct setting_parser_info *const *roots;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_output set_output;
dbe06905918a415a34c5621b9fdf45be0b9c8e64Timo Sirainen const struct dynamic_settings_parser *dyn_parsers;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen unsigned int i;
8d5c97bf940e43e8ec6e9f1ec8655f3b20edafbeTimo Sirainen mail_storage_service_input_get_flags(ctx, input);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen /* settings reader may exec doveconf, which is going to clear
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen environment, and if we're not doing a userdb lookup we want to
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (flags & MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS) != 0;
d2ca20a479e76af8557b4a74b0b51e4de0e3c9e3Timo Sirainen /* global settings read - don't create a cache for thi */
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen ctx->set_cache_module = p_strdup(ctx->pool, set_input.module);
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen ctx->set_cache_service = p_strdup(ctx->pool, set_input.service);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ctx->set_cache = master_service_settings_cache_init(
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen ctx->service, set_input.module, set_input.service);
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen /* already looked up settings at least once.
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen we really shouldn't be execing anymore. */
dbe06905918a415a34c5621b9fdf45be0b9c8e64Timo Sirainen dyn_parsers = mail_storage_get_dynamic_parsers(pool);
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen if (null_strcmp(set_input.module, ctx->set_cache_module) == 0 &&
d2ca20a479e76af8557b4a74b0b51e4de0e3c9e3Timo Sirainen null_strcmp(set_input.service, ctx->set_cache_service) == 0 &&
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (master_service_settings_cache_read(ctx->set_cache,
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen settings_parser_dyn_update(pool, &set_input.roots, dyn_parsers);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (master_service_settings_read(ctx->service, &set_input,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen mail_user_setting_parser_info.module_name) == 0) {
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainenvoid mail_storage_service_set_auth_conn(struct mail_storage_service_ctx *ctx,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenmail_storage_service_first_init(struct mail_storage_service_ctx *ctx,
72f2a851238e5661695c63bff0e9a9e800ba577aTimo Sirainen ctx->debug = mail_user_set_get_mail_debug(user_info, user_set);
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_IDLE_TIMEOUT) != 0)
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen auth_master_init(user_set->auth_socket_path, flags));
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainenmail_storage_service_load_modules(struct mail_storage_service_ctx *ctx,
351668ae6972c9f55059501ddb2ed6e70afa2f31Timo Sirainen const char **error_r)
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainen if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS) != 0)
8552b0cad8ffe9ccb8270577ba28b8010c89af11Timo Sirainen mod_set.binary_name = master_service_get_name(ctx->service);
72f2a851238e5661695c63bff0e9a9e800ba577aTimo Sirainen mod_set.debug = mail_user_set_get_mail_debug(user_info, user_set);
351668ae6972c9f55059501ddb2ed6e70afa2f31Timo Sirainen return module_dir_try_load_missing(&mail_storage_service_modules,
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainenstatic int extra_field_key_cmp_p(const char *const *s1, const char *const *s2)
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainenmail_storage_service_set_log_prefix(struct mail_storage_service_ctx *ctx,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen const struct mail_storage_service_input *input,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen const struct mail_storage_service_privileges *priv)
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen mail_storage_service_var_expand(ctx, str, user_set->mail_log_prefix,
d6601a0bc4fd60e58bedbddf2481abd82cba76d7Timo Sirainenstatic const char *mail_storage_service_generate_session_id(pool_t pool)
d6601a0bc4fd60e58bedbddf2481abd82cba76d7Timo Sirainen string_t *str = str_new(pool, MAX_BASE64_ENCODED_SIZE(sizeof(guid)));
d6601a0bc4fd60e58bedbddf2481abd82cba76d7Timo Sirainen /* remove the trailing "==" */
d6601a0bc4fd60e58bedbddf2481abd82cba76d7Timo Sirainen i_assert(str_data(str)[str_len(str)-2] == '=');
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainenmail_storage_service_lookup_real(struct mail_storage_service_ctx *ctx,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen const struct mail_storage_service_input *input,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen const char **error_r)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct setting_parser_context *set_parser;
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen user_pool = pool_alloconly_create(MEMPOOL_GROWING"mail storage service user", 1024*6);
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen flags = mail_storage_service_input_get_flags(ctx, input);
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen /* we dropped privileges only temporarily. switch back to root
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen before reading settings, so we'll definitely have enough
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen permissions to connect to the config socket. */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (mail_storage_service_read_settings(ctx, input, user_pool,
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen /* just restart and maybe next time we will open the
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen config socket before dropping privileges */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0 &&
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen /* initialize logging again, in case we only read the
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen settings for the first above */
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen sets = master_service_settings_parser_get_others(master_service,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen mail_storage_service_set_log_prefix(ctx, user_set, NULL, input, NULL);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_storage_service_first_init(ctx, user_info, user_set);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen /* load global plugins */
351668ae6972c9f55059501ddb2ed6e70afa2f31Timo Sirainen if (mail_storage_service_load_modules(ctx, user_info, user_set, &error) < 0) {
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen temp_pool = pool_alloconly_create("userdb lookup", 2048);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ret = service_auth_userdb_lookup(ctx, input, temp_pool,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen user = p_new(user_pool, struct mail_storage_service_user, 1);
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen user->input.userdb_fields = userdb_fields == NULL ? NULL :
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen user->input.username = p_strdup(user_pool, username);
bff606130fa332dbf837569f922028b68f45fd61Timo Sirainen user->input.session_id = p_strdup(user_pool, input->session_id);
d6601a0bc4fd60e58bedbddf2481abd82cba76d7Timo Sirainen mail_storage_service_generate_session_id(user_pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen user->set_parser = settings_parser_dup(set_parser, user_pool);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (!settings_parser_check(user->set_parser, user_pool, &error))
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen i_panic("settings_parser_check() failed: %s", error);
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen sets = master_service_settings_parser_get_others(master_service,
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
44fea1d434a885f08b399459748b001a89f61c77Timo Sirainen (void)settings_parse_line(user->set_parser, "mail_debug=yes");
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen auth_user_fields_parse(userdb_fields, temp_pool, &reply);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen array_sort(&reply.extra_fields, extra_field_key_cmp_p);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (user_reply_handle(ctx, user, &reply, &error) < 0) {
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen i_error("Invalid settings in userdb: %s", error);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen /* load per-user plugins */
351668ae6972c9f55059501ddb2ed6e70afa2f31Timo Sirainen if (mail_storage_service_load_modules(ctx, user_info,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainenint mail_storage_service_lookup(struct mail_storage_service_ctx *ctx,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen const struct mail_storage_service_input *input,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen const char **error_r)
a48ccadf62d342063d0fff00fadc791423cc915fTimo Sirainen char *old_log_prefix = i_strdup(i_get_failure_prefix());
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen if (io_loop_get_current_context(current_ioloop) == NULL) {
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen /* no user yet. log prefix should be just "imap:" or something
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen equally unhelpful. we don't know the proper log format yet,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen but initialize it to something better until we know it. */
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen master_service_get_name(ctx->service), input->username,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen t_strdup_printf(",%s", net_ip2addr(&input->remote_ip)));
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen /* we might be here because we're doing a user lookup for a
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen shared user. the log prefix is likely already usable, so
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen just append our own without replacing the whole thing. */
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen ret = mail_storage_service_lookup_real(ctx, input, update_log_prefix,
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainenvoid mail_storage_service_save_userdb_fields(struct mail_storage_service_ctx *ctx,
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen pool_t pool, const char *const **userdb_fields_r)
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainenmail_storage_service_next_real(struct mail_storage_service_ctx *ctx,
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen unsigned int len;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (service_parse_privileges(ctx, user, &priv, &error) < 0) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (*priv.home != '/' && *priv.home != '\0') {
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen i_error("Relative home directory paths not supported: %s",
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen /* we can't chroot if we want to switch between users. there's
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen not much point either (from security point of view). but if we're
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen already chrooted, we'll just have to continue and hope that the
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen current chroot is the same as the wanted chroot */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (len > 2 && strcmp(priv.chroot + len - 2, "/.") == 0 &&
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen strncmp(priv.home, priv.chroot, len - 2) == 0) {
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen /* mail_chroot = /chroot/. means that the home dir already
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen contains the chroot dir. remove it from home. */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen priv.chroot = t_strndup(priv.chroot, len - 2);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen set_keyval(ctx, user, "mail_home", priv.home);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen set_keyval(ctx, user, "mail_chroot", priv.chroot);
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen /* we're not going to chroot. fix home directory so we can
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen access it. */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (*priv.home == '\0' || strcmp(priv.home, "/") == 0)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen priv.home = t_strconcat(priv.chroot, priv.home, NULL);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen set_keyval(ctx, user, "mail_home", priv.home);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_storage_service_init_log(ctx, user, &priv);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen i_error("Couldn't drop privileges: %s", error);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) != 0)
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen /* privileges are dropped. initialize plugins that haven't been
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen initialized yet. */
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen module_dir_init(mail_storage_service_modules);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (mail_storage_service_init_post(ctx, user, &priv,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen i_error("User initialization failed: %s", error);
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainenint mail_storage_service_next(struct mail_storage_service_ctx *ctx,
a48ccadf62d342063d0fff00fadc791423cc915fTimo Sirainen char *old_log_prefix = i_strdup(i_get_failure_prefix());
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen mail_storage_service_set_log_prefix(ctx, user->user_set, user,
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen ret = mail_storage_service_next_real(ctx, user, mail_user_r);
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) != 0)
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainenvoid mail_storage_service_restrict_setenv(struct mail_storage_service_ctx *ctx,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (service_parse_privileges(ctx, user, &priv, &error) < 0)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_fatal("user %s: %s", user->input.username, error);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_fatal("user %s: %s", user->input.username, error);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenint mail_storage_service_lookup_next(struct mail_storage_service_ctx *ctx,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const struct mail_storage_service_input *input,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const char **error_r)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen ret = mail_storage_service_lookup(ctx, input, &user, error_r);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen ret = mail_storage_service_next(ctx, user, mail_user_r);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen *error_r = ret == -2 ? ERRSTR_INVALID_USER_SETTINGS :
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid mail_storage_service_user_free(struct mail_storage_service_user **_user)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen struct mail_storage_service_user *user = *_user;
ae800c8a965688ab17415397dbc759a429e78199Timo Sirainen io_loop_context_remove_callbacks(user->ioloop_ctx,
85779ec11f23eb8efeb8993b1e0b9aad62c4122aTimo Sirainen mail_storage_service_io_deactivate_user, user);
192488b417fd4411210c616eaf50f6e8c0c5f916Timo Sirainen if (io_loop_get_current_context(current_ioloop) == user->ioloop_ctx)
192488b417fd4411210c616eaf50f6e8c0c5f916Timo Sirainen mail_storage_service_io_deactivate_user(user);
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainenvoid mail_storage_service_init_settings(struct mail_storage_service_ctx *ctx,
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen const struct mail_storage_service_input *input)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct setting_parser_context *set_parser;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen temp_pool = pool_alloconly_create("service all settings", 4096);
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen if (mail_storage_service_read_settings(ctx, input, temp_pool,
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen sets = master_service_settings_parser_get_others(master_service,
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen mail_storage_service_first_init(ctx, user_info, user_set);
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainenmail_storage_service_all_iter_deinit(struct mail_storage_service_ctx *ctx)
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen ret = auth_master_user_list_deinit(&ctx->auth_list);
4dc81fe17cc3aca2e8e9ccb988f90bae12ca2ad0Timo Sirainenvoid mail_storage_service_all_init(struct mail_storage_service_ctx *ctx)
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen (void)mail_storage_service_all_iter_deinit(ctx);
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen mail_storage_service_init_settings(ctx, NULL);
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen /* create a new connection, because the iteration might take a while
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen and we might want to do USER lookups during it, which don't mix
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen well in the same connection. */
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen ctx->iter_conn = auth_master_init(auth_master_get_socket_path(ctx->conn),
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen ctx->auth_list = auth_master_user_list_init(ctx->iter_conn, "", NULL);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenint mail_storage_service_all_next(struct mail_storage_service_ctx *ctx,
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen i_assert((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0);
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen *username_r = auth_master_user_list_next(ctx->auth_list);
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen return mail_storage_service_all_iter_deinit(ctx);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid mail_storage_service_deinit(struct mail_storage_service_ctx **_ctx)
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen (void)mail_storage_service_all_iter_deinit(ctx);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen master_service_settings_cache_deinit(&ctx->set_cache);
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen module_dir_unload(&mail_storage_service_modules);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid **mail_storage_service_user_get_set(struct mail_storage_service_user *user)
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen return master_service_settings_parser_get_others(master_service,
544a946df4de398125bafb51f26d5e3697bde649Timo Sirainenmail_storage_service_user_get_mail_set(struct mail_storage_service_user *user)
7e95ba7f38b9b421287d36c6152f8a9e6b9f225bTimo Sirainenmail_storage_service_user_get_input(struct mail_storage_service_user *user)
608bdb7f008cd5cd332d727018a9e8173abec998Timo Sirainenmail_storage_service_user_get_settings_parser(struct mail_storage_service_user *user)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid *mail_storage_service_get_settings(struct master_service *service)