[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;