Michael Thomas cc5a4cd
diff -Naur --exclude '*.swp' bsd-games-2.17/hack/hack.bones.c bsd-games-2.17.new/hack/hack.bones.c
Michael Thomas cc5a4cd
--- bsd-games-2.17/hack/hack.bones.c	2003-12-16 18:47:37.000000000 -0800
Michael Thomas cc5a4cd
+++ bsd-games-2.17.new/hack/hack.bones.c	2006-04-27 14:17:06.000000000 -0700
Michael Thomas cc5a4cd
@@ -140,10 +140,14 @@
Michael Thomas cc5a4cd
 						 * ghost */
Michael Thomas cc5a4cd
 		}
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
-	if ((fd = creat(bones, FMASK)) < 0)
Michael Thomas cc5a4cd
+        setgid(hackgid);
Michael Thomas cc5a4cd
+	if ((fd = creat(bones, FMASK)) < 0) {
Michael Thomas cc5a4cd
+                setgid(getgid());
Michael Thomas cc5a4cd
 		return;
Michael Thomas cc5a4cd
+        }
Michael Thomas cc5a4cd
 	savelev(fd, dlevel);
Michael Thomas cc5a4cd
 	(void) close(fd);
Michael Thomas cc5a4cd
+        setgid(getgid());
Michael Thomas cc5a4cd
 }
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 int
Michael Thomas cc5a4cd
@@ -168,9 +172,12 @@
Michael Thomas cc5a4cd
 	if (!wizard)		/* duvel!frans: don't remove bones while
Michael Thomas cc5a4cd
 				 * debugging */
Michael Thomas cc5a4cd
 #endif	/* WiZARD */
Michael Thomas cc5a4cd
+                setgid(hackgid);
Michael Thomas cc5a4cd
 		if (unlink(bones) < 0) {
Michael Thomas cc5a4cd
+                        setgid(getgid());
Michael Thomas cc5a4cd
 			pline("Cannot unlink %s .", bones);
Michael Thomas cc5a4cd
 			return (0);
Michael Thomas cc5a4cd
 		}
Michael Thomas cc5a4cd
+                setgid(getgid());
Michael Thomas cc5a4cd
 	return (ok);
Michael Thomas cc5a4cd
 }
Michael Thomas cc5a4cd
diff -Naur --exclude '*.swp' bsd-games-2.17/hack/hack.do.c bsd-games-2.17.new/hack/hack.do.c
Michael Thomas cc5a4cd
--- bsd-games-2.17/hack/hack.do.c	2004-01-27 12:52:07.000000000 -0800
Michael Thomas cc5a4cd
+++ bsd-games-2.17.new/hack/hack.do.c	2006-04-27 14:32:43.000000000 -0700
Michael Thomas cc5a4cd
@@ -206,7 +206,9 @@
Michael Thomas cc5a4cd
 		return;		/* this can happen */
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 	glo(dlevel);
Michael Thomas cc5a4cd
+        setgid(hackgid);
Michael Thomas cc5a4cd
 	fd = creat(lock, FMASK);
Michael Thomas cc5a4cd
+        setgid(getgid());
Michael Thomas cc5a4cd
 	if (fd < 0) {
Michael Thomas cc5a4cd
 		/*
Michael Thomas cc5a4cd
 		 * This is not quite impossible: e.g., we may have
Michael Thomas cc5a4cd
@@ -231,8 +233,10 @@
Michael Thomas cc5a4cd
 	u.ux = FAR;		/* hack */
Michael Thomas cc5a4cd
 	(void) inshop();	/* probably was a trapdoor */
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
+        setgid(hackgid);
Michael Thomas cc5a4cd
 	savelev(fd, dlevel);
Michael Thomas cc5a4cd
 	(void) close(fd);
Michael Thomas cc5a4cd
+        setgid(getgid());
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 	dlevel = newlevel;
Michael Thomas cc5a4cd
 	if (maxdlevel < dlevel)
Michael Thomas cc5a4cd
diff -Naur --exclude '*.swp' bsd-games-2.17/hack/hack.end.c bsd-games-2.17.new/hack/hack.end.c
Michael Thomas cc5a4cd
--- bsd-games-2.17/hack/hack.end.c	2003-12-16 18:47:37.000000000 -0800
Michael Thomas cc5a4cd
+++ bsd-games-2.17.new/hack/hack.end.c	2006-04-27 15:48:03.000000000 -0700
Michael Thomas cc5a4cd
@@ -290,7 +290,11 @@
Michael Thomas cc5a4cd
 #ifdef WIZARD
Michael Thomas cc5a4cd
 	if (!wizard)
Michael Thomas cc5a4cd
 #endif	/* WIZARD */
Michael Thomas cc5a4cd
-		topten();
Michael Thomas cc5a4cd
+        {
Michael Thomas cc5a4cd
+            setgid(hackgid);
Michael Thomas cc5a4cd
+            topten();
Michael Thomas cc5a4cd
+            setgid(getgid());
Michael Thomas cc5a4cd
+        }
Michael Thomas cc5a4cd
 	if (done_stopprint)
Michael Thomas cc5a4cd
 		printf("\n\n");
Michael Thomas cc5a4cd
 	exit(0);
Michael Thomas cc5a4cd
diff -Naur --exclude '*.swp' bsd-games-2.17/hack/hack.h bsd-games-2.17.new/hack/hack.h
Michael Thomas cc5a4cd
--- bsd-games-2.17/hack/hack.h	2004-01-27 12:52:07.000000000 -0800
Michael Thomas cc5a4cd
+++ bsd-games-2.17.new/hack/hack.h	2006-04-27 11:48:15.000000000 -0700
Michael Thomas cc5a4cd
@@ -218,6 +218,7 @@
Michael Thomas cc5a4cd
 extern int bases[];
Michael Thomas cc5a4cd
 extern int doorindex;
Michael Thomas cc5a4cd
 extern int hackpid;
Michael Thomas cc5a4cd
+extern gid_t hackgid;
Michael Thomas cc5a4cd
 extern int multi;
Michael Thomas cc5a4cd
 extern int nroom;
Michael Thomas cc5a4cd
 extern long moves;
Michael Thomas cc5a4cd
diff -Naur --exclude '*.swp' bsd-games-2.17/hack/hack.main.c bsd-games-2.17.new/hack/hack.main.c
Michael Thomas cc5a4cd
--- bsd-games-2.17/hack/hack.main.c	2004-01-27 12:52:07.000000000 -0800
Michael Thomas cc5a4cd
+++ bsd-games-2.17.new/hack/hack.main.c	2006-04-27 20:16:23.000000000 -0700
Michael Thomas cc5a4cd
@@ -61,6 +61,7 @@
Michael Thomas cc5a4cd
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Michael Thomas cc5a4cd
  */
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
+#define _GNU_SOURCE /* this must be done before the first include of unistd.h */
Michael Thomas cc5a4cd
 #include <sys/cdefs.h>
Michael Thomas cc5a4cd
 #ifndef lint
Michael Thomas cc5a4cd
 __RCSID("$NetBSD: hack.main.c,v 1.9 2004/01/27 20:30:29 jsm Exp $");
Michael Thomas cc5a4cd
@@ -70,6 +71,9 @@
Michael Thomas cc5a4cd
 #include <stdlib.h>
Michael Thomas cc5a4cd
 #include <unistd.h>
Michael Thomas cc5a4cd
 #include <fcntl.h>
Michael Thomas cc5a4cd
+#include <sys/types.h>
Michael Thomas cc5a4cd
+#include <pwd.h>
Michael Thomas cc5a4cd
+#include <limits.h>
Michael Thomas cc5a4cd
 #include "hack.h"
Michael Thomas cc5a4cd
 #include "extern.h"
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
@@ -83,12 +87,13 @@
Michael Thomas cc5a4cd
 int             (*occupation)(void);
Michael Thomas cc5a4cd
 const char           *occtxt;		/* defined when occupation != NULL */
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
+gid_t           hackgid;        /* privileged gid for writing scoreboard */
Michael Thomas cc5a4cd
 int             hackpid;	/* current pid */
Michael Thomas cc5a4cd
 int             locknum;	/* max num of players */
Michael Thomas cc5a4cd
 #ifdef DEF_PAGER
Michael Thomas cc5a4cd
 const char     *catmore;	/* default pager */
Michael Thomas cc5a4cd
 #endif
Michael Thomas cc5a4cd
-char            SAVEF[PL_NSIZ + 11] = "save/";	/* save/99999player */
Michael Thomas cc5a4cd
+char            SAVEF[PATH_MAX + PL_NSIZ + 11] = ".hack.save";
Michael Thomas cc5a4cd
 char           *hname;		/* name of the game (argv[0] of call) */
Michael Thomas cc5a4cd
 char            obuf[BUFSIZ];	/* BUFSIZ is defined in stdio.h */
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
@@ -101,9 +106,10 @@
Michael Thomas cc5a4cd
 	char           *argv[];
Michael Thomas cc5a4cd
 {
Michael Thomas cc5a4cd
 	int             fd;
Michael Thomas cc5a4cd
-#ifdef CHDIR
Michael Thomas cc5a4cd
-	char           *dir;
Michael Thomas cc5a4cd
-#endif
Michael Thomas cc5a4cd
+        char           *savedir = (char *)NULL;
Michael Thomas cc5a4cd
+
Michael Thomas cc5a4cd
+        hackgid = getegid();
Michael Thomas cc5a4cd
+        setgid(getgid());
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 	/* Check for dirty tricks with closed fds 0, 1, 2 */
Michael Thomas cc5a4cd
 	fd = open("/dev/null", O_RDONLY);
Michael Thomas cc5a4cd
@@ -114,31 +120,47 @@
Michael Thomas cc5a4cd
 	hname = argv[0];
Michael Thomas cc5a4cd
 	hackpid = getpid();
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
-#ifdef CHDIR			/* otherwise no chdir() */
Michael Thomas cc5a4cd
 	/*
Michael Thomas cc5a4cd
-	 * See if we must change directory to the playground.
Michael Thomas cc5a4cd
-	 * (Perhaps hack runs suid and playground is inaccessible
Michael Thomas cc5a4cd
-	 *  for the player.)
Michael Thomas cc5a4cd
+         * Find the directory containing the save files.
Michael Thomas cc5a4cd
 	 * The environment variable HACKDIR is overridden by a
Michael Thomas cc5a4cd
 	 *  -d command line option (must be the first option given)
Michael Thomas cc5a4cd
 	 */
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
-	dir = getenv("HACKDIR");
Michael Thomas cc5a4cd
+	savedir = getenv("HACKDIR");
Michael Thomas cc5a4cd
 	if (argc > 1 && !strncmp(argv[1], "-d", 2)) {
Michael Thomas cc5a4cd
 		argc--;
Michael Thomas cc5a4cd
 		argv++;
Michael Thomas cc5a4cd
-		dir = argv[0] + 2;
Michael Thomas cc5a4cd
-		if (*dir == '=' || *dir == ':')
Michael Thomas cc5a4cd
-			dir++;
Michael Thomas cc5a4cd
-		if (!*dir && argc > 1) {
Michael Thomas cc5a4cd
+		savedir = argv[0] + 2;
Michael Thomas cc5a4cd
+		if (*savedir == '=' || *savedir == ':')
Michael Thomas cc5a4cd
+			savedir++;
Michael Thomas cc5a4cd
+		if (!*savedir && argc > 1) {
Michael Thomas cc5a4cd
 			argc--;
Michael Thomas cc5a4cd
 			argv++;
Michael Thomas cc5a4cd
-			dir = argv[0];
Michael Thomas cc5a4cd
+			savedir = argv[0];
Michael Thomas cc5a4cd
 		}
Michael Thomas cc5a4cd
-		if (!*dir)
Michael Thomas cc5a4cd
+		if (!*savedir)
Michael Thomas cc5a4cd
 			error("Flag -d must be followed by a directory name.");
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
-#endif
Michael Thomas cc5a4cd
+
Michael Thomas cc5a4cd
+        /*
Michael Thomas cc5a4cd
+         * If the user didn't tell us where the save games are stored then
Michael Thomas cc5a4cd
+         * look in the home directory.
Michael Thomas cc5a4cd
+         */
Michael Thomas cc5a4cd
+        if (savedir == (char *)NULL) {
Michael Thomas cc5a4cd
+            if ((savedir = getenv("HOME")) == (char *)NULL) {
Michael Thomas cc5a4cd
+                struct passwd *pwe;
Michael Thomas cc5a4cd
+                pwe = getpwuid(getuid());
Michael Thomas cc5a4cd
+                if (pwe == NULL || (savedir = pwe->pw_dir) == (char *)NULL) {
Michael Thomas cc5a4cd
+                    savedir = ".";
Michael Thomas cc5a4cd
+                }
Michael Thomas cc5a4cd
+            }
Michael Thomas cc5a4cd
+        }
Michael Thomas cc5a4cd
+        /*
Michael Thomas cc5a4cd
+         * One final check in case we missed something earlier.
Michael Thomas cc5a4cd
+         */
Michael Thomas cc5a4cd
+        if (savedir == NULL || strlen(savedir) > PATH_MAX-30) {
Michael Thomas cc5a4cd
+            savedir = ".";
Michael Thomas cc5a4cd
+        }
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 	/*
Michael Thomas cc5a4cd
 	 * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS
Michael Thomas cc5a4cd
@@ -155,12 +177,21 @@
Michael Thomas cc5a4cd
 		char           *s;
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 		initoptions();
Michael Thomas cc5a4cd
-		if (!*plname && (s = getenv("USER")))
Michael Thomas cc5a4cd
+		if (!*plname && (s = getenv("USER"))) {
Michael Thomas cc5a4cd
 			(void) strncpy(plname, s, sizeof(plname) - 1);
Michael Thomas cc5a4cd
-		if (!*plname && (s = getenv("LOGNAME")))
Michael Thomas cc5a4cd
+                }
Michael Thomas cc5a4cd
+		if (!*plname && (s = getenv("LOGNAME"))) {
Michael Thomas cc5a4cd
 			(void) strncpy(plname, s, sizeof(plname) - 1);
Michael Thomas cc5a4cd
-		if (!*plname && (s = getlogin()))
Michael Thomas cc5a4cd
+                }
Michael Thomas cc5a4cd
+		if (!*plname && (s = getlogin())) {
Michael Thomas cc5a4cd
 			(void) strncpy(plname, s, sizeof(plname) - 1);
Michael Thomas cc5a4cd
+                }
Michael Thomas cc5a4cd
+                /*
Michael Thomas cc5a4cd
+                 * Ensure that plname is null-terminated.  strncpy
Michael Thomas cc5a4cd
+                 * doesn't guarantee it if the source is longer than
Michael Thomas cc5a4cd
+                 * the destination.
Michael Thomas cc5a4cd
+                 */
Michael Thomas cc5a4cd
+                plname[sizeof(plname) - 1] = (char)NULL;
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 	/*
Michael Thomas cc5a4cd
@@ -169,11 +200,12 @@
Michael Thomas cc5a4cd
 	 */
Michael Thomas cc5a4cd
 	if (argc > 1 && !strncmp(argv[1], "-s", 2)) {
Michael Thomas cc5a4cd
 #ifdef CHDIR
Michael Thomas cc5a4cd
-		chdirx(dir, 0);
Michael Thomas cc5a4cd
+		chdirx(_PATH_HACK, 0);
Michael Thomas cc5a4cd
 #endif
Michael Thomas cc5a4cd
 		prscore(argc, argv);
Michael Thomas cc5a4cd
 		exit(0);
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
+
Michael Thomas cc5a4cd
 	/*
Michael Thomas cc5a4cd
 	 * It seems he really wants to play.
Michael Thomas cc5a4cd
 	 * Remember tty modes, to be restored on exit.
Michael Thomas cc5a4cd
@@ -191,13 +223,13 @@
Michael Thomas cc5a4cd
 	 * Find the creation date of this game,
Michael Thomas cc5a4cd
 	 * so as to avoid restoring outdated savefiles.
Michael Thomas cc5a4cd
 	 */
Michael Thomas cc5a4cd
-	gethdate(hname);
Michael Thomas cc5a4cd
+	gethdate(argv[0]);
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 	/*
Michael Thomas cc5a4cd
 	 * We cannot do chdir earlier, otherwise gethdate will fail.
Michael Thomas cc5a4cd
 	 */
Michael Thomas cc5a4cd
 #ifdef CHDIR
Michael Thomas cc5a4cd
-	chdirx(dir, 1);
Michael Thomas cc5a4cd
+	chdirx(_PATH_HACK, 1);
Michael Thomas cc5a4cd
 #endif
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 	/*
Michael Thomas cc5a4cd
@@ -277,7 +309,9 @@
Michael Thomas cc5a4cd
 		(void) signal(SIGINT, SIG_IGN);
Michael Thomas cc5a4cd
 		if (!locknum)
Michael Thomas cc5a4cd
 			(void) strcpy(lock, plname);
Michael Thomas cc5a4cd
+                setgid(hackgid);
Michael Thomas cc5a4cd
 		getlock();	/* sets lock if locknum != 0 */
Michael Thomas cc5a4cd
+                setgid(getgid());
Michael Thomas cc5a4cd
 #ifdef WIZARD
Michael Thomas cc5a4cd
 	} else {
Michael Thomas cc5a4cd
 		char           *sfoo;
Michael Thomas cc5a4cd
@@ -308,10 +342,21 @@
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
 #endif
Michael Thomas cc5a4cd
 	setftty();
Michael Thomas cc5a4cd
-	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
Michael Thomas cc5a4cd
-	regularize(SAVEF + 5);	/* avoid . or / in name */
Michael Thomas cc5a4cd
-	if ((fd = open(SAVEF, O_RDONLY)) >= 0 &&
Michael Thomas cc5a4cd
-	    (uptodate(fd) || unlink(SAVEF) == 666)) {
Michael Thomas cc5a4cd
+
Michael Thomas cc5a4cd
+	(void) snprintf(SAVEF, PATH_MAX, "%s/.hack.save-%d%s", savedir, getuid(), plname);
Michael Thomas cc5a4cd
+        /* Disable this regularization.  It's only needed when using
Michael Thomas cc5a4cd
+         * setgid and a a shared directory for save games.  In Fedora we've
Michael Thomas cc5a4cd
+         * patched it to save games with normal user permissions (not setgid),
Michael Thomas cc5a4cd
+         * so this isn't necessary anymore.
Michael Thomas cc5a4cd
+         */
Michael Thomas cc5a4cd
+	/*regularize(SAVEF + 5);*/	/* avoid . or / in name */
Michael Thomas cc5a4cd
+        /*
Michael Thomas cc5a4cd
+         * Removed check if the save game is up-to-date so we can avoid
Michael Thomas cc5a4cd
+         * invalidating games during bugfix releases.  It would be
Michael Thomas cc5a4cd
+         * _much_ better to store some sort of savefile version number
Michael Thomas cc5a4cd
+         * in the savefile itself.
Michael Thomas cc5a4cd
+         */
Michael Thomas cc5a4cd
+	if ((fd = open(SAVEF, O_RDONLY)) >= 0) {
Michael Thomas cc5a4cd
 		(void) signal(SIGINT, done1);
Michael Thomas cc5a4cd
 		pline("Restoring old save file...");
Michael Thomas cc5a4cd
 		(void) fflush(stdout);
Michael Thomas cc5a4cd
@@ -540,16 +585,6 @@
Michael Thomas cc5a4cd
 	boolean         wr;
Michael Thomas cc5a4cd
 {
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
-#ifdef SECURE
Michael Thomas cc5a4cd
-	if (dir			/* User specified directory? */
Michael Thomas cc5a4cd
-#ifdef HACKDIR
Michael Thomas cc5a4cd
-	    && strcmp(dir, HACKDIR)	/* and not the default? */
Michael Thomas cc5a4cd
-#endif
Michael Thomas cc5a4cd
-		) {
Michael Thomas cc5a4cd
-		(void) setuid(getuid());	/* Ron Wessels */
Michael Thomas cc5a4cd
-		(void) setregid(getgid(), getgid());
Michael Thomas cc5a4cd
-	}
Michael Thomas cc5a4cd
-#endif
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 #ifdef HACKDIR
Michael Thomas cc5a4cd
 	if (dir == NULL)
Michael Thomas cc5a4cd
@@ -568,12 +603,34 @@
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 		if (dir == NULL)
Michael Thomas cc5a4cd
 			dir = ".";
Michael Thomas cc5a4cd
-		if ((fd = open(RECORD, O_RDWR)) < 0) {
Michael Thomas cc5a4cd
-			printf("Warning: cannot write %s/%s", dir, RECORD);
Michael Thomas cc5a4cd
+
Michael Thomas cc5a4cd
+                setgid(hackgid);
Michael Thomas cc5a4cd
+		fd = open(RECORD, O_RDWR);
Michael Thomas cc5a4cd
+                setgid(getgid());
Michael Thomas cc5a4cd
+
Michael Thomas cc5a4cd
+		if (fd < 0) {
Michael Thomas cc5a4cd
+			printf("Warning: cannot write %s", RECORD);
Michael Thomas cc5a4cd
 			getret();
Michael Thomas cc5a4cd
 		} else
Michael Thomas cc5a4cd
 			(void) close(fd);
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
+
Michael Thomas cc5a4cd
+#ifdef SECURE
Michael Thomas cc5a4cd
+	if (dir			/* User specified directory? */
Michael Thomas cc5a4cd
+#ifdef HACKDIR
Michael Thomas cc5a4cd
+	    && strcmp(dir, HACKDIR)	/* and not the default? */
Michael Thomas cc5a4cd
+#endif
Michael Thomas cc5a4cd
+		) {
Michael Thomas cc5a4cd
+                if (setresuid(-1, getuid(), getuid()) == -1) {
Michael Thomas cc5a4cd
+                    perror("Could not drop setuid privileges.  Aborting.");
Michael Thomas cc5a4cd
+                    exit(1);
Michael Thomas cc5a4cd
+                }
Michael Thomas cc5a4cd
+                if (setresgid(-1, getgid(), getgid()) == -1) {
Michael Thomas cc5a4cd
+                    perror("Could not drop setgid privileges.  Aborting.");
Michael Thomas cc5a4cd
+                    exit(1);
Michael Thomas cc5a4cd
+                }
Michael Thomas cc5a4cd
+	}
Michael Thomas cc5a4cd
+#endif
Michael Thomas cc5a4cd
 }
Michael Thomas cc5a4cd
 #endif
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
diff -Naur --exclude '*.swp' bsd-games-2.17/hack/hack.save.c bsd-games-2.17.new/hack/hack.save.c
Michael Thomas cc5a4cd
--- bsd-games-2.17/hack/hack.save.c	2003-12-16 18:47:37.000000000 -0800
Michael Thomas cc5a4cd
+++ bsd-games-2.17.new/hack/hack.save.c	2006-04-27 20:12:41.000000000 -0700
Michael Thomas cc5a4cd
@@ -105,8 +105,9 @@
Michael Thomas cc5a4cd
 	(void) signal(SIGHUP, SIG_IGN);
Michael Thomas cc5a4cd
 	(void) signal(SIGINT, SIG_IGN);
Michael Thomas cc5a4cd
 	if ((fd = creat(SAVEF, FMASK)) < 0) {
Michael Thomas cc5a4cd
-		if (!hu)
Michael Thomas cc5a4cd
-			pline("Cannot open save file. (Continue or Quit)");
Michael Thomas cc5a4cd
+		if (!hu) {
Michael Thomas cc5a4cd
+			pline("Cannot open save file %s. (Continue or Quit)", SAVEF);
Michael Thomas cc5a4cd
+                }
Michael Thomas cc5a4cd
 		(void) unlink(SAVEF);	/* ab@unido */
Michael Thomas cc5a4cd
 		return (0);
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
@@ -198,10 +199,14 @@
Michael Thomas cc5a4cd
 			break;
Michael Thomas cc5a4cd
 		getlev(fd, 0, tmp);
Michael Thomas cc5a4cd
 		glo(tmp);
Michael Thomas cc5a4cd
-		if ((nfd = creat(lock, FMASK)) < 0)
Michael Thomas cc5a4cd
+                setgid(hackgid);
Michael Thomas cc5a4cd
+		if ((nfd = creat(lock, FMASK)) < 0) {
Michael Thomas cc5a4cd
+                        setgid(getgid());
Michael Thomas cc5a4cd
 			panic("Cannot open temp file %s!\n", lock);
Michael Thomas cc5a4cd
+                }
Michael Thomas cc5a4cd
 		savelev(nfd, tmp);
Michael Thomas cc5a4cd
 		(void) close(nfd);
Michael Thomas cc5a4cd
+                setgid(getgid());
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
 	(void) lseek(fd, (off_t) 0, SEEK_SET);
Michael Thomas cc5a4cd
 	getlev(fd, 0, 0);
Michael Thomas cc5a4cd
diff -Naur --exclude '*.swp' bsd-games-2.17/hack/hack.unix.c bsd-games-2.17.new/hack/hack.unix.c
Michael Thomas cc5a4cd
--- bsd-games-2.17/hack/hack.unix.c	2003-12-16 18:47:37.000000000 -0800
Michael Thomas cc5a4cd
+++ bsd-games-2.17.new/hack/hack.unix.c	2006-04-27 19:50:20.000000000 -0700
Michael Thomas cc5a4cd
@@ -161,6 +161,9 @@
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 struct stat     buf, hbuf;
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
+/*
Michael Thomas cc5a4cd
+ * Get the timestamp of the named executable.
Michael Thomas cc5a4cd
+ */
Michael Thomas cc5a4cd
 void
Michael Thomas cc5a4cd
 gethdate(name)
Michael Thomas cc5a4cd
 	char           *name;
Michael Thomas cc5a4cd
@@ -192,9 +195,15 @@
Michael Thomas cc5a4cd
 	for (;;) {
Michael Thomas cc5a4cd
 		if ((np = strchr(path, ':')) == NULL)
Michael Thomas cc5a4cd
 			np = path + strlen(path);	/* point to end str */
Michael Thomas cc5a4cd
-		if (np - path <= 1)	/* %% */
Michael Thomas cc5a4cd
+		if (np - path <= 1) {	/* %% */
Michael Thomas cc5a4cd
 			(void) strcpy(filename, name);
Michael Thomas cc5a4cd
-		else {
Michael Thomas cc5a4cd
+                } else if (strlen(path) >= MAXPATHLEN-strlen(name)-2) {
Michael Thomas cc5a4cd
+                /*
Michael Thomas cc5a4cd
+                 * Protect against long directories in PATH by skipping them.
Michael Thomas cc5a4cd
+                 */
Michael Thomas cc5a4cd
+                    path = np + 1;
Michael Thomas cc5a4cd
+                    continue;
Michael Thomas cc5a4cd
+                } else {
Michael Thomas cc5a4cd
 			(void) strncpy(filename, path, np - path);
Michael Thomas cc5a4cd
 			filename[np - path] = '/';
Michael Thomas cc5a4cd
 			(void) strcpy(filename + (np - path) + 1, name);
Michael Thomas cc5a4cd
@@ -231,6 +240,9 @@
Michael Thomas cc5a4cd
 {
Michael Thomas cc5a4cd
 	int             i;
Michael Thomas cc5a4cd
 	time_t          date;
Michael Thomas cc5a4cd
+        gid_t           initial_egid;
Michael Thomas cc5a4cd
+
Michael Thomas cc5a4cd
+        initial_egid = getegid();
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
 	if (fstat(fd, &buf))
Michael Thomas cc5a4cd
 		return (0);	/* cannot get status */
Michael Thomas cc5a4cd
@@ -255,13 +267,17 @@
Michael Thomas cc5a4cd
 			return (0);
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
 	(void) close(fd);
Michael Thomas cc5a4cd
+        setgid(hackgid);
Michael Thomas cc5a4cd
 	for (i = 1; i <= MAXLEVEL; i++) {	/* try to remove all */
Michael Thomas cc5a4cd
 		glo(i);
Michael Thomas cc5a4cd
 		(void) unlink(lock);
Michael Thomas cc5a4cd
 	}
Michael Thomas cc5a4cd
 	glo(0);
Michael Thomas cc5a4cd
-	if (unlink(lock))
Michael Thomas cc5a4cd
+	if (unlink(lock)) {
Michael Thomas cc5a4cd
+                setgid(initial_egid);
Michael Thomas cc5a4cd
 		return (0);	/* cannot remove it */
Michael Thomas cc5a4cd
+        }
Michael Thomas cc5a4cd
+        setgid(initial_egid);
Michael Thomas cc5a4cd
 	return (1);		/* success! */
Michael Thomas cc5a4cd
 }
Michael Thomas cc5a4cd
 
Michael Thomas cc5a4cd
@@ -321,8 +337,9 @@
Michael Thomas cc5a4cd
 	      : "There is a game in progress under your name.");
Michael Thomas cc5a4cd
 gotlock:
Michael Thomas cc5a4cd
 	fd = creat(lock, FMASK);
Michael Thomas cc5a4cd
-	if (unlink(LLOCK) == -1)
Michael Thomas cc5a4cd
+	if (unlink(LLOCK) == -1) {
Michael Thomas cc5a4cd
 		error("Cannot unlink %s.", LLOCK);
Michael Thomas cc5a4cd
+        }
Michael Thomas cc5a4cd
 	if (fd == -1) {
Michael Thomas cc5a4cd
 		error("cannot creat lock file.");
Michael Thomas cc5a4cd
 	} else {