[dovecot-cvs] dovecot/src/lib restrict-access.c, 1.12, 1.13 restrict-access.h, 1.5, 1.6

cras at procontrol.fi cras at procontrol.fi
Wed Jun 16 05:04:04 EEST 2004


Update of /home/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv2666/src/lib

Modified Files:
	restrict-access.c restrict-access.h 
Log Message:
Added mail_extra_groups setting.



Index: restrict-access.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/restrict-access.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- restrict-access.c	26 Aug 2003 21:18:16 -0000	1.12
+++ restrict-access.c	16 Jun 2004 02:04:02 -0000	1.13
@@ -17,7 +17,8 @@
 
 void restrict_access_set_env(const char *user, uid_t uid, gid_t gid,
 			     const char *chroot_dir,
-			     gid_t first_valid_gid, gid_t last_valid_gid)
+			     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));
@@ -26,6 +27,10 @@
 
 	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",
@@ -37,12 +42,34 @@
 	}
 }
 
+static gid_t *get_groups_list(int *gid_count_r)
+{
+	/* @UNSAFE */
+	gid_t *gid_list;
+	int ret, gid_count;
+
+	gid_count = NGROUPS_MAX;
+	gid_list = t_buffer_get(sizeof(gid_t) * gid_count);
+	while ((ret = getgroups(gid_count, gid_list)) < 0) {
+		if (errno != EINVAL ||
+		    gid_count < HARD_MAX_GROUPS)
+			i_fatal("getgroups() failed: %m");
+
+		gid_count *= 2;
+		gid_list = t_buffer_reget(gid_list, sizeof(gid_t) * gid_count);
+	}
+	t_buffer_alloc(sizeof(gid_t) * ret);
+
+	*gid_count_r = ret;
+	return gid_list;
+}
+
 static void drop_restricted_groups(void)
 {
 	/* @UNSAFE */
 	const char *env;
 	gid_t *gid_list, first_valid_gid, last_valid_gid;
-	int ret, i, gid_count;
+	int i, used, gid_count;
 
 	env = getenv("RESTRICT_GID_FIRST");
 	first_valid_gid = env == NULL ? 0 : (gid_t)atol(env);
@@ -52,29 +79,58 @@
 	if (first_valid_gid == 0 && last_valid_gid == 0)
 		return;
 
-	gid_count = NGROUPS_MAX;
-	gid_list = t_buffer_get(sizeof(gid_t) * gid_count);
-	while ((ret = getgroups(gid_count, gid_list)) < 0) {
-		if (errno != EINVAL ||
-		    gid_count < HARD_MAX_GROUPS)
-			i_fatal("getgroups() failed: %m");
-
-		gid_count *= 2;
-		gid_list = t_buffer_reget(gid_list, sizeof(gid_t) * gid_count);
-	}
+	t_push();
+	gid_list = get_groups_list(&gid_count);
 
-	gid_count = 0;
-	for (i = 0; i < ret; i++) {
+	for (i = 0, used = 0; i < gid_count; i++) {
 		if (gid_list[i] >= first_valid_gid &&
 		    (last_valid_gid == 0 || gid_list[i] <= last_valid_gid))
-			gid_list[gid_count++] = gid_list[i];
+			gid_list[used++] = gid_list[i];
 	}
 
-	if (ret != gid_count) {
-		/* it did contain 0, remove it */
+	if (used != gid_count) {
+		/* it did contain restricted groups, remove it */
 		if (setgroups(gid_count, gid_list) < 0)
 			i_fatal("setgroups() failed: %m");
 	}
+	t_pop();
+}
+
+static gid_t get_group_id(const char *name)
+{
+	struct group *group;
+
+	if (is_numeric(name, '\0'))
+		return (gid_t)atol(name);
+
+	group = getgrnam(name);
+	if (group == NULL)
+		i_fatal("unknown group name in extra_groups: %s", name);
+	return group->gr_gid;
+}
+
+static void grant_extra_groups(const char *groups)
+{
+	const char *const *tmp;
+	gid_t *gid_list;
+	int gid_count;
+
+	t_push();
+	tmp = t_strsplit(groups, ", ");
+	gid_list = get_groups_list(&gid_count);
+	for (; *tmp != NULL; tmp++) {
+		if (**tmp == '\0')
+			continue;
+
+		if (!t_try_realloc(gid_list, (gid_count+1) * sizeof(gid_t)))
+			i_panic("won't happen");
+		gid_list[gid_count++] = get_group_id(*tmp);
+	}
+
+	if (setgroups(gid_count, gid_list) < 0)
+		i_fatal("setgroups() failed: %m");
+
+	t_pop();
 }
 
 void restrict_access_by_env(int disallow_root)
@@ -109,9 +165,14 @@
 		}
 	}
 
+	/* grant additional groups to process */
+	env = getenv("RESTRICT_SETEXTRAGROUPS");
+	if (env != NULL && *env != '\0')
+		grant_extra_groups(env);
+
 	/* chrooting */
 	env = getenv("RESTRICT_CHROOT");
-	if (env != NULL) {
+	if (env != NULL && *env != '\0') {
 		/* kludge: localtime() must be called before chroot(),
 		   or the timezone isn't known */
 		time_t t = 0;
@@ -142,4 +203,13 @@
 		if (getgid() == 0 || getegid() == 0 || setgid(0) == 0)
 			i_fatal("We couldn't drop root group privileges");
 	}
+
+	/* 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=");
 }

Index: restrict-access.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/restrict-access.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- restrict-access.h	26 May 2003 15:26:29 -0000	1.5
+++ restrict-access.h	16 Jun 2004 02:04:02 -0000	1.6
@@ -5,7 +5,8 @@
    restrict_access_by_env() */
 void restrict_access_set_env(const char *user, uid_t uid, gid_t gid,
 			     const char *chroot_dir,
-			     gid_t first_valid_gid, gid_t last_valid_gid);
+			     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



More information about the dovecot-cvs mailing list