--- doc/nethack.6 +++ doc/nethack.6 @@ -197,7 +197,7 @@ supplies a directory which is to serve as the playground. It overrides the value from NETHACKDIR, HACKDIR, or the directory specified by the game administrator during compilation -(usually /usr/games/lib/nethackdir). +(usually /usr/share/games/nethack). This option is usually only useful to the game administrator. The playground must contain several auxiliary files such as help files, the list of top scorers, and a subdirectory @@ -283,7 +283,7 @@ .br MAILREADER Replacement for default reader .br - (probably /bin/mail or /usr/ucb/mail). + (probably /usr/bin/mail). .br NETHACKDIR Playground. .br --- util/recover.c +++ util/recover.c @@ -15,6 +15,12 @@ #include "win32api.h" #endif +#ifdef SECURE +#include +#include +#include +#endif + #ifdef VMS extern int FDECL(vms_creat, (const char *,unsigned)); extern int FDECL(vms_open, (const char *,int,unsigned)); @@ -106,15 +112,23 @@ } #if defined(SECURE) && !defined(VMS) if (dir -# ifdef HACKDIR +# ifdef VAR_PLAYGROUND + && strcmp(dir, VAR_PLAYGROUND) +# else +# ifdef HACKDIR && strcmp(dir, HACKDIR) -# endif +# endif +# endif /* VAR_PLAYGROUND */ ) { (void) setgid(getgid()); (void) setuid(getuid()); } #endif /* SECURE && !VMS */ +#ifdef VAR_PLAYGROUND + if (!dir) dir = VAR_PLAYGROUND; +#endif + #ifdef HACKDIR if (!dir) dir = HACKDIR; #endif @@ -157,11 +171,19 @@ #endif } +#ifdef SECURE +static uid_t save_uid = -1; +#endif + int open_levelfile(lev) int lev; { int fd; +#ifdef SECURE + struct stat level_stat; + uid_t uid; +#endif set_levelfile_name(lev); #if defined(MICRO) || defined(WIN32) || defined(MSDOS) @@ -169,6 +191,21 @@ #else fd = open(lock, O_RDONLY, 0); #endif + /* Security check: does the user calling recover own the file? */ +#ifdef SECURE + if (fd != -1) { + uid = getuid(); + if (fstat(fd, &level_stat) == -1) { + Fprintf(stderr, "No permission to stat level file %s.\n", lock); + return -1; + } + if (uid != 0 && level_stat.st_uid != uid) { + Fprintf(stderr, "You are not the owner of level file %s.\n", lock); + return -1; + } + save_uid = level_stat.st_uid; + } +#endif return fd; } @@ -181,6 +218,13 @@ fd = open(savename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); #else fd = creat(savename, FCMASK); +#endif + +#ifdef SECURE + if (fchown(fd, save_uid, -1) == -1) { + Fprintf(stderr, "could not chown %s to %i!\n", savename, + save_uid); + } #endif return fd; } --- src/cmd.c +++ src/cmd.c @@ -2133,6 +2133,16 @@ readchar_queue = click_to_cmd(x, y, mod); sym = *readchar_queue++; } + + if(sym == 27) { /* ESC (generated by Alt-key) */ +#ifdef REDO + sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod); +#else + sym = Getchar(); +#endif + sym |= 0x80; + } + return((char) sym); }