-- Added UNIX security checks.

This commit is contained in:
dfs
1997-07-31 01:49:37 +00:00
parent 3c53ab13c9
commit 7897067eda
2 changed files with 78 additions and 12 deletions

View File

@@ -4,7 +4,7 @@ CHANGES TO REMIND
+ MINOR ENHANCEMENTS
- Made Remind accept date specs like "Jan 6, 1998" -- the comma is
- Made REMIND accept date specs like "Jan 6, 1998" -- the comma is
ignored. This was suggested by John Conover <john@johncon.johncon.com>.
You can even do "REM 27, Aug, 1998, msg bar". (But I don't know why
you'd want to.)
@@ -13,12 +13,20 @@ CHANGES TO REMIND
`remind -p ...' to an HTML table. The script was contributed by
Don Schwarz <darkowl@mcs.net>
- New security features: Because of the risk of statically-allocated
buffer, REMIND now refuses to run if it is installed set-uid or set-gid.
If REMIND is run as root, it refuses to read files not owned by root.
It also won't open group- or world-writable files, no matter who is
running it. REMIND doesn't do security checks on stdin, though, so
be careful if you run it as root in a script.
NOTE: REMIND doesn't do the world- and group-writable checks
on devices, FIFOs, etc. Otherwise "remind /dev/null" fails...
+ BUG FIXES
- Increased sizes of some statically-allocated buffers. This doesn't
really fix the problem, but makes it more manageable. Because of
the risk of statically-allocated buffers, REMIND now refuses to
run if it is installed set-uid or set-gid.
really fix the problem, but makes it more manageable.
- Using the "-u" option now implies the "-r" option. This is a
security feature.

74
files.c
View File

@@ -12,7 +12,7 @@
/***************************************************************/
#include "config.h"
static char const RCSID[] = "$Id: files.c,v 1.5 1997-03-30 19:07:39 dfs Exp $";
static char const RCSID[] = "$Id: files.c,v 1.6 1997-07-31 01:49:38 dfs Exp $";
#include <stdio.h>
#ifdef HAVE_STDLIB_H
@@ -27,6 +27,10 @@ static char const RCSID[] = "$Id: files.c,v 1.5 1997-03-30 19:07:39 dfs Exp $";
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD
#include <unistd.h>
#endif
#if defined(__MSDOS__)
#include <io.h>
#endif
@@ -78,6 +82,7 @@ static int IStackPtr = 0;
PRIVATE int ReadLineFromFile ARGS ((void));
PRIVATE int CacheFile ARGS ((const char *fname));
PRIVATE void DestroyCache ARGS ((CachedFile *cf));
PRIVATE int CheckSafety ARGS ((void));
/***************************************************************/
/* */
@@ -194,7 +199,7 @@ char *fname;
} else {
fp = fopen(fname, "r");
}
if (!fp) return E_CANT_OPEN;
if (!fp || !CheckSafety()) return E_CANT_OPEN;
CLine = NULL;
if (ShouldCache) {
LineNo = 0;
@@ -203,11 +208,12 @@ char *fname;
fp = NULL;
CLine = CachedFiles->cache;
} else {
if (strcmp(fname, "-"))
if (strcmp(fname, "-")) {
fp = fopen(fname, "r");
else
if (!fp || !CheckSafety()) return E_CANT_OPEN;
} else {
fp = stdin;
if (!fp) return E_CANT_OPEN;
}
}
}
STRSET(FileName, fname);
@@ -327,11 +333,12 @@ int PopFile()
STRSET(FileName, i->filename);
if (!CLine && (i->offset != -1L)) {
/* We must open the file, then seek to specified position */
if (strcmp(i->filename, "-"))
if (strcmp(i->filename, "-")) {
fp = fopen(i->filename, "r");
else
if (!fp || !CheckSafety()) return E_CANT_OPEN;
} else {
fp = stdin;
if (!fp) return E_CANT_OPEN;
}
if (fp != stdin)
(void) fseek(fp, i->offset, 0); /* Trust that it works... */
}
@@ -556,3 +563,54 @@ int TopLevel()
{
return !IStackPtr;
}
/***************************************************************/
/* */
/* CheckSafety */
/* */
/* Returns 1 if current file is safe to read; 0 otherwise. */
/* Currently only meaningful for UNIX. If we are running as */
/* root, we refuse to open files not owned by root. */
/* We also reject group- or world-writable files, no matter */
/* who we're running as. */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int CheckSafety(void)
#else
static int CheckSafety()
#endif
{
#ifdef UNIX
struct stat statbuf;
if (fstat(fileno(fp), &statbuf)) {
fclose(fp);
fp = NULL;
return 0;
}
/* Under UNIX, take extra precautions if running as root */
if (!geteuid()) {
/* Reject files not owned by root or group/world writable */
if (statbuf.st_uid != 0) {
fprintf(ErrFp, "SECURITY: Won't read non-root-owned file when running as root!\n");
fclose(fp);
fp = NULL;
return 0;
}
}
/* Sigh... /dev/null is usually world-writable, so ignore devices,
FIFOs, sockets, etc. */
if (!S_ISREG(statbuf.st_mode)) {
return 1;
}
if ((statbuf.st_mode & S_IWGRP) ||
(statbuf.st_mode & S_IWOTH)) {
fprintf(ErrFp, "SECURITY: Won't read group- or world-writable file!");
fclose(fp);
fp = NULL;
return 0;
}
#endif
return 1;
}