Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7091:59ac3628b8d8 HEAD
Build environment using envarr and pass it to execve(). This is faster than
using putenv() directly. restrict_access_*_env() API changed to take
environment array parameter.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 02 Jan 2008 01:36:51 +0200 |
parents | c8878d66c4a1 |
children | a31c0f6f4386 |
files | src/auth/main.c src/deliver/auth-client.c src/dict/main.c src/imap/main.c src/lib/restrict-access.c src/lib/restrict-access.h src/login-common/main.c src/master/auth-process.c src/master/child-process.c src/master/child-process.h src/master/dict-process.c src/master/login-process.c src/master/mail-process.c src/master/ssl-init.c src/plugins/expire/auth-client.c src/pop3/main.c src/util/rawlog.c |
diffstat | 17 files changed, 355 insertions(+), 294 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/main.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/auth/main.c Wed Jan 02 01:36:51 2008 +0200 @@ -209,7 +209,7 @@ add_extra_listeners(); /* Password lookups etc. may require roots, allow it. */ - restrict_access_by_env(FALSE); + restrict_access_by_env(NULL, FALSE); } static void main_init(bool nodaemon)
--- a/src/deliver/auth-client.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/deliver/auth-client.c Wed Jan 02 01:36:51 2008 +0200 @@ -173,7 +173,7 @@ extra_groups, NULL)); } - restrict_access_by_env(TRUE); + restrict_access_by_env(NULL, TRUE); return_value = EX_OK; }
--- a/src/dict/main.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/dict/main.c Wed Jan 02 01:36:51 2008 +0200 @@ -51,7 +51,7 @@ sql_drivers_init(); sql_drivers_register_all(); - restrict_access_by_env(FALSE); + restrict_access_by_env(NULL, FALSE); } static void main_init(void)
--- a/src/imap/main.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/imap/main.c Wed Jan 02 01:36:51 2008 +0200 @@ -157,7 +157,7 @@ TRUE, version); } - restrict_access_by_env(!IS_STANDALONE()); + restrict_access_by_env(NULL, !IS_STANDALONE()); } static void main_init(void)
--- a/src/lib/restrict-access.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/lib/restrict-access.c Wed Jan 02 01:36:51 2008 +0200 @@ -1,6 +1,7 @@ /* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "array.h" #include "restrict-access.h" #include "env-util.h" @@ -9,31 +10,54 @@ #include <time.h> #include <grp.h> -void restrict_access_set_env(const char *user, uid_t uid, gid_t gid, +enum restrict_env { + RESTRICT_ENV_USER, + RESTRICT_ENV_CHROOT, + RESTRICT_ENV_SETUID, + RESTRICT_ENV_SETGID, + RESTRICT_ENV_SETEXTRAGROUPS, + RESTRICT_ENV_GID_FIRST, + RESTRICT_ENV_GID_LAST, + + RESTRICT_ENV_COUNT +}; + +static const char *restrict_env_strings[RESTRICT_ENV_COUNT] = { + "RESTRICT_USER", + "RESTRICT_CHROOT", + "RESTRICT_SETUID", + "RESTRICT_SETGID", + "RESTRICT_SETEXTRAGROUPS", + "RESTRICT_GID_FIRST", + "RESTRICT_GID_LAST" +}; + +static void renv_add(ARRAY_TYPE(const_string) *env, enum restrict_env key, + const char *value) +{ + envarr_add(env, restrict_env_strings[key], value); +} + +void restrict_access_set_env(ARRAY_TYPE(const_string) *env, + const char *user, uid_t uid, gid_t gid, const char *chroot_dir, gid_t first_valid_gid, gid_t last_valid_gid, const char *extra_groups) { if (user != NULL && *user != '\0') - env_put(t_strconcat("RESTRICT_USER=", user, NULL)); + renv_add(env, RESTRICT_ENV_USER, user); if (chroot_dir != NULL && *chroot_dir != '\0') - env_put(t_strconcat("RESTRICT_CHROOT=", chroot_dir, NULL)); + renv_add(env, RESTRICT_ENV_CHROOT, chroot_dir); - env_put(t_strdup_printf("RESTRICT_SETUID=%s", dec2str(uid))); - env_put(t_strdup_printf("RESTRICT_SETGID=%s", dec2str(gid))); - if (extra_groups != NULL && *extra_groups != '\0') { - env_put(t_strconcat("RESTRICT_SETEXTRAGROUPS=", - extra_groups, NULL)); - } + renv_add(env, RESTRICT_ENV_SETUID, dec2str(uid)); + renv_add(env, RESTRICT_ENV_SETGID, dec2str(gid)); + if (extra_groups != NULL && *extra_groups != '\0') + renv_add(env, RESTRICT_ENV_SETEXTRAGROUPS, extra_groups); - if (first_valid_gid != 0) { - env_put(t_strdup_printf("RESTRICT_GID_FIRST=%s", - dec2str(first_valid_gid))); - } - if (last_valid_gid != 0) { - env_put(t_strdup_printf("RESTRICT_GID_LAST=%s", - dec2str(last_valid_gid))); - } + if (first_valid_gid != 0) + renv_add(env, RESTRICT_ENV_GID_FIRST, dec2str(first_valid_gid)); + if (last_valid_gid != 0) + renv_add(env, RESTRICT_ENV_GID_LAST, dec2str(last_valid_gid)); } static gid_t *get_groups_list(unsigned int *gid_count_r) @@ -53,7 +77,8 @@ return gid_list; } -static bool drop_restricted_groups(gid_t *gid_list, unsigned int *gid_count, +static bool drop_restricted_groups(const char *const *env_values, + gid_t *gid_list, unsigned int *gid_count, bool *have_root_group) { /* @UNSAFE */ @@ -61,9 +86,9 @@ const char *env; unsigned int i, used; - env = getenv("RESTRICT_GID_FIRST"); + env = env_values[RESTRICT_ENV_GID_FIRST]; first_valid = env == NULL ? 0 : (gid_t)strtoul(env, NULL, 10); - env = getenv("RESTRICT_GID_LAST"); + env = env_values[RESTRICT_ENV_GID_LAST]; last_valid = env == NULL ? (gid_t)-1 : (gid_t)strtoul(env, NULL, 10); for (i = 0, used = 0; i < *gid_count; i++) { @@ -93,19 +118,20 @@ return group->gr_gid; } -static void fix_groups_list(const char *extra_groups, gid_t egid, +static void fix_groups_list(const char *const *env_values, gid_t egid, bool preserve_existing, bool *have_root_group) { gid_t *gid_list; - const char *const *tmp, *empty = NULL; + const char *const *tmp, *extra_groups, *empty = NULL; unsigned int gid_count; + extra_groups = env_values[RESTRICT_ENV_SETEXTRAGROUPS]; tmp = extra_groups == NULL ? &empty : t_strsplit_spaces(extra_groups, ", "); if (preserve_existing) { gid_list = get_groups_list(&gid_count); - if (!drop_restricted_groups(gid_list, &gid_count, + if (!drop_restricted_groups(env_values, gid_list, &gid_count, have_root_group) && *tmp == NULL) { /* nothing dropped, no extra groups to grant. */ @@ -135,17 +161,40 @@ } } -void restrict_access_by_env(bool disallow_root) +void restrict_access_by_env(ARRAY_TYPE(const_string) *envarr, + bool disallow_root) { - const char *env; + const char *env_values[RESTRICT_ENV_COUNT], *const *envs, *env; + const char *home = NULL; + unsigned int i, j, count, len; gid_t gid; uid_t uid; bool is_root, have_root_group, preserve_groups = FALSE; + if (envarr == NULL) { + /* use environment */ + for (i = 0; i < RESTRICT_ENV_COUNT; i++) + env_values[i] = getenv(restrict_env_strings[i]); + home = getenv("HOME"); + } else { + envs = array_get(envarr, &count); + memset(env_values, 0, sizeof(env_values)); + for (i = 0; i < count; i++) { + for (j = 0; j < RESTRICT_ENV_COUNT; j++) { + len = strlen(restrict_env_strings[j]); + if (strncmp(envs[i], restrict_env_strings[j], + len) == 0 && + envs[i][len] == '=') + env_values[j] = envs[i] + len + 1; + } + if (strncmp(envs[i], "HOME=", 5) == 0) + home = envs[i] + 5; + } + } is_root = geteuid() == 0; /* set the primary group */ - env = getenv("RESTRICT_SETGID"); + env = env_values[RESTRICT_ENV_SETGID]; gid = env == NULL || *env == '\0' ? (gid_t)-1 : (gid_t)strtoul(env, NULL, 10); have_root_group = gid == 0; @@ -158,7 +207,7 @@ } /* set system user's groups */ - env = getenv("RESTRICT_USER"); + env = env_values[RESTRICT_ENV_USER]; if (env != NULL && *env != '\0' && is_root) { if (initgroups(env, gid) < 0) { i_fatal("initgroups(%s, %s) failed: %m", @@ -169,20 +218,18 @@ /* add extra groups. if we set system user's groups, drop the restricted groups at the same time. */ - env = getenv("RESTRICT_SETEXTRAGROUPS"); if (is_root) { T_FRAME( - fix_groups_list(env, gid, preserve_groups, + fix_groups_list(env_values, gid, preserve_groups, &have_root_group); ); } /* chrooting */ - env = getenv("RESTRICT_CHROOT"); + env = env_values[RESTRICT_ENV_CHROOT]; if (env != NULL && *env != '\0') { /* kludge: localtime() must be called before chroot(), or the timezone isn't known */ - const char *home = getenv("HOME"); time_t t = 0; (void)localtime(&t); @@ -202,7 +249,7 @@ } /* uid last */ - env = getenv("RESTRICT_SETUID"); + env = env_values[RESTRICT_ENV_SETUID]; uid = env == NULL || *env == '\0' ? 0 : (uid_t)strtoul(env, NULL, 10); if (uid != 0) { if (setuid(uid) != 0) { @@ -220,7 +267,7 @@ } } - env = getenv("RESTRICT_GID_FIRST"); + env = env_values[RESTRICT_ENV_GID_FIRST]; if ((!have_root_group || (env != NULL && atoi(env) != 0)) && uid != 0) { if (getgid() == 0 || getegid() == 0 || setgid(0) == 0) { if (gid == 0) @@ -230,13 +277,4 @@ dec2str(getgid()), dec2str(getegid())); } } - - /* clear the environment, so we don't fail if we get back here */ - env_put("RESTRICT_USER="); - env_put("RESTRICT_CHROOT="); - env_put("RESTRICT_SETUID="); - env_put("RESTRICT_SETGID="); - env_put("RESTRICT_SETEXTRAGROUPS="); - env_put("RESTRICT_GID_FIRST="); - env_put("RESTRICT_GID_LAST="); }
--- a/src/lib/restrict-access.h Wed Jan 02 01:35:21 2008 +0200 +++ b/src/lib/restrict-access.h Wed Jan 02 01:36:51 2008 +0200 @@ -3,14 +3,17 @@ /* set environment variables so they can be read with restrict_access_by_env() */ -void restrict_access_set_env(const char *user, uid_t uid, gid_t gid, +void restrict_access_set_env(ARRAY_TYPE(const_string) *env, + const char *user, uid_t uid, gid_t gid, const char *chroot_dir, gid_t first_valid_gid, gid_t last_valid_gid, const char *extra_groups); /* chroot, setuid() and setgid() based on environment variables. If disallow_roots is TRUE, we'll kill ourself if we didn't have the - environment settings and we have root uid or gid. */ -void restrict_access_by_env(bool disallow_root); + environment settings and we have root uid or gid. If env=NULL, the real + environment is used. */ +void restrict_access_by_env(ARRAY_TYPE(const_string) *env, + bool disallow_root); #endif
--- a/src/login-common/main.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/login-common/main.c Wed Jan 02 01:36:51 2008 +0200 @@ -275,7 +275,7 @@ /* Refuse to run as root - we should never need it and it's dangerous with SSL. */ - restrict_access_by_env(TRUE); + restrict_access_by_env(NULL, TRUE); /* make sure we can't fork() */ restrict_process_size((unsigned int)-1, 1);
--- a/src/master/auth-process.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/master/auth-process.c Wed Jan 02 01:36:51 2008 +0200 @@ -378,18 +378,25 @@ } static void -socket_settings_env_put(const char *env_base, struct socket_settings *set) +socket_settings_env_put(ARRAY_TYPE(const_string) *env, + const char *env_base, struct socket_settings *set) { if (!set->used) return; - env_put(t_strdup_printf("%s=%s", env_base, set->path)); - if (set->mode != 0) - env_put(t_strdup_printf("%s_MODE=%o", env_base, set->mode)); - if (*set->user != '\0') - env_put(t_strdup_printf("%s_USER=%s", env_base, set->user)); - if (*set->group != '\0') - env_put(t_strdup_printf("%s_GROUP=%s", env_base, set->group)); + envarr_add(env, env_base, set->path); + if (set->mode != 0) { + envarr_add(env, t_strdup_printf("%s_MODE", env_base), + t_strdup_printf("%o", set->mode)); + } + if (*set->user != '\0') { + envarr_add(env, t_strdup_printf("%s_USER", env_base), + set->user); + } + if (*set->group != '\0') { + envarr_add(env, t_strdup_printf("%s_GROUP", env_base), + set->group); + } } static int connect_auth_socket(struct auth_process_group *group, @@ -411,7 +418,8 @@ return 0; } -static void auth_set_environment(struct auth_settings *set) +static void auth_set_environment(ARRAY_TYPE(const_string) *env, + struct auth_settings *set) { struct auth_socket_settings *as; struct auth_passdb_settings *ap; @@ -420,46 +428,46 @@ int i; /* setup access environment */ - restrict_access_set_env(set->user, set->uid, set->gid, set->chroot, + restrict_access_set_env(env, set->user, set->uid, set->gid, set->chroot, 0, 0, NULL); /* set other environment */ - env_put("DOVECOT_MASTER=1"); - env_put(t_strconcat("AUTH_NAME=", set->name, NULL)); - env_put(t_strconcat("MECHANISMS=", set->mechanisms, NULL)); - env_put(t_strconcat("REALMS=", set->realms, NULL)); - env_put(t_strconcat("DEFAULT_REALM=", set->default_realm, NULL)); - env_put(t_strconcat("USERNAME_CHARS=", set->username_chars, NULL)); - env_put(t_strconcat("ANONYMOUS_USERNAME=", - set->anonymous_username, NULL)); - env_put(t_strconcat("USERNAME_TRANSLATION=", - set->username_translation, NULL)); - env_put(t_strconcat("USERNAME_FORMAT=", set->username_format, NULL)); - env_put(t_strconcat("MASTER_USER_SEPARATOR=", - set->master_user_separator, NULL)); - env_put(t_strdup_printf("CACHE_SIZE=%u", set->cache_size)); - env_put(t_strdup_printf("CACHE_TTL=%u", set->cache_ttl)); - env_put(t_strdup_printf("CACHE_NEGATIVE_TTL=%u", - set->cache_negative_ttl)); + envarr_addb(env, "DOVECOT_MASTER"); + envarr_add(env, "AUTH_NAME", set->name); + envarr_add(env, "MECHANISMS", set->mechanisms); + envarr_add(env, "REALMS", set->realms); + envarr_add(env, "DEFAULT_REALM", set->default_realm); + envarr_add(env, "USERNAME_CHARS", set->username_chars); + envarr_add(env, "ANONYMOUS_USERNAME", set->anonymous_username); + envarr_add(env, "USERNAME_TRANSLATION", set->username_translation); + envarr_add(env, "USERNAME_FORMAT", set->username_format); + envarr_add(env, "MASTER_USER_SEPARATOR", set->master_user_separator); + envarr_addi(env, "CACHE_SIZE=%u", set->cache_size); + envarr_addi(env, "CACHE_TTL=%u", set->cache_ttl); + envarr_addi(env, "CACHE_NEGATIVE_TTL", set->cache_negative_ttl); for (ap = set->passdbs, i = 1; ap != NULL; ap = ap->next, i++) { - env_put(t_strdup_printf("PASSDB_%u_DRIVER=%s", i, ap->driver)); + envarr_add(env, t_strdup_printf("PASSDB_%u_DRIVER", i), + ap->driver); if (ap->args != NULL) { - env_put(t_strdup_printf("PASSDB_%u_ARGS=%s", - i, ap->args)); + envarr_add(env, t_strdup_printf("PASSDB_%u_ARGS", i), + ap->args); } if (ap->deny) - env_put(t_strdup_printf("PASSDB_%u_DENY=1", i)); + envarr_addb(env, t_strdup_printf("PASSDB_%u_DENY", i)); if (ap->pass) - env_put(t_strdup_printf("PASSDB_%u_PASS=1", i)); - if (ap->master) - env_put(t_strdup_printf("PASSDB_%u_MASTER=1", i)); + envarr_addb(env, t_strdup_printf("PASSDB_%u_PASS", i)); + if (ap->master) { + envarr_addb(env, + t_strdup_printf("PASSDB_%u_MASTER", i)); + } } for (au = set->userdbs, i = 1; au != NULL; au = au->next, i++) { - env_put(t_strdup_printf("USERDB_%u_DRIVER=%s", i, au->driver)); + envarr_add(env, t_strdup_printf("USERDB_%u_DRIVER", i), + au->driver); if (au->args != NULL) { - env_put(t_strdup_printf("USERDB_%u_ARGS=%s", - i, au->args)); + envarr_add(env, t_strdup_printf("USERDB_%u_ARGS", i), + au->args); } } @@ -468,34 +476,31 @@ continue; str = t_strdup_printf("AUTH_%u", i); - socket_settings_env_put(str, &as->client); - socket_settings_env_put(t_strconcat(str, "_MASTER", NULL), + socket_settings_env_put(env, str, &as->client); + socket_settings_env_put(env, t_strconcat(str, "_MASTER", NULL), &as->master); } if (set->verbose) - env_put("VERBOSE=1"); + envarr_addb(env, "VERBOSE"); if (set->debug) - env_put("VERBOSE_DEBUG=1"); + envarr_addb(env, "VERBOSE_DEBUG"); if (set->debug_passwords) - env_put("VERBOSE_DEBUG_PASSWORDS=1"); + envarr_addb(env, "VERBOSE_DEBUG_PASSWORDS"); if (set->ssl_require_client_cert) - env_put("SSL_REQUIRE_CLIENT_CERT=1"); + envarr_addb(env, "SSL_REQUIRE_CLIENT_CERT"); if (set->ssl_username_from_cert) - env_put("SSL_USERNAME_FROM_CERT=1"); + envarr_addb(env, "SSL_USERNAME_FROM_CERT"); if (set->ntlm_use_winbind) - env_put("NTLM_USE_WINBIND=1"); + envarr_addb(env, "NTLM_USE_WINBIND"); if (*set->krb5_keytab != '\0') { /* Environment used by Kerberos 5 library directly */ - env_put(t_strconcat("KRB5_KTNAME=", set->krb5_keytab, NULL)); + envarr_add(env, "KRB5_KTNAME", set->krb5_keytab); } - if (*set->gssapi_hostname != '\0') { - env_put(t_strconcat("GSSAPI_HOSTNAME=", - set->gssapi_hostname, NULL)); - } - env_put(t_strconcat("WINBIND_HELPER_PATH=", - set->winbind_helper_path, NULL)); - env_put(t_strdup_printf("FAILURE_DELAY=%u", set->failure_delay)); + if (*set->gssapi_hostname != '\0') + envarr_add(env, "GSSAPI_HOSTNAME", set->gssapi_hostname); + envarr_add(env, "WINBIND_HELPER_PATH", set->winbind_helper_path); + envarr_addi(env, "FAILURE_DELAY", set->failure_delay); restrict_process_size(set->process_size, (unsigned int)-1); } @@ -507,6 +512,7 @@ struct log_io *log; pid_t pid; int fd[2], log_fd, i; + ARRAY_TYPE(const_string) env; /* see if this is a connect socket */ as = group->set->sockets; @@ -566,7 +572,7 @@ if (dup2(log_fd, 2) < 0) i_fatal("dup2(stderr) failed: %m"); - child_process_init_env(); + child_process_init_env(&env); if (group->listen_fd != 3) { if (dup2(group->listen_fd, 3) < 0) @@ -577,23 +583,24 @@ for (i = 0; i <= 2; i++) fd_close_on_exec(i, FALSE); - auth_set_environment(group->set); + auth_set_environment(&env, group->set); - env_put(t_strdup_printf("AUTH_WORKER_PATH=%s/auth-worker.%s", - *group->set->chroot != '\0' ? "" : - group->set->parent->defaults->base_dir, - dec2str(getpid()))); - env_put(t_strdup_printf("AUTH_WORKER_MAX_COUNT=%u", - group->set->worker_max_count)); - env_put(t_strdup_printf("AUTH_WORKER_MAX_REQUEST_COUNT=%u", - group->set->worker_max_request_count)); + envarr_add(&env, "AUTH_WORKER_PATH", + t_strdup_printf("%s/auth-worker.%s", + *group->set->chroot != '\0' ? "" : + group->set->parent->defaults->base_dir, + dec2str(getpid()))); + envarr_addi(&env, "AUTH_WORKER_MAX_COUNT", + group->set->worker_max_count); + envarr_addi(&env, "AUTH_WORKER_MAX_REQUEST_COUNT", + group->set->worker_max_request_count); /* make sure we don't leak syslog fd, but do it last so that any errors above will be logged */ closelog(); executable = group->set->executable; - client_process_exec(executable, ""); + client_process_exec(executable, "", &env); i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable); return -1; } @@ -604,6 +611,7 @@ const char *prefix, *executable; pid_t pid; int log_fd, i; + ARRAY_TYPE(const_string) env; log_fd = log_create_pipe(&log, 0); if (log_fd < 0) @@ -651,15 +659,15 @@ fd_close_on_exec(i, FALSE); fd_close_on_exec(4, FALSE); - child_process_init_env(); - auth_set_environment(process->group->set); + child_process_init_env(&env); + auth_set_environment(&env, process->group->set); /* make sure we don't leak syslog fd, but do it last so that any errors above will be logged */ closelog(); executable = t_strconcat(process->group->set->executable, " -w", NULL); - client_process_exec(executable, ""); + client_process_exec(executable, "", &env); i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable); return -1; }
--- a/src/master/child-process.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/master/child-process.c Wed Jan 02 01:36:51 2008 +0200 @@ -2,6 +2,7 @@ #include "common.h" #include "lib-signals.h" +#include "array.h" #include "hash.h" #include "env-util.h" #include "syslog-util.h" @@ -40,32 +41,32 @@ hash_remove(processes, POINTER_CAST(pid)); } -void child_process_init_env(void) +void child_process_init_env(ARRAY_TYPE(const_string) *env) { int facility; - /* remove all environment, we don't need them */ - env_clean(); + t_array_init(env, 128); /* we'll log through master process */ - env_put("LOG_TO_MASTER=1"); + envarr_addb(env, "LOG_TO_MASTER"); if (env_tz != NULL) - env_put(t_strconcat("TZ=", env_tz, NULL)); + envarr_add(env, "TZ=", env_tz); if (settings_root == NULL || !syslog_facility_find(settings_root->defaults->syslog_facility, &facility)) facility = LOG_MAIL; - env_put(t_strdup_printf("SYSLOG_FACILITY=%d", facility)); + envarr_addi(env, "SYSLOG_FACILITY", facility); if (settings_root != NULL && !settings_root->defaults->version_ignore) - env_put("DOVECOT_VERSION="PACKAGE_VERSION); + envarr_add(env, "DOVECOT_VERSION", PACKAGE_VERSION); #ifdef DEBUG - if (gdb) env_put("GDB=1"); + if (gdb) envarr_addb(env, "GDB"); #endif } -void client_process_exec(const char *cmd, const char *title) +void client_process_exec(const char *cmd, const char *title, + ARRAY_TYPE(const_string) *env) { const char *executable, *p, **argv; @@ -81,7 +82,9 @@ p = strrchr(argv[0], '/'); if (p != NULL) argv[0] = p+1; - execv(executable, (char **)argv); + (void)array_append_space(env); /* NULL-terminate */ + execve(executable, (char **)argv, + (char **)array_idx_modifiable(env, 0)); } static const char *get_exit_status_message(enum fatal_exit_status status)
--- a/src/master/child-process.h Wed Jan 02 01:35:21 2008 +0200 +++ b/src/master/child-process.h Wed Jan 02 01:36:51 2008 +0200 @@ -30,8 +30,9 @@ void child_process_add(pid_t pid, struct child_process *process); void child_process_remove(pid_t pid); -void child_process_init_env(void); -void client_process_exec(const char *cmd, const char *title); +void child_process_init_env(ARRAY_TYPE(const_string) *env); +void client_process_exec(const char *cmd, const char *title, + ARRAY_TYPE(const_string) *env); void child_process_set_destroy_callback(enum process_type type, child_process_destroy_callback_t *cb);
--- a/src/master/dict-process.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/master/dict-process.c Wed Jan 02 01:36:51 2008 +0200 @@ -36,6 +36,7 @@ unsigned int i, count; int log_fd; pid_t pid; + ARRAY_TYPE(const_string) env; log_fd = log_create_pipe(&log, 0); if (log_fd < 0) @@ -81,20 +82,22 @@ for (i = 0; i <= 3; i++) fd_close_on_exec(i, FALSE); - child_process_init_env(); - env_put(t_strconcat("DICT_LISTEN_FROM_FD=", process->path, NULL)); + child_process_init_env(&env); + envarr_add(&env, "DICT_LISTEN_FROM_FD", process->path); dicts = array_get(&settings_root->dicts, &count); i_assert((count % 2) == 0); - for (i = 0; i < count; i += 2) - env_put(t_strdup_printf("DICT_%s=%s", dicts[i], dicts[i+1])); + for (i = 0; i < count; i += 2) { + envarr_add(&env, t_strdup_printf("DICT_%s", dicts[i]), + dicts[i+1]); + } /* make sure we don't leak syslog fd, but do it last so that any errors above will be logged */ closelog(); executable = PKG_LIBEXECDIR"/dict"; - client_process_exec(executable, ""); + client_process_exec(executable, "", &env); i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable); return -1; }
--- a/src/master/login-process.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/master/login-process.c Wed Jan 02 01:36:51 2008 +0200 @@ -505,22 +505,23 @@ i_free(p); } -static void login_process_init_env(struct login_group *group, pid_t pid) +static void login_process_init_env(ARRAY_TYPE(const_string) *env, + struct login_group *group, pid_t pid) { struct settings *set = group->set; - child_process_init_env(); + child_process_init_env(env); /* setup access environment - needs to be done after clean_child_process() since it clears environment. Don't set user parameter since we don't want to call initgroups() for login processes. */ - restrict_access_set_env(NULL, set->login_uid, + restrict_access_set_env(env, NULL, set->login_uid, set->server->login_gid, set->login_chroot ? set->login_dir : NULL, 0, 0, NULL); - env_put("DOVECOT_MASTER=1"); + envarr_addb(env, "DOVECOT_MASTER"); if (!set->ssl_disable) { const char *ssl_key_password; @@ -528,57 +529,51 @@ ssl_key_password = *set->ssl_key_password != '\0' ? set->ssl_key_password : ssl_manual_key_password; - if (*set->ssl_ca_file != '\0') { - env_put(t_strconcat("SSL_CA_FILE=", - set->ssl_ca_file, NULL)); + if (*set->ssl_ca_file != '\0') + envarr_add(env, "SSL_CA_FILE", set->ssl_ca_file); + envarr_add(env, "SSL_CERT_FILE", set->ssl_cert_file); + envarr_add(env, "SSL_KEY_FILE", set->ssl_key_file); + envarr_add(env, "SSL_KEY_PASSWORD", ssl_key_password); + envarr_add(env, "SSL_PARAM_FILE", SSL_PARAMETERS_FILENAME); + if (*set->ssl_cipher_list != '\0') { + envarr_add(env, "SSL_CIPHER_LIST", + set->ssl_cipher_list); } - env_put(t_strconcat("SSL_CERT_FILE=", - set->ssl_cert_file, NULL)); - env_put(t_strconcat("SSL_KEY_FILE=", - set->ssl_key_file, NULL)); - env_put(t_strconcat("SSL_KEY_PASSWORD=", - ssl_key_password, NULL)); - env_put("SSL_PARAM_FILE="SSL_PARAMETERS_FILENAME); - if (*set->ssl_cipher_list != '\0') { - env_put(t_strconcat("SSL_CIPHER_LIST=", - set->ssl_cipher_list, NULL)); - } - env_put(t_strconcat("SSL_CERT_USERNAME_FIELD=", - set->ssl_cert_username_field, NULL)); + envarr_add(env, "SSL_CERT_USERNAME_FIELD", + set->ssl_cert_username_field); if (set->ssl_verify_client_cert) - env_put("SSL_VERIFY_CLIENT_CERT=1"); + envarr_addb(env, "SSL_VERIFY_CLIENT_CERT"); } if (set->disable_plaintext_auth) - env_put("DISABLE_PLAINTEXT_AUTH=1"); + envarr_addb(env, "DISABLE_PLAINTEXT_AUTH"); if (set->verbose_proctitle) - env_put("VERBOSE_PROCTITLE=1"); + envarr_addb(env, "VERBOSE_PROCTITLE"); if (set->verbose_ssl) - env_put("VERBOSE_SSL=1"); + envarr_addb(env, "VERBOSE_SSL"); if (set->server->auths->verbose) - env_put("VERBOSE_AUTH=1"); + envarr_addb(env, "VERBOSE_AUTH"); if (set->login_process_per_connection) { - env_put("PROCESS_PER_CONNECTION=1"); - env_put("MAX_CONNECTIONS=1"); + envarr_addi(env, "PROCESS_PER_CONNECTION", 1); + envarr_addi(env, "MAX_CONNECTIONS", 1); } else { - env_put(t_strdup_printf("MAX_CONNECTIONS=%u", - set->login_max_connections)); + envarr_addi(env, "MAX_CONNECTIONS", + set->login_max_connections); } - env_put(t_strconcat("PROCESS_UID=", dec2str(pid), NULL)); - env_put(t_strconcat("GREETING=", set->login_greeting, NULL)); - env_put(t_strconcat("LOG_FORMAT_ELEMENTS=", - set->login_log_format_elements, NULL)); - env_put(t_strconcat("LOG_FORMAT=", set->login_log_format, NULL)); + envarr_add(env, "PROCESS_UID", dec2str(pid)); + envarr_add(env, "GREETING", set->login_greeting); + envarr_add(env, "LOG_FORMAT_ELEMENTS", set->login_log_format_elements); + envarr_add(env, "LOG_FORMAT", set->login_log_format); if (set->login_greeting_capability) - env_put("GREETING_CAPABILITY=1"); + envarr_addb(env, "GREETING_CAPABILITY"); if (group->mail_process_type == PROCESS_TYPE_IMAP) { - env_put(t_strconcat("CAPABILITY_STRING=", - *set->imap_capability != '\0' ? - set->imap_capability : - set->imap_generated_capability, NULL)); + envarr_add(env, "CAPABILITY_STRING", + *set->imap_capability != '\0' ? + set->imap_capability : + set->imap_generated_capability); } } @@ -592,6 +587,7 @@ ARRAY_TYPE(dup2) dups; unsigned int i, fd_limit, listen_count = 0, ssl_listen_count = 0; int fd[2], log_fd, cur_fd, tmp_fd; + ARRAY_TYPE(const_string) env; if (group->set->login_uid == 0) i_fatal("Login process must not run as root"); @@ -672,10 +668,10 @@ (void)close(fd[0]); (void)close(fd[1]); - login_process_init_env(group, getpid()); + login_process_init_env(&env, group, getpid()); - env_put(t_strdup_printf("LISTEN_FDS=%u", listen_count)); - env_put(t_strdup_printf("SSL_LISTEN_FDS=%u", ssl_listen_count)); + envarr_addi(&env, "LISTEN_FDS", listen_count); + envarr_addi(&env, "SSL_LISTEN_FDS", ssl_listen_count); if (!group->set->login_chroot) { /* no chrooting, but still change to the directory */ @@ -701,7 +697,7 @@ i_assert(fd_limit > (unsigned int)cur_fd+1); (void)close(cur_fd+1); - client_process_exec(group->set->login_executable, ""); + client_process_exec(group->set->login_executable, "", &env); i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", group->set->login_executable); return -1; @@ -847,18 +843,20 @@ static int login_process_send_env(struct login_process *p) { - extern char **environ; - char **env; + ARRAY_TYPE(const_string) env; + const char *const *envs; ssize_t len; + unsigned int i, count; int ret = 0; /* this will clear our environment. luckily we don't need it. */ - login_process_init_env(p->group, p->pid); + login_process_init_env(&env, p->group, p->pid); - for (env = environ; *env != NULL; env++) { - len = strlen(*env); + envs = array_get(&env, &count); + for (i = 0; i < count; i++) { + len = strlen(envs[i]); - if (o_stream_send(p->output, *env, len) != len || + if (o_stream_send(p->output, envs[i], len) != len || o_stream_send(p->output, "\n", 1) != 1) { ret = -1; break; @@ -884,11 +882,16 @@ static bool login_process_init_group(struct login_process *p) { + int ret; + p->group->refcount++; p->group->processes++; p->group->listening_processes++; - if (login_process_send_env(p) < 0) { + T_FRAME( + ret = login_process_send_env(p); + ); + if (ret < 0) { i_error("login: Couldn't send environment"); return FALSE; }
--- a/src/master/mail-process.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/master/mail-process.c Wed Jan 02 01:36:51 2008 +0200 @@ -235,8 +235,14 @@ return str_c(str); } +static const char *ns_env_key(const char *name, unsigned int i) +{ + return t_strdup_printf("NAMESPACE_%u_%s", i, name); +} + static void -env_put_namespace(struct namespace_settings *ns, const char *default_location, +env_add_namespace(ARRAY_TYPE(const_string) *env, + struct namespace_settings *ns, const char *default_location, const struct var_expand_table *table) { const char *location; @@ -250,37 +256,32 @@ location = *ns->location != '\0' ? ns->location : default_location; location = expand_mail_env(location, table); - env_put(t_strdup_printf("NAMESPACE_%u=%s", i, location)); + envarr_add(env, t_strdup_printf("NAMESPACE_%u", i), location); - if (ns->separator != NULL) { - env_put(t_strdup_printf("NAMESPACE_%u_SEP=%s", - i, ns->separator)); - } - if (ns->type != NULL) { - env_put(t_strdup_printf("NAMESPACE_%u_TYPE=%s", - i, ns->type)); - } + if (ns->separator != NULL) + envarr_add(env, ns_env_key("SEP", i), ns->separator); + if (ns->type != NULL) + envarr_add(env, ns_env_key("TYPE", i), ns->type); if (ns->prefix != NULL) { /* expand variables, eg. ~%u/ can be useful */ str = t_str_new(256); - str_printfa(str, "NAMESPACE_%u_PREFIX=", i); var_expand(str, ns->prefix, table); - env_put(str_c(str)); + envarr_add(env, ns_env_key("PREFIX", i), str_c(str)); } if (ns->inbox) - env_put(t_strdup_printf("NAMESPACE_%u_INBOX=1", i)); + envarr_addb(env, ns_env_key("INBOX", i)); if (ns->hidden) - env_put(t_strdup_printf("NAMESPACE_%u_HIDDEN=1", i)); + envarr_addb(env, ns_env_key("HIDDEN", i)); if (ns->list) - env_put(t_strdup_printf("NAMESPACE_%u_LIST=1", i)); + envarr_addb(env, ns_env_key("LIST", i)); if (ns->subscriptions) - env_put(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS=1", - i)); + envarr_addb(env, ns_env_key("SUBSCRIPTIONS", i)); } } static void -mail_process_set_environment(struct settings *set, const char *mail, +mail_process_set_environment(ARRAY_TYPE(const_string) *env, + struct settings *set, const char *mail, const struct var_expand_table *var_expand_table, bool dump_capability) { @@ -288,104 +289,96 @@ string_t *str; unsigned int i, count; - 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("MAIL_CACHE_MIN_MAIL_COUNT=%u", - set->mail_cache_min_mail_count)); - env_put(t_strdup_printf("MAILBOX_IDLE_CHECK_INTERVAL=%u", - set->mailbox_idle_check_interval)); - env_put(t_strdup_printf("MAIL_MAX_KEYWORD_LENGTH=%u", - set->mail_max_keyword_length)); + (void)umask(set->umask); + + envarr_add(env, "MAIL_CACHE_FIELDS", set->mail_cache_fields); + envarr_add(env, "MAIL_NEVER_CACHE_FIELDS", + set->mail_never_cache_fields); + envarr_addi(env, "MAIL_CACHE_MIN_MAIL_COUNT", + set->mail_cache_min_mail_count); + envarr_addi(env, "MAILBOX_IDLE_CHECK_INTERVAL", + set->mailbox_idle_check_interval); + envarr_addi(env, "MAIL_MAX_KEYWORD_LENGTH", + set->mail_max_keyword_length); if (set->protocol == MAIL_PROTOCOL_IMAP) { - env_put(t_strdup_printf("IMAP_MAX_LINE_LENGTH=%u", - set->imap_max_line_length)); + envarr_addi(env, "IMAP_MAX_LINE_LENGTH", + set->imap_max_line_length); if (*set->imap_capability != '\0') { - env_put(t_strconcat("IMAP_CAPABILITY=", - set->imap_capability, NULL)); + envarr_add(env, "IMAP_CAPABILITY", + set->imap_capability); } - env_put(t_strconcat("IMAP_CLIENT_WORKAROUNDS=", - set->imap_client_workarounds, NULL)); - env_put(t_strconcat("IMAP_LOGOUT_FORMAT=", - set->imap_logout_format, NULL)); + envarr_add(env, "IMAP_CLIENT_WORKAROUNDS", + set->imap_client_workarounds); + envarr_add(env, "IMAP_LOGOUT_FORMAT", set->imap_logout_format); } if (set->protocol == MAIL_PROTOCOL_POP3) { - env_put(t_strconcat("POP3_CLIENT_WORKAROUNDS=", - set->pop3_client_workarounds, NULL)); - env_put(t_strconcat("POP3_LOGOUT_FORMAT=", - set->pop3_logout_format, NULL)); + envarr_add(env, "POP3_CLIENT_WORKAROUNDS", + set->pop3_client_workarounds); + envarr_add(env, "POP3_LOGOUT_FORMAT", set->pop3_logout_format); if (set->pop3_no_flag_updates) - env_put("POP3_NO_FLAG_UPDATES=1"); + envarr_addb(env, "POP3_NO_FLAG_UPDATES"); if (set->pop3_reuse_xuidl) - env_put("POP3_REUSE_XUIDL=1"); + envarr_addb(env, "POP3_REUSE_XUIDL"); if (set->pop3_enable_last) - env_put("POP3_ENABLE_LAST=1"); + envarr_addb(env, "POP3_ENABLE_LAST"); if (set->pop3_lock_session) - env_put("POP3_LOCK_SESSION=1"); + envarr_addb(env, "POP3_LOCK_SESSION"); } /* We care about POP3 UIDL format in all process types */ - env_put(t_strconcat("POP3_UIDL_FORMAT=", set->pop3_uidl_format, NULL)); + envarr_add(env, "POP3_UIDL_FORMAT", set->pop3_uidl_format); if (set->mail_save_crlf) - env_put("MAIL_SAVE_CRLF=1"); + envarr_addb(env, "MAIL_SAVE_CRLF"); if (set->mmap_disable) - env_put("MMAP_DISABLE=1"); + envarr_addb(env, "MMAP_DISABLE"); if (set->dotlock_use_excl) - env_put("DOTLOCK_USE_EXCL=1"); + envarr_addb(env, "DOTLOCK_USE_EXCL"); if (set->fsync_disable) - env_put("FSYNC_DISABLE=1"); + envarr_addb(env, "FSYNC_DISABLE"); if (set->mail_nfs_storage) - env_put("MAIL_NFS_STORAGE=1"); + envarr_addb(env, "MAIL_NFS_STORAGE"); if (set->mail_nfs_index) - env_put("MAIL_NFS_INDEX=1"); + envarr_addb(env, "MAIL_NFS_INDEX"); if (set->mailbox_list_index_disable) - env_put("MAILBOX_LIST_INDEX_DISABLE=1"); + envarr_addb(env, "MAILBOX_LIST_INDEX_DISABLE"); if (set->maildir_stat_dirs) - env_put("MAILDIR_STAT_DIRS=1"); + envarr_addb(env, "MAILDIR_STAT_DIRS"); if (set->maildir_copy_with_hardlinks) - env_put("MAILDIR_COPY_WITH_HARDLINKS=1"); + envarr_addb(env, "MAILDIR_COPY_WITH_HARDLINKS"); if (set->maildir_copy_preserve_filename) - env_put("MAILDIR_COPY_PRESERVE_FILENAME=1"); + envarr_addb(env, "MAILDIR_COPY_PRESERVE_FILENAME"); if (set->mail_debug) - env_put("DEBUG=1"); + envarr_addb(env, "DEBUG"); if (set->mail_full_filesystem_access) - env_put("FULL_FILESYSTEM_ACCESS=1"); + envarr_addb(env, "FULL_FILESYSTEM_ACCESS"); if (set->mbox_dirty_syncs) - env_put("MBOX_DIRTY_SYNCS=1"); + envarr_addb(env, "MBOX_DIRTY_SYNCS"); if (set->mbox_very_dirty_syncs) - env_put("MBOX_VERY_DIRTY_SYNCS=1"); + envarr_addb(env, "MBOX_VERY_DIRTY_SYNCS"); if (set->mbox_lazy_writes) - env_put("MBOX_LAZY_WRITES=1"); + envarr_addb(env, "MBOX_LAZY_WRITES"); /* when running dump-capability log still points to stderr, and io_add()ing it might break (epoll_ctl() gives EPERM) */ if (set->shutdown_clients && !dump_capability) - env_put("STDERR_CLOSE_SHUTDOWN=1"); - (void)umask(set->umask); + envarr_addb(env, "STDERR_CLOSE_SHUTDOWN"); - env_put(t_strconcat("LOCK_METHOD=", set->lock_method, NULL)); - 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)); - env_put(t_strdup_printf("MBOX_MIN_INDEX_SIZE=%u", - set->mbox_min_index_size)); + envarr_add(env, "LOCK_METHOD", set->lock_method); + envarr_add(env, "MBOX_READ_LOCKS", set->mbox_read_locks); + envarr_add(env, "MBOX_WRITE_LOCKS", set->mbox_write_locks); + envarr_addi(env, "MBOX_LOCK_TIMEOUT", set->mbox_lock_timeout); + envarr_addi(env, "MBOX_DOTLOCK_CHANGE_TIMEOUT", + set->mbox_dotlock_change_timeout); + envarr_addi(env, "MBOX_MIN_INDEX_SIZE", set->mbox_min_index_size); - env_put(t_strdup_printf("DBOX_ROTATE_SIZE=%u", - set->dbox_rotate_size)); - env_put(t_strdup_printf("DBOX_ROTATE_MIN_SIZE=%u", - set->dbox_rotate_min_size)); - env_put(t_strdup_printf("DBOX_ROTATE_DAYS=%u", - set->dbox_rotate_days)); + envarr_addi(env, "DBOX_ROTATE_SIZE", set->dbox_rotate_size); + envarr_addi(env, "DBOX_ROTATE_MIN_SIZE", set->dbox_rotate_min_size); + envarr_addi(env, "DBOX_ROTATE_DAYS", set->dbox_rotate_days); if (*set->mail_plugins != '\0') { - env_put(t_strconcat("MAIL_PLUGIN_DIR=", - set->mail_plugin_dir, NULL)); - env_put(t_strconcat("MAIL_PLUGINS=", set->mail_plugins, NULL)); + envarr_add(env, "MAIL_PLUGIN_DIR", set->mail_plugin_dir); + envarr_add(env, "MAIL_PLUGINS", set->mail_plugins); } /* user given environment - may be malicious. virtual_user comes from @@ -393,10 +386,10 @@ mechanism might allow leaving extra data there. */ if ((mail == NULL || *mail == '\0') && *set->mail_location != '\0') mail = expand_mail_env(set->mail_location, var_expand_table); - env_put(t_strconcat("MAIL=", mail, NULL)); + envarr_add(env, "MAIL", mail); if (set->server->namespaces != NULL) { - env_put_namespace(set->server->namespaces, + env_add_namespace(env, set->server->namespaces, mail, var_expand_table); } @@ -407,8 +400,7 @@ str_truncate(str, 0); var_expand(str, envs[i+1], var_expand_table); - env_put(t_strconcat(t_str_ucase(envs[i]), "=", - str_c(str), NULL)); + envarr_add(env, t_str_ucase(envs[i]), str_c(str)); } } @@ -418,6 +410,7 @@ const struct var_expand_table *var_expand_table; struct settings *set; const char *executable; + ARRAY_TYPE(const_string) env; if (strcmp(protocol, "ext") == 0) { /* external binary. section contains path for it. */ @@ -451,24 +444,24 @@ getpid(), geteuid()); /* set up logging */ - env_put(t_strconcat("LOG_TIMESTAMP=", set->log_timestamp, NULL)); + t_array_init(&env, 128); + envarr_add(&env, "LOG_TIMESTAMP", set->log_timestamp); if (*set->log_path == '\0') - env_put("USE_SYSLOG=1"); + envarr_addb(&env, "USE_SYSLOG"); else - env_put(t_strconcat("LOGFILE=", set->log_path, NULL)); + envarr_add(&env, "LOGFILE", set->log_path); if (*set->info_log_path != '\0') - env_put(t_strconcat("INFOLOGFILE=", set->info_log_path, NULL)); + envarr_add(&env, "INFOLOGFILE", set->info_log_path); if (*set->mail_log_prefix != '\0') { string_t *str = t_str_new(256); - str_append(str, "LOG_PREFIX="); var_expand(str, set->mail_log_prefix, var_expand_table); - env_put(str_c(str)); + envarr_add(&env, "LOG_PREFIX", str_c(str)); } - mail_process_set_environment(set, getenv("MAIL"), var_expand_table, + mail_process_set_environment(&env, set, getenv("MAIL"), var_expand_table, FALSE); - client_process_exec(executable, ""); + client_process_exec(executable, "", &env); i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable); } @@ -528,6 +521,7 @@ pid_t pid; uid_t uid; gid_t gid; + ARRAY_TYPE(const_string) env, restrict_env, *dest_env; ARRAY_DEFINE(extra_args, const char *); unsigned int i, count, left, process_count; int ret, log_fd, nice, chdir_errno; @@ -700,7 +694,7 @@ log_set_prefix(log, str_c(str)); } - child_process_init_env(); + child_process_init_env(&env); /* move the client socket into stdin and stdout fds, log to stderr */ if (dup2(dump_capability ? null_fd : socket, 0) < 0) @@ -715,14 +709,20 @@ /* setup environment - set the most important environment first (paranoia about filling up environment without noticing) */ - restrict_access_set_env(system_user, uid, gid, chroot_dir, + if (!set->mail_drop_priv_before_exec) + dest_env = &env; + else { + t_array_init(&restrict_env, 8); + dest_env = &restrict_env; + } + restrict_access_set_env(dest_env, system_user, uid, gid, chroot_dir, set->first_valid_gid, set->last_valid_gid, set->mail_extra_groups); restrict_process_size(set->mail_process_size, (unsigned int)-1); if (dump_capability) - env_put("DUMP_CAPABILITY=1"); + envarr_addb(&env, "DUMP_CAPABILITY"); if (*home_dir == '\0') { full_home_dir = ""; @@ -772,7 +772,7 @@ i_fatal("chdir(/tmp) failed: %m"); } - mail_process_set_environment(set, mail, var_expand_table, + mail_process_set_environment(&env, set, mail, var_expand_table, dump_capability); /* extra args. uppercase key value. */ @@ -786,12 +786,13 @@ p = strchr(args[i], '='); if (p == NULL) { /* boolean */ - env_put(t_strconcat(t_str_ucase(args[i]), "=1", NULL)); + envarr_addb(&env, t_str_ucase(args[i])); } else { /* key=value */ - env_put(t_strconcat(t_str_ucase( - t_strdup_until(args[i], p)), p, NULL)); + envarr_add(&env, + t_str_ucase(t_strdup_until(args[i], p)), + p + 1); } } @@ -805,12 +806,12 @@ nfs_warn_if_found(mail_location, full_home_dir); } - env_put("LOGGED_IN=1"); - env_put(t_strconcat("HOME=", home_dir, NULL)); - env_put(t_strconcat("USER=", user, NULL)); + envarr_addb(&env, "LOGGED_IN"); + envarr_add(&env, "HOME", home_dir); + envarr_add(&env, "USER", user); addr = net_ip2addr(remote_ip); - env_put(t_strconcat("IP=", addr, NULL)); + envarr_add(&env, "IP", addr); if (!set->verbose_proctitle) title[0] = '\0'; @@ -826,9 +827,9 @@ closelog(); if (set->mail_drop_priv_before_exec) - restrict_access_by_env(TRUE); + restrict_access_by_env(&restrict_env, TRUE); - client_process_exec(set->mail_executable, title); + client_process_exec(set->mail_executable, title, &env); i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", set->mail_executable);
--- a/src/master/ssl-init.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/master/ssl-init.c Wed Jan 02 01:36:51 2008 +0200 @@ -31,6 +31,7 @@ struct log_io *log; pid_t pid; int log_fd; + ARRAY_TYPE(const_string) env; log_fd = log_create_pipe(&log, 10); if (log_fd == -1) @@ -60,9 +61,9 @@ if (dup2(log_fd, 2) < 0) i_fatal("dup2(stderr) failed: %m"); - child_process_init_env(); + child_process_init_env(&env); client_process_exec(t_strconcat(binpath, " "SSL_PARAMETERS_PERM_PATH, - NULL), ""); + NULL), "", &env); i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", binpath); }
--- a/src/plugins/expire/auth-client.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/plugins/expire/auth-client.c Wed Jan 02 01:36:51 2008 +0200 @@ -143,7 +143,7 @@ conn->current_uid = uid; } - restrict_access_by_env(FALSE); + restrict_access_by_env(NULL, FALSE); conn->return_value = 1; }
--- a/src/pop3/main.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/pop3/main.c Wed Jan 02 01:36:51 2008 +0200 @@ -177,7 +177,7 @@ TRUE, version); } - restrict_access_by_env(!IS_STANDALONE()); + restrict_access_by_env(NULL, !IS_STANDALONE()); } static int main_init(void)
--- a/src/util/rawlog.c Wed Jan 02 01:35:21 2008 +0200 +++ b/src/util/rawlog.c Wed Jan 02 01:36:51 2008 +0200 @@ -309,7 +309,7 @@ } (void)close(sfd[1]); - restrict_access_by_env(TRUE); + restrict_access_by_env(NULL, TRUE); process_title_set(t_strdup_printf("[%s:%s rawlog]", getenv("USER"), dec2str(getppid())));