dovecot: Build environment using envarr and pass it to execve()....
dovecot at dovecot.org
dovecot at dovecot.org
Wed Jan 2 01:36:56 EET 2008
details: http://hg.dovecot.org/dovecot/rev/59ac3628b8d8
changeset: 7091:59ac3628b8d8
user: Timo Sirainen <tss at iki.fi>
date: Wed Jan 02 01:36:51 2008 +0200
description:
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.
diffstat:
17 files changed, 373 insertions(+), 312 deletions(-)
src/auth/main.c | 2
src/deliver/auth-client.c | 2
src/dict/main.c | 2
src/imap/main.c | 2
src/lib/restrict-access.c | 130 ++++++++++++++-------
src/lib/restrict-access.h | 9 +
src/login-common/main.c | 2
src/master/auth-process.c | 146 +++++++++++++-----------
src/master/child-process.c | 23 ++-
src/master/child-process.h | 5
src/master/dict-process.c | 13 +-
src/master/login-process.c | 113 +++++++++----------
src/master/mail-process.c | 225 +++++++++++++++++++-------------------
src/master/ssl-init.c | 5
src/plugins/expire/auth-client.c | 2
src/pop3/main.c | 2
src/util/rawlog.c | 2
diffs (truncated from 1346 to 300 lines):
diff -r c8878d66c4a1 -r 59ac3628b8d8 src/auth/main.c
--- 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 @@ static void drop_privileges(void)
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)
diff -r c8878d66c4a1 -r 59ac3628b8d8 src/deliver/auth-client.c
--- 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 @@ static void auth_parse_input(struct auth
extra_groups, NULL));
}
- restrict_access_by_env(TRUE);
+ restrict_access_by_env(NULL, TRUE);
return_value = EX_OK;
}
diff -r c8878d66c4a1 -r 59ac3628b8d8 src/dict/main.c
--- 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 @@ static void drop_privileges(void)
sql_drivers_init();
sql_drivers_register_all();
- restrict_access_by_env(FALSE);
+ restrict_access_by_env(NULL, FALSE);
}
static void main_init(void)
diff -r c8878d66c4a1 -r 59ac3628b8d8 src/imap/main.c
--- 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 @@ static void drop_privileges(void)
TRUE, version);
}
- restrict_access_by_env(!IS_STANDALONE());
+ restrict_access_by_env(NULL, !IS_STANDALONE());
}
static void main_init(void)
diff -r c8878d66c4a1 -r 59ac3628b8d8 src/lib/restrict-access.c
--- 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));
-
- 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));
- }
-
- 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)));
- }
+ renv_add(env, RESTRICT_ENV_CHROOT, chroot_dir);
+
+ 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)
+ 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 @@ static gid_t *get_groups_list(unsigned i
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 @@ static bool drop_restricted_groups(gid_t
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 @@ static gid_t get_group_id(const char *na
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 @@ static void fix_groups_list(const char *
}
}
-void restrict_access_by_env(bool disallow_root)
-{
- const char *env;
+void restrict_access_by_env(ARRAY_TYPE(const_string) *envarr,
+ bool disallow_root)
+{
+ 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 @@ void restrict_access_by_env(bool disallo
}
/* 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 @@ void restrict_access_by_env(bool disallo
/* 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 @@ void restrict_access_by_env(bool disallo
}
/* 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 @@ void restrict_access_by_env(bool disallo
}
}
- 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 @@ void restrict_access_by_env(bool disallo
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=");
-}
+}
diff -r c8878d66c4a1 -r 59ac3628b8d8 src/lib/restrict-access.h
--- 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,
More information about the dovecot-cvs
mailing list