Module Name:    src
Committed By:   bouyer
Date:           Wed Jul  1 07:22:52 UTC 2015

Modified Files:
        src/usr.bin/calendar [netbsd-6-0]: calendar.c

Log Message:
Pull up following revision(s) (requested by dholland in ticket #1309):
        usr.bin/calendar/calendar.c: revision 1.51
Correct privilege handling problems in calendar -a (which runs as root
from /etc/daily); do not exec other programs while the real uid is
still 0.
Also, clear the supplementary groups list up front and call initgroups
when becoming another user, to avoid leaking any extra group
privileges that we might have.
And finally, don't silently ignore errors changing uid and gid; those
are serious if they happen.


To generate a diff of this commit:
cvs rdiff -u -r1.48 -r1.48.12.1 src/usr.bin/calendar/calendar.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/calendar/calendar.c
diff -u src/usr.bin/calendar/calendar.c:1.48 src/usr.bin/calendar/calendar.c:1.48.12.1
--- src/usr.bin/calendar/calendar.c:1.48	Tue Dec  8 13:49:08 2009
+++ src/usr.bin/calendar/calendar.c	Wed Jul  1 07:22:52 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: calendar.c,v 1.48 2009/12/08 13:49:08 wiz Exp $	*/
+/*	$NetBSD: calendar.c,v 1.48.12.1 2015/07/01 07:22:52 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993, 1994
@@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 19
 #if 0
 static char sccsid[] = "@(#)calendar.c	8.4 (Berkeley) 1/7/95";
 #endif
-__RCSID("$NetBSD: calendar.c,v 1.48 2009/12/08 13:49:08 wiz Exp $");
+__RCSID("$NetBSD: calendar.c,v 1.48.12.1 2015/07/01 07:22:52 bouyer Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -48,6 +48,7 @@ __RCSID("$NetBSD: calendar.c,v 1.48 2009
 #include <sys/uio.h>
 #include <sys/wait.h>
 
+#include <assert.h>
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
@@ -112,6 +113,7 @@ static const char *months[] = {
 static void	 atodays(int, char *, unsigned short *);
 static void	 cal(void);
 static void	 closecal(FILE *);
+static void	 changeuser(void);
 static int	 getday(char *);
 static int	 getfield(char *, char **, int *);
 static void	 getmmdd(struct tm *, char *);
@@ -171,12 +173,24 @@ main(int argc, char **argv)
 		 * XXX - This ignores the user's CALENDAR_DIR variable.
 		 *       Run under user's login shell?
 		 */
+		if (setgroups(0, NULL) == -1) {
+			err(EXIT_FAILURE, "setgroups");
+		}
 		while ((pw = getpwent()) != NULL) {
-			(void)setegid(pw->pw_gid);
-			(void)seteuid(pw->pw_uid);
-			if (chdir(pw->pw_dir) != -1)
+			if (setegid(pw->pw_gid) == -1) {
+				warn("%s: setegid", pw->pw_name);
+				continue;
+			}
+			if (seteuid(pw->pw_uid) == -1) {
+				warn("%s: seteuid", pw->pw_name);
+				continue;
+			}
+			if (chdir(pw->pw_dir) != -1) {
 				cal();
-			(void)seteuid(0);
+			}
+			if (seteuid(0) == -1) {
+				warn("%s: seteuid back to 0", pw->pw_name);
+			}
 		}
 	} else if ((caldir = getenv("CALENDAR_DIR")) != NULL) {
 		if (chdir(caldir) != -1)
@@ -424,6 +438,10 @@ opencal(void)
 			(void)close(pdes[1]);
 		}
 		(void)close(pdes[0]);
+		if (doall) {
+			/* become the user properly */
+			changeuser();
+		}
 		/* tell CPP to only open regular files */
 		if(!cpp_restricted && setenv("CPP_RESTRICTED", "", 1) == -1)
 			err(EXIT_FAILURE, "Cannot restrict cpp");
@@ -488,6 +506,10 @@ closecal(FILE *fp)
 			(void)close(pdes[0]);
 		}
 		(void)close(pdes[1]);
+		if (doall) {
+			/* become the user properly */
+			changeuser();
+		}
 		(void)execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
 		    "\"Reminder Service\"", "-f", "root", NULL);
 		err(EXIT_FAILURE, "Cannot exec `%s'", _PATH_SENDMAIL);
@@ -511,6 +533,34 @@ done:	(void)fclose(fp);
 		continue;
 }
 
+static void
+changeuser(void)
+{
+	uid_t uid;
+	gid_t gid;
+
+	uid = geteuid();
+	gid = getegid();
+	assert(uid == pw->pw_uid);
+	assert(gid == pw->pw_gid);
+
+	if (seteuid(0) == -1) {
+		err(EXIT_FAILURE, "%s: changing user: cannot reassert uid 0",
+		    pw->pw_name);
+	}
+	if (setgid(gid) == -1) {
+		err(EXIT_FAILURE, "%s: cannot assume gid %d",
+		    pw->pw_name, (int)gid);
+	}
+	if (initgroups(pw->pw_name, gid) == -1) {
+		err(EXIT_FAILURE, "%s: cannot initgroups", pw->pw_name);
+	}
+	if (setuid(uid) == -1) {
+		err(EXIT_FAILURE, "%s: cannot assume uid %d",
+		    pw->pw_name, (int)uid);
+	}
+}
+
 static int
 getmonth(char *s)
 {

Reply via email to