dovecot-1.0: Make sure the primary GID is in supplementary group...

dovecot at dovecot.org dovecot at dovecot.org
Sun Mar 9 10:35:13 EET 2008


details:   http://hg.dovecot.org/dovecot-1.0/rev/28fa25a294ff
changeset: 5536:28fa25a294ff
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Mar 09 10:35:09 2008 +0200
description:
Make sure the primary GID is in supplementary groups when using
mail_privileged_group so when effective GID is switched to the privileged
GID we still have primary GID's access as well.

diffstat:

1 file changed, 41 insertions(+), 27 deletions(-)
src/lib/restrict-access.c |   68 +++++++++++++++++++++++++++------------------

diffs (122 lines):

diff -r 647633551555 -r 28fa25a294ff src/lib/restrict-access.c
--- a/src/lib/restrict-access.c	Sun Mar 09 10:31:31 2008 +0200
+++ b/src/lib/restrict-access.c	Sun Mar 09 10:35:09 2008 +0200
@@ -112,7 +112,7 @@ 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 void drop_restricted_groups(gid_t *gid_list, unsigned int *gid_count,
 				   bool *have_root_group)
 {
 	/* @UNSAFE */
@@ -133,10 +133,7 @@ static bool drop_restricted_groups(gid_t
 			gid_list[used++] = gid_list[i];
 		}
 	}
-	if (*gid_count == used)
-		return FALSE;
 	*gid_count = used;
-	return TRUE;
 }
 
 static gid_t get_group_id(const char *name)
@@ -152,42 +149,57 @@ 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 *extra_groups,
 			    bool preserve_existing, bool *have_root_group)
 {
-	gid_t *gid_list, *gid_list2;
+	gid_t gid, *gid_list, *gid_list2;
 	const char *const *tmp, *empty = NULL;
-	unsigned int gid_count;
+	unsigned int i, gid_count;
+	bool add_primary_gid;
+
+	/* if we're using a privileged GID, we can temporarily drop our
+	   effective GID. we still want to be able to use its privileges,
+	   so add it to supplementary groups. */
+	add_primary_gid = privileged_gid != (gid_t)-1;
 
 	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,
-					    have_root_group) &&
-		    *tmp == NULL) {
-			/* nothing dropped, no extra groups to grant. */
-			return;
+		drop_restricted_groups(gid_list, &gid_count,
+				       have_root_group);
+		/* see if the list already contains the primary GID */
+		for (i = 0; i < gid_count; i++) {
+			if (gid_list[i] == primary_gid) {
+				add_primary_gid = FALSE;
+				break;
+			}
 		}
 	} else {
-		if (egid == (gid_t)-1 && *tmp == NULL) {
-			/* nothing to do */
-			return;
-		}
+		gid_list = NULL;
+		gid_count = 0;
+	}
+	if (gid_count == 0) {
 		/* Some OSes don't like an empty groups list,
-		   so use the effective GID as the only one. */
+		   so use the primary GID as the only one. */
 		gid_list = t_new(gid_t, 2);
-		gid_list[0] = egid != (gid_t)-1 ? egid : getegid();
+		gid_list[0] = primary_gid;
 		gid_count = 1;
-	}
-
-	if (*tmp != NULL) {
-		/* @UNSAFE: add extra groups to gids list */
-		gid_list2 = t_new(gid_t, gid_count + strarray_length(tmp));
+		add_primary_gid = FALSE;
+	}
+
+	if (*tmp != NULL || add_primary_gid) {
+		/* @UNSAFE: add extra groups and/or primary GID to gids list */
+		gid_list2 = t_new(gid_t, gid_count + strarray_length(tmp) + 1);
 		memcpy(gid_list2, gid_list, gid_count * sizeof(gid_t));
-		for (; *tmp != NULL; tmp++)
-			gid_list2[gid_count++] = get_group_id(*tmp);
+		for (; *tmp != NULL; tmp++) {
+			gid = get_group_id(*tmp);
+			if (gid != primary_gid)
+				gid_list2[gid_count++] = gid;
+		}
+		if (add_primary_gid)
+			gid_list2[gid_count++] = primary_gid;
 		gid_list = gid_list2;
 	}
 
@@ -223,6 +235,9 @@ void restrict_access_by_env(bool disallo
 		if (primary_gid == (gid_t)-1)
 			primary_gid = getegid();
 		restrict_init_groups(primary_gid, privileged_gid);
+	} else {
+		if (primary_gid == (gid_t)-1)
+			primary_gid = getegid();
 	}
 
 	/* set system user's groups */
@@ -240,8 +255,7 @@ void restrict_access_by_env(bool disallo
 	env = getenv("RESTRICT_SETEXTRAGROUPS");
 	if (is_root) {
 		t_push();
-		fix_groups_list(env, primary_gid, preserve_groups,
-				&have_root_group);
+		fix_groups_list(env, preserve_groups, &have_root_group);
 		t_pop();
 	}
 


More information about the dovecot-cvs mailing list