summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-08-29 04:19:35 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-08-29 04:19:35 +0000
commit7e0963d3da76f27bcfe5d4d10a7c38240ee29e74 (patch)
tree1337677c77f0d20dfa579f165a3f3bb796297b11
parent1b359128ab0a6007ceb84e87c58dd5adff9c890c (diff)
buf oflows, deal with 1777 spool, general DOS attack protection; help from david mazieres
-rw-r--r--libexec/mail.local/mail.local.c99
1 files changed, 90 insertions, 9 deletions
diff --git a/libexec/mail.local/mail.local.c b/libexec/mail.local/mail.local.c
index ff8f797f817..6b3e9bd85f4 100644
--- a/libexec/mail.local/mail.local.c
+++ b/libexec/mail.local/mail.local.c
@@ -39,7 +39,7 @@ char copyright[] =
#ifndef lint
/*static char sccsid[] = "from: @(#)mail.local.c 5.6 (Berkeley) 6/19/91";*/
-static char rcsid[] = "$Id: mail.local.c,v 1.4 1996/08/27 20:33:41 dm Exp $";
+static char rcsid[] = "$Id: mail.local.c,v 1.5 1996/08/29 04:19:34 deraadt Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -67,6 +67,7 @@ void notifybiff __P((char *));
int store __P((char *));
void usage __P((void));
+int
main(argc, argv)
int argc;
char **argv;
@@ -167,6 +168,22 @@ store(from)
return(fd);
}
+void
+baditem(path)
+ char *path;
+{
+ char npath[MAXPATHLEN];
+
+ if (unlink(path) == 0)
+ return;
+ snprintf(npath, sizeof npath, "%s/XXXXXXXXX", _PATH_MAILDIR);
+ if (mktemp(npath) == NULL)
+ return;
+ if (rename(path, npath) != -1)
+ err(NOTFATAL, "nasty spool item %s renamed to %s",
+ path, npath);
+}
+
int
deliver(fd, name, lockfile)
int fd;
@@ -188,15 +205,79 @@ deliver(fd, name, lockfile)
return(1);
}
- (void)sprintf(path, "%s/%s", _PATH_MAILDIR, name);
+ (void)snprintf(path, sizeof path, "%s/%s", _PATH_MAILDIR, name);
if (lockfile) {
- (void)sprintf(lpath, "%s/%s.lock", _PATH_MAILDIR, name);
-
- if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL,
- S_IRUSR|S_IWUSR)) < 0) {
- err(NOTFATAL, "%s: %s", lpath, strerror(errno));
- return(1);
+ int tries = 0;
+
+ (void)snprintf(lpath, sizeof lpath, "%s/%s.lock",
+ _PATH_MAILDIR, name);
+
+ if (stat(_PATH_MAILDIR, &sb) != -1 &&
+ (sb.st_mode & 7) == 7) {
+ /*
+ * We have a writeable spool, deal with it as
+ * securely as possible.
+ */
+ time_t ctim = -1;
+
+ seteuid(pw->pw_uid);
+ if (lstat(lpath, &sb) != -1)
+ ctim = sb.st_ctime;
+ while (1) {
+ /*
+ * Deal with existing user.lock files
+ * or directories or symbolic links that
+ * should not be here.
+ */
+ if (readlink(lpath, buf, sizeof buf) != -1) {
+ if (lstat(lpath, &sb) != -1 &&
+ S_ISLNK(fsb.st_mode)) {
+ seteuid(sb.st_uid);
+ unlink(lpath);
+ seteuid(pw->pw_uid);
+ }
+ goto again;
+ }
+ if ((lfd = open(lpath,
+ O_CREAT|O_WRONLY|O_EXCL|O_EXLOCK,
+ S_IRUSR|S_IWUSR)) != -1)
+ break;
+again:
+ if (tries > 10) {
+ err(NOTFATAL, "%s: %s", lpath,
+ strerror(errno));
+ seteuid(0);
+ return(1);
+ }
+ if (tries > 9 &&
+ (lfd = open(lpath, O_WRONLY|O_EXLOCK,
+ 0)) != -1) {
+ if (fstat(lfd, &fsb) != -1 &&
+ lstat(lpath, &sb) != -1) {
+ if (fsb.st_dev == sb.st_dev &&
+ fsb.st_ino == sb.st_ino &&
+ ctim == fsb.st_ctime ) {
+ seteuid(fsb.st_uid);
+ baditem(lpath);
+ seteuid(pw->pw_uid);
+ }
+ }
+ }
+ sleep(1 << tries);
+ tries++;
+ continue;
+ }
+ seteuid(0);
+ } else {
+ /*
+ * Only root can write the spool directory.
+ */
+ if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL,
+ S_IRUSR|S_IWUSR)) < 0) {
+ err(NOTFATAL, "%s: %s", lpath, strerror(errno));
+ return(1);
+ }
}
}
@@ -255,7 +336,7 @@ retry:
}
curoff = lseek(mbfd, 0, SEEK_END);
- (void)sprintf(biffmsg, "%s@%qd\n", name, curoff);
+ (void)snprintf(biffmsg, sizeof biffmsg, "%s@%qd\n", name, curoff);
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
err(FATAL, "temporary file: %s", strerror(errno));
goto bad;