}
static const struct var_expand_table *
-get_var_expand_table(enum process_type process_type,
+get_var_expand_table(const char *protocol,
const char *user, const char *home,
- const struct ip_addr *local_ip,
- const struct ip_addr *remote_ip, pid_t pid)
+ const char *local_ip, const char *remote_ip, pid_t pid)
{
static struct var_expand_table static_tab[] = {
{ 'u', NULL },
tab[1].value = t_strcut(user, '@');
tab[2].value = strchr(user, '@');
if (tab[2].value != NULL) tab[2].value++;
- tab[3].value = t_str_ucase(process_names[process_type]);
+ tab[3].value = t_str_ucase(protocol);
tab[4].value = home;
- tab[5].value = net_ip2addr(local_ip);
- tab[6].value = net_ip2addr(remote_ip);
+ tab[5].value = local_ip;
+ tab[6].value = remote_ip;
tab[7].value = dec2str(pid);
return tab;
}
}
+static void
+mail_process_set_environment(struct settings *set, const char *mail,
+ const struct var_expand_table *var_expand_table)
+{
+ env_put(t_strconcat("MAIL_CACHE_FIELDS=",
+ set->mail_cache_fields, NULL));
+ env_put(t_strconcat("MAIL_NEVER_CACHE_FIELDS=",
+ set->mail_never_cache_fields, NULL));
+ env_put(t_strdup_printf("MAILBOX_CHECK_INTERVAL=%u",
+ set->mailbox_check_interval));
+ env_put(t_strdup_printf("MAILBOX_IDLE_CHECK_INTERVAL=%u",
+ set->mailbox_idle_check_interval));
+ env_put(t_strconcat("CLIENT_WORKAROUNDS=",
+ set->client_workarounds, NULL));
+ env_put(t_strdup_printf("MAIL_MAX_KEYWORD_LENGTH=%u",
+ set->mail_max_keyword_length));
+ env_put(t_strdup_printf("IMAP_MAX_LINE_LENGTH=%u",
+ set->imap_max_line_length));
+ env_put(t_strconcat("IMAP_CAPABILITY=",
+ set->imap_capability, NULL));
+
+ if (set->mail_save_crlf)
+ env_put("MAIL_SAVE_CRLF=1");
+ if (set->mail_read_mmaped)
+ env_put("MAIL_READ_MMAPED=1");
+ if (set->mmap_disable)
+ env_put("MMAP_DISABLE=1");
+ if (set->mmap_no_write)
+ env_put("MMAP_NO_WRITE=1");
+ if (set->fcntl_locks_disable)
+ env_put("FCNTL_LOCKS_DISABLE=1");
+ if (set->maildir_stat_dirs)
+ env_put("MAILDIR_STAT_DIRS=1");
+ if (set->maildir_copy_with_hardlinks)
+ env_put("MAILDIR_COPY_WITH_HARDLINKS=1");
+ if (set->maildir_check_content_changes)
+ env_put("MAILDIR_CHECK_CONTENT_CHANGES=1");
+ if (set->mail_full_filesystem_access)
+ env_put("FULL_FILESYSTEM_ACCESS=1");
+ if (set->pop3_mails_keep_recent)
+ env_put("POP3_MAILS_KEEP_RECENT=1");
+ (void)umask(set->umask);
+
+ env_put(t_strconcat("MBOX_READ_LOCKS=", set->mbox_read_locks, NULL));
+ env_put(t_strconcat("MBOX_WRITE_LOCKS=", set->mbox_write_locks, NULL));
+ env_put(t_strdup_printf("MBOX_LOCK_TIMEOUT=%u",
+ set->mbox_lock_timeout));
+ env_put(t_strdup_printf("MBOX_DOTLOCK_CHANGE_TIMEOUT=%u",
+ set->mbox_dotlock_change_timeout));
+
+ if (set->mail_use_modules &&
+ set->mail_modules != NULL && *set->mail_modules != '\0') {
+ env_put(t_strconcat("MODULE_DIR=",
+ set->mail_modules, NULL));
+ }
+
+ /* user given environment - may be malicious. virtual_user comes from
+ auth process, but don't trust that too much either. Some auth
+ mechanism might allow leaving extra data there. */
+ if ((mail == NULL || *mail == '\0') && set->default_mail_env != NULL)
+ mail = expand_mail_env(set->default_mail_env, var_expand_table);
+ env_put(t_strconcat("MAIL=", mail, NULL));
+
+ if (set->server->namespaces != NULL) {
+ env_put_namespace(set->server->namespaces,
+ mail, var_expand_table);
+ }
+}
+
+static void mail_process_exec_set(struct settings *set, const char *title)
+{
+ const char *executable, *p, *argv[4];
+ int i;
+
+ /* very simple argument splitting. */
+ i = 0;
+ argv[i++] = executable = t_strcut(set->mail_executable, ' ');
+ argv[i] = strchr(set->mail_executable, ' ');
+ if (argv[i] != NULL) {
+ argv[i]++;
+ i++;
+ }
+ if (title[0] != '\0')
+ argv[i++] = title;
+ argv[i] = NULL;
+
+ /* hide the path, it's ugly */
+ p = strrchr(argv[0], '/');
+ if (p != NULL) argv[0] = p+1;
+
+ execv(executable, (char **) argv);
+}
+
+void mail_process_exec(const char *protocol, const char *section)
+{
+ struct server_settings *server = settings_root;
+ const struct var_expand_table *var_expand_table;
+ struct settings *set;
+
+ if (section != NULL) {
+ for (; server != NULL; server = server->next) {
+ if (strcmp(server->name, section) == 0)
+ break;
+ }
+ if (server == NULL)
+ i_fatal("Section not found: '%s'", section);
+ }
+
+ if (strcmp(protocol, "imap") == 0)
+ set = server->imap;
+ else if (strcmp(protocol, "pop3") == 0)
+ set = server->pop3;
+ else
+ i_fatal("Unknown protocol: '%s'", protocol);
+
+ var_expand_table =
+ get_var_expand_table(protocol, getenv("USER"), getenv("HOME"),
+ getenv("TCPLOCALIP"),
+ getenv("TCPREMOTEIP"), getpid());
+
+ mail_process_set_environment(set, getenv("MAIL"), var_expand_table);
+ mail_process_exec_set(set, "");
+
+ i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
+ set->mail_executable);
+}
+
int create_mail_process(struct login_group *group, int socket,
const struct ip_addr *local_ip,
const struct ip_addr *remote_ip,
{
struct settings *set = group->set;
const struct var_expand_table *var_expand_table;
- const char *argv[4];
const char *addr, *mail, *user, *chroot_dir, *home_dir, *full_home_dir;
- const char *executable, *p;
- struct log_io *log;
char title[1024];
+ struct log_io *log;
string_t *str;
pid_t pid;
int i, err, ret, log_fd;
}
var_expand_table =
- get_var_expand_table(group->process_type, user, home_dir,
- local_ip, remote_ip,
+ get_var_expand_table(process_names[group->process_type],
+ user, home_dir,
+ net_ip2addr(local_ip),
+ net_ip2addr(remote_ip),
pid != 0 ? pid : getpid());
str = t_str_new(128);
set->first_valid_gid, set->last_valid_gid,
set->mail_extra_groups);
- restrict_process_size(group->set->mail_process_size, (unsigned int)-1);
+ restrict_process_size(set->mail_process_size, (unsigned int)-1);
if (*home_dir == '\0')
ret = -1;
i_fatal("chdir(/tmp) failed: %m");
}
+ mail_process_set_environment(set, mail, var_expand_table);
+
env_put("LOGGED_IN=1");
env_put(t_strconcat("HOME=", home_dir, NULL));
- env_put(t_strconcat("MAIL_CACHE_FIELDS=",
- set->mail_cache_fields, NULL));
- env_put(t_strconcat("MAIL_NEVER_CACHE_FIELDS=",
- set->mail_never_cache_fields, NULL));
- env_put(t_strdup_printf("MAILBOX_CHECK_INTERVAL=%u",
- set->mailbox_check_interval));
- env_put(t_strdup_printf("MAILBOX_IDLE_CHECK_INTERVAL=%u",
- set->mailbox_idle_check_interval));
- env_put(t_strconcat("CLIENT_WORKAROUNDS=",
- set->client_workarounds, NULL));
- env_put(t_strdup_printf("MAIL_MAX_KEYWORD_LENGTH=%u",
- set->mail_max_keyword_length));
- env_put(t_strdup_printf("IMAP_MAX_LINE_LENGTH=%u",
- set->imap_max_line_length));
- env_put(t_strconcat("IMAP_CAPABILITY=",
- set->imap_capability, NULL));
-
- if (set->mail_save_crlf)
- env_put("MAIL_SAVE_CRLF=1");
- if (set->mail_read_mmaped)
- env_put("MAIL_READ_MMAPED=1");
- if (set->mmap_disable)
- env_put("MMAP_DISABLE=1");
- if (set->mmap_no_write)
- env_put("MMAP_NO_WRITE=1");
- if (set->fcntl_locks_disable)
- env_put("FCNTL_LOCKS_DISABLE=1");
- if (set->maildir_stat_dirs)
- env_put("MAILDIR_STAT_DIRS=1");
- if (set->maildir_copy_with_hardlinks)
- env_put("MAILDIR_COPY_WITH_HARDLINKS=1");
- if (set->maildir_check_content_changes)
- env_put("MAILDIR_CHECK_CONTENT_CHANGES=1");
- if (set->mail_full_filesystem_access)
- env_put("FULL_FILESYSTEM_ACCESS=1");
- if (set->pop3_mails_keep_recent)
- env_put("POP3_MAILS_KEEP_RECENT=1");
- (void)umask(set->umask);
-
- env_put(t_strconcat("MBOX_READ_LOCKS=", set->mbox_read_locks, NULL));
- env_put(t_strconcat("MBOX_WRITE_LOCKS=", set->mbox_write_locks, NULL));
- env_put(t_strdup_printf("MBOX_LOCK_TIMEOUT=%u",
- set->mbox_lock_timeout));
- env_put(t_strdup_printf("MBOX_DOTLOCK_CHANGE_TIMEOUT=%u",
- set->mbox_dotlock_change_timeout));
-
- if (group->set->mail_use_modules &&
- group->set->mail_modules != NULL &&
- *group->set->mail_modules != '\0') {
- env_put(t_strconcat("MODULE_DIR=",
- group->set->mail_modules, NULL));
- }
-
- /* user given environment - may be malicious. virtual_user comes from
- auth process, but don't trust that too much either. Some auth
- mechanism might allow leaving extra data there. */
- if (*mail == '\0' && set->default_mail_env != NULL)
- mail = expand_mail_env(set->default_mail_env, var_expand_table);
-
- if (set->server->namespaces != NULL) {
- env_put_namespace(set->server->namespaces,
- mail, var_expand_table);
- }
-
- env_put(t_strconcat("MAIL=", mail, NULL));
env_put(t_strconcat("USER=", data + reply->virtual_user_idx, NULL));
addr = net_ip2addr(remote_ip);
if (set->mail_drop_priv_before_exec)
restrict_access_by_env(TRUE);
- /* very simple argument splitting. */
- i = 0;
- argv[i++] = executable = t_strcut(group->set->mail_executable, ' ');
- argv[i] = strchr(group->set->mail_executable, ' ');
- if (argv[i] != NULL) {
- argv[i]++;
- i++;
- }
- if (title[0] != '\0')
- argv[i++] = title;
- argv[i] = NULL;
-
- /* hide the path, it's ugly */
- p = strrchr(argv[0], '/');
- if (p != NULL) argv[0] = p+1;
-
- execv(executable, (char **) argv);
+ mail_process_exec_set(set, title);
err = errno;
for (i = 0; i < 3; i++)
errno = err;
i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
- group->set->mail_executable);
+ set->mail_executable);
/* not reached */
return FALSE;