dovecot-1.3: Cleaned up restrict_access*() API.

dovecot at dovecot.org dovecot at dovecot.org
Wed Apr 8 03:49:02 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.3/rev/967bfafe6c0a
changeset: 9044:967bfafe6c0a
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Apr 07 20:48:53 2009 -0400
description:
Cleaned up restrict_access*() API.

diffstat:

13 files changed, 187 insertions(+), 111 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        |  198 ++++++++++++++++++++++----------------
src/lib/restrict-access.h        |   44 ++++++--
src/login-common/main.c          |    2 
src/master/auth-process.c        |   10 +
src/master/login-process.c       |   11 +-
src/master/mail-process.c        |   18 ++-
src/plugins/expire/auth-client.c |    3 
src/pop3/main.c                  |    2 
src/util/rawlog.c                |    2 

diffs (truncated from 574 to 300 lines):

diff -r 126a819f1fa7 -r 967bfafe6c0a src/auth/main.c
--- a/src/auth/main.c	Tue Apr 07 18:15:25 2009 -0400
+++ b/src/auth/main.c	Tue Apr 07 20:48:53 2009 -0400
@@ -236,7 +236,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);
 	restrict_access_allow_coredumps(TRUE);
 }
 
diff -r 126a819f1fa7 -r 967bfafe6c0a src/deliver/auth-client.c
--- a/src/deliver/auth-client.c	Tue Apr 07 18:15:25 2009 -0400
+++ b/src/deliver/auth-client.c	Tue Apr 07 20:48:53 2009 -0400
@@ -141,7 +141,7 @@ int auth_client_lookup_and_restrict(cons
 	case 1:
 		if (set_env(&reply, *user, euid) == 0) {
 			*user = p_strdup(pool, reply.user);
-			restrict_access_by_env(TRUE);
+			restrict_access_by_env(getenv("HOME"), TRUE);
 			ret = EX_OK;
 		}
 		break;
diff -r 126a819f1fa7 -r 967bfafe6c0a src/dict/main.c
--- a/src/dict/main.c	Tue Apr 07 18:15:25 2009 -0400
+++ b/src/dict/main.c	Tue Apr 07 20:48:53 2009 -0400
@@ -57,7 +57,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 126a819f1fa7 -r 967bfafe6c0a src/imap/main.c
--- a/src/imap/main.c	Tue Apr 07 18:15:25 2009 -0400
+++ b/src/imap/main.c	Tue Apr 07 20:48:53 2009 -0400
@@ -159,7 +159,7 @@ static void main_preinit(const struct im
 		module_dir_load((*set_r)->mail_plugin_dir,
 				(*set_r)->mail_plugins, TRUE, version);
 
-	restrict_access_by_env(!IS_STANDALONE());
+	restrict_access_by_env(getenv("HOME"), !IS_STANDALONE());
 	restrict_access_allow_coredumps(TRUE);
 }
 
diff -r 126a819f1fa7 -r 967bfafe6c0a src/lib/restrict-access.c
--- a/src/lib/restrict-access.c	Tue Apr 07 18:15:25 2009 -0400
+++ b/src/lib/restrict-access.c	Tue Apr 07 20:48:53 2009 -0400
@@ -21,36 +21,15 @@ static gid_t process_privileged_gid = (g
 static gid_t process_privileged_gid = (gid_t)-1;
 static bool process_using_priv_gid = FALSE;
 
-void restrict_access_set_env(const char *user, uid_t uid,
-			     gid_t gid, gid_t privileged_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));
-	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 (privileged_gid != (gid_t)-1) {
-		env_put(t_strdup_printf("RESTRICT_SETGID_PRIV=%s",
-					dec2str(privileged_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)));
-	}
+void restrict_access_init(struct restrict_access_settings *set)
+{
+	memset(set, 0, sizeof(*set));
+
+	set->uid = (uid_t)-1;
+	set->gid = (gid_t)-1;
+	set->privileged_gid = (gid_t)-1;
+	set->first_valid_gid = 0;
+	set->last_valid_gid = (gid_t)-1;
 }
 
 static const char *get_uid_str(uid_t uid)
@@ -148,22 +127,17 @@ static gid_t *get_groups_list(unsigned i
 	return gid_list;
 }
 
-static void drop_restricted_groups(gid_t *gid_list, unsigned int *gid_count,
+static void drop_restricted_groups(const struct restrict_access_settings *set,
+				   gid_t *gid_list, unsigned int *gid_count,
 				   bool *have_root_group)
 {
 	/* @UNSAFE */
-	gid_t first_valid, last_valid;
-	const char *env;
 	unsigned int i, used;
 
-	env = getenv("RESTRICT_GID_FIRST");
-	first_valid = env == NULL ? 0 : (gid_t)strtoul(env, NULL, 10);
-	env = getenv("RESTRICT_GID_LAST");
-	last_valid = env == NULL ? (gid_t)-1 : (gid_t)strtoul(env, NULL, 10);
-
 	for (i = 0, used = 0; i < *gid_count; i++) {
-		if (gid_list[i] >= first_valid &&
-		    (last_valid == (gid_t)-1 || gid_list[i] <= last_valid)) {
+		if (gid_list[i] >= set->first_valid_gid &&
+		    (set->last_valid_gid == (gid_t)-1 ||
+		     gid_list[i] <= set->last_valid_gid)) {
 			if (gid_list[i] == 0)
 				*have_root_group = TRUE;
 			gid_list[used++] = gid_list[i];
@@ -185,7 +159,7 @@ static gid_t get_group_id(const char *na
 	return group->gr_gid;
 }
 
-static void fix_groups_list(const char *extra_groups,
+static void fix_groups_list(const struct restrict_access_settings *set,
 			    bool preserve_existing, bool *have_root_group)
 {
 	gid_t gid, *gid_list, *gid_list2;
@@ -198,12 +172,12 @@ static void fix_groups_list(const char *
 	   so add it to supplementary groups. */
 	add_primary_gid = process_privileged_gid != (gid_t)-1;
 
-	tmp = extra_groups == NULL ? &empty :
-		t_strsplit_spaces(extra_groups, ", ");
+	tmp = set->extra_groups == NULL ? &empty :
+		t_strsplit_spaces(set->extra_groups, ", ");
 
 	if (preserve_existing) {
 		gid_list = get_groups_list(&gid_count);
-		drop_restricted_groups(gid_list, &gid_count,
+		drop_restricted_groups(set, gid_list, &gid_count,
 				       have_root_group);
 		/* see if the list already contains the primary GID */
 		for (i = 0; i < gid_count; i++) {
@@ -242,29 +216,25 @@ static void fix_groups_list(const char *
 	if (setgroups(gid_count, gid_list) < 0) {
 		if (errno == EINVAL) {
 			i_fatal("setgroups(%s) failed: Too many extra groups",
-				extra_groups == NULL ? "" : extra_groups);
+				set->extra_groups == NULL ? "" :
+				set->extra_groups);
 		} else {
 			i_fatal("setgroups() failed: %m");
 		}
 	}
 }
 
-void restrict_access_by_env(bool disallow_root)
-{
-	const char *env;
-	uid_t uid;
+void restrict_access(const struct restrict_access_settings *set,
+		     const char *home)
+{
 	bool is_root, have_root_group, preserve_groups = FALSE;
 	bool allow_root_gid;
 
 	is_root = geteuid() == 0;
 
 	/* set the primary/privileged group */
-	env = getenv("RESTRICT_SETGID");
-	process_primary_gid = env == NULL || *env == '\0' ? (gid_t)-1 :
-		(gid_t)strtoul(env, NULL, 10);
-	env = getenv("RESTRICT_SETGID_PRIV");
-	process_privileged_gid = env == NULL || *env == '\0' ? (gid_t)-1 :
-		(gid_t)strtoul(env, NULL, 10);
+	process_primary_gid = set->gid;
+	process_privileged_gid = set->privileged_gid;
 
 	have_root_group = process_primary_gid == 0;
 	if (process_primary_gid != (gid_t)-1 ||
@@ -279,33 +249,32 @@ void restrict_access_by_env(bool disallo
 	}
 
 	/* set system user's groups */
-	env = getenv("RESTRICT_USER");
-	if (env != NULL && *env != '\0' && is_root) {
-		if (initgroups(env, process_primary_gid) < 0) {
+	if (set->system_groups_user != NULL && is_root) {
+		if (initgroups(set->system_groups_user,
+			       process_primary_gid) < 0) {
 			i_fatal("initgroups(%s, %s) failed: %m",
-				env, get_gid_str(process_primary_gid));
+				set->system_groups_user,
+				get_gid_str(process_primary_gid));
 		}
 		preserve_groups = TRUE;
 	}
 
 	/* 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_BEGIN {
-		fix_groups_list(env, preserve_groups, &have_root_group);
+		fix_groups_list(set, preserve_groups,
+				&have_root_group);
 	} T_END;
 
 	/* chrooting */
-	env = getenv("RESTRICT_CHROOT");
-	if (env != NULL && *env != '\0') {
+	if (set->chroot_dir != NULL) {
 		/* 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);
 
-		if (chroot(env) != 0)
-			i_fatal("chroot(%s) failed: %m", env);
+		if (chroot(set->chroot_dir) != 0)
+			i_fatal("chroot(%s) failed: %m", set->chroot_dir);
 
 		if (home != NULL) {
 			if (chdir(home) < 0) {
@@ -320,33 +289,30 @@ void restrict_access_by_env(bool disallo
 	}
 
 	/* uid last */
-	env = getenv("RESTRICT_SETUID");
-	uid = env == NULL || *env == '\0' ? 0 : (uid_t)strtoul(env, NULL, 10);
-	if (uid != 0) {
-		if (setuid(uid) != 0) {
+	if (set->uid != (uid_t)-1) {
+		if (setuid(set->uid) != 0) {
 			i_fatal("setuid(%s) failed with euid=%s: %m",
-				get_uid_str(uid), get_uid_str(geteuid()));
+				get_uid_str(set->uid), get_uid_str(geteuid()));
 		}
 	}
 
 	/* verify that we actually dropped the privileges */
-	if (uid != 0 || disallow_root) {
+	if (set->uid != (uid_t)-1) {
 		if (setuid(0) == 0) {
-			if (uid == 0)
-				i_fatal("Running as root isn't permitted");
+			if (set->uid == 0)
+				i_fatal("This process must not be run as root");
 			i_fatal("We couldn't drop root privileges");
 		}
 	}
 
-	env = getenv("RESTRICT_GID_FIRST");
-	if (env != NULL && atoi(env) != 0)
+	if (set->first_valid_gid != 0)
 		allow_root_gid = FALSE;
 	else if (process_primary_gid == 0 || process_privileged_gid == 0)
 		allow_root_gid = TRUE;
 	else
 		allow_root_gid = FALSE;
 
-	if (!allow_root_gid && uid != 0) {
+	if (!allow_root_gid && set->uid != 0) {
 		if (getgid() == 0 || getegid() == 0 || setgid(0) == 0) {
 			if (process_primary_gid == 0)
 				i_fatal("GID 0 isn't permitted");
@@ -356,10 +322,80 @@ void restrict_access_by_env(bool disallo
 				get_gid_str(getgid()), get_gid_str(getegid()));
 		}
 	}
+}
+
+void restrict_access_set_env(const struct restrict_access_settings *set)
+{
+	if (set->system_groups_user != NULL &&
+	    *set->system_groups_user != '\0') {
+		env_put(t_strconcat("RESTRICT_USER=",
+				    set->system_groups_user, NULL));
+	}
+	if (set->chroot_dir != NULL && *set->chroot_dir != '\0')
+		env_put(t_strconcat("RESTRICT_CHROOT=", set->chroot_dir, NULL));
+
+	if (set->uid != (uid_t)-1) {
+		env_put(t_strdup_printf("RESTRICT_SETUID=%s",
+					dec2str(set->uid)));
+	}
+	if (set->gid != (gid_t)-1) {
+		env_put(t_strdup_printf("RESTRICT_SETGID=%s",
+					dec2str(set->gid)));
+	}
+	if (set->privileged_gid != (gid_t)-1) {
+		env_put(t_strdup_printf("RESTRICT_SETGID_PRIV=%s",
+					dec2str(set->privileged_gid)));


More information about the dovecot-cvs mailing list