[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Fixes to smtpserver and mailbox
The patches below fix the following bugs in zmailer 2.2:
transports/mailbox/mailbox.c:
There's a race condition between the time zmailer checks
a mailbox file and opens it for write.
Fix: use O_EXCL when creating new mailboxes, and verify that
the file hasn't changed after opening it.
Btw, I have a version of mailbox.c that does V7-style
file locking (link to foo.LOCK), so you can run the vendor's MUAs
safely if they use that method (SunOS does).
smtpserver/smtpserver.c:
Detect and complain about SMTP commands that are
too long to handle (>8k).
Long arguments to SMTP HELO no longer overwrite a static buffer.
RCS file: RCS/mailbox.c,v
retrieving revision 1.1
diff -c -r1.1 mailbox.c
*** /tmp/,RCSt1a09953 Thu Mar 24 22:54:55 1994
--- mailbox.c Thu Mar 24 22:51:53 1994
***************
*** 396,402 ****
register char **maild;
int fdmail, uid, messagefd;
FILE *fp;
! struct stat st;
char *file, *cp;
#if defined(BIFF) || defined(RBIFF)
struct biffer *nbp;
--- 396,402 ----
register char **maild;
int fdmail, uid, messagefd;
FILE *fp;
! struct stat st, s2;
char *file, *cp;
#if defined(BIFF) || defined(RBIFF)
struct biffer *nbp;
***************
*** 439,452 ****
return;
file = emalloc(strlen(rp->addr->user)+1);
(void) strcpy(file, rp->addr->user);
! fdmail = createfile(rp, file, uid);
! setrootuid(rp);
! if (fdmail >= 0) {
(void) close(fdmail);
- } else {
- free(file);
- return;
}
break;
default: /* local user */
if ((pw = getpwnam(rp->addr->user)) == NULL) {
--- 439,453 ----
return;
file = emalloc(strlen(rp->addr->user)+1);
(void) strcpy(file, rp->addr->user);
! if (access(file, F_OK) < 0) {
! fdmail = createfile(rp, file, uid);
! if (fdmail < 0) {
! free(file);
! return;
! }
(void) close(fdmail);
}
+ setrootuid(rp);
break;
default: /* local user */
if ((pw = getpwnam(rp->addr->user)) == NULL) {
***************
*** 536,541 ****
--- 537,559 ----
DIAGNOSTIC(rp, rp->status, fmtbuf, file);
return;
}
+ /*
+ * The mbox may have been removed and symlinked
+ * after the exstat() above, but before the open(),
+ * so verify that we have the same inode.
+ */
+ if (fstat(fdmail, &s2) < 0) {
+ DIAGNOSTIC(rp, EX_TEMPFAIL,
+ "can't fstat mailbox \"%s\"", file);
+ close(fdmail);
+ return;
+ }
+ if (st.st_ino != s2.st_ino || st.st_dev != s2.st_dev || s2.st_nlink != 1) {
+ DIAGNOSTIC(rp, EX_TEMPFAIL,
+ "lost race for mailbox \"%s\"", file);
+ close(fdmail);
+ return;
+ }
if ((st.st_mode & S_IFMT) != S_IFREG)
/* don't lock non-files */;
else
***************
*** 921,927 ****
extern int setupuidgid(), exstat();
extern void setrootuid();
! if ((fd = open(file, O_RDWR|O_CREAT, MAILMODE)) < 0) {
saverrno = errno;
if ((cp = strrchr(file, '/')) != NULL) {
*cp = '\0';
--- 939,945 ----
extern int setupuidgid(), exstat();
extern void setrootuid();
! if ((fd = open(file, O_RDWR|O_CREAT|O_EXCL, MAILMODE)) < 0) {
saverrno = errno;
if ((cp = strrchr(file, '/')) != NULL) {
*cp = '\0';
***************
*** 939,945 ****
}
*cp = '/';
}
! if ((fd = open(file, O_RDWR|O_CREAT, MAILMODE)) < 0) {
setrootuid(rp);
saverrno = errno;
} else {
--- 957,963 ----
}
*cp = '/';
}
! if ((fd = open(file, O_RDWR|O_CREAT|O_EXCL, MAILMODE)) < 0) {
setrootuid(rp);
saverrno = errno;
} else {
RCS file: RCS/smtpserver.c,v
retrieving revision 1.1
diff -c -r1.1 smtpserver.c
*** /tmp/,RCSt1a09967 Thu Mar 24 22:55:12 1994
--- smtpserver.c Thu Mar 24 22:45:51 1994
***************
*** 122,128 ****
char *progname, *cmdline, *eocmdline, *logfile;
char *postoffice = NULL;
char *routerprog = NULL;
- char helobuf[MAXHOSTNAMELEN+1];
char myhostname[MAXHOSTNAMELEN+1];
char rhostname[MAXHOSTNAMELEN+1];
char ihostaddr[3*4+1*3+2+1 /* == 18 for '[255.255.255.255]' */ +10/*slack*/];
--- 122,127 ----
***************
*** 510,515 ****
--- 509,515 ----
struct stat stbuf;
struct smtpconf *cfinfo;
char buf[8192]; /* XX: limits size of SMTP commands... */
+ char helobuf[sizeof buf/sizeof(char)];
extern char *Version;
extern u_char *rfc822date();
extern void mvdata(), type(), report();
***************
*** 567,573 ****
(void) fflush(logfp);
}
while (fgets(buf, sizeof buf, stdin)) {
! report("%s", buf);
for (cp = buf + strlen(buf) - 1;
cp > buf && isascii(*cp) && isspace(*cp); --cp)
continue;
--- 567,577 ----
(void) fflush(logfp);
}
while (fgets(buf, sizeof buf, stdin)) {
! if (strchr(buf, '\n') == NULL) {
! type(500, "Line too long");
! continue;
! }
! report("%.100s", buf);
for (cp = buf + strlen(buf) - 1;
cp > buf && isascii(*cp) && isspace(*cp); --cp)
continue;