Submitted By: Jim Gifford (patches at jg555 dot com)
Date: 2003-09-16
Initial Package Version: 3.0.1
Origin: Mandrake Spec CVS
Description: Fixes Security Problems and Updates to Compile with gcc 3

You can go to http://cvs.mandrakesoft.com/cgi-bin/cvsweb.cgi/%7echeckout%7e/SPECS/vixie-cron
to get information on the specific patches.

diff -Naur vixie-cron-3.0.1.orig/FEATURES vixie-cron-3.0.1/FEATURES
--- vixie-cron-3.0.1.orig/FEATURES	1995-05-31 21:38:25.000000000 +0000
+++ vixie-cron-3.0.1/FEATURES	2003-09-16 17:21:12.000000000 +0000
@@ -82,3 +82,8 @@
 	act this way and do the more reasonable thing, which is (IMHO) to "or"
 	the various field-matches together.  In that sense this cron may not
 	be completely similar to some AT&T crons.
+
+--	If it exists, the /etc/cron.d/ directory is parsed like the cron
+	spool directory, except that the files in it are not user-specific
+	and are therefore read with /etc/crontab syntax (the user is
+	specified explicitly in the 6th column).
diff -Naur vixie-cron-3.0.1.orig/compat.c vixie-cron-3.0.1/compat.c
--- vixie-cron-3.0.1.orig/compat.c	1995-05-31 21:37:20.000000000 +0000
+++ vixie-cron-3.0.1/compat.c	2003-09-16 17:21:12.000000000 +0000
@@ -73,7 +73,7 @@
 		return sys_errlist[error];
 	}
 
-	sprintf(buf, "Unknown error: %d", error);
+	snprintf(buf, 32, "Unknown error: %d", error);
 	return buf;
 }
 #endif
@@ -218,16 +218,19 @@
 	int overwrite;
 {
 	char *tmp;
-
+	int tmp_size;
+	
 	if (overwrite && getenv(name))
 		return -1;
 
-	if (!(tmp = malloc(strlen(name) + strlen(value) + 2))) {
+	tmp_size = strlen(name) + strlen(value) + 2;
+	if (!(tmp = malloc(tmp_size))) {
 		errno = ENOMEM;
 		return -1;
 	}
 
-	sprintf("%s=%s", name, value);
+	/* boy, that was really broken... */
+	snprintf(tmp, tmp_size, "%s=%s", name, value);
 	return putenv(tmp);	/* intentionally orphan 'tmp' storage */
 }
 #endif
diff -Naur vixie-cron-3.0.1.orig/compat.h vixie-cron-3.0.1/compat.h
--- vixie-cron-3.0.1.orig/compat.h	1995-05-31 21:37:20.000000000 +0000
+++ vixie-cron-3.0.1/compat.h	2003-09-16 17:21:12.000000000 +0000
@@ -62,7 +62,7 @@
 #endif
 
 #ifndef POSIX
-# if (BSD >= 199103) || defined(__linux) || defined(ultrix) || defined(AIX) ||\
+# if (BSD >= 199103) || defined(__linux__) || defined(ultrix) || defined(AIX) ||\
 	defined(HPUX) || defined(CONVEX) || defined(IRIX)
 #  define POSIX
 # endif
@@ -76,16 +76,16 @@
 
 /*****************************************************************/
 
-#if !defined(BSD) && !defined(HPUX) && !defined(CONVEX) && !defined(__linux)
+#if !defined(BSD) && !defined(HPUX) && !defined(CONVEX) && !defined(__linux__)
 # define NEED_VFORK
 #endif
 
-#if (!defined(BSD) || (BSD < 198902)) && !defined(__linux) && \
+#if (!defined(BSD) || (BSD < 198902)) && !defined(__linux__) && \
 	!defined(IRIX) && !defined(NeXT) && !defined(HPUX)
 # define NEED_STRCASECMP
 #endif
 
-#if (!defined(BSD) || (BSD < 198911)) && !defined(__linux) &&\
+#if (!defined(BSD) || (BSD < 198911)) && !defined(__linux__) &&\
 	!defined(IRIX) && !defined(UNICOS) && !defined(HPUX)
 # define NEED_STRDUP
 #endif
@@ -102,7 +102,7 @@
 # define NEED_SETSID
 #endif
 
-#if (defined(POSIX) && !defined(BSD)) && !defined(__linux)
+#if (defined(POSIX) && !defined(BSD)) && !defined(__linux__)
 # define NEED_GETDTABLESIZE
 #endif
 
@@ -110,9 +110,7 @@
 # define HAVE_SAVED_UIDS
 #endif
 
-#if !defined(ATT) && !defined(__linux) && !defined(IRIX) && !defined(UNICOS)
 # define USE_SIGCHLD
-#endif
 
 #if !defined(AIX) && !defined(UNICOS)
 # define SYS_TIME_H 1
diff -Naur vixie-cron-3.0.1.orig/config.h vixie-cron-3.0.1/config.h
--- vixie-cron-3.0.1.orig/config.h	2003-09-16 17:20:48.000000000 +0000
+++ vixie-cron-3.0.1/config.h	2003-09-16 17:21:12.000000000 +0000
@@ -42,11 +42,13 @@
 			 */
 
 #define MAILCMD _PATH_SENDMAIL					/*-*/
-#define MAILARGS "%s -FCronDaemon -odi -oem -or0s %s"		/*-*/
+#define MAILARGS "%s -FCronDaemon -odi -oem %s"			/*-*/
 			/* -Fx	 = set full-name of sender
 			 * -odi	 = Option Deliverymode Interactive
 			 * -oem	 = Option Errors Mailedtosender
 			 * -or0s = Option Readtimeout -- don't time out
+			 * XXX: sendmail doesn't allow -or0s when invoked
+			 * by joe user.  --okir
 			 */
 
 /* #define MAILCMD "/bin/mail"			/*-*/
@@ -83,4 +85,4 @@
 			 * are both defined, then logging will go to both
 			 * places.
 			 */
-/*#define SYSLOG	 			/*-*/
+#define SYSLOG
diff -Naur vixie-cron-3.0.1.orig/cron.8 vixie-cron-3.0.1/cron.8
--- vixie-cron-3.0.1.orig/cron.8	2003-09-16 17:20:48.000000000 +0000
+++ vixie-cron-3.0.1/cron.8	2003-09-16 17:21:12.000000000 +0000
@@ -32,7 +32,8 @@
 searches /var/spool/cron for crontab files which are named after accounts in
 /etc/passwd; crontabs found are loaded into memory.
 .I Cron
-also searches for /etc/crontab which is in a different format (see
+also searches for /etc/crontab and the files in the /etc/cron.d/ directory,
+which are in a different format (see
 .IR crontab(5)).
 .I Cron
 then wakes up every minute, examining all stored crontabs, checking each
diff -Naur vixie-cron-3.0.1.orig/cron.c vixie-cron-3.0.1/cron.c
--- vixie-cron-3.0.1.orig/cron.c	1995-05-31 21:37:20.000000000 +0000
+++ vixie-cron-3.0.1/cron.c	2003-09-16 17:21:12.000000000 +0000
@@ -27,6 +27,7 @@
 #include <sys/signal.h>
 #if SYS_TIME_H
 # include <sys/time.h>
+# include <time.h>
 #else
 # include <time.h>
 #endif
@@ -113,8 +114,8 @@
 	database.mtime = (time_t) 0;
 	load_database(&database);
 	run_reboot_jobs(&database);
-	cron_sync();
 	while (TRUE) {
+		cron_sync();
 # if DEBUGGING
 		if (!(DebugFlags & DTEST))
 # endif /*DEBUGGING*/
@@ -125,10 +126,6 @@
 		/* do this iteration
 		 */
 		cron_tick(&database);
-
-		/* sleep 1 minute
-		 */
-		TargetTime += 60;
 	}
 }
 
@@ -205,14 +202,35 @@
  * could then get it to execute a given minute's jobs more than once.
  * instead we have the chance of missing a minute's jobs completely, but
  * that's something sysadmin's know to expect what with crashing computers..
+ * 
+ * Patch from <pererik@onedial.se>:
+ *   Do cron_sync() before each cron_sleep(), to handle changes to the system
+ *   time.
+ *
+ * Redhat bug 29868:
+ * The above patch introduced an anomaly.
+ *
+ * Unwanted double execution can occur for small backwards adjustments in
+ * clock time, such as may occur on a system that regularly syncs its clock
+ * with an outside time source. I suspect a race condition with sleep(3)
+ * as well that triggers this as well. The solution is to enforce the rule
+ * that we cannot wait for time N to occur twice in a row. Time must be 
+ * elastic enough to absorb these small adjustments. <alane@geeksrus.net>
  */
 static void
 cron_sync() {
+	static time_t lastTarget = 0;
+
  	register struct tm	*tm;
 
 	TargetTime = time((time_t*)0);
 	tm = localtime(&TargetTime);
 	TargetTime += (60 - tm->tm_sec);
+
+        if (TargetTime == lastTarget) {
+        	TargetTime += 60;
+        }
+        lastTarget = TargetTime;
 }
 
 
@@ -278,6 +296,10 @@
 static void
 sighup_handler(x) {
 	log_close();
+
+	/* we should use sigaction for proper signal blocking as this 
+	   has a race, but... */
+	signal(SIGHUP, sighup_handler);
 }
 
 
diff -Naur vixie-cron-3.0.1.orig/cron.h vixie-cron-3.0.1/cron.h
--- vixie-cron-3.0.1.orig/cron.h	1995-05-31 21:37:21.000000000 +0000
+++ vixie-cron-3.0.1/cron.h	2003-09-16 17:21:12.000000000 +0000
@@ -68,7 +68,7 @@
 #define	MAX_COMMAND	1000	/* max length of internally generated cmd */
 #define	MAX_ENVSTR	1000	/* max length of envvar=value\0 strings */
 #define	MAX_TEMPSTR	100	/* obvious */
-#define	MAX_UNAME	20	/* max length of username, should be overkill */
+#define	MAX_UNAME	32	/* max length of username, should be overkill */
 #define	ROOT_UID	0	/* don't change this, it really must be root */
 #define	ROOT_USER	"root"	/* ditto */
 
@@ -225,7 +225,7 @@
 entry		*load_entry __P((FILE *, void (*)(),
 				 struct passwd *, char **));
 
-FILE		*cron_popen __P((char *, char *));
+FILE		*cron_popen __P((char *, char *, entry *));
 
 
 				/* in the C tradition, we only create
@@ -253,6 +253,7 @@
 	};
 
 char	*ProgramName;
+char    *SyslogName;
 int	LineNumber;
 time_t	TargetTime;
 
@@ -267,7 +268,8 @@
 extern	char	*copyright[],
 		*MonthNames[],
 		*DowNames[],
-		*ProgramName;
+		*ProgramName,
+                *SyslogName;
 extern	int	LineNumber;
 extern	time_t	TargetTime;
 # if DEBUGGING
diff -Naur vixie-cron-3.0.1.orig/crontab.5 vixie-cron-3.0.1/crontab.5
--- vixie-cron-3.0.1.orig/crontab.5	1995-05-31 21:38:25.000000000 +0000
+++ vixie-cron-3.0.1/crontab.5	2003-09-16 17:21:12.000000000 +0000
@@ -84,8 +84,15 @@
 .I and
 when at least one of the two day fields (day of month, or day of week)
 match the current time (see ``Note'' below).
+Note that this means that non-existant times, such as "missing hours"
+during daylight savings conversion, will never match, causing jobs
+scheduled during the "missing times" not to be run.  Similarly, times
+that occur more than once (again, during daylight savings conversion)
+will cause matching jobs to be run twice.
+.PP
 .IR cron (8)
 examines cron entries once every minute.
+.PP
 The time and date fields are:
 .IP
 .ta 1.5i
@@ -97,9 +104,9 @@
 .br
 hour	0-23
 .br
-day of month	0-31
+day of month	1-31
 .br
-month	0-12 (or names, see below)
+month	1-12 (or names, see below)
 .br
 day of week	0-7 (0 or 7 is Sun, or use names)
 .br
@@ -163,6 +170,9 @@
 23 0-23/2 * * * echo "run 23 minutes after midn, 2am, 4am ..., everyday"
 5 4 * * sun     echo "run at 5 after 4 every sunday"
 .fi
+.SH FILES
+/etc/crontab			System crontab file
+
 .SH SEE ALSO
 cron(8), crontab(1)
 .SH EXTENSIONS
diff -Naur vixie-cron-3.0.1.orig/crontab.c vixie-cron-3.0.1/crontab.c
--- vixie-cron-3.0.1.orig/crontab.c	1995-05-31 21:38:25.000000000 +0000
+++ vixie-cron-3.0.1/crontab.c	2003-09-16 17:21:12.000000000 +0000
@@ -143,8 +143,8 @@
 		fprintf(stderr, "bailing out.\n");
 		exit(ERROR_EXIT);
 	}
-	strcpy(User, pw->pw_name);
-	strcpy(RealUser, User);
+	strncpy(User, pw->pw_name, MAX_UNAME-1);
+	strncpy(RealUser, User, MAX_UNAME-1);
 	Filename[0] = '\0';
 	Option = opt_unknown;
 	while (EOF != (argch = getopt(argc, argv, "u:lerx:"))) {
@@ -166,7 +166,7 @@
 					ProgramName, optarg);
 				exit(ERROR_EXIT);
 			}
-			(void) strcpy(User, optarg);
+			(void) strncpy(User, optarg, MAX_UNAME - 1);
 			break;
 		case 'l':
 			if (Option != opt_unknown)
@@ -197,7 +197,9 @@
 	} else {
 		if (argv[optind] != NULL) {
 			Option = opt_replace;
-			(void) strcpy (Filename, argv[optind]);
+			(void) strncpy (Filename, argv[optind], 
+					sizeof(Filename) - 1);
+			Filename[sizeof(Filename) - 1] = '\0';
 		} else {
 			usage("file name must be specified for replace");
 		}
@@ -246,7 +248,7 @@
 	int	ch;
 
 	log_it(RealUser, Pid, "LIST", User);
-	(void) sprintf(n, CRON_TAB(User));
+	(void) snprintf(n, MAX_FNAME, CRON_TAB(User));
 	if (!(f = fopen(n, "r"))) {
 		if (errno == ENOENT)
 			fprintf(stderr, "no crontab for %s\n", User);
@@ -269,7 +271,7 @@
 	char	n[MAX_FNAME];
 
 	log_it(RealUser, Pid, "DELETE", User);
-	(void) sprintf(n, CRON_TAB(User));
+	(void) snprintf(n, MAX_FNAME, CRON_TAB(User));
 	if (unlink(n)) {
 		if (errno == ENOENT)
 			fprintf(stderr, "no crontab for %s\n", User);
@@ -294,14 +296,14 @@
 edit_cmd() {
 	char		n[MAX_FNAME], q[MAX_TEMPSTR], *editor;
 	FILE		*f;
-	int		ch, t, x;
+	int		ch, t, x, saved_uid;
 	struct stat	statbuf;
 	time_t		mtime;
 	WAIT_T		waiter;
 	PID_T		pid, xpid;
 
 	log_it(RealUser, Pid, "BEGIN EDIT", User);
-	(void) sprintf(n, CRON_TAB(User));
+	(void) snprintf(n, MAX_FNAME, CRON_TAB(User));
 	if (!(f = fopen(n, "r"))) {
 		if (errno != ENOENT) {
 			perror(n);
@@ -315,7 +317,7 @@
 		}
 	}
 
-	(void) sprintf(Filename, "/tmp/crontab.%d", Pid);
+	(void) snprintf(Filename, MAX_FNAME, "/tmp/crontab.%d", Pid);
 	if (-1 == (t = open(Filename, O_CREAT|O_EXCL|O_RDWR, 0600))) {
 		perror(Filename);
 		goto fatal;
@@ -362,6 +364,12 @@
 		perror(Filename);
 		exit(ERROR_EXIT);
 	}
+	/* Do not move this statement! */
+	saved_uid = getuid();
+	if (saved_uid < 0) {
+		perror("getuid");
+		exit(ERROR_EXIT);
+	}
  again:
 	rewind(NewCrontab);
 	if (ferror(NewCrontab)) {
@@ -396,7 +404,7 @@
 		goto fatal;
 	case 0:
 		/* child */
-		if (setuid(getuid()) < 0) {
+		if (setuid(saved_uid) < 0) {
 			perror("setuid(getuid())");
 			exit(ERROR_EXIT);
 		}
@@ -409,7 +417,7 @@
 				ProgramName);
 			exit(ERROR_EXIT);
 		}
-		sprintf(q, "%s %s", editor, Filename);
+		snprintf(q, MAX_TEMPSTR, "%s %s", editor, Filename);
 		execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", q, NULL);
 		perror(editor);
 		exit(ERROR_EXIT);
@@ -496,8 +504,8 @@
 	time_t	now = time(NULL);
 	char	**envp = env_init();
 
-	(void) sprintf(n, "tmp.%d", Pid);
-	(void) sprintf(tn, CRON_TAB(n));
+	(void) snprintf(n, MAX_FNAME, "tmp.%d", Pid);
+	(void) snprintf(tn, MAX_FNAME, CRON_TAB(n));
 	if (!(tmp = fopen(tn, "w+"))) {
 		perror(tn);
 		return (-2);
@@ -585,7 +593,7 @@
 		return (-2);
 	}
 
-	(void) sprintf(n, CRON_TAB(User));
+	(void) snprintf(n, sizeof(n), CRON_TAB(User));
 	if (rename(tn, n)) {
 		fprintf(stderr, "%s: error renaming %s to %s\n",
 			ProgramName, tn, n);
diff -Naur vixie-cron-3.0.1.orig/database.c vixie-cron-3.0.1/database.c
--- vixie-cron-3.0.1.orig/database.c	1995-05-31 21:37:21.000000000 +0000
+++ vixie-cron-3.0.1/database.c	2003-09-16 17:21:12.000000000 +0000
@@ -44,6 +44,7 @@
 	DIR		*dir;
 	struct stat	statbuf;
 	struct stat	syscron_stat;
+	struct stat	crond_stat;
 	DIR_T   	*dp;
 	cron_db		new_db;
 	user		*u, *nu;
@@ -59,6 +60,11 @@
 		(void) exit(ERROR_EXIT);
 	}
 
+	if (stat("/etc/cron.d", &crond_stat) < OK) {
+		log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);
+		(void) exit(ERROR_EXIT);
+	}
+
 	/* track system crontab file
 	 */
 	if (stat(SYSCRONTAB, &syscron_stat) < OK)
@@ -71,7 +77,8 @@
 	 * so is guaranteed to be different than the stat() mtime the first
 	 * time this function is called.
 	 */
-	if (old_db->mtime == TMAX(statbuf.st_mtime, syscron_stat.st_mtime)) {
+	if (old_db->mtime == TMAX(crond_stat.st_mtime,
+			      TMAX(statbuf.st_mtime, syscron_stat.st_mtime))) {
 		Debug(DLOAD, ("[%d] spool dir mtime unch, no load needed.\n",
 			      getpid()))
 		return;
@@ -82,7 +89,8 @@
 	 * actually changed.  Whatever is left in the old database when
 	 * we're done is chaff -- crontabs that disappeared.
 	 */
-	new_db.mtime = TMAX(statbuf.st_mtime, syscron_stat.st_mtime);
+	new_db.mtime = TMAX(crond_stat.st_mtime,
+			    TMAX(statbuf.st_mtime, syscron_stat.st_mtime));
 	new_db.head = new_db.tail = NULL;
 
 	if (syscron_stat.st_mtime) {
@@ -91,6 +99,32 @@
 				&new_db, old_db);
 	}
 
+	if (!(dir = opendir("/etc/cron.d"))) {
+		log_it("CRON", getpid(), "OPENDIR FAILED", "/etc/cron.d");
+		(void) exit(ERROR_EXIT);
+	}
+
+	while (NULL != (dp = readdir(dir))) {
+		char	fname[MAXNAMLEN+1],
+			tabname[MAXNAMLEN+1];
+
+		/* avoid file names beginning with ".".  this is good
+		 * because we would otherwise waste two guaranteed calls
+		 * to getpwnam() for . and .., and there shouldn't be 
+		 * hidden files in here anyway
+		 */
+		if (dp->d_name[0] == '.')
+			continue;
+		/* ignore files starting with # and ending with ~ */
+
+		(void) strncpy(fname, dp->d_name, MAXNAMLEN);
+		snprintf(tabname, MAXNAMLEN+1, "/etc/cron.d/%s", fname);
+
+		process_crontab("root", "*system*", tabname,
+				&crond_stat, &new_db, old_db);
+	}
+	closedir(dir);
+
 	/* we used to keep this dir open all the time, for the sake of
 	 * efficiency.  however, we need to close it in every fork, and
 	 * we fork a lot more often than the mtime of the dir changes.
@@ -112,8 +146,8 @@
 		if (dp->d_name[0] == '.')
 			continue;
 
-		(void) strcpy(fname, dp->d_name);
-		sprintf(tabname, CRON_TAB(fname));
+		(void) strncpy(fname, dp->d_name, MAXNAMLEN);
+		snprintf(tabname, MAXNAMLEN+1, CRON_TAB(fname));
 
 		process_crontab(fname, fname, tabname,
 				&statbuf, &new_db, old_db);
diff -Naur vixie-cron-3.0.1.orig/do_command.c vixie-cron-3.0.1/do_command.c
--- vixie-cron-3.0.1.orig/do_command.c	1995-05-31 21:37:28.000000000 +0000
+++ vixie-cron-3.0.1/do_command.c	2003-09-16 17:21:12.000000000 +0000
@@ -86,6 +86,7 @@
 	/*local*/{
 		register char	*pch;
 
+		SyslogName = strdup(ProgramName);
 		for (pch = ProgramName;  *pch;  pch++)
 			*pch = MkUpper(*pch);
 	}
@@ -95,6 +96,21 @@
 	usernm = env_get("LOGNAME", e->envp);
 	mailto = env_get("MAILTO", e->envp);
 
+	/* Check for arguments */
+	if (mailto) {
+		const char	*end;
+
+		/* These chars have to match those cron_popen()
+		 * uses to split the command string */
+		mailto += strspn(mailto, " \t\n");
+		end = mailto + strcspn(mailto, " \t\n");
+		if (*mailto == '-' || *end != '\0') {
+			printf("Bad Mailto karma.\n");
+			log_it("CRON",getpid(),"error","bad mailto");
+			mailto = NULL;
+		}
+	}
+
 #ifdef USE_SIGCHLD
 	/* our parent is watching for our death by catching SIGCHLD.  we
 	 * do not care to watch for our children's deaths this way -- we
@@ -207,7 +223,7 @@
 		 * we set uid, we've lost root privledges.
 		 */
 		setgid(e->gid);
-# if defined(BSD)
+# if defined(BSD) || defined(linux)
 		initgroups(env_get("LOGNAME", e->envp), e->gid);
 # endif
 		setuid(e->uid);		/* we aren't root after this... */
@@ -227,6 +243,14 @@
 				_exit(OK_EXIT);
 			}
 # endif /*DEBUGGING*/
+#ifdef USE_SIGCHLD
+			/* Our grandparent is watching for our parent's death by
+			 * catching SIGCHLD. Meanwhile, our parent will use wait
+			 * explicitly and so has disabled SIGCHLD. So now it's
+			 * time to reset SIGCHLD handling.
+			 */
+			(void) signal(SIGCHLD, SIG_DFL);
+#endif
 			execle(shell, shell, "-c", e->cmd, (char *)0, e->envp);
 			fprintf(stderr, "execl: couldn't exec `%s'\n", shell);
 			perror("execl");
@@ -366,9 +390,9 @@
 				auto char	hostname[MAXHOSTNAMELEN];
 
 				(void) gethostname(hostname, MAXHOSTNAMELEN);
-				(void) sprintf(mailcmd, MAILARGS,
+				(void) snprintf(mailcmd, MAX_COMMAND, MAILARGS,
 					       MAILCMD, mailto);
-				if (!(mail = cron_popen(mailcmd, "w"))) {
+				if (!(mail = cron_popen(mailcmd, "w", e))) {
 					perror(MAILCMD);
 					(void) _exit(ERROR_EXIT);
 				}
@@ -425,7 +449,7 @@
 			if (mailto && status) {
 				char buf[MAX_TEMPSTR];
 
-				sprintf(buf,
+				snprintf(buf, MAX_TEMPSTR,
 			"mailed %d byte%s of output but got status 0x%04x\n",
 					bytes, (bytes==1)?"":"s",
 					status);
diff -Naur vixie-cron-3.0.1.orig/entry.c vixie-cron-3.0.1/entry.c
--- vixie-cron-3.0.1.orig/entry.c	1995-05-31 21:37:28.000000000 +0000
+++ vixie-cron-3.0.1/entry.c	2003-09-16 17:21:12.000000000 +0000
@@ -249,21 +249,21 @@
 	 */
 	e->envp = env_copy(envp);
 	if (!env_get("SHELL", e->envp)) {
-		sprintf(envstr, "SHELL=%s", _PATH_BSHELL);
+		snprintf(envstr, MAX_ENVSTR, "SHELL=%s", _PATH_BSHELL);
 		e->envp = env_set(e->envp, envstr);
 	}
 	if (!env_get("HOME", e->envp)) {
-		sprintf(envstr, "HOME=%s", pw->pw_dir);
+		snprintf(envstr, MAX_ENVSTR, "HOME=%s", pw->pw_dir);
 		e->envp = env_set(e->envp, envstr);
 	}
 	if (!env_get("PATH", e->envp)) {
-		sprintf(envstr, "PATH=%s", _PATH_DEFPATH);
+		snprintf(envstr, MAX_ENVSTR, "PATH=%s", _PATH_DEFPATH);
 		e->envp = env_set(e->envp, envstr);
 	}
-	sprintf(envstr, "%s=%s", "LOGNAME", pw->pw_name);
+	snprintf(envstr, MAX_ENVSTR, "%s=%s", "LOGNAME", pw->pw_name);
 	e->envp = env_set(e->envp, envstr);
 #if defined(BSD)
-	sprintf(envstr, "%s=%s", "USER", pw->pw_name);
+	snprintf(envstr, MAX_ENVSTR, "%s=%s", "USER", pw->pw_name);
 	e->envp = env_set(e->envp, envstr);
 #endif
 
diff -Naur vixie-cron-3.0.1.orig/env.c vixie-cron-3.0.1/env.c
--- vixie-cron-3.0.1.orig/env.c	1995-05-31 21:38:25.000000000 +0000
+++ vixie-cron-3.0.1/env.c	2003-09-16 17:21:12.000000000 +0000
@@ -115,14 +115,15 @@
 {
 	long	filepos;
 	int	fileline;
-	char	name[MAX_TEMPSTR], val[MAX_ENVSTR];
+	char	name[MAX_ENVSTR], val[MAX_ENVSTR], *val2;
 	int	fields;
 
 	filepos = ftell(f);
 	fileline = LineNumber;
 	skip_comments(f);
-	if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n"))
+	if (EOF == get_string(envstr, MAX_ENVSTR - 1, f, "\n"))
 		return (ERR);
+	envstr[MAX_ENVSTR - 1] = '\0';
 
 	Debug(DPARS, ("load_env, read <%s>\n", envstr))
 
@@ -141,6 +142,7 @@
 	/*
 	 * process value string
 	 */
+	val2 = val;
 	/*local*/{
 		int	len = strdtb(val);
 
@@ -148,14 +150,14 @@
 			if (val[0] == '\'' || val[0] == '"') {
 				if (val[len-1] == val[0]) {
 					val[len-1] = '\0';
-					(void) strcpy(val, val+1);
+					val2 = val + 1;
 				}
 			}
 		}
 	}
 
-	(void) sprintf(envstr, "%s=%s", name, val);
-	Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val, envstr))
+	(void) snprintf(envstr, MAX_ENVSTR, "%s=%s", name, val2);
+	Debug(DPARS, ("load_env, <%s> <%s> -> <%s>\n", name, val2, envstr))
 	return (TRUE);
 }
 
diff -Naur vixie-cron-3.0.1.orig/misc.c vixie-cron-3.0.1/misc.c
--- vixie-cron-3.0.1.orig/misc.c	1995-05-31 21:37:28.000000000 +0000
+++ vixie-cron-3.0.1/misc.c	2003-09-16 17:21:12.000000000 +0000
@@ -263,11 +263,11 @@
 		char	buf[MAX_TEMPSTR];
 		int	fd, otherpid;
 
-		(void) sprintf(pidfile, PIDFILE, PIDDIR);
+		(void) snprintf(pidfile, MAX_FNAME, PIDFILE, PIDDIR);
 		if ((-1 == (fd = open(pidfile, O_RDWR|O_CREAT, 0644)))
 		    || (NULL == (fp = fdopen(fd, "r+")))
 		    ) {
-			sprintf(buf, "can't open or create %s: %s",
+			snprintf(buf, MAX_TEMPSTR, "can't open or create %s: %s",
 				pidfile, strerror(errno));
 			fprintf(stderr, "%s: %s\n", ProgramName, buf);
 			log_it("CRON", getpid(), "DEATH", buf);
@@ -278,7 +278,7 @@
 			int save_errno = errno;
 
 			fscanf(fp, "%d", &otherpid);
-			sprintf(buf, "can't lock %s, otherpid may be %d: %s",
+			snprintf(buf, MAX_TEMPSTR, "can't lock %s, otherpid may be %d: %s",
 				pidfile, otherpid, strerror(save_errno));
 			fprintf(stderr, "%s: %s\n", ProgramName, buf);
 			log_it("CRON", getpid(), "DEATH", buf);
@@ -467,7 +467,7 @@
 	TIME_T			now = time((TIME_T) 0);
 	register struct tm	*t = localtime(&now);
 #endif /*LOG_FILE*/
-
+	int 			msg_size;
 #if defined(SYSLOG)
 	static int		syslog_open = 0;
 #endif
@@ -475,11 +475,14 @@
 #if defined(LOG_FILE)
 	/* we assume that MAX_TEMPSTR will hold the date, time, &punctuation.
 	 */
-	msg = malloc(strlen(username)
-		     + strlen(event)
-		     + strlen(detail)
-		     + MAX_TEMPSTR);
-
+	msg_size = strlen(username) + strlen(event) + strlen(detail) + MAX_TEMPSTR;
+	msg = malloc(msg_size);
+	if (msg == NULL) {
+	    /* damn, out of mem and we did not test that before... */
+	    fprintf(stderr, "%s: Run OUT OF MEMORY while %s\n",
+		    ProgramName, __FUNCTION__);
+	    return;
+	}
 	if (LogFD < OK) {
 		LogFD = open(LOG_FILE, O_WRONLY|O_APPEND|O_CREAT, 0600);
 		if (LogFD < OK) {
@@ -491,16 +494,16 @@
 		}
 	}
 
-	/* we have to sprintf() it because fprintf() doesn't always write
+	/* we have to snprintf() it because fprintf() doesn't always write
 	 * everything out in one chunk and this has to be atomically appended
 	 * to the log file.
 	 */
-	sprintf(msg, "%s (%02d/%02d-%02d:%02d:%02d-%d) %s (%s)\n",
+	snprintf(msg, msg_size, "%s (%02d/%02d-%02d:%02d:%02d-%d) %s (%s)\n",
 		username,
 		t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, pid,
 		event, detail);
 
-	/* we have to run strlen() because sprintf() returns (char*) on old BSD
+	/* we have to run strlen() because snprintf() returns (char*) on old BSD
 	 */
 	if (LogFD < OK || write(LogFD, msg, strlen(msg)) < OK) {
 		if (LogFD >= OK)
@@ -519,9 +522,9 @@
 		 * print the pid ourselves.
 		 */
 # ifdef LOG_DAEMON
-		openlog(ProgramName, LOG_PID, LOG_CRON);
+		openlog(SyslogName, LOG_PID, LOG_CRON);
 # else
-		openlog(ProgramName, LOG_PID);
+		openlog(SyslogName, LOG_PID);
 # endif
 		syslog_open = TRUE;		/* assume openlog success */
 	}
@@ -604,8 +607,10 @@
 			*dst++ = '^';
 			*dst++ = '?';
 		} else {			/* parity character */
-			sprintf(dst, "\\%03o", ch);
-			dst += 4;
+		    /* well, the following snprintf is paranoid, but that will
+		     * keep grep happy */
+		    snprintf(dst, 5, "\\%03o", ch);
+		    dst += 4;
 		}
 	}
 	*dst = '\0';
@@ -640,7 +645,7 @@
 	struct tm *tm = localtime(&t);
 	static char ret[30];	/* zone name might be >3 chars */
 	
-	(void) sprintf(ret, "%s, %2d %s %2d %02d:%02d:%02d %s",
+	(void) snprintf(ret, 30, "%s, %2d %s %2d %02d:%02d:%02d %s",
 		       DowNames[tm->tm_wday],
 		       tm->tm_mday,
 		       MonthNames[tm->tm_mon],
diff -Naur vixie-cron-3.0.1.orig/pathnames.h vixie-cron-3.0.1/pathnames.h
--- vixie-cron-3.0.1.orig/pathnames.h	2003-09-16 17:20:48.000000000 +0000
+++ vixie-cron-3.0.1/pathnames.h	2003-09-16 17:21:12.000000000 +0000
@@ -49,7 +49,7 @@
 			 */
 #define	ALLOW_FILE	"/etc/cron.allow"		/*-*/
 #define DENY_FILE	"/etc/cron.deny"		/*-*/
-#define LOG_FILE	"/var/log/cron"		/*-*/
+/* #define LOG_FILE	"/var/log/cron"		*/
 
 			/* where should the daemon stick its PID?
 			 */
diff -Naur vixie-cron-3.0.1.orig/popen.c vixie-cron-3.0.1/popen.c
--- vixie-cron-3.0.1.orig/popen.c	1995-05-31 21:37:21.000000000 +0000
+++ vixie-cron-3.0.1/popen.c	2003-09-16 17:21:13.000000000 +0000
@@ -43,8 +43,9 @@
 static int fds;
 
 FILE *
-cron_popen(program, type)
+cron_popen(program, type, e)
 	char *program, *type;
+	entry *e;
 {
 	register char *cp;
 	FILE *iop;
@@ -114,6 +115,14 @@
 			}
 			(void)close(pdes[1]);
 		}
+		/* Lose root privilege */
+		setgid(e->gid);
+# if defined(BSD) || defined(POSIX)
+		initgroups(env_get("LOGNAME", e->envp), e->gid);
+# endif
+		setuid(e->uid);
+		chdir(env_get("HOME", e->envp));
+
 #if WANT_GLOBBING
 		execvp(gargv[0], gargv);
 #else
