summaryrefslogtreecommitdiffstats
path: root/usr.sbin/sendmail
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1997-06-27 15:17:19 +0000
committerpeter <peter@FreeBSD.org>1997-06-27 15:17:19 +0000
commitffc2d3d70315c587069f7268c77ccacce772a7e4 (patch)
tree8cbd2d8ef7f7d2877b971c8365f2641d3c6564ad /usr.sbin/sendmail
parent30e296b7618348906cd1a4d7dddfe581ded43a2a (diff)
downloadFreeBSD-src-ffc2d3d70315c587069f7268c77ccacce772a7e4.zip
FreeBSD-src-ffc2d3d70315c587069f7268c77ccacce772a7e4.tar.gz
Merge in sendmail-8.8.5 -> 8.8.6 changes to those files that have left the
vendor branch.
Diffstat (limited to 'usr.sbin/sendmail')
-rw-r--r--usr.sbin/sendmail/mail.local/mail.local.c63
-rw-r--r--usr.sbin/sendmail/mailstats/mailstats.c11
-rw-r--r--usr.sbin/sendmail/makemap/Makefile9
-rw-r--r--usr.sbin/sendmail/makemap/makemap.c303
-rw-r--r--usr.sbin/sendmail/praliases/praliases.c7
-rw-r--r--usr.sbin/sendmail/src/Makefile10
-rw-r--r--usr.sbin/sendmail/src/collect.c37
-rw-r--r--usr.sbin/sendmail/src/conf.c837
-rw-r--r--usr.sbin/sendmail/src/conf.h142
-rw-r--r--usr.sbin/sendmail/src/daemon.c245
-rw-r--r--usr.sbin/sendmail/src/deliver.c186
-rw-r--r--usr.sbin/sendmail/src/domain.c8
-rw-r--r--usr.sbin/sendmail/src/headers.c155
-rw-r--r--usr.sbin/sendmail/src/main.c193
-rw-r--r--usr.sbin/sendmail/src/mime.c36
-rw-r--r--usr.sbin/sendmail/src/parseaddr.c64
-rw-r--r--usr.sbin/sendmail/src/readcf.c77
-rw-r--r--usr.sbin/sendmail/src/recipient.c138
-rw-r--r--usr.sbin/sendmail/src/savemail.c37
-rw-r--r--usr.sbin/sendmail/src/sendmail.85
-rw-r--r--usr.sbin/sendmail/src/sendmail.h63
-rw-r--r--usr.sbin/sendmail/src/srvrsmtp.c139
-rw-r--r--usr.sbin/sendmail/src/udb.c54
-rw-r--r--usr.sbin/sendmail/src/usersmtp.c79
-rw-r--r--usr.sbin/sendmail/src/util.c669
25 files changed, 2151 insertions, 1416 deletions
diff --git a/usr.sbin/sendmail/mail.local/mail.local.c b/usr.sbin/sendmail/mail.local/mail.local.c
index a61cde5..d854e78 100644
--- a/usr.sbin/sendmail/mail.local/mail.local.c
+++ b/usr.sbin/sendmail/mail.local/mail.local.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mail.local.c,v 1.7 1997/02/22 16:13:23 peter Exp $
+ * $Id: mail.local.c,v 1.8 1997/03/31 05:11:16 imp Exp $
*/
#ifndef lint
@@ -40,7 +40,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)mail.local.c 8.34 (Berkeley) 11/24/96";
+static char sccsid[] = "@(#)mail.local.c 8.39 (Berkeley) 5/28/97";
#endif /* not lint */
/*
@@ -88,6 +88,7 @@ static char sccsid[] = "@(#)mail.local.c 8.34 (Berkeley) 11/24/96";
#if defined(_AIX)
# define USE_LOCKF 1
+# define USET_SETEUID 1
# define USE_VSYSLOG 0
#endif
@@ -148,9 +149,17 @@ static char sccsid[] = "@(#)mail.local.c 8.34 (Berkeley) 11/24/96";
# define _BSD_VA_LIST_ va_list
#endif
+#if defined(BSD4_4) || defined(linux)
+# define HASSNPRINTF 1
+#endif
+
+#if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206)
+# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */
+#endif
+
#if !defined(BSD4_4) && !defined(linux)
extern char *strerror __P((int));
-extern int snprintf __P((char *, int, const char *, ...));
+extern int snprintf __P((char *, size_t, const char *, ...));
extern FILE *fdopen __P((int, const char *));
#endif
@@ -384,9 +393,13 @@ deliver(fd, name, nobiff, nofsync)
*/
tryagain:
lockmbox(path);
- if (lstat(path, &sb)) {
+ if (lstat(path, &sb) < 0) {
mbfd = open(path,
O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
+ if (lstat(path, &sb) < 0)
+ goto filechanged;
+ else
+ sb.st_uid = pw->pw_uid;
if (mbfd == -1) {
if (errno == EEXIST)
goto tryagain;
@@ -405,20 +418,20 @@ tryagain:
goto err0;
} else {
mbfd = open(path, O_APPEND|O_WRONLY, 0);
- if (mbfd != -1 &&
- (fstat(mbfd, &fsb) || fsb.st_nlink != 1 ||
- !S_ISREG(fsb.st_mode) || sb.st_dev != fsb.st_dev ||
- sb.st_ino != fsb.st_ino || sb.st_uid != fsb.st_uid)) {
- eval = EX_CANTCREAT;
- warn("%s: file changed after open", path);
- goto err1;
- }
}
if (mbfd == -1) {
e_to_sys(errno);
warn("%s: %s", path, strerror(errno));
goto err0;
+ } else if (fstat(mbfd, &fsb) < 0 ||
+ fsb.st_nlink != 1 || sb.st_nlink != 1 ||
+ !S_ISREG(fsb.st_mode) || sb.st_dev != fsb.st_dev ||
+ sb.st_ino != fsb.st_ino || sb.st_uid != fsb.st_uid) {
+filechanged:
+ eval = EX_CANTCREAT;
+ warn("%s: file changed after open", path);
+ goto err1;
}
/* Wait until we can get a lock on the file. */
@@ -486,9 +499,9 @@ err0: unlockmbox();
if (close(mbfd)) {
e_to_sys(errno);
warn("%s: %s", path, strerror(errno));
- unlockmbox();
- return;
- }
+ truncate(path, curoff);
+ } else if (!nobiff)
+ notifybiff(biffmsg);
if (setreuid(0, 0) < 0) {
e_to_sys(errno);
@@ -498,8 +511,6 @@ err0: unlockmbox();
printf("reset euid = %d\n", geteuid());
#endif
unlockmbox();
- if (!nobiff)
- notifybiff(biffmsg);
}
/*
@@ -520,6 +531,8 @@ lockmbox(path)
if (locked)
return;
+ if (strlen(path) + 6 > sizeof lockname)
+ return;
sprintf(lockname, "%s.lock", path);
for (;; sleep(5)) {
int fd;
@@ -774,16 +787,16 @@ strerror(eno)
return ebuf;
}
-# endif
+#endif /* !defined(BSD4_4) && !defined(__osf__) */
-#if !defined(BSD4_4) && !defined(linux)
+#if !HASSNPRINTF
# if __STDC__
-snprintf(char *buf, int bufsiz, const char *fmt, ...)
+snprintf(char *buf, size_t bufsiz, const char *fmt, ...)
# else
snprintf(buf, bufsiz, fmt, va_alist)
char *buf;
- int bufsiz;
+ size_t bufsiz;
const char *fmt;
va_dcl
# endif
@@ -799,7 +812,7 @@ snprintf(buf, bufsiz, fmt, va_alist)
va_end(ap);
}
-#endif
+#endif /* !HASSNPRINTF */
#ifdef ultrix
@@ -892,7 +905,7 @@ _gettemp(path, doopen)
break;
if (*trv == '/') {
*trv = '\0';
- if (stat(path, &sbuf))
+ if (stat(path, &sbuf) < 0)
return(0);
if (!S_ISDIR(sbuf.st_mode)) {
errno = ENOTDIR;
@@ -911,7 +924,7 @@ _gettemp(path, doopen)
if (errno != EEXIST)
return(0);
}
- else if (stat(path, &sbuf))
+ else if (stat(path, &sbuf) < 0)
return(errno == ENOENT ? 1 : 0);
/* tricky little algorithm for backward compatibility */
@@ -932,4 +945,4 @@ _gettemp(path, doopen)
/*NOTREACHED*/
}
-#endif
+#endif /* ultrix */
diff --git a/usr.sbin/sendmail/mailstats/mailstats.c b/usr.sbin/sendmail/mailstats/mailstats.c
index 3833da3..625b44c 100644
--- a/usr.sbin/sendmail/mailstats/mailstats.c
+++ b/usr.sbin/sendmail/mailstats/mailstats.c
@@ -40,7 +40,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)mailstats.c 8.8 (Berkeley) 9/25/96";
+static char sccsid[] = "@(#)mailstats.c 8.10 (Berkeley) 5/30/97";
#endif /* not lint */
#define NOT_SENDMAIL
@@ -66,7 +66,7 @@ main(argc, argv)
bool mnames;
long frmsgs = 0, frbytes = 0, tomsgs = 0, tobytes = 0;
char mtable[MAXMAILERS][MNAMELEN+1];
- char sfilebuf[100];
+ char sfilebuf[MAXLINE];
char buf[MAXLINE];
extern char *ctime();
@@ -145,6 +145,13 @@ main(argc, argv)
}
/* this is the S or StatusFile option -- save it */
+ if (strlen(b) >= sizeof sfilebuf)
+ {
+ fprintf(stderr,
+ "StatusFile filename too long: %.30s...\n",
+ s);
+ exit(EX_CONFIG);
+ }
strcpy(sfilebuf, b);
b = strchr(sfilebuf, '#');
if (b == NULL)
diff --git a/usr.sbin/sendmail/makemap/Makefile b/usr.sbin/sendmail/makemap/Makefile
index 1cc9b59..db59c4f 100644
--- a/usr.sbin/sendmail/makemap/Makefile
+++ b/usr.sbin/sendmail/makemap/Makefile
@@ -1,8 +1,13 @@
-# @(#)Makefile 8.1 (Berkeley) 6/7/93
+# @(#)Makefile 8.4 (Berkeley) 6/10/97
PROG= makemap
MAN8= makemap.8
-CFLAGS+=-I${.CURDIR}/../src -DNEWDB
+CFLAGS+=-I${.CURDIR}/../src -DNEWDB -DNOT_SENDMAIL
+
+SRCS= makemap.c safefile.c
+
+safefile.c: ${.CURDIR}/../src/safefile.c
+ ln -s ${.CURDIR}/../src/safefile.c
.include "../../Makefile.inc"
.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/makemap/makemap.c b/usr.sbin/sendmail/makemap/makemap.c
index a1e73c4..7ef4612 100644
--- a/usr.sbin/sendmail/makemap/makemap.c
+++ b/usr.sbin/sendmail/makemap/makemap.c
@@ -33,21 +33,15 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)makemap.c 8.19 (Berkeley) 11/18/96";
+static char sccsid[] = "@(#)makemap.c 8.35 (Berkeley) 6/10/97";
#endif /* not lint */
-#include <stdio.h>
-#include <sysexits.h>
#include <sys/types.h>
-#include <ctype.h>
-#include <string.h>
#include <sys/errno.h>
#ifndef ISC_UNIX
# include <sys/file.h>
#endif
-#define NOT_SENDMAIL
-#include "useful.h"
-#include "conf.h"
+#include "sendmail.h"
#ifdef NDBM
#include <ndbm.h>
@@ -74,6 +68,17 @@ union dbent
} xx;
};
+uid_t RealUid;
+gid_t RealGid;
+char *RealUserName;
+uid_t RunAsUid;
+uid_t RunAsGid;
+char *RunAsUserName;
+int Verbose = 2;
+bool DontInitGroups = TRUE;
+bool UnsafeGroupWrites = FALSE;
+u_char tTdvect[100];
+
#define BUFSIZE 1024
main(argc, argv)
@@ -87,12 +92,12 @@ main(argc, argv)
bool allowdups = FALSE;
bool verbose = FALSE;
bool foldcase = TRUE;
+ bool ignoresafeties = FALSE;
int exitstat;
int opt;
char *typename;
char *mapname;
char *ext;
- char *lext;
int lineno;
int st;
int mode;
@@ -117,15 +122,33 @@ main(argc, argv)
#endif
char ibuf[BUFSIZE];
char fbuf[MAXNAME];
- char lbuf[MAXNAME];
+ char dbuf[MAXNAME];
+ char pbuf[MAXNAME];
+ static char rnamebuf[MAXNAME]; /* holds RealUserName */
+ struct passwd *pw;
+ int sff = SFF_ROOTOK|SFF_REGONLY|SFF_NOLINK|SFF_NOWLINK;
+ struct stat std, stp;
extern char *optarg;
extern int optind;
extern bool lockfile();
progname = argv[0];
-#ifdef FFR_CFLAG
-#define OPTIONS "Nc:dforv"
+ RunAsUid = RealUid = getuid();
+ RunAsGid = RealGid = getgid();
+ pw = getpwuid(RealUid);
+ if (pw != NULL)
+ {
+ if (strlen(pw->pw_name) > MAXNAME - 1)
+ pw->pw_name[MAXNAME] = 0;
+ sprintf(rnamebuf, "%s", pw->pw_name);
+ }
+ else
+ sprintf(rnamebuf, "Unknown UID %d", RealUid);
+ RunAsUserName = RealUserName = rnamebuf;
+
+#if _FFR_NEW_MAKEMAP_FLAGS
+#define OPTIONS "Nc:dforsv"
#else
#define OPTIONS "Ndforv"
#endif
@@ -137,7 +160,7 @@ main(argc, argv)
inclnull = TRUE;
break;
-#ifdef FFR_CFLAG
+#if _FFR_NEW_MAKEMAP_FLAGS
case 'c':
dbcachesize = atol(optarg);
break;
@@ -159,6 +182,12 @@ main(argc, argv)
allowreplace = TRUE;
break;
+#if _FFR_NEW_MAKEMAP_FLAGS
+ case 's':
+ ignoresafeties = TRUE;
+ break;
+#endif
+
case 'v':
verbose = TRUE;
break;
@@ -178,12 +207,10 @@ main(argc, argv)
typename = argv[0];
mapname = argv[1];
ext = NULL;
- lext = NULL;
if (strcmp(typename, "dbm") == 0)
{
type = T_DBM;
- lext = ".dir";
}
else if (strcmp(typename, "btree") == 0)
{
@@ -202,8 +229,10 @@ main(argc, argv)
switch (type)
{
case T_ERR:
-#ifdef FFR_CFLAG
- fprintf(stderr, "Usage: %s [-N] [-c cachesize] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname);
+#if _FFR_NEW_MAKEMAP_FLAGS
+ fprintf(stderr,
+ "Usage: %s [-N] [-c cachesize] [-d] [-f] [-o] [-r] [-s] [-v] type mapname\n",
+ progname);
#else
fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname);
#endif
@@ -270,6 +299,11 @@ main(argc, argv)
el = strlen(ext);
fl = strlen(mapname);
+ if (el + fl + 1 >= sizeof fbuf)
+ {
+ fprintf(stderr, "%s: file name too long", mapname);
+ exit(EX_USAGE);
+ }
if (fl < el || strcmp(&mapname[fl - el], ext) != 0)
{
strcpy(fbuf, mapname);
@@ -278,9 +312,68 @@ main(argc, argv)
}
}
- strcpy(lbuf, mapname);
- if (lext != NULL)
- strcat(lbuf, lext);
+ if (!notrunc)
+ sff |= SFF_CREAT;
+ switch (type)
+ {
+#ifdef NEWDB
+ case T_BTREE:
+ case T_HASH:
+ if (strlen(mapname) >= sizeof dbuf)
+ {
+ fprintf(stderr,
+ "%s: map name too long\n", mapname);
+ exit(EX_USAGE);
+ }
+ strcpy(dbuf, mapname);
+ if (!ignoresafeties &&
+ (st = safefile(dbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &std)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ dbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ break;
+#endif
+#ifdef NDBM
+ case T_DBM:
+ if (strlen(mapname) + 5 > sizeof dbuf)
+ {
+ fprintf(stderr,
+ "%s: map name too long\n", mapname);
+ exit(EX_USAGE);
+ }
+ sprintf(dbuf, "%s.dir", mapname);
+ if (!ignoresafeties &&
+ (st = safefile(dbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &std)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ dbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ sprintf(pbuf, "%s.pag", mapname);
+ if (!ignoresafeties &&
+ (st = safefile(pbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &stp)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ pbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ break;
+#endif
+ default:
+ fprintf(stderr,
+ "%s: internal error: type %d\n",
+ progname,
+ type);
+ exit(EX_SOFTWARE);
+ }
/*
** Create the database.
@@ -289,24 +382,36 @@ main(argc, argv)
mode = O_RDWR;
if (!notrunc)
mode |= O_CREAT|O_TRUNC;
-#ifdef O_EXLOCK
+#if O_EXLOCK
mode |= O_EXLOCK;
#else
/* pre-lock the database */
- fd = open(lbuf, mode & ~O_TRUNC, 0644);
+ if (ignoresafeties)
+ fd = dfopen(dbuf, mode & ~O_TRUNC, 0644, sff);
+ else
+ fd = safeopen(dbuf, mode & ~O_TRUNC, 0644, sff);
if (fd < 0)
{
fprintf(stderr, "%s: cannot create type %s map %s\n",
progname, typename, mapname);
exit(EX_CANTCREAT);
}
- (void) lockfile(fd);
#endif
switch (type)
{
#ifdef NDBM
case T_DBM:
dbp.dbm = dbm_open(mapname, mode, 0644);
+ if (!ignoresafeties && dbp.dbm != NULL &&
+ (filechanged(dbuf, dbm_dirfno(dbp.dbm), &std, sff) ||
+ filechanged(pbuf, dbm_pagfno(dbp.dbm), &stp, sff)))
+ {
+ fprintf(stderr,
+ "dbm map %s: file changed after open\n",
+ mapname);
+ dbm_close(dbp.dbm);
+ exit(EX_CANTCREAT);
+ }
break;
#endif
@@ -315,10 +420,19 @@ main(argc, argv)
/* tweak some parameters for performance */
hinfo.nelem = 4096;
hinfo.cachesize = dbcachesize;
-
+
dbp.db = dbopen(mapname, mode, 0644, DB_HASH, &hinfo);
if (dbp.db != NULL)
{
+ if (!ignoresafeties &&
+ filechanged(dbuf, dbp.db->fd(dbp.db), &std, sff))
+ {
+ fprintf(stderr,
+ "db map %s: file changed after open\n",
+ mapname);
+ dbp.db->close(dbp.db);
+ exit(EX_CANTCREAT);
+ }
# if OLD_NEWDB
(void) (*dbp.db->sync)(dbp.db);
# else
@@ -334,6 +448,15 @@ main(argc, argv)
dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti);
if (dbp.db != NULL)
{
+ if (!ignoresafeties &&
+ filechanged(dbuf, dbp.db->fd(dbp.db), &std, sff))
+ {
+ fprintf(stderr,
+ "db map %s: file changed after open\n",
+ mapname);
+ dbp.db->close(dbp.db);
+ exit(EX_CANTCREAT);
+ }
# if OLD_NEWDB
(void) (*dbp.db->sync)(dbp.db);
# else
@@ -344,7 +467,8 @@ main(argc, argv)
#endif
default:
- fprintf(stderr, "%s: internal error: type %d\n", progname, type);
+ fprintf(stderr, "%s: internal error: type %d\n",
+ progname, type);
exit(EX_SOFTWARE);
}
@@ -447,7 +571,8 @@ main(argc, argv)
}
else if (st > 0)
{
- fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n",
+ fprintf(stderr,
+ "%s: %s: line %d: key %s: duplicate key\n",
progname, mapname, lineno, key.xx.data);
}
}
@@ -477,7 +602,7 @@ main(argc, argv)
#endif
}
-#ifndef O_EXLOCK
+#if !O_EXLOCK
/* release locks */
close(fd);
#endif
@@ -489,6 +614,11 @@ main(argc, argv)
**
** Parameters:
** fd -- the file descriptor of the file.
+** filename -- the file name (for error messages).
+** ext -- the filename extension.
+** type -- type of the lock. Bits can be:
+** LOCK_EX -- exclusive lock.
+** LOCK_NB -- non-blocking.
**
** Returns:
** TRUE if the lock was acquired.
@@ -496,8 +626,11 @@ main(argc, argv)
*/
bool
-lockfile(fd)
+lockfile(fd, filename, ext, type)
int fd;
+ char *filename;
+ char *ext;
+ int type;
{
# if !HASFLOCK
int action;
@@ -505,8 +638,16 @@ lockfile(fd)
extern int errno;
bzero(&lfd, sizeof lfd);
- lfd.l_type = F_WRLCK;
- action = F_SETLKW;
+ if (bitset(LOCK_UN, type))
+ lfd.l_type = F_UNLCK;
+ else if (bitset(LOCK_EX, type))
+ lfd.l_type = F_WRLCK;
+ else
+ lfd.l_type = F_RDLCK;
+ if (bitset(LOCK_NB, type))
+ action = F_SETLK;
+ else
+ action = F_SETLKW;
if (fcntl(fd, action, &lfd) >= 0)
return TRUE;
@@ -525,10 +666,110 @@ lockfile(fd)
# else /* HASFLOCK */
- if (flock(fd, LOCK_EX) >= 0)
+ if (flock(fd, type) >= 0)
return TRUE;
# endif
return FALSE;
}
+
+/*VARARGS2*/
+void
+#ifdef __STDC__
+message(const char *msg, ...)
+#else
+message(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif
+{
+ const char *m;
+ VA_LOCAL_DECL
+
+ m = msg;
+ if (isdigit(m[0]) && isdigit(m[1]) && isdigit(m[2]) && m[3] == ' ')
+ m += 4;
+ VA_START(msg);
+ vfprintf(stderr, m, ap);
+ VA_END;
+ fprintf(stderr, "\n");
+}
+
+/*VARARGS2*/
+void
+#ifdef __STDC__
+syserr(const char *msg, ...)
+#else
+syserr(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif
+{
+ const char *m;
+ VA_LOCAL_DECL
+
+ m = msg;
+ if (isdigit(m[0]) && isdigit(m[1]) && isdigit(m[2]) && m[3] == ' ')
+ m += 4;
+ VA_START(msg);
+ vfprintf(stderr, m, ap);
+ VA_END;
+ fprintf(stderr, "\n");
+}
+
+const char *
+errstring(err)
+ int err;
+{
+ static char errstr[64];
+#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+#endif
+
+ /* handle pseudo-errors internal to sendmail */
+ switch (err)
+ {
+ case E_SM_OPENTIMEOUT:
+ return "Timeout on file open";
+
+ case E_SM_NOSLINK:
+ return "Symbolic links not allowed";
+
+ case E_SM_NOHLINK:
+ return "Hard links not allowed";
+
+ case E_SM_REGONLY:
+ return "Regular files only";
+
+ case E_SM_ISEXEC:
+ return "Executable files not allowed";
+
+ case E_SM_WWDIR:
+ return "World writable directory";
+
+ case E_SM_GWDIR:
+ return "Group writable directory";
+
+ case E_SM_FILECHANGE:
+ return "File changed after open";
+
+ case E_SM_WWFILE:
+ return "World writable file";
+
+ case E_SM_GWFILE:
+ return "Group writable file";
+ }
+
+#if HASSTRERROR
+ return strerror(err);
+#else
+ if (err < 0 || err > sys_nerr)
+ {
+ sprintf(errstr, "Error %d", err);
+ return errstr;
+ }
+ return sys_errlist[err];
+#endif
+}
diff --git a/usr.sbin/sendmail/praliases/praliases.c b/usr.sbin/sendmail/praliases/praliases.c
index 1177164..e0cae65 100644
--- a/usr.sbin/sendmail/praliases/praliases.c
+++ b/usr.sbin/sendmail/praliases/praliases.c
@@ -39,7 +39,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)praliases.c 8.4 (Berkeley) 9/25/96";
+static char sccsid[] = "@(#)praliases.c 8.5 (Berkeley) 5/28/97";
#endif /* not lint */
#include <ndbm.h>
@@ -83,6 +83,11 @@ main(argc, argv)
argv += optind;
#ifdef NEWDB
+ if (strlen(filename) + 4 >= sizeof buf)
+ {
+ fprintf(stderr, "Alias filename too long: %.30s...\n", filename);
+ exit(EX_USAGE);
+ }
(void) strcpy(buf, filename);
(void) strcat(buf, ".db");
if (db = dbopen(buf, O_RDONLY, 0444 , DB_HASH, NULL)) {
diff --git a/usr.sbin/sendmail/src/Makefile b/usr.sbin/sendmail/src/Makefile
index f8d8370..a634725 100644
--- a/usr.sbin/sendmail/src/Makefile
+++ b/usr.sbin/sendmail/src/Makefile
@@ -1,4 +1,4 @@
-# @(#)Makefile 8.7 (Berkeley) 10/31/95
+# @(#)Makefile 8.8 (Berkeley) 3/28/97
#########################################################################
# This Makefile is for 4.4BSD only!!! For all other systems, use #
@@ -25,14 +25,14 @@ CFLAGS+=-I${.CURDIR} ${DBMDEF} ${NIS} #-DNETISO
SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
- mci.c mime.c parseaddr.c queue.c readcf.c recipient.c savemail.c \
- srvrsmtp.c stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
- util.c version.c
+ mci.c mime.c parseaddr.c queue.c readcf.c recipient.c safefile.c \
+ savemail.c srvrsmtp.c stab.c stats.c sysexits.c trace.c udb.c \
+ usersmtp.c util.c version.c
DPADD= ${LIBUTIL}
LDADD= -lutil
MAN1= mailq.1 newaliases.1
MAN5= aliases.5
-MAN8= sendmail.8
+MAN8= sendmail.8
LINKS= /usr/sbin/sendmail /usr/bin/newaliases \
/usr/sbin/sendmail /usr/bin/mailq \
/usr/sbin/sendmail /usr/bin/hoststat \
diff --git a/usr.sbin/sendmail/src/collect.c b/usr.sbin/sendmail/src/collect.c
index d5d8982..219a47f 100644
--- a/usr.sbin/sendmail/src/collect.c
+++ b/usr.sbin/sendmail/src/collect.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)collect.c 8.62 (Berkeley) 12/11/96";
+static char sccsid[] = "@(#)collect.c 8.69 (Berkeley) 5/29/97";
#endif /* not lint */
# include <errno.h>
@@ -52,8 +52,6 @@ static char sccsid[] = "@(#)collect.c 8.62 (Berkeley) 12/11/96";
** style message to say we are ready to collect
** input, and never ignore a single dot to mean
** end of message.
-** requeueflag -- this message will be requeued later, so
-** don't do final processing on it.
** hdrp -- the location to stash the header.
** e -- the current envelope.
**
@@ -83,10 +81,9 @@ static EVENT *CollectTimeout;
#define MS_BODY 2 /* reading message body */
void
-collect(fp, smtpmode, requeueflag, hdrp, e)
+collect(fp, smtpmode, hdrp, e)
FILE *fp;
bool smtpmode;
- bool requeueflag;
HDR **hdrp;
register ENVELOPE *e;
{
@@ -103,7 +100,7 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
volatile int mstate;
u_char *volatile pbp;
u_char peekbuf[8];
- char dfname[20];
+ char dfname[MAXQFNAME];
char bufbuf[MAXLINE];
extern bool isheader();
extern void eatheader();
@@ -117,10 +114,12 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
if (!headeronly)
{
+ int tfd;
struct stat stbuf;
strcpy(dfname, queuename(e, 'd'));
- if ((tf = dfopen(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode)) == NULL)
+ tfd = dfopen(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode, SFF_ANYFILE);
+ if (tfd < 0 || (tf = fdopen(tfd, "w")) == NULL)
{
syserr("Cannot create %s", dfname);
e->e_flags |= EF_NO_BODY_RETN;
@@ -169,12 +168,10 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
/* handle possible input timeout */
if (setjmp(CtxCollectTimeout) != 0)
{
-#ifdef LOG
if (LogLevel > 2)
- syslog(LOG_NOTICE,
+ sm_syslog(LOG_NOTICE, e->e_id,
"timeout waiting for input from %s during message collect",
CurHostName ? CurHostName : "<local machine>");
-#endif
errno = 0;
usrerr("451 timeout waiting for input during message collect");
goto readerr;
@@ -417,10 +414,9 @@ readerr:
if (tTd(30, 1))
printf("collect: premature EOM: %s\n", errmsg);
-#ifdef LOG
if (LogLevel >= 2)
- syslog(LOG_WARNING, "collect: premature EOM: %s", errmsg);
-#endif
+ sm_syslog(LOG_WARNING, e->e_id,
+ "collect: premature EOM: %s", errmsg);
inputerr = TRUE;
}
@@ -455,14 +451,12 @@ readerr:
problem = "I/O error";
else
problem = "read timeout";
-# ifdef LOG
if (LogLevel > 0 && feof(fp))
- syslog(LOG_NOTICE,
+ sm_syslog(LOG_NOTICE, e->e_id,
"collect: %s on connection from %.100s, sender=%s: %s",
problem, host,
shortenstring(e->e_from.q_paddr, 203),
errstring(errno));
-# endif
if (feof(fp))
usrerr("451 collect: %s on connection from %s, from=%s",
problem, host,
@@ -501,7 +495,7 @@ readerr:
markstats(e, (ADDRESS *) NULL);
}
-#ifdef _FFR_DSN_RRT
+#if _FFR_DSN_RRT_OPTION
/*
** If we have a Return-Receipt-To:, turn it into a DSN.
*/
@@ -576,11 +570,10 @@ readerr:
e->e_status = "5.2.3";
usrerr("552 Message exceeds maximum fixed size (%ld)",
MaxMessageSize);
-# ifdef LOG
if (LogLevel > 6)
- syslog(LOG_NOTICE, "%s: message size (%ld) exceeds maximum (%ld)",
- e->e_id, e->e_msgsize, MaxMessageSize);
-# endif
+ sm_syslog(LOG_NOTICE, e->e_id,
+ "message size (%ld) exceeds maximum (%ld)",
+ e->e_msgsize, MaxMessageSize);
}
/* check for illegal 8-bit data */
diff --git a/usr.sbin/sendmail/src/conf.c b/usr.sbin/sendmail/src/conf.c
index a768d18..0d50508 100644
--- a/usr.sbin/sendmail/src/conf.c
+++ b/usr.sbin/sendmail/src/conf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)conf.c 8.333 (Berkeley) 1/21/97";
+static char sccsid[] = "@(#)conf.c 8.362 (Berkeley) 6/14/97";
#endif /* not lint */
# include "sendmail.h"
@@ -140,6 +140,9 @@ struct prival PrivacyValues[] =
{ "novrfy", PRIV_NOVRFY },
{ "restrictmailq", PRIV_RESTRICTMAILQ },
{ "restrictqrun", PRIV_RESTRICTQRUN },
+#if _FFR_PRIVACY_NOETRN
+ { "noetrn", PRIV_NOETRN },
+#endif
{ "authwarnings", PRIV_AUTHWARNINGS },
{ "noreceipts", PRIV_NORECEIPTS },
{ "goaway", PRIV_GOAWAY },
@@ -187,6 +190,7 @@ setdefaults(e)
extern void setdefuser();
extern void setupmaps();
extern void setupmailers();
+ extern void setupheaders();
SpaceSub = ' '; /* option B */
QueueLA = 8; /* option x */
@@ -233,6 +237,7 @@ setdefaults(e)
setdefuser();
setupmaps();
setupmailers();
+ setupheaders();
}
@@ -252,46 +257,6 @@ setdefuser()
defpwent == NULL ? "nobody" : defpwent->pw_name);
}
/*
-** HOST_MAP_INIT -- initialize host class structures
-*/
-
-bool host_map_init __P((MAP *map, char *args));
-
-bool
-host_map_init(MAP *map, char *args)
-{
- register char *p = args;
-
- for (;;)
- {
- while (isascii(*p) && isspace(*p))
- p++;
- if (*p != '-')
- break;
- switch (*++p)
- {
- case 'a':
- map->map_app = ++p;
- break;
-
- case 'm':
- map->map_mflags |= MF_MATCHONLY;
- break;
-
- case 't':
- map->map_mflags |= MF_NODEFER;
- break;
- }
- while (*p != '\0' && !(isascii(*p) && isspace(*p)))
- p++;
- if (*p != '\0')
- *p++ = '\0';
- }
- if (map->map_app != NULL)
- map->map_app = newstr(map->map_app);
- return TRUE;
-}
- /*
** SETUPMAILERS -- initialize default mailers
*/
@@ -366,8 +331,8 @@ setupmaps()
#endif
#ifdef LDAPMAP
MAPDEF("ldapx", NULL, 0,
- ldap_map_parseargs, ldap_map_open, ldap_map_close,
- ldap_map_lookup, null_map_store);
+ ldap_map_parseargs, ldap_map_open, ldap_map_close,
+ ldap_map_lookup, null_map_store);
#endif
#ifdef HESIOD
@@ -1060,7 +1025,11 @@ setsignal(sig, handler)
sigfunc_t handler;
{
#if defined(SYS5SIGNALS) || defined(BSD4_3)
+# ifdef BSD4_3
return signal(sig, handler);
+# else
+ return sigset(sig, handler);
+# endif
#else
struct sigaction n, o;
@@ -1523,8 +1492,8 @@ getla()
dg_sys_info((long *)&load_info,
DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (load_info.one_minute + 0.5));
+ if (tTd(3, 1))
+ printf("getla: %d\n", (int) (load_info.one_minute + 0.5));
return((int) (load_info.one_minute + 0.5));
}
@@ -1555,8 +1524,8 @@ getla()
(size_t) 1, 0) == -1)
return 0;
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5));
+ if (tTd(3, 1))
+ printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5));
return (int) (pstd.psd_avg_1_min + 0.5);
}
@@ -1697,8 +1666,7 @@ int getla(void)
static int kmem = -1;
static enum { getla_none, getla_32, getla_64 } kernel_type =
getla_none;
- uint32_t avenrun32[3];
- uint64_t avenrun64[3];
+ uint32_t avenrun[3];
if (kernel_type == getla_none)
{
@@ -1781,57 +1749,47 @@ int getla(void)
switch (kernel_type)
{
+ case getla_none:
+ return -1;
+
case getla_32:
if (lseek(kmem, (off_t) Nl32[X_AVENRUN].n_value, SEEK_SET) == -1 ||
- read(kmem, (char *) avenrun32, sizeof(avenrun32)) < sizeof(avenrun32))
+ read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
{
if (tTd(3, 1))
printf("getla: lseek or read: %s\n",
errstring(errno));
return -1;
}
- if (tTd(3, 5))
- {
- printf("getla: avenrun{32} = %ld",
- (long int) avenrun32[0]);
- if (tTd(3, 15))
- printf(", %ld, %ld",
- (long int)avenrun32[1],
- (long int)avenrun32[2]);
- printf("\n");
- }
- if (tTd(3, 1))
- printf("getla: %d\n",
- (int) (avenrun32[0] + FSCALE/2) >> FSHIFT);
- return ((int) (avenrun32[0] + FSCALE/2) >> FSHIFT);
+ break;
case getla_64:
/* Using of lseek64 is perhaps overkill ... */
if (lseek64(kmem, (off64_t) Nl64[X_AVENRUN].n_value, SEEK_SET) == -1 ||
- read(kmem, (char *) avenrun64, sizeof(avenrun64)) <
- sizeof(avenrun64))
+ read(kmem, (char *) avenrun, sizeof(avenrun)) <
+ sizeof(avenrun))
{
if (tTd(3, 1))
printf("getla: lseek64 or read: %s\n",
errstring(errno));
return -1;
}
- if (tTd(3, 5))
- {
- printf("getla: avenrun{64} = %lld",
- (long long int) avenrun64[0]);
- if (tTd(3, 15))
- printf(", %lld, %lld",
- (long long int) avenrun64[1],
- (long long int) avenrun64[2]);
- printf("\n");
- }
- if (tTd(3, 1))
- printf("getla: %d\n",
- (int) (avenrun64[0] + FSCALE/2) >> FSHIFT);
- return ((int) (avenrun64[0] + FSCALE/2) >> FSHIFT);
+ break;
}
- return -1;
+ if (tTd(3, 5))
+ {
+ printf("getla: avenrun = %ld",
+ (long int) avenrun[0]);
+ if (tTd(3, 15))
+ printf(", %ld, %ld",
+ (long int)avenrun[1],
+ (long int)avenrun[2]);
+ printf("\n");
+ }
+ if (tTd(3, 1))
+ printf("getla: %d\n",
+ (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
+ return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
}
#endif
@@ -1911,7 +1869,9 @@ getla()
afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC);
if (afd < 0)
{
- syslog(LOG_ERR, "can't open %s: %m", _PATH_AVENRUN);
+ sm_syslog(LOG_ERR, NOQID,
+ "can't open %s: %m",
+ _PATH_AVENRUN);
return -1;
}
}
@@ -2031,16 +1991,19 @@ int getloadavg( call_data )
** none.
*/
+extern int get_num_procs_online __P((void));
+
bool
shouldqueue(pri, ctime)
long pri;
time_t ctime;
{
bool rval;
+ int queuela = QueueLA * get_num_procs_online();
if (tTd(3, 30))
printf("shouldqueue: CurrentLA=%d, pri=%ld: ", CurrentLA, pri);
- if (CurrentLA < QueueLA)
+ if (CurrentLA < queuela)
{
if (tTd(3, 30))
printf("FALSE (CurrentLA < QueueLA)\n");
@@ -2054,7 +2017,7 @@ shouldqueue(pri, ctime)
return (TRUE);
}
#endif
- rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1));
+ rval = pri > (QueueFactor / (CurrentLA - queuela + 1));
if (tTd(3, 30))
printf("%s (by calculation)\n", rval ? "TRUE" : "FALSE");
return rval;
@@ -2078,6 +2041,7 @@ bool
refuseconnections(port)
int port;
{
+ int refusela = RefuseLA * get_num_procs_online();
time_t now;
static time_t lastconn = (time_t) 0;
static int conncnt = 0;
@@ -2100,24 +2064,22 @@ refuseconnections(port)
/* sleep to flatten out connection load */
setproctitle("deferring connections on port %d: %d per second",
port, ConnRateThrottle);
-#ifdef LOG
if (LogLevel >= 14)
- syslog(LOG_INFO, "deferring connections on port %d: %d per second",
+ sm_syslog(LOG_INFO, NOQID,
+ "deferring connections on port %d: %d per second",
port, ConnRateThrottle);
-#endif
sleep(1);
}
CurrentLA = getla();
- if (CurrentLA >= RefuseLA)
+ if (CurrentLA >= refusela)
{
setproctitle("rejecting connections on port %d: load average: %d",
port, CurrentLA);
-#ifdef LOG
if (LogLevel >= 14)
- syslog(LOG_INFO, "rejecting connections on port %d: load average: %d",
+ sm_syslog(LOG_INFO, NOQID,
+ "rejecting connections on port %d: load average: %d",
port, CurrentLA);
-#endif
return TRUE;
}
@@ -2125,11 +2087,10 @@ refuseconnections(port)
{
setproctitle("rejecting connections on port %d: min free: %d",
port, MinBlocksFree);
-#ifdef LOG
if (LogLevel >= 14)
- syslog(LOG_INFO, "rejecting connections on port %d: min free: %d",
+ sm_syslog(LOG_INFO, NOQID,
+ "rejecting connections on port %d: min free: %d",
port, MinBlocksFree);
-#endif
return TRUE;
}
@@ -2142,11 +2103,10 @@ refuseconnections(port)
{
setproctitle("rejecting connections on port %d: %d children, max %d",
port, CurChildren, MaxChildren);
-#ifdef LOG
if (LogLevel >= 14)
- syslog(LOG_INFO, "rejecting connections on port %d: %d children, max %d",
+ sm_syslog(LOG_INFO, NOQID,
+ "rejecting connections on port %d: %d children, max %d",
port, CurChildren, MaxChildren);
-#endif
return TRUE;
}
}
@@ -2175,6 +2135,7 @@ refuseconnections(port)
#define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
#define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
#define SPT_SCO 6 /* write kernel u. area */
+#define SPT_CHANGEARGV 7 /* write our own strings into argv[] */
#ifndef SPT_TYPE
# define SPT_TYPE SPT_REUSEARGV
@@ -2199,7 +2160,7 @@ typedef unsigned int *pt_entry_t;
# endif
# endif
-# if SPT_TYPE == SPT_PSSTRINGS
+# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
# define SETPROC_STATIC static
# else
# define SETPROC_STATIC
@@ -2248,7 +2209,7 @@ initsetproctitle(argc, argv, envp)
extern char **environ;
/*
- ** Move the environment so setproctitle can use the space at
+ ** Move the environment so setproctitle can use the space at
** the top of memory.
*/
@@ -2350,11 +2311,65 @@ setproctitle(fmt, va_alist)
*p++ = SPT_PADCHAR;
Argv[1] = NULL;
# endif
+# if SPT_TYPE == SPT_CHANGEARGV
+ Argv[0] = buf;
+ Argv[1] = 0;
+# endif
# endif /* SPT_TYPE != SPT_NONE */
}
#endif /* SPT_TYPE != SPT_BUILTIN */
/*
+** WAITFOR -- wait for a particular process id.
+**
+** Parameters:
+** pid -- process id to wait for.
+**
+** Returns:
+** status of pid.
+** -1 if pid never shows up.
+**
+** Side Effects:
+** none.
+*/
+
+int
+waitfor(pid)
+ pid_t pid;
+{
+#ifdef WAITUNION
+ union wait st;
+#else
+ auto int st;
+#endif
+ pid_t i;
+#if defined(ISC_UNIX) || defined(_SCO_unix_)
+ int savesig;
+#endif
+
+ do
+ {
+ errno = 0;
+#if defined(ISC_UNIX) || defined(_SCO_unix_)
+ savesig = releasesignal(SIGCHLD);
+#endif
+ i = wait(&st);
+#if defined(ISC_UNIX) || defined(_SCO_unix_)
+ if (savesig > 0)
+ blocksignal(SIGCHLD);
+#endif
+ if (i > 0)
+ proc_list_drop(i);
+ } while ((i >= 0 || errno == EINTR) && i != pid);
+ if (i < 0)
+ return -1;
+#ifdef WAITUNION
+ return st.w_status;
+#else
+ return st;
+#endif
+}
+ /*
** REAPCHILD -- pick up the body of my child, lest it become a zombie
**
** Parameters:
@@ -2382,12 +2397,10 @@ reapchild(sig)
{
if (count++ > 1000)
{
-#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT,
+ sm_syslog(LOG_ALERT, NOQID,
"reapchild: waitpid loop: pid=%d, status=%x",
pid, status);
-#endif
break;
}
proc_list_drop(pid);
@@ -2401,7 +2414,14 @@ reapchild(sig)
# else /* WNOHANG */
auto int status;
- while ((pid = wait(&status)) > 0)
+ /*
+ ** Catch one zombie -- we will be re-invoked (we hope) if there
+ ** are more. Unreliable signals probably break this, but this
+ ** is the "old system" situation -- waitpid or wait3 are to be
+ ** strongly preferred.
+ */
+
+ if ((pid = wait(&status)) > 0)
proc_list_drop(pid);
# endif /* WNOHANG */
# endif
@@ -2875,12 +2895,10 @@ vsprintf(s, fmt, ap)
** %lx has been added.
*/
-#if !HASSNPRINTF
-
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
- * A bombproof version of doprnt (dopr) included.
+ * A bombproof version of doprnt (sm_dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
@@ -2891,10 +2909,12 @@ vsprintf(s, fmt, ap)
* causing nast effects.
**************************************************************/
-static void dopr();
-static char *end;
+static void sm_dopr();
+static char *DoprEnd;
static int SnprfOverflow;
+#if !HASSNPRINTF
+
/* VARARGS3 */
int
# ifdef __STDC__
@@ -2926,19 +2946,22 @@ vsnprintf(str, count, fmt, args)
va_list args;
{
str[0] = 0;
- end = str + count - 1;
+ DoprEnd = str + count - 1;
SnprfOverflow = 0;
- dopr( str, fmt, args );
+ sm_dopr( str, fmt, args );
if (count > 0)
- end[0] = 0;
+ DoprEnd[0] = 0;
if (SnprfOverflow && tTd(57, 2))
printf("\nvsnprintf overflow, len = %d, str = %s",
count, shortenstring(str, 203));
return strlen(str);
}
+# endif /* !luna2 */
+#endif /* !HASSNPRINTF */
+
/*
- * dopr(): poor man's version of doprintf
+ * sm_dopr(): poor man's version of doprintf
*/
static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
@@ -2946,9 +2969,10 @@ static void fmtnum __P((long value, int base, int dosign, int ljust, int len, in
static void dostr __P(( char * , int ));
static char *output;
static void dopr_outch __P(( int c ));
+static int SyslogErrno;
static void
-dopr( buffer, format, args )
+sm_dopr( buffer, format, args )
char *buffer;
const char *format;
va_list args;
@@ -2962,30 +2986,35 @@ dopr( buffer, format, args )
int ljust;
int len;
int zpad;
+# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+# endif
+
output = buffer;
while( (ch = *format++) ){
- switch( ch ){
- case '%':
- ljust = len = zpad = maxwidth = 0;
- longflag = pointflag = 0;
- nextch:
- ch = *format++;
- switch( ch ){
- case 0:
- dostr( "**end of format**" , 0);
- return;
- case '-': ljust = 1; goto nextch;
- case '0': /* set zero padding if len not set */
- if(len==0 && !pointflag) zpad = '0';
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
+ switch( ch ){
+ case '%':
+ ljust = len = zpad = maxwidth = 0;
+ longflag = pointflag = 0;
+ nextch:
+ ch = *format++;
+ switch( ch ){
+ case 0:
+ dostr( "**end of format**" , 0);
+ return;
+ case '-': ljust = 1; goto nextch;
+ case '0': /* set zero padding if len not set */
+ if(len==0 && !pointflag) zpad = '0';
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
if (pointflag)
maxwidth = maxwidth*10 + ch - '0';
else
len = len*10 + ch - '0';
- goto nextch;
+ goto nextch;
case '*':
if (pointflag)
maxwidth = va_arg( args, int );
@@ -2993,64 +3022,78 @@ dopr( buffer, format, args )
len = va_arg( args, int );
goto nextch;
case '.': pointflag = 1; goto nextch;
- case 'l': longflag = 1; goto nextch;
- case 'u': case 'U':
- /*fmtnum(value,base,dosign,ljust,len,zpad) */
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value, 10,0, ljust, len, zpad ); break;
- case 'o': case 'O':
- /*fmtnum(value,base,dosign,ljust,len,zpad) */
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value, 8,0, ljust, len, zpad ); break;
- case 'd': case 'D':
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value, 10,1, ljust, len, zpad ); break;
- case 'x':
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value, 16,0, ljust, len, zpad ); break;
- case 'X':
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value,-16,0, ljust, len, zpad ); break;
- case 's':
- strvalue = va_arg( args, char *);
+ case 'l': longflag = 1; goto nextch;
+ case 'u': case 'U':
+ /*fmtnum(value,base,dosign,ljust,len,zpad) */
+ if( longflag ){
+ value = va_arg( args, long );
+ } else {
+ value = va_arg( args, int );
+ }
+ fmtnum( value, 10,0, ljust, len, zpad ); break;
+ case 'o': case 'O':
+ /*fmtnum(value,base,dosign,ljust,len,zpad) */
+ if( longflag ){
+ value = va_arg( args, long );
+ } else {
+ value = va_arg( args, int );
+ }
+ fmtnum( value, 8,0, ljust, len, zpad ); break;
+ case 'd': case 'D':
+ if( longflag ){
+ value = va_arg( args, long );
+ } else {
+ value = va_arg( args, int );
+ }
+ fmtnum( value, 10,1, ljust, len, zpad ); break;
+ case 'x':
+ if( longflag ){
+ value = va_arg( args, long );
+ } else {
+ value = va_arg( args, int );
+ }
+ fmtnum( value, 16,0, ljust, len, zpad ); break;
+ case 'X':
+ if( longflag ){
+ value = va_arg( args, long );
+ } else {
+ value = va_arg( args, int );
+ }
+ fmtnum( value,-16,0, ljust, len, zpad ); break;
+ case 's':
+ strvalue = va_arg( args, char *);
if (maxwidth > 0 || !pointflag) {
if (pointflag && len > maxwidth)
len = maxwidth; /* Adjust padding */
fmtstr( strvalue,ljust,len,zpad, maxwidth);
}
break;
- case 'c':
- ch = va_arg( args, int );
- dopr_outch( ch ); break;
- case '%': dopr_outch( ch ); continue;
- default:
- dostr( "???????" , 0);
- }
- break;
- default:
- dopr_outch( ch );
- break;
- }
+ case 'c':
+ ch = va_arg( args, int );
+ dopr_outch( ch ); break;
+ case 'm':
+#if HASSTRERROR
+ dostr(strerror(SyslogErrno), 0);
+#else
+ if (SyslogErrno < 0 || SyslogErrno > sys_nerr)
+ {
+ dostr("Error ", 0);
+ fmtnum(SyslogErrno, 10, 0, 0, 0, 0);
+ }
+ else
+ dostr(sys_errlist[SyslogErrno], 0);
+#endif
+ break;
+
+ case '%': dopr_outch( ch ); continue;
+ default:
+ dostr( "???????" , 0);
+ }
+ break;
+ default:
+ dopr_outch( ch );
+ break;
+ }
}
*output = 0;
}
@@ -3063,7 +3106,7 @@ fmtstr( value, ljust, len, zpad, maxwidth )
int padlen, strlen; /* amount to pad */
if( value == 0 ){
- value = "<NULL>";
+ value = "<NULL>";
}
for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */
if (strlen > maxwidth && maxwidth)
@@ -3072,13 +3115,13 @@ fmtstr( value, ljust, len, zpad, maxwidth )
if( padlen < 0 ) padlen = 0;
if( ljust ) padlen = -padlen;
while( padlen > 0 ) {
- dopr_outch( ' ' );
- --padlen;
+ dopr_outch( ' ' );
+ --padlen;
}
dostr( value, maxwidth );
while( padlen < 0 ) {
- dopr_outch( ' ' );
- ++padlen;
+ dopr_outch( ' ' );
+ ++padlen;
}
}
@@ -3095,50 +3138,50 @@ fmtnum( value, base, dosign, ljust, len, zpad )
int caps = 0;
/* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
- value, base, dosign, ljust, len, zpad )); */
+ value, base, dosign, ljust, len, zpad )); */
uvalue = value;
if( dosign ){
- if( value < 0 ) {
- signvalue = '-';
- uvalue = -value;
- }
+ if( value < 0 ) {
+ signvalue = '-';
+ uvalue = -value;
+ }
}
if( base < 0 ){
- caps = 1;
- base = -base;
+ caps = 1;
+ base = -base;
}
do{
- convert[place++] =
- (caps? "0123456789ABCDEF":"0123456789abcdef")
- [uvalue % (unsigned)base ];
- uvalue = (uvalue / (unsigned)base );
+ convert[place++] =
+ (caps? "0123456789ABCDEF":"0123456789abcdef")
+ [uvalue % (unsigned)base ];
+ uvalue = (uvalue / (unsigned)base );
}while(uvalue);
convert[place] = 0;
padlen = len - place;
if( padlen < 0 ) padlen = 0;
if( ljust ) padlen = -padlen;
/* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
- convert,place,signvalue,padlen)); */
+ convert,place,signvalue,padlen)); */
if( zpad && padlen > 0 ){
- if( signvalue ){
- dopr_outch( signvalue );
- --padlen;
- signvalue = 0;
- }
- while( padlen > 0 ){
- dopr_outch( zpad );
- --padlen;
- }
+ if( signvalue ){
+ dopr_outch( signvalue );
+ --padlen;
+ signvalue = 0;
+ }
+ while( padlen > 0 ){
+ dopr_outch( zpad );
+ --padlen;
+ }
}
while( padlen > 0 ) {
- dopr_outch( ' ' );
- --padlen;
+ dopr_outch( ' ' );
+ --padlen;
}
if( signvalue ) dopr_outch( signvalue );
while( place > 0 ) dopr_outch( convert[--place] );
while( padlen < 0 ){
- dopr_outch( ' ' );
- ++padlen;
+ dopr_outch( ' ' );
+ ++padlen;
}
}
@@ -3160,20 +3203,16 @@ dopr_outch( c )
{
#if 0
if( iscntrl(c) && c != '\n' && c != '\t' ){
- c = '@' + (c & 0x1F);
- if( end == 0 || output < end )
- *output++ = '^';
+ c = '@' + (c & 0x1F);
+ if( DoprEnd == 0 || output < DoprEnd )
+ *output++ = '^';
}
#endif
- if( end == 0 || output < end )
- *output++ = c;
+ if( DoprEnd == 0 || output < DoprEnd )
+ *output++ = c;
else
SnprfOverflow++;
}
-
-# endif /* !luna2 */
-
-#endif /* !HASSNPRINTF */
/*
** USERSHELLOK -- tell if a user's shell is ok for unrestricted use
**
@@ -3428,7 +3467,7 @@ freediskspace(dir, bsize)
{
if (bsize != NULL)
*bsize = FSBLOCKSIZE;
- if (fs.SFS_BAVAIL < 0)
+ if (fs.SFS_BAVAIL <= 0)
return 0;
else
return fs.SFS_BAVAIL;
@@ -3477,15 +3516,12 @@ enoughdiskspace(msize)
if (bfree < msize)
{
-#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT,
- "%s: low on space (have %ld, %s needs %ld in %s)",
- CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id,
+ sm_syslog(LOG_ALERT, CurEnv->e_id,
+ "low on space (have %ld, %s needs %ld in %s)",
bfree,
CurHostName == NULL ? "SMTP-DAEMON" : CurHostName,
msize, QueueDir);
-#endif
return FALSE;
}
}
@@ -3591,7 +3627,7 @@ transienterror(err)
#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
case ENOSR: /* Out of streams resources */
#endif
- case EOPENTIMEOUT: /* PSEUDO: open timed out */
+ case E_SM_OPENTIMEOUT: /* PSEUDO: open timed out */
return TRUE;
}
@@ -3621,6 +3657,7 @@ lockfile(fd, filename, ext, type)
char *ext;
int type;
{
+ int i;
# if !HASFLOCK
int action;
struct flock lfd;
@@ -3645,7 +3682,9 @@ lockfile(fd, filename, ext, type)
printf("lockfile(%s%s, action=%d, type=%d): ",
filename, ext, action, lfd.l_type);
- if (fcntl(fd, action, &lfd) >= 0)
+ while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
+ continue;
+ if (i >= 0)
{
if (tTd(55, 60))
printf("SUCCESS\n");
@@ -3691,7 +3730,9 @@ lockfile(fd, filename, ext, type)
if (tTd(55, 60))
printf("lockfile(%s%s, type=%o): ", filename, ext, type);
- if (flock(fd, type) >= 0)
+ while ((i = flock(fd, type)) < 0 && errno == EINTR)
+ continue;
+ if (i >= 0)
{
if (tTd(55, 60))
printf("SUCCESS\n");
@@ -3722,53 +3763,73 @@ lockfile(fd, filename, ext, type)
/*
** CHOWNSAFE -- tell if chown is "safe" (executable only by root)
**
+** Unfortunately, given that we can't predict other systems on which
+** a remote mounted (NFS) filesystem will be mounted, the answer is
+** almost always that this is unsafe.
+**
+** Note also that many operating systems have non-compliant
+** implementations of the _POSIX_CHOWN_RESTRICTED variable and the
+** fpathconf() routine. According to IEEE 1003.1-1990, if
+** _POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then
+** no non-root process can give away the file. However, vendors
+** don't take NFS into account, so a comfortable value of
+** _POSIX_CHOWN_RESTRICTED tells us nothing.
+**
+** Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf()
+** even on files where chown is not restricted. Many systems get
+** this wrong on NFS-based filesystems (that is, they say that chown
+** is restricted [safe] on NFS filesystems where it may not be, since
+** other systems can access the same filesystem and do file giveaway;
+** only the NFS server knows for sure!) Hence, it is important to
+** get the value of SAFENFSPATHCONF correct -- it should be defined
+** _only_ after testing (see test/t_pathconf.c) a system on an unsafe
+** NFS-based filesystem to ensure that you can get meaningful results.
+** If in doubt, assume unsafe!
+**
+** You may also need to tweak IS_SAFE_CHOWN -- it should be a
+** condition indicating whether the return from pathconf indicates
+** that chown is safe (typically either > 0 or >= 0 -- there isn't
+** even any agreement about whether a zero return means that a file
+** is or is not safe). It defaults to "> 0".
+**
+** If the parent directory is safe (writable only by owner back
+** to the root) then we can relax slightly and trust fpathconf
+** in more circumstances. This is really a crock -- if this is an
+** NFS mounted filesystem then we really know nothing about the
+** underlying implementation. However, most systems pessimize and
+** return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which
+** we interpret as unsafe, as we should. Thus, this heuristic gets
+** us into a possible problem only on systems that have a broken
+** pathconf implementation and which are also poorly configured
+** (have :include: files in group- or world-writable directories).
+**
** Parameters:
** fd -- the file descriptor to check.
+** safedir -- set if the parent directory is safe.
**
** Returns:
-** TRUE -- if only root can chown the file to an arbitrary
-** user.
+** TRUE -- if the chown(2) operation is "safe" -- that is,
+** only root can chown the file to an arbitrary user.
** FALSE -- if an arbitrary user can give away a file.
*/
+#ifndef IS_SAFE_CHOWN
+# define IS_SAFE_CHOWN > 0
+#endif
+
bool
-chownsafe(fd)
+chownsafe(fd, safedir)
int fd;
+ bool safedir;
{
-#ifdef __hpux
- char *s;
- int tfd;
- uid_t o_uid, o_euid;
- gid_t o_gid, o_egid;
- bool rval;
- struct stat stbuf;
-
- o_uid = getuid();
- o_euid = geteuid();
- o_gid = getgid();
- o_egid = getegid();
- fstat(fd, &stbuf);
- setresuid(stbuf.st_uid, stbuf.st_uid, -1);
- setresgid(stbuf.st_gid, stbuf.st_gid, -1);
- s = tmpnam(NULL);
- tfd = open(s, O_RDONLY|O_CREAT, 0600);
- rval = fchown(tfd, DefUid, DefGid) != 0;
- close(tfd);
- setresuid(o_uid, o_euid, -1);
- setresgid(o_gid, o_egid, -1);
- unlink(s);
- return rval;
-#else
-# ifdef _POSIX_CHOWN_RESTRICTED
-# if _POSIX_CHOWN_RESTRICTED == -1
- return FALSE;
-# else
- return TRUE;
-# endif
-# else
-# ifdef _PC_CHOWN_RESTRICTED
+#if !defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1
+# if defined(_PC_CHOWN_RESTRICTED)
int rval;
+ /* give the system administrator a chance to override */
+ if (ChownAlwaysSafe)
+ return TRUE;
+
/*
** Some systems (e.g., SunOS) seem to have the call and the
** #define _PC_CHOWN_RESTRICTED, but don't actually implement
@@ -3777,15 +3838,14 @@ chownsafe(fd)
errno = 0;
rval = fpathconf(fd, _PC_CHOWN_RESTRICTED);
- if (errno == 0)
- return rval > 0;
-# endif
-# ifdef BSD
- return TRUE;
+# if SAFENFSPATHCONF
+ return errno == 0 && rval IS_SAFE_CHOWN;
# else
- return FALSE;
+ return safedir && errno == 0 && rval IS_SAFE_CHOWN;
# endif
# endif
+#else
+ return ChownAlwaysSafe;
#endif
}
/*
@@ -4022,11 +4082,10 @@ validate_connection(sap, hostname, e)
#if TCPWRAPPERS
if (!hosts_ctl("sendmail", hostname, anynet_ntoa(sap), STRING_UNKNOWN))
{
-# ifdef LOG
if (LogLevel >= 4)
- syslog(LOG_NOTICE, "tcpwrappers (%s, %s) rejection",
+ sm_syslog(LOG_NOTICE, NOQID,
+ "tcpwrappers (%s, %s) rejection",
hostname, anynet_ntoa(sap));
-# endif
return FALSE;
}
#endif
@@ -4379,7 +4438,7 @@ secureware_setup_secure(uid)
** Loads $=w with the names of all the interfaces.
*/
-#ifdef SIOCGIFCONF
+#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
struct rtentry;
struct mbuf;
# include <arpa/inet.h>
@@ -4392,19 +4451,38 @@ struct mbuf;
void
load_if_names()
{
-#ifdef SIOCGIFCONF
+#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
int s;
int i;
- struct ifconf ifc;
- char interfacebuf[10240];
+ struct ifconf ifc;
+ int numifs;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1)
return;
/* get the list of known IP address from the kernel */
- ifc.ifc_buf = interfacebuf;
- ifc.ifc_len = sizeof interfacebuf;
+# ifdef SIOCGIFNUM
+ if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0)
+ {
+ /* can't get number of interfaces -- fall back */
+ if (tTd(0, 4))
+ printf("SIOCGIFNUM failed: %s\n", errstring(errno));
+ numifs = -1;
+ }
+ else if (tTd(0, 42))
+ printf("system has %d interfaces\n", numifs);
+ if (numifs < 0)
+# endif
+ numifs = 512;
+
+ if (numifs <= 0)
+ {
+ close(s);
+ return;
+ }
+ ifc.ifc_len = numifs * sizeof (struct ifreq);
+ ifc.ifc_buf = xalloc(ifc.ifc_len);
if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
{
if (tTd(0, 4))
@@ -4429,7 +4507,6 @@ load_if_names()
#endif
char ip_addr[256];
extern char *inet_ntoa();
- extern struct hostent *gethostbyaddr();
#ifdef BSD4_4_SOCKADDR
if (sa->sa_len > sizeof ifr->ifr_addr)
@@ -4450,12 +4527,12 @@ load_if_names()
ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
if (tTd(0, 41))
printf("\tflags: %x\n", ifrf.ifr_flags);
- if (!bitset(IFF_UP, ifrf.ifr_flags))
- continue;
+# define IFRFREF ifrf
#else
- if (!bitset(IFF_UP, ifr->ifr_flags))
- continue;
+# define IFRFREF (*ifr)
#endif
+ if (!bitset(IFF_UP, IFRFREF.ifr_flags))
+ continue;
/* extract IP address from the list*/
ia = (((struct sockaddr_in *) sa)->sin_addr);
@@ -4478,18 +4555,21 @@ load_if_names()
}
/* skip "loopback" interface "lo" */
- if (strcmp("lo0", ifr->ifr_name) == 0)
+ if (bitset(IFF_LOOPBACK, IFRFREF.ifr_flags))
continue;
/* lookup name with IP address */
hp = sm_gethostbyaddr((char *) &ia, sizeof(ia), AF_INET);
if (hp == NULL)
{
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_WARNING,
- "gethostbyaddr() failed for %.100s\n",
- inet_ntoa(ia));
+ sm_syslog(LOG_WARNING, NOQID,
+ "gethostbyaddr(%.100s) failed: %d\n",
+ inet_ntoa(ia),
+#if NAMED_BIND
+ h_errno);
+#else
+ -1);
#endif
continue;
}
@@ -4514,7 +4594,166 @@ load_if_names()
hp->h_aliases++;
}
}
+ free(ifc.ifc_buf);
close(s);
+# undef IFRFREF
+#endif
+}
+ /*
+** GET_NUM_PROCS_ONLINE -- return the number of processors currently online
+**
+** Parameters:
+** none.
+**
+** Returns:
+** The number of processors online.
+*/
+
+int
+get_num_procs_online()
+{
+ int nproc = 0;
+
+#if _FFR_SCALE_LA_BY_NUM_PROCS
+#ifdef _SC_NPROCESSORS_ONLN
+ nproc = (int) sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+#endif
+ if (nproc <= 0)
+ nproc = 1;
+ return nproc;
+}
+ /*
+** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE
+**
+** Parameters:
+** level -- syslog level
+** id -- envelope ID or NULL (NOQUEUE)
+** fmt -- format string
+** arg... -- arguments as implied by fmt.
+**
+** Returns:
+** none
+*/
+
+/* VARARGS3 */
+void
+# ifdef __STDC__
+sm_syslog(int level, const char *id, const char *fmt, ...)
+# else
+sm_syslog(level, id, fmt, va_alist)
+ int level;
+ const char *id;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ static char *buf = NULL;
+ static size_t bufsize = MAXLINE;
+ char *begin, *end;
+ int seq = 1;
+ int idlen;
+ extern int SnprfOverflow;
+ VA_LOCAL_DECL
+
+ SyslogErrno = errno;
+ if (id == NULL)
+ {
+ id = "NOQUEUE";
+ idlen = 9;
+ }
+ else if (strcmp(id, NOQID) == 0)
+ {
+ id = "";
+ idlen = 0;
+ }
+ else
+ idlen = strlen(id + 2);
+bufalloc:
+ if (buf == NULL)
+ buf = (char *) xalloc(sizeof(char) * bufsize);
+
+ /* do a virtual vsnprintf into buf */
+ VA_START(fmt);
+ buf[0] = 0;
+ DoprEnd = buf + bufsize - 1;
+ SnprfOverflow = 0;
+ sm_dopr(buf, fmt, ap);
+ *DoprEnd = '\0';
+ VA_END;
+ /* end of virtual vsnprintf */
+
+ if (SnprfOverflow)
+ {
+ /* String too small, redo with correct size */
+ bufsize += SnprfOverflow + 1;
+ free(buf);
+ buf = NULL;
+ goto bufalloc;
+ }
+ if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE)
+ {
+#if LOG
+ if (*id == '\0')
+ syslog(level, "%s", buf);
+ else
+ syslog(level, "%s: %s", id, buf);
+#else
+ /*XXX should do something more sensible */
+ if (*id == '\0')
+ fprintf(stderr, "%s\n", buf);
+ else
+ fprintf(stderr, "%s: %s\n", id, buf);
+#endif
+ return;
+ }
+
+ begin = buf;
+ while (*begin != '\0' &&
+ (strlen(begin) + idlen + 5) > SYSLOG_BUFSIZE)
+ {
+ char save;
+
+ if (seq == 999)
+ {
+ /* Too many messages */
+ break;
+ }
+ end = begin + SYSLOG_BUFSIZE - idlen - 12;
+ while (end > begin)
+ {
+ /* Break on comma or space */
+ if (*end == ',' || *end == ' ')
+ {
+ end++; /* Include separator */
+ break;
+ }
+ end--;
+ }
+ /* No separator, break midstring... */
+ if (end == begin)
+ end = begin + SYSLOG_BUFSIZE - idlen - 12;
+ save = *end;
+ *end = 0;
+#if LOG
+ syslog(level, "%s[%d]: %s ...", id, seq++, begin);
+#else
+ fprintf(stderr, "%s[%d]: %s ...\n", id, seq++, begin);
+#endif
+ *end = save;
+ begin = end;
+ }
+ if (seq == 999)
+#if LOG
+ syslog(level, "%s[%d]: log terminated, too many parts", id, seq);
+#else
+ fprintf(stderr, "%s[%d]: log terminated, too many parts\n", id, seq);
+#endif
+ else if (*begin != '\0')
+#if LOG
+ syslog(level, "%s[%d]: %s", id, seq, begin);
+#else
+ fprintf(stderr, "%s[%d]: %s\n", id, seq, begin);
#endif
}
/*
@@ -4547,7 +4786,7 @@ hard_syslog(pri, msg, va_alist)
# endif
{
int i;
- char buf[SYSLOG_BUFSIZE * 2];
+ char buf[SYSLOG_BUFSIZE];
VA_LOCAL_DECL;
VA_START(msg);
@@ -4607,7 +4846,7 @@ char *CompileOptions[] =
#if LDAPMAP
"LDAPMAP",
#endif
-#ifdef LOG
+#if LOG
"LOG",
#endif
#if MATCHGECOS
@@ -4689,6 +4928,9 @@ char *CompileOptions[] =
char *OsCompileOptions[] =
{
+#if BOGUS_O_EXCL
+ "BOGUS_O_EXCL",
+#endif
#if HASFCHMOD
"HASFCHMOD",
#endif
@@ -4725,6 +4967,9 @@ char *OsCompileOptions[] =
#if HASSNPRINTF
"HASSNPRINTF",
#endif
+#if HASSTRERROR
+ "HASSTRERROR",
+#endif
#if HASULIMIT
"HASULIMIT",
#endif
@@ -4752,12 +4997,18 @@ char *OsCompileOptions[] =
#if RLIMIT_NEEDS_SYS_TIME_H
"RLIMIT_NEEDS_SYS_TIME_H",
#endif
+#if SAFENFSPATHCONF
+ "SAFENFSPATHCONF",
+#endif
#if SECUREWARE
"SECUREWARE",
#endif
#if SHARE_V1
"SHARE_V1",
#endif
+#if SIOCGIFCONF_IS_BROKEN
+ "SIOCGIFCONF_IS_BROKEN",
+#endif
#if SYS5SETPGRP
"SYS5SETPGRP",
#endif
diff --git a/usr.sbin/sendmail/src/conf.h b/usr.sbin/sendmail/src/conf.h
index 1e0b765..745b7a0 100644
--- a/usr.sbin/sendmail/src/conf.h
+++ b/usr.sbin/sendmail/src/conf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)conf.h 8.288 (Berkeley) 1/17/97
+ * @(#)conf.h 8.313 (Berkeley) 6/11/97
*/
/*
@@ -79,6 +79,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
# define MAXMIMEARGS 20 /* max args in Content-Type: */
# define MAXMIMENESTING 20 /* max MIME multipart nesting */
# define QUEUESEGSIZE 1000 /* increment for queue size */
+# define MAXQFNAME 20 /* max qf file name length */
/**********************************************************************
** Compilation options.
@@ -130,7 +131,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
** be turned off unless absolutely necessary.
**********************************************************************/
-# define LOG /* enable logging -- don't turn off */
+# define LOG 1 /* enable logging -- don't turn off */
/**********************************************************************
** End of site-specific configuration.
@@ -175,6 +176,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
# define HASINITGROUPS 1 /* has initgroups(3) call */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define USESETEUID 1 /* has useable seteuid(2) call */
+# define BOGUS_O_EXCL 1 /* exclusive open follows symlinks */
# define seteuid(e) setresuid(-1, e, -1)
# define IP_SRCROUTE 1 /* can check IP source routing */
# define LA_TYPE LA_HPUX
@@ -185,6 +187,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */
# endif
# define syslog hard_syslog
+# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */
# ifdef V4FS
/* HP-UX 10.x */
@@ -217,6 +220,7 @@ extern void hard_syslog(int, char *, ...);
*/
#ifdef _AIX4
+# include <sys/select.h>
# define _AIX3 1 /* pull in AIX3 stuff */
# define USESETEUID 1 /* seteuid(2) works */
# define TZ_TYPE TZ_NAME /* use tzname[] vector */
@@ -336,6 +340,7 @@ typedef int pid_t;
# define SFS_BAVAIL f_bfree /* alternate field name */
# ifdef IRIX6
# define LA_TYPE LA_IRIX6 /* figure out at run time */
+# define SAFENFSPATHCONF 0 /* pathconf(2) lies on NFS filesystems */
# else
# define LA_TYPE LA_INT
@@ -373,6 +378,7 @@ typedef int pid_t;
# define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define IP_SRCROUTE 1 /* can check IP source routing */
+# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */
# ifdef SOLARIS_2_3
# define SOLARIS 20300 /* for back compat only -- use -DSOLARIS=20300 */
@@ -402,6 +408,9 @@ typedef int pid_t;
# ifndef SYSLOG_BUFSIZE
# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */
# endif
+# ifndef TZ_TYPE
+# define TZ_TYPE TZ_TZNAME
+# endif
# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203)
# define USESETEUID 1 /* seteuid works as of 2.3 */
# endif
@@ -529,6 +538,7 @@ extern long dgux_inet_addr();
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* pre-4.4 TCP/IP implementation is broken */
# endif
+# define SYSLOG_BUFSIZE 256
#endif
@@ -558,6 +568,8 @@ extern long dgux_inet_addr();
# ifndef TZ_TYPE
# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
# endif
+# define GIDSET_T gid_t
+# define MAXNAMLEN NAME_MAX
#endif
@@ -600,8 +612,10 @@ extern long dgux_inet_addr();
# define UID_T int /* compiler gripes on uid_t */
# define GID_T int /* ditto for gid_t */
# define MODE_T int /* and mode_t */
-# define sleep sleepX
# define setpgid setpgrp
+# ifndef NOT_SENDMAIL
+# define sleep sleepX
+# endif
# ifndef LA_TYPE
# define LA_TYPE LA_MACH
# endif
@@ -624,12 +638,13 @@ typedef int pid_t;
** See also BSD defines.
*/
-#if defined(BSD4_4) && !defined(__bsdi__)
+#if defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__)
# include <paths.h>
# define HASUNSETENV 1 /* has unsetenv(3) call */
# define USESETEUID 1 /* has useable seteuid(2) call */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
+# define HASSTRERROR 1 /* has strerror(3) */
# include <sys/cdefs.h>
# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
# define BSD4_4_SOCKADDR /* has sa_len */
@@ -655,6 +670,7 @@ typedef int pid_t;
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
# define HASUNAME 1 /* has uname(2) syscall */
+# define HASSTRERROR 1 /* has strerror(3) */
# include <sys/cdefs.h>
# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
# define BSD4_4_SOCKADDR /* has sa_len */
@@ -696,9 +712,12 @@ typedef int pid_t;
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
# define HASUNAME 1 /* has uname(2) syscall */
+# define HASSTRERROR 1 /* has strerror(3) */
+# include <sys/cdefs.h>
# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
# define BSD4_4_SOCKADDR /* has sa_len */
# define NETLINK 1 /* supports AF_LINK */
+# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */
# define GIDSET_T gid_t
# ifndef LA_TYPE
# define LA_TYPE LA_SUBR
@@ -740,7 +759,7 @@ typedef int pid_t;
** For mt Xinu's Mach386 system.
*/
-#if defined(MACH) && defined(i386)
+#if defined(MACH) && defined(i386) && !defined(__GNU__)
# define MACH386 1
# define HASUNSETENV 1 /* has unsetenv(3) call */
# define HASINITGROUPS 1 /* has initgroups(3) call */
@@ -764,6 +783,50 @@ typedef int pid_t;
#endif
+
+/*
+** GNU OS (hurd)
+** Largely BSD & posix compatible.
+** Port contributed by Miles Bader <miles@gnu.ai.mit.edu>.
+*/
+
+#ifdef __GNU_HURD__
+# define SIOCGIFCONF_IS_BROKEN 1
+# define IP_SRCROUTE 0
+# define HASFCHMOD 1
+# define HASFLOCK 1
+# define HASUNAME 1
+# define HASUNSETENV 1
+# define HASSETSID 1
+# define HASINITGROUPS 1
+# define HASSETVBUF 1
+# define HASSETREUID 1
+# define USESETEUID 1
+# define HASLSTAT 1
+# define HASSETRLIMIT 1
+# define HASWAITPID 1
+# define HASGETDTABLESIZE 1
+# define HASSTRERROR 1
+/* # define NEEDGETOPT 1 */
+# define HASGETUSERSHELL 1
+# define ERRLIST_PREDEFINED 1
+# define BSD4_4_SOCKADDR 1
+# define GIDSET_T gid_t
+# define LA_TYPE LA_MACH
+
+/* GNU uses mach[34], which renames some rpcs from mach2.x. */
+# define host_self mach_host_self
+# define SFS_TYPE SFS_STATFS
+# define SPT_TYPE SPT_CHANGEARGV
+
+/* GNU has no MAXPATHLEN; ideally the code should be changed to not use it. */
+# define MAXPATHLEN 2048
+
+/* Define device num frobbing macros. */
+# define major(x) ((x)>>8)
+# define minor(x) ((x)&0xFF)
+#endif /* GNU */
+
/*
** 4.3 BSD -- this is for very old systems
**
@@ -1069,6 +1132,7 @@ extern void *malloc();
# define GIDSET_T gid_t /* from <linux/types.h> */
# define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */
# define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */
+# define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */
# ifndef HASFLOCK
# include <linux/version.h>
# if LINUX_VERSION_CODE < 66399
@@ -1120,10 +1184,12 @@ extern void *malloc();
# define HASUNAME 1 /* use System V uname(2) system call */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define HASINITGROUPS 1 /* has initgroups(3) call */
-# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+# define HASSETVBUF 1 /* has setvbuf(3) in libc */
+# define HASSTRERROR 1 /* has strerror(3) */
# define SIGFUNC_DEFINED /* sigfunc_t already defined */
-# define SIGFUNC_RETURN (0) /* XXX this is a guess */
-# define SIGFUNC_DECL int /* XXX this is a guess */
+# define SIGFUNC_RETURN /* POSIX-mode */
+# define SIGFUNC_DECL void /* POSIX-mode */
+# define ERRLIST_PREDEFINED 1
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
@@ -1832,7 +1898,7 @@ typedef struct msgb mblk_t;
** are closed. Some firewalls return this error if you try to connect
** to the IDENT port (113), so you can't receive email from these hosts
** on these systems. The firewall really should use a more specific
-** message such as ICMP_UNREACH_PROTOCOL or _PORT or _NET_PROHIB. If
+** message such as ICMP_UNREACH_PROTOCOL or _PORT or _FILTER_PROHIB. If
** not explicitly set to zero above, default it on.
*/
@@ -1933,12 +1999,21 @@ typedef struct msgb mblk_t;
#if !defined(S_ISLNK) && defined(S_IFLNK)
# define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK)
#endif
+#ifndef S_IRUSR
+# define S_IRUSR 0400
+#endif
#ifndef S_IWUSR
# define S_IWUSR 0200
#endif
+#ifndef S_IRGRP
+# define S_IRGRP 0040
+#endif
#ifndef S_IWGRP
# define S_IWGRP 0020
#endif
+#ifndef S_IROTH
+# define S_IROTH 0004
+#endif
#ifndef S_IWOTH
# define S_IWOTH 0002
#endif
@@ -1960,6 +2035,13 @@ typedef struct msgb mblk_t;
/*
+** An "impossible" file mode to indicate that the file does not exist.
+*/
+
+#define ST_MODE_NOFILE 0171147 /* unlikely to occur */
+
+
+/*
** These are used in a few cases where we need some special
** error codes, but where the system doesn't provide something
** reasonable. They are printed in errstring.
@@ -1969,7 +2051,16 @@ typedef struct msgb mblk_t;
# define E_PSEUDOBASE 256
#endif
-#define EOPENTIMEOUT (E_PSEUDOBASE + 0) /* timeout on open */
+#define E_SM_OPENTIMEOUT (E_PSEUDOBASE + 0) /* Timeout on file open */
+#define E_SM_NOSLINK (E_PSEUDOBASE + 1) /* Symbolic links not allowed */
+#define E_SM_NOHLINK (E_PSEUDOBASE + 2) /* Hard links not allowed */
+#define E_SM_REGONLY (E_PSEUDOBASE + 3) /* Regular files only */
+#define E_SM_ISEXEC (E_PSEUDOBASE + 4) /* Executable files not allowed */
+#define E_SM_WWDIR (E_PSEUDOBASE + 5) /* World writable directory */
+#define E_SM_GWDIR (E_PSEUDOBASE + 6) /* Group writable directory */
+#define E_SM_FILECHANGE (E_PSEUDOBASE + 7) /* File changed after open */
+#define E_SM_WWFILE (E_PSEUDOBASE + 8) /* World writable file */
+#define E_SM_GWFILE (E_PSEUDOBASE + 9) /* Group writable file */
#define E_DNSBASE (E_PSEUDOBASE + 20) /* base for DNS h_errno */
/* type of arbitrary pointer */
@@ -1981,16 +2072,8 @@ typedef struct msgb mblk_t;
# include "cdefs.h"
#endif
-#if NAMED_BIND
-# include <arpa/nameser.h>
-# ifdef __svr4__
-# ifdef NOERROR
-# undef NOERROR /* avoid compiler conflict with stream.h */
-# endif
-# endif
-# ifndef __ksr__
-extern int h_errno;
-# endif
+#if NAMED_BIND && !defined(__ksr__)
+extern int h_errno;
#endif
/*
@@ -2136,7 +2219,7 @@ typedef void (*sigfunc_t) __P((int));
# if (SYSLOG_BUFSIZE) > 768
# define TOBUFSIZE (SYSLOG_BUFSIZE - 512)
# else
-# define TOBUFSIZE 256
+# define TOBUFSIZE (SYSLOG_BUFSIZE / 2)
# endif
#endif
@@ -2185,3 +2268,18 @@ typedef void (*sigfunc_t) __P((int));
#if !defined(NGROUPS_MAX) && defined(NGROUPS)
# define NGROUPS_MAX NGROUPS /* POSIX naming convention */
#endif
+
+/*
+** If we don't have a system syslog, simulate it.
+*/
+
+#if !LOG
+# define LOG_EMERG 0 /* system is unusable */
+# define LOG_ALERT 1 /* action must be taken immediately */
+# define LOG_CRIT 2 /* critical conditions */
+# define LOG_ERR 3 /* error conditions */
+# define LOG_WARNING 4 /* warning conditions */
+# define LOG_NOTICE 5 /* normal but significant condition */
+# define LOG_INFO 6 /* informational */
+# define LOG_DEBUG 7 /* debug-level messages */
+#endif
diff --git a/usr.sbin/sendmail/src/daemon.c b/usr.sbin/sendmail/src/daemon.c
index bd8a914..41f1a72 100644
--- a/usr.sbin/sendmail/src/daemon.c
+++ b/usr.sbin/sendmail/src/daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -37,13 +37,17 @@
#ifndef lint
#ifdef DAEMON
-static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (with daemon mode)";
+static char sccsid[] = "@(#)daemon.c 8.175 (Berkeley) 6/1/97 (with daemon mode)";
#else
-static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (without daemon mode)";
+static char sccsid[] = "@(#)daemon.c 8.175 (Berkeley) 6/1/97 (without daemon mode)";
#endif
#endif /* not lint */
-#if DAEMON || defined(SOCK_STREAM)
+#if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__)
+# define USE_SOCK_STREAM 1
+#endif
+
+#if DAEMON || defined(USE_SOCK_STREAM)
# include <arpa/inet.h>
# if NAMED_BIND
# include <resolv.h>
@@ -55,6 +59,8 @@ static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (without daemon mo
#if DAEMON
+# include <sys/time.h>
+
# if IP_SRCROUTE
# include <netinet/in_systm.h>
# include <netinet/ip.h>
@@ -166,8 +172,12 @@ getrequests(e)
/* write the pid to the log file for posterity */
pidf = safefopen(PidFile, O_WRONLY|O_CREAT|O_TRUNC, 0644,
- SFF_NOSLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT);
- if (pidf != NULL)
+ SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT);
+ if (pidf == NULL)
+ {
+ sm_syslog(LOG_ERR, NOQID, "unable to write %s", PidFile);
+ }
+ else
{
extern char *CommandLineArgs;
@@ -200,7 +210,6 @@ getrequests(e)
int savederrno;
int pipefd[2];
extern bool refuseconnections();
- extern int getla();
/* see if we are rejecting connections */
(void) blocksignal(SIGALRM);
@@ -234,13 +243,15 @@ getrequests(e)
if (!wordinclass(jbuf, 'w'))
{
dumpstate("daemon lost $j");
- syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog");
+ sm_syslog(LOG_ALERT, NOQID,
+ "daemon process doesn't have $j in $=w; see syslog");
abort();
}
else if (j_has_dot && strchr(jbuf, '.') == NULL)
{
dumpstate("daemon $j lost dot");
- syslog(LOG_ALERT, "daemon process $j lost dot; see syslog");
+ sm_syslog(LOG_ALERT, NOQID,
+ "daemon process $j lost dot; see syslog");
abort();
}
}
@@ -260,13 +271,29 @@ getrequests(e)
log an error here;
#endif
(void) releasesignal(SIGALRM);
- do
+ for (;;)
{
+ fd_set readfds;
+ struct timeval timeout;
+
+ FD_ZERO(&readfds);
+ FD_SET(DaemonSocket, &readfds);
+ timeout.tv_sec = 60;
+ timeout.tv_usec = 0;
+
+ t = select(DaemonSocket + 1, &readfds, NULL, NULL, &timeout);
+ if (DoQueueRun)
+ (void) runqueue(TRUE, FALSE);
+ if (t <= 0 || !FD_ISSET(DaemonSocket, &readfds))
+ continue;
+
errno = 0;
lotherend = socksize;
t = accept(DaemonSocket,
(struct sockaddr *)&RealHostAddr, &lotherend);
- } while (t < 0 && errno == EINTR);
+ if (t >= 0 || errno != EINTR)
+ break;
+ }
savederrno = errno;
(void) blocksignal(SIGALRM);
if (t < 0)
@@ -381,6 +408,9 @@ getrequests(e)
OutChannel = outchannel;
DisConnected = FALSE;
+ /* open maps for check_relay ruleset */
+ initmaps(FALSE, e);
+
/* validate the connection */
HoldErrs = TRUE;
nullconn = !validate_connection(&RealHostAddr, RealHostName, e);
@@ -463,10 +493,9 @@ opendaemonsocket(firsttime)
saveerrno = errno;
syserr("opendaemonsocket: can't create server SMTP socket");
severe:
-# ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "problem creating SMTP socket");
-# endif /* LOG */
+ sm_syslog(LOG_ALERT, NOQID,
+ "problem creating SMTP socket");
DaemonSocket = -1;
continue;
}
@@ -747,7 +776,7 @@ makeconnection(host, port, mci, e)
register MCI *mci;
ENVELOPE *e;
{
- register volatile int i = 0;
+ register volatile int addrno = 0;
register volatile int s;
register struct hostent *volatile hp = (struct hostent *)NULL;
SOCKADDR addr;
@@ -870,7 +899,7 @@ gothostent:
hp->h_length);
break;
}
- i = 1;
+ addrno = 1;
}
/*
@@ -883,10 +912,9 @@ gothostent:
if (sp == NULL)
{
-#ifdef LOG
if (LogLevel > 2)
- syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown");
-#endif
+ sm_syslog(LOG_ERR, NOQID,
+ "makeconnection: service \"smtp\" unknown");
port = htons(25);
}
else
@@ -988,22 +1016,23 @@ gothostent:
if (setjmp(CtxConnectTimeout) == 0)
{
+ int i;
+
if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0);
else if (TimeOuts.to_connect != 0)
ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
else
ev = NULL;
- if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0)
- {
- if (ev != NULL)
- clrevent(ev);
+ i = connect(s, (struct sockaddr *) &addr, addrlen);
+ sav_errno = errno;
+ if (ev != NULL)
+ clrevent(ev);
+ if (i >= 0)
break;
- }
}
- sav_errno = errno;
- if (ev != NULL)
- clrevent(ev);
+ else
+ sav_errno = errno;
/* if running demand-dialed connection, try again */
if (DialDelay > 0 && firstconnect)
@@ -1018,7 +1047,7 @@ gothostent:
/* couldn't connect.... figure out why */
(void) close(s);
- if (hp != NULL && hp->h_addr_list[i])
+ if (hp != NULL && hp->h_addr_list[addrno])
{
if (tTd(16, 1))
printf("Connect failed (%s); trying new address....\n",
@@ -1027,14 +1056,14 @@ gothostent:
{
#if NETINET
case AF_INET:
- bcopy(hp->h_addr_list[i++],
+ bcopy(hp->h_addr_list[addrno++],
&addr.sin.sin_addr,
INADDRSZ);
break;
#endif
default:
- bcopy(hp->h_addr_list[i++],
+ bcopy(hp->h_addr_list[addrno++],
addr.sa.sa_data,
hp->h_length);
break;
@@ -1129,19 +1158,17 @@ myhostname(hostbuf, size)
if (strchr(hostbuf, '.') == NULL &&
!getcanonname(hostbuf, size, TRUE))
{
-#ifdef LOG
- syslog(LOG_CRIT, "My unqualified host name (%s) unknown; sleeping for retry",
+ sm_syslog(LOG_CRIT, NOQID,
+ "My unqualified host name (%s) unknown; sleeping for retry",
hostbuf);
-#endif
message("My unqualified host name (%s) unknown; sleeping for retry",
hostbuf);
sleep(60);
if (!getcanonname(hostbuf, size, TRUE))
{
-#ifdef LOG
- syslog(LOG_ALERT, "unable to qualify my own domain name (%s) -- using short name",
+ sm_syslog(LOG_ALERT, NOQID,
+ "unable to qualify my own domain name (%s) -- using short name",
hostbuf);
-#endif
message("WARNING: unable to qualify my own domain name (%s) -- using short name",
hostbuf);
}
@@ -1181,6 +1208,9 @@ getauthinfo(fd)
int i;
EVENT *ev;
int nleft;
+ struct hostent *hp;
+ char **ha;
+ bool may_be_forged;
char ibuf[MAXNAME + 1];
static char hbuf[MAXNAME * 2 + 2];
@@ -1203,6 +1233,30 @@ getauthinfo(fd)
RealHostName[MAXNAME - 1] = '\0';
}
+ /* cross check RealHostName with forward DNS lookup */
+ if (anynet_ntoa(&RealHostAddr)[0] == '[')
+ {
+ /* address is not a socket */
+ may_be_forged = FALSE;
+ }
+ else
+ {
+ /* try to match the reverse against the forward lookup */
+ hp = gethostbyname(RealHostName);
+
+ if (hp == NULL)
+ may_be_forged = TRUE;
+ else
+ {
+ for (ha = hp->h_addr_list; *ha != NULL; ha++)
+ if (bcmp(*ha,
+ (char *) &RealHostAddr.sin.sin_addr,
+ hp->h_length) == 0)
+ break;
+ may_be_forged = *ha == NULL;
+ }
+ }
+
if (TimeOuts.to_ident == 0)
goto noident;
@@ -1340,6 +1394,9 @@ noident:
postident:
#if IP_SRCROUTE
+# ifndef GET_IPOPT_DST
+# define GET_IPOPT_DST(dst) (dst)
+# endif
/*
** Extract IP source routing information.
**
@@ -1383,21 +1440,31 @@ postident:
case IPOPT_SSRR:
case IPOPT_LSRR:
+ /*
+ ** Source routing.
+ ** o[0] is the option type (loose/strict).
+ ** o[1] is the length of this option,
+ ** including option type and
+ ** length.
+ ** o[2] is the pointer into the route
+ ** data.
+ ** o[3] begins the route data.
+ */
+
p = &hbuf[strlen(hbuf)];
l = sizeof hbuf - (hbuf - p) - 6;
snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s",
*o == IPOPT_SSRR ? "!" : "",
l > 240 ? 120 : l / 2,
- inet_ntoa(ipopt.ipopt_dst));
+ inet_ntoa(GET_IPOPT_DST(ipopt.ipopt_dst)));
i = strlen(p);
p += i;
l -= strlen(p);
- /* o[1] is option length */
- j = *++o / sizeof(struct in_addr) - 1;
+ j = o[1] / sizeof(struct in_addr) - 1;
/* q skips length and router pointer to data */
- q = o + 2;
+ q = &o[3];
for ( ; j >= 0; j--)
{
memcpy(&addr, q, sizeof(addr));
@@ -1412,7 +1479,7 @@ postident:
l -= i + 1;
q += sizeof(struct in_addr);
}
- o += *o;
+ o += o[1];
break;
default:
@@ -1433,6 +1500,11 @@ noipsr:
(void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]",
anynet_ntoa(&RealHostAddr));
}
+ if (may_be_forged)
+ {
+ p = &hbuf[strlen(hbuf)];
+ (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)");
+ }
postipsr:
if (tTd(9, 1))
@@ -1443,7 +1515,7 @@ postipsr:
** HOST_MAP_LOOKUP -- turn a hostname into canonical form
**
** Parameters:
-** map -- a pointer to this map (unused).
+** map -- a pointer to this map.
** name -- the (presumably unqualified) hostname.
** av -- unused -- for compatibility with other mapping
** functions.
@@ -1457,7 +1529,8 @@ postipsr:
** Side Effects:
** Looks up the host specified in hbuf. If it is not
** the canonical name for that host, return the canonical
-** name.
+** name (unless MF_MATCHONLY is set, which will cause the
+** status only to be returned).
*/
char *
@@ -1498,7 +1571,16 @@ host_map_lookup(map, name, av, statp)
message("851 %s: Name server timeout",
shortenstring(name, 33));
}
- return s->s_namecanon.nc_cname;
+ if (*statp != EX_OK)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ cp = map_rewrite(map, name, strlen(name), NULL);
+ else
+ cp = map_rewrite(map,
+ s->s_namecanon.nc_cname,
+ strlen(s->s_namecanon.nc_cname),
+ av);
+ return cp;
}
/*
@@ -1532,16 +1614,12 @@ host_map_lookup(map, name, av, statp)
{
if (tTd(9, 1))
printf("%s\n", hbuf);
+ s->s_namecanon.nc_stat = EX_OK;
+ s->s_namecanon.nc_cname = newstr(hbuf);
if (bitset(MF_MATCHONLY, map->map_mflags))
- {
- cp = map_rewrite(map, name, strlen(name), av);
- s->s_namecanon.nc_cname = newstr(hbuf);
- }
+ cp = map_rewrite(map, name, strlen(name), NULL);
else
- {
cp = map_rewrite(map, hbuf, strlen(hbuf), av);
- s->s_namecanon.nc_cname = newstr(cp);
- }
return cp;
}
else
@@ -1589,6 +1667,7 @@ host_map_lookup(map, name, av, statp)
return (NULL);
*cp = '\0';
in_addr.s_addr = inet_addr(&name[1]);
+ *cp = ']';
/* nope -- ask the name server */
hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET);
@@ -1604,9 +1683,12 @@ host_map_lookup(map, name, av, statp)
}
/* found a match -- copy out */
- cp = map_rewrite(map, (char *) hp->h_name, strlen(hp->h_name), av);
s->s_namecanon.nc_stat = *statp = EX_OK;
- s->s_namecanon.nc_cname = newstr(cp);
+ s->s_namecanon.nc_cname = newstr(hp->h_name);
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ cp = map_rewrite(map, name, strlen(name), NULL);
+ else
+ cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av);
return cp;
}
@@ -1688,16 +1770,63 @@ host_map_lookup(map, name, avp, statp)
char *statp;
{
register struct hostent *hp;
+ char *cp;
hp = sm_gethostbyname(name);
- if (hp != NULL)
- return hp->h_name;
- *statp = EX_NOHOST;
- return NULL;
+ if (hp == NULL)
+ {
+ *statp = EX_NOHOST;
+ return NULL;
+ }
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ cp = map_rewrite(map, name, strlen(name), NULL);
+ else
+ cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av);
+ return cp;
}
#endif /* DAEMON */
/*
+** HOST_MAP_INIT -- initialize host class structures
+*/
+
+bool
+host_map_init(map, args)
+ MAP *map;
+ char *args;
+{
+ register char *p = args;
+
+ for (;;)
+ {
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p != '-')
+ break;
+ switch (*++p)
+ {
+ case 'a':
+ map->map_app = ++p;
+ break;
+
+ case 'm':
+ map->map_mflags |= MF_MATCHONLY;
+ break;
+
+ case 't':
+ map->map_mflags |= MF_NODEFER;
+ break;
+ }
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+ }
+ if (map->map_app != NULL)
+ map->map_app = newstr(map->map_app);
+ return TRUE;
+}
+ /*
** ANYNET_NTOA -- convert a network address to printable form.
**
** Parameters:
@@ -1707,7 +1836,7 @@ host_map_lookup(map, name, avp, statp)
** A printable version of that sockaddr.
*/
-#ifdef SOCK_STREAM
+#ifdef USE_SOCK_STREAM
#if NETLINK
# include <net/if_dl.h>
diff --git a/usr.sbin/sendmail/src/deliver.c b/usr.sbin/sendmail/src/deliver.c
index fb6db2d..b5d5413 100644
--- a/usr.sbin/sendmail/src/deliver.c
+++ b/usr.sbin/sendmail/src/deliver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)deliver.c 8.266 (Berkeley) 1/17/97";
+static char sccsid[] = "@(#)deliver.c 8.282 (Berkeley) 6/11/97";
#endif /* not lint */
#include "sendmail.h"
@@ -76,7 +76,7 @@ sendall(e, mode)
int otherowners;
register ENVELOPE *ee;
ENVELOPE *splitenv = NULL;
- bool oldverbose = Verbose;
+ int oldverbose = Verbose;
bool somedeliveries = FALSE;
pid_t pid;
extern void sendenvelope();
@@ -96,7 +96,6 @@ sendall(e, mode)
}
/* determine actual delivery mode */
- CurrentLA = getla();
if (mode == SM_DEFAULT)
{
mode = e->e_sendmode;
@@ -295,6 +294,7 @@ sendall(e, mode)
{
extern HDR *copyheader();
extern ADDRESS *copyqueue();
+ extern void dup_queue_file __P((ENVELOPE *, ENVELOPE *, int));
/*
** Split this envelope into two.
@@ -360,42 +360,12 @@ sendall(e, mode)
}
if (mode != SM_VERIFY && bitset(EF_HAS_DF, e->e_flags))
- {
- char df1buf[20], df2buf[20];
-
- ee->e_dfp = NULL;
- snprintf(df1buf, sizeof df1buf, "%s",
- queuename(e, 'd'));
- snprintf(df2buf, sizeof df2buf, "%s",
- queuename(ee, 'd'));
- if (link(df1buf, df2buf) < 0)
- {
- int saverrno = errno;
-
- syserr("sendall: link(%s, %s)",
- df1buf, df2buf);
- if (saverrno == EEXIST)
- {
- if (unlink(df2buf) < 0)
- {
- syserr("!sendall: unlink(%s): permanent",
- df2buf);
- /*NOTREACHED*/
- }
- if (link(df1buf, df2buf) < 0)
- {
- syserr("!sendall: link(%s, %s): permanent",
- df1buf, df2buf);
- /*NOTREACHED*/
- }
- }
- }
- }
-#ifdef LOG
+ dup_queue_file(e, ee, 'd');
+ openxscript(ee);
if (LogLevel > 4)
- syslog(LOG_INFO, "%s: clone %s, owner=%s",
- ee->e_id, e->e_id, owner);
-#endif
+ sm_syslog(LOG_INFO, ee->e_id,
+ "clone %s, owner=%s",
+ e->e_id, owner);
}
}
@@ -420,6 +390,15 @@ sendall(e, mode)
if (tTd(13, 29))
printf("No deliveries: auto-queuing\n");
mode = SM_QUEUE;
+
+ /* treat this as a delivery in terms of counting tries */
+ e->e_dtime = curtime();
+ e->e_ntries++;
+ for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
+ {
+ ee->e_dtime = curtime();
+ ee->e_ntries++;
+ }
}
# if QUEUE
@@ -462,7 +441,7 @@ sendall(e, mode)
switch (mode)
{
case SM_VERIFY:
- Verbose = TRUE;
+ Verbose = 2;
break;
case SM_QUEUE:
@@ -563,6 +542,9 @@ sendall(e, mode)
finis();
}
+ /* be sure to give error messages in child */
+ QuickAbort = OnlyOneError = FALSE;
+
/*
** Close any cached connections.
**
@@ -619,12 +601,10 @@ sendenvelope(e, mode)
printf("sendenvelope(%s) e_flags=0x%lx\n",
e->e_id == NULL ? "[NOQUEUE]" : e->e_id,
e->e_flags);
-#ifdef LOG
if (LogLevel > 80)
- syslog(LOG_DEBUG, "%s: sendenvelope, flags=0x%x",
- e->e_id == NULL ? "[NOQUEUE]" : e->e_id,
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "sendenvelope, flags=0x%x",
e->e_flags);
-#endif
/*
** If we have had global, fatal errors, don't bother sending
@@ -709,6 +689,51 @@ sendenvelope(e, mode)
#endif
}
/*
+** DUP_QUEUE_FILE -- duplicate a queue file into a split queue
+**
+** Parameters:
+** e -- the existing envelope
+** ee -- the new envelope
+** type -- the queue file type (e.g., 'd')
+**
+** Returns:
+** none
+*/
+
+void
+dup_queue_file(e, ee, type)
+ struct envelope *e, *ee;
+ int type;
+{
+ char f1buf[MAXQFNAME], f2buf[MAXQFNAME];
+
+ ee->e_dfp = NULL;
+ ee->e_xfp = NULL;
+ snprintf(f1buf, sizeof f1buf, "%s", queuename(e, type));
+ snprintf(f2buf, sizeof f2buf, "%s", queuename(ee, type));
+ if (link(f1buf, f2buf) < 0)
+ {
+ int saverrno = errno;
+
+ syserr("sendall: link(%s, %s)", f1buf, f2buf);
+ if (saverrno == EEXIST)
+ {
+ if (unlink(f2buf) < 0)
+ {
+ syserr("!sendall: unlink(%s): permanent",
+ f2buf);
+ /*NOTREACHED*/
+ }
+ if (link(f1buf, f2buf) < 0)
+ {
+ syserr("!sendall: link(%s, %s): permanent",
+ f1buf, f2buf);
+ /*NOTREACHED*/
+ }
+ }
+ }
+}
+ /*
** DOFORK -- do a fork, retrying a couple of times on failure.
**
** This MUST be a macro, since after a vfork we are running
@@ -826,6 +851,7 @@ deliver(e, firstto)
time_t xstart;
bool suidwarn;
bool anyok; /* at least one address was OK */
+ bool goodmxfound = FALSE; /* at least one MX was OK */
int mpvect[2];
int rpvect[2];
char *pv[MAXPV+1];
@@ -1018,6 +1044,7 @@ deliver(e, firstto)
e->e_flags |= EF_NO_BODY_RETN;
to->q_status = "5.2.3";
usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
+ markfailure(e, to, NULL, EX_UNAVAILABLE);
giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, xstart, e);
continue;
}
@@ -1294,8 +1321,11 @@ tryhost:
curhost++;
continue;
}
- strncpy(hostbuf, curhost, p - curhost);
- hostbuf[p - curhost] = '\0';
+ i = p - curhost;
+ if (i >= sizeof hostbuf)
+ i = sizeof hostbuf - 1;
+ strncpy(hostbuf, curhost, i);
+ hostbuf[i] = '\0';
if (*p != '\0')
p++;
curhost = p;
@@ -1318,11 +1348,16 @@ tryhost:
}
mci->mci_mailer = m;
if (mci->mci_exitstat != EX_OK)
+ {
+ if (mci->mci_exitstat == EX_TEMPFAIL)
+ goodmxfound = TRUE;
continue;
+ }
if (mci_lock_host(mci) != EX_OK)
{
mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
+ goodmxfound = TRUE;
continue;
}
@@ -1343,6 +1378,7 @@ tryhost:
#endif
if (i == EX_OK)
{
+ goodmxfound = TRUE;
mci->mci_state = MCIS_OPENING;
mci_cache(mci);
if (TrafficLogFile != NULL)
@@ -1355,6 +1391,8 @@ tryhost:
if (tTd(11, 1))
printf("openmailer: makeconnection => stat=%d, errno=%d\n",
i, errno);
+ if (i == EX_TEMPFAIL)
+ goodmxfound = TRUE;
mci_unlock_host(mci);
}
@@ -1863,7 +1901,12 @@ tryhost:
for (to = tochain; to != NULL; to = to->q_tchain)
{
e->e_to = to->q_paddr;
- if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
+ if (strlen(to->q_paddr) + (t - tobuf) + 2 >= sizeof tobuf)
+ {
+ /* not enough room */
+ continue;
+ }
+ else if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
{
markfailure(e, to, mci, i);
giveresponse(i, m, mci, ctladdr, xstart, e);
@@ -1948,8 +1991,15 @@ tryhost:
rcode = smtpgetstat(m, mci, e);
if (rcode == EX_OK)
{
- strcat(tobuf, ",");
- strcat(tobuf, to->q_paddr);
+ if (strlen(to->q_paddr) + strlen(tobuf) + 2 >= sizeof tobuf)
+ {
+ syserr("LMTP tobuf overflow");
+ }
+ else
+ {
+ strcat(tobuf, ",");
+ strcat(tobuf, to->q_paddr);
+ }
anyok = TRUE;
}
else
@@ -1968,6 +2018,8 @@ tryhost:
/* mark bad addresses */
if (rcode != EX_OK)
{
+ if (goodmxfound && rcode == EX_NOHOST)
+ rcode = EX_TEMPFAIL;
markfailure(e, to, mci, rcode);
continue;
}
@@ -2084,6 +2136,7 @@ markfailure(e, q, mci, rcode)
case EX_IOERR:
case EX_OSERR:
q->q_flags |= QQUEUEUP;
+ q->q_flags &= ~QDONTSEND;
break;
default:
@@ -2203,7 +2256,7 @@ endmailer(mci, e, pv)
if (mci->mci_pid == 0)
return (EX_OK);
-#ifdef _FFR_TIMEOUT_WAIT
+#if _FFR_TIMEOUT_WAIT
put a timeout around the wait
#endif
@@ -2428,7 +2481,6 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
time_t xstart;
register ENVELOPE *e;
{
-# ifdef LOG
register char *bp;
register char *p;
int l;
@@ -2533,11 +2585,12 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
if (q == NULL)
break;
- syslog(LOG_INFO, "%s: to=%.*s [more]%s",
- e->e_id, ++q - p, p, buf);
+ sm_syslog(LOG_INFO, e->e_id,
+ "to=%.*s [more]%s",
+ ++q - p, p, buf);
p = q;
}
- syslog(LOG_INFO, "%s: to=%s%s", e->e_id, p, buf);
+ sm_syslog(LOG_INFO, e->e_id, "to=%s%s", p, buf);
# else /* we have a very short log buffer size */
@@ -2549,11 +2602,12 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
if (q == NULL)
break;
- syslog(LOG_INFO, "%s: to=%.*s [more]",
- e->e_id, ++q - p, p);
+ sm_syslog(LOG_INFO, e->e_id,
+ "to=%.*s [more]",
+ ++q - p, p);
p = q;
}
- syslog(LOG_INFO, "%s: to=%s", e->e_id, p);
+ sm_syslog(LOG_INFO, e->e_id, "to=%s", p);
if (ctladdr != NULL)
{
@@ -2567,7 +2621,7 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
ctladdr->q_uid, ctladdr->q_gid);
bp += strlen(bp);
}
- syslog(LOG_INFO, "%s: %s", e->e_id, buf);
+ sm_syslog(LOG_INFO, e->e_id, "%s", buf);
}
bp = buf;
snprintf(bp, SPACELEFT(buf, bp), "delay=%s",
@@ -2585,7 +2639,7 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
snprintf(bp, SPACELEFT(buf, bp), ", mailer=%s", m->m_name);
bp += strlen(bp);
}
- syslog(LOG_INFO, "%s: %.1000s", e->e_id, buf);
+ sm_syslog(LOG_INFO, e->e_id, "%.1000s", buf);
buf[0] = '\0';
bp = buf;
@@ -2612,11 +2666,10 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
snprintf(buf, sizeof buf, "relay=%.100s", p);
}
if (buf[0] != '\0')
- syslog(LOG_INFO, "%s: %.1000s", e->e_id, buf);
+ sm_syslog(LOG_INFO, e->e_id, "%.1000s", buf);
- syslog(LOG_INFO, "%s: stat=%s", e->e_id, shortenstring(stat, 63));
+ sm_syslog(LOG_INFO, e->e_id, "stat=%s", shortenstring(stat, 63));
# endif /* short log buffer */
-# endif /* LOG */
}
/*
** PUTFROMLINE -- output a UNIX-style from line (or whatever)
@@ -2688,7 +2741,7 @@ putfromline(mci, e)
}
}
expand(template, buf, sizeof buf, e);
- putxline(buf, mci, PXLF_NOTHINGSPECIAL);
+ putxline(buf, strlen(buf), mci, PXLF_NOTHINGSPECIAL);
}
/*
** PUTBODY -- put the body of a message.
@@ -2828,7 +2881,7 @@ putbody(mci, e, separator)
switch (ostate)
{
case OS_HEAD:
-#ifdef _FFR_NONULLS
+#if _FFR_NONULLS
if (c == '\0' &&
bitnset(M_NONULLS, mci->mci_mailer->m_flags))
break;
@@ -2933,7 +2986,7 @@ putbody(mci, e, separator)
ostate = OS_CR;
continue;
}
-#ifdef _FFR_NONULLS
+#if _FFR_NONULLS
if (c == '\0' &&
bitnset(M_NONULLS, mci->mci_mailer->m_flags))
break;
@@ -3214,7 +3267,7 @@ mailfile(filename, ctladdr, sfflags, e)
if (setuid(RealUid) < 0 && suidwarn)
syserr("mailfile: setuid(%ld) failed", (long) RealUid);
- sfflags |= SFF_NOPATHCHECK;
+ sfflags |= SFF_NOPATHCHECK|SFF_NOLINK;
sfflags &= ~SFF_OPENASROOT;
f = safefopen(filename, oflags, FileMode, sfflags);
if (f == NULL)
@@ -3252,6 +3305,7 @@ mailfile(filename, ctladdr, sfflags, e)
#endif
(void) xfclose(f, "mailfile", filename);
(void) fflush(stdout);
+ setuid(RealUid);
exit(ExitStat);
/*NOTREACHED*/
}
diff --git a/usr.sbin/sendmail/src/domain.c b/usr.sbin/sendmail/src/domain.c
index ca2d8f8..741a7cd 100644
--- a/usr.sbin/sendmail/src/domain.c
+++ b/usr.sbin/sendmail/src/domain.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1986, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1986, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#if NAMED_BIND
-static char sccsid[] = "@(#)domain.c 8.64 (Berkeley) 10/30/96 (with name server)";
+static char sccsid[] = "@(#)domain.c 8.67 (Berkeley) 4/9/97 (with name server)";
#else
-static char sccsid[] = "@(#)domain.c 8.64 (Berkeley) 10/30/96 (without name server)";
+static char sccsid[] = "@(#)domain.c 8.67 (Berkeley) 4/9/97 (without name server)";
#endif
#endif /* not lint */
@@ -197,6 +197,7 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
goto punt;
case TRY_AGAIN:
+ case -1:
/* couldn't connect to the name server */
if (fallbackMX != NULL)
{
@@ -880,6 +881,7 @@ gethostalias(host)
fclose(fp);
return NULL;
}
+ fclose(fp);
/* got a match; extract the equivalent name */
while (*p != '\0' && isascii(*p) && isspace(*p))
diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c
index 310f45f..940faf7 100644
--- a/usr.sbin/sendmail/src/headers.c
+++ b/usr.sbin/sendmail/src/headers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,13 +33,36 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)headers.c 8.103 (Berkeley) 12/11/96";
+static char sccsid[] = "@(#)headers.c 8.110 (Berkeley) 6/14/97";
#endif /* not lint */
# include <errno.h>
# include "sendmail.h"
/*
+** SETUPHEADERS -- initialize headers in symbol table
+**
+** Parameters:
+** none
+**
+** Returns:
+** none
+*/
+
+void
+setupheaders()
+{
+ struct hdrinfo *hi;
+ STAB *s;
+
+ for (hi = HdrInfo; hi->hi_field != NULL; hi++)
+ {
+ s = stab(hi->hi_field, ST_HEADER, ST_ENTER);
+ s->s_header.hi_flags = hi->hi_flags;
+ s->s_header.hi_ruleset = NULL;
+ }
+}
+ /*
** CHOMPHEADER -- process and save a header line.
**
** Called by collect and by readcf to deal with header lines.
@@ -58,6 +81,8 @@ static char sccsid[] = "@(#)headers.c 8.103 (Berkeley) 12/11/96";
** Contents of 'line' are destroyed.
*/
+struct hdrinfo NormalHeader = { NULL, 0, NULL };
+
int
chompheader(line, def, hdrp, e)
char *line;
@@ -70,9 +95,10 @@ chompheader(line, def, hdrp, e)
HDR **hp;
char *fname;
char *fvalue;
- struct hdrinfo *hi;
bool cond = FALSE;
bool headeronly;
+ STAB *s;
+ struct hdrinfo *hi;
BITMAP mopts;
if (tTd(31, 6))
@@ -116,7 +142,7 @@ chompheader(line, def, hdrp, e)
if (*p++ != ':' || fname == fvalue)
{
syserr("553 header syntax error, line \"%s\"", line);
- return (0);
+ return 0;
}
*fvalue = '\0';
fvalue = p;
@@ -129,19 +155,44 @@ chompheader(line, def, hdrp, e)
if (strlen(fname) > 100)
return H_EOH;
- /* see if it is a known type */
- for (hi = HdrInfo; hi->hi_field != NULL; hi++)
+#if _FFR_HEADER_RSCHECK
+ /* check to see if it represents a ruleset call */
+ if (def)
{
- if (strcasecmp(hi->hi_field, fname) == 0)
- break;
+ char hbuf[50];
+
+ (void) expand(fvalue, hbuf, sizeof hbuf, e);
+ for (p = hbuf; isascii(*p) && isspace(*p); )
+ p++;
+ if ((*p++ & 0377) == CALLSUBR)
+ {
+ auto char *endp;
+
+ if (strtorwset(p, &endp, ST_ENTER) > 0)
+ {
+ *endp = '\0';
+ s = stab(fname, ST_HEADER, ST_ENTER);
+ s->s_header.hi_ruleset = newstr(p);
+ }
+ return 0;
+ }
}
+#endif
+
+ /* see if it is a known type */
+ s = stab(fname, ST_HEADER, ST_FIND);
+ if (s != NULL)
+ hi = &s->s_header;
+ else
+ hi = &NormalHeader;
if (tTd(31, 9))
{
- if (hi->hi_field == NULL)
- printf("no header match\n");
+ if (s == NULL)
+ printf("no header flags match\n");
else
- printf("header match, hi_flags=%x\n", hi->hi_flags);
+ printf("header match, flags=%x, ruleset=%s\n",
+ hi->hi_flags, hi->hi_ruleset);
}
/* see if this is a resent message */
@@ -155,7 +206,7 @@ chompheader(line, def, hdrp, e)
/* if this means "end of header" quit now */
if (bitset(H_EOH, hi->hi_flags))
- return (hi->hi_flags);
+ return hi->hi_flags;
/*
** Horrible hack to work around problem with Lotus Notes SMTP
@@ -172,6 +223,13 @@ chompheader(line, def, hdrp, e)
}
/*
+ ** If there is a check ruleset, verify it against the header.
+ */
+
+ if (!def && hi->hi_ruleset != NULL)
+ (void) rscheck(hi->hi_ruleset, fvalue, NULL, e);
+
+ /*
** Drop explicit From: if same as what we would generate.
** This is to make MH (which doesn't always give a full name)
** insert the full name information in all circumstances.
@@ -191,7 +249,7 @@ chompheader(line, def, hdrp, e)
if (e->e_from.q_paddr != NULL &&
(strcmp(fvalue, e->e_from.q_paddr) == 0 ||
strcmp(fvalue, e->e_from.q_user) == 0))
- return (hi->hi_flags);
+ return hi->hi_flags;
}
/* delete default value for this header */
@@ -232,7 +290,7 @@ chompheader(line, def, hdrp, e)
e->e_flags &= ~EF_OLDSTYLE;
}
- return (h->h_flags);
+ return h->h_flags;
}
/*
** ADDHEADER -- add a header entry to the end of the queue.
@@ -258,15 +316,11 @@ addheader(field, value, hdrlist)
HDR **hdrlist;
{
register HDR *h;
- register struct hdrinfo *hi;
+ STAB *s;
HDR **hp;
/* find info struct */
- for (hi = HdrInfo; hi->hi_field != NULL; hi++)
- {
- if (strcasecmp(field, hi->hi_field) == 0)
- break;
- }
+ s = stab(field, ST_HEADER, ST_FIND);
/* find current place in list -- keep back pointer? */
for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
@@ -280,7 +334,9 @@ addheader(field, value, hdrlist)
h->h_field = field;
h->h_value = newstr(value);
h->h_link = *hp;
- h->h_flags = hi->hi_flags | H_DEFAULT;
+ h->h_flags = H_DEFAULT;
+ if (s != NULL)
+ h->h_flags |= s->s_header.hi_flags;
clrbitmap(h->h_mflags);
*hp = h;
}
@@ -577,10 +633,8 @@ eatheader(e, full)
** Log collection information.
*/
-# ifdef LOG
if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
logsender(e, msgid);
-# endif /* LOG */
e->e_flags &= ~EF_LOGSENDER;
}
/*
@@ -599,7 +653,6 @@ logsender(e, msgid)
register ENVELOPE *e;
char *msgid;
{
-# ifdef LOG
char *name;
register char *sbp;
register char *p;
@@ -663,37 +716,39 @@ logsender(e, msgid)
p = macvalue('r', e);
if (p != NULL)
(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", proto=%.20s", p);
- syslog(LOG_INFO, "%s: %.850s, relay=%.100s",
- e->e_id, sbuf, name);
+ sm_syslog(LOG_INFO, e->e_id,
+ "%.850s, relay=%.100s",
+ sbuf, name);
# else /* short syslog buffer */
- syslog(LOG_INFO, "%s: from=%s",
- e->e_id, e->e_from.q_paddr == NULL ? "<NONE>" :
- shortenstring(e->e_from.q_paddr, 83));
- syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d",
- e->e_id, e->e_msgsize, e->e_class,
- e->e_msgpriority, e->e_nrcpts);
+ sm_syslog(LOG_INFO, e->e_id,
+ "from=%s",
+ e->e_from.q_paddr == NULL ? "<NONE>"
+ : shortenstring(e->e_from.q_paddr, 83));
+ sm_syslog(LOG_INFO, e->e_id,
+ "size=%ld, class=%ld, pri=%ld, nrcpts=%d",
+ e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts);
if (msgid != NULL)
- syslog(LOG_INFO, "%s: msgid=%s",
- e->e_id, shortenstring(mbuf, 83));
+ sm_syslog(LOG_INFO, e->e_id,
+ "msgid=%s",
+ shortenstring(mbuf, 83));
sbp = sbuf;
- snprintf(sbp, SPACELEFT(sbuf, sbp), "%s:", e->e_id);
- sbp += strlen(sbp);
+ *sbp = '\0';
if (e->e_bodytype != NULL)
{
- snprintf(sbp, SPACELEFT(sbuf, sbp), " bodytype=%.20s,", e->e_bodytype);
+ snprintf(sbp, SPACELEFT(sbuf, sbp), "bodytype=%.20s, ", e->e_bodytype);
sbp += strlen(sbp);
}
p = macvalue('r', e);
if (p != NULL)
{
- snprintf(sbp, SPACELEFT(sbuf, sbp), " proto=%.20s,", p);
+ snprintf(sbp, SPACELEFT(sbuf, sbp), "proto=%.20s, ", p);
sbp += strlen(sbp);
}
- syslog(LOG_INFO, "%.400s relay=%.100s", sbuf, name);
+ sm_syslog(LOG_INFO, e->e_id,
+ "%.400srelay=%.100s", sbuf, name);
# endif
-# endif
}
/*
** PRIENCODE -- encode external priority names into internal values.
@@ -788,7 +843,7 @@ crackaddr(addr)
*/
bp = bufhead = buf;
- buflim = &buf[sizeof buf - 6];
+ buflim = &buf[sizeof buf - 7];
p = addrhead = addr;
copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
bracklev = 0;
@@ -1165,7 +1220,7 @@ putheader(mci, hdr, e)
/* suppress return receipts if requested */
if (bitset(H_RECEIPTTO, h->h_flags) &&
-#if _FFR_DSN_RRT
+#if _FFR_DSN_RRT_OPTION
(RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags)))
#else
bitset(EF_NORECEIPT, e->e_flags))
@@ -1181,7 +1236,7 @@ putheader(mci, hdr, e)
{
expand(p, buf, sizeof buf, e);
p = buf;
- if (p == NULL || *p == '\0')
+ if (*p == '\0')
{
if (tTd(34, 11))
printf(" (skipped -- null value)\n");
@@ -1275,7 +1330,7 @@ put_vanilla_header(h, v, mci)
char obuf[MAXLINE];
putflags = 0;
-#ifdef _FFR_7BITHDRS
+#if _FFR_7BITHDRS
if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
putflags |= PXLF_STRIP8BIT;
#endif
@@ -1290,7 +1345,7 @@ put_vanilla_header(h, v, mci)
l = sizeof obuf - (obp - obuf);
snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
- putxline(obuf, mci, putflags);
+ putxline(obuf, strlen(obuf), mci, putflags);
v += l + 1;
obp = obuf;
if (*v != ' ' && *v != '\t')
@@ -1298,7 +1353,7 @@ put_vanilla_header(h, v, mci)
}
snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
sizeof obuf - (obp - obuf) - 1, v);
- putxline(obuf, mci, putflags);
+ putxline(obuf, strlen(obuf), mci, putflags);
}
/*
** COMMAIZE -- output a header field, making a comma-translated list.
@@ -1340,7 +1395,7 @@ commaize(h, p, oldstyle, mci, e)
if (tTd(14, 2))
printf("commaize(%s: %s)\n", h->h_field, p);
-#ifdef _FFR_7BITHDRS
+#if _FFR_7BITHDRS
if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
putflags |= PXLF_STRIP8BIT;
#endif
@@ -1348,6 +1403,8 @@ commaize(h, p, oldstyle, mci, e)
obp = obuf;
(void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", h->h_field);
opos = strlen(h->h_field) + 2;
+ if (opos > 202)
+ opos = 202;
obp += opos;
omax = mci->mci_mailer->m_linelimit - 2;
if (omax < 0 || omax > 78)
@@ -1441,7 +1498,7 @@ commaize(h, p, oldstyle, mci, e)
if (opos > omax && !firstone)
{
snprintf(obp, SPACELEFT(obuf, obp), ",\n");
- putxline(obuf, mci, putflags);
+ putxline(obuf, strlen(obuf), mci, putflags);
obp = obuf;
(void) strcpy(obp, " ");
opos = strlen(obp);
@@ -1460,7 +1517,7 @@ commaize(h, p, oldstyle, mci, e)
*p = savechar;
}
*obp = '\0';
- putxline(obuf, mci, putflags);
+ putxline(obuf, strlen(obuf), mci, putflags);
}
/*
** COPYHEADER -- copy header list
diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c
index 193ba54..b9be725 100644
--- a/usr.sbin/sendmail/src/main.c
+++ b/usr.sbin/sendmail/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -39,7 +39,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)main.c 8.230 (Berkeley) 1/17/97";
+static char sccsid[] = "@(#)main.c 8.246 (Berkeley) 6/11/97";
#endif /* not lint */
#define _DEFINE
@@ -62,13 +62,8 @@ char edata, end;
** turn calls a bunch of mail servers that do the real work of
** delivering the mail.
**
-** Sendmail is driven by tables read in from /usr/lib/sendmail.cf
-** (read by readcf.c). Some more static configuration info,
-** including some code that you may want to tailor for your
-** installation, is in conf.c. You may also want to touch
-** daemon.c (if you have some other IPC mechanism), acct.c
-** (to change your accounting), names.c (to adjust the name
-** server mechanism).
+** Sendmail is driven by settings read in from /etc/sendmail.cf
+** (read by readcf.c).
**
** Usage:
** /usr/lib/sendmail [flags] addr ...
@@ -82,7 +77,7 @@ char edata, end;
** International Computer Science Institute
** (11/88 - 9/89).
** UCB/Mammoth Project (10/89 - 7/95).
-** InReference, Inc. (8/95 - present).
+** InReference, Inc. (8/95 - 1/97).
** The support of the my employers is gratefully acknowledged.
** Few of them (Britton-Lee in particular) have had
** anything to gain from my involvement in this project.
@@ -99,6 +94,10 @@ char *CommandLineArgs; /* command line args for pid file */
bool Warn_Q_option = FALSE; /* warn about Q option use */
char **SaveArgv; /* argument vector for re-execing */
+#ifdef NGROUPS_MAX
+GIDSET_T InitialGidSet[NGROUPS_MAX];
+#endif
+
static void obsolete();
extern void printmailer __P((MAILER *));
extern void tTflag __P((char *));
@@ -219,7 +218,7 @@ main(argc, argv, envp)
}
errno = 0;
-#ifdef LOG
+#if LOG
# ifdef LOG_MAIL
openlog("sendmail", LOG_PID, LOG_MAIL);
# else
@@ -229,6 +228,15 @@ main(argc, argv, envp)
tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+#ifdef NGROUPS_MAX
+ /* save initial group set for future checks */
+ i = getgroups(NGROUPS_MAX, InitialGidSet);
+ if (i == 0)
+ InitialGidSet[0] = (GID_T) -1;
+ while (i < NGROUPS_MAX)
+ InitialGidSet[i++] = InitialGidSet[0];
+#endif
+
/* drop group id privileges (RunAsUser not yet set) */
drop_privileges();
@@ -489,9 +497,6 @@ main(argc, argv, envp)
#endif
}
- /* probe interfaces and locate any additional names */
- load_if_names();
-
/* current time */
define('b', arpadate((char *) NULL), CurEnv);
@@ -828,6 +833,10 @@ main(argc, argv, envp)
expand("\201m", jbuf, sizeof jbuf, CurEnv);
setclass('m', jbuf);
+ /* probe interfaces and locate any additional names */
+ if (!DontProbeInterfaces)
+ load_if_names();
+
if (tTd(0, 1))
{
printf("\n============ SYSTEM IDENTITY (after readcf) ============");
@@ -880,6 +889,10 @@ main(argc, argv, envp)
setuserenv("TZ", NULL);
tzset();
+ /* be sure we don't pick up bogus HOSTALIASES environment variable */
+ if (queuemode && RealUid != 0)
+ (void) unsetenv("HOSTALIASES");
+
/* check for sane configuration level */
if (ConfigLevel > MAXCONFIGLEVEL)
{
@@ -904,13 +917,12 @@ main(argc, argv, envp)
/* check for permissions */
if ((OpMode == MD_DAEMON || OpMode == MD_PURGESTAT) && RealUid != 0)
{
-#ifdef LOG
if (LogLevel > 1)
- syslog(LOG_ALERT, "user %d attempted to %s",
+ sm_syslog(LOG_ALERT, NOQID,
+ "user %d attempted to %s",
RealUid,
OpMode == MD_DAEMON ? "run daemon"
: "purge host status");
-#endif
usrerr("Permission denied");
exit(EX_USAGE);
}
@@ -923,6 +935,8 @@ main(argc, argv, envp)
case MD_TEST:
/* don't have persistent host status in test mode */
HostStatDir = NULL;
+ Verbose = 2;
+ CurEnv->e_errormode = EM_PRINT;
break;
case MD_FGDAEMON:
@@ -938,10 +952,9 @@ main(argc, argv, envp)
GrabTo = FALSE;
/* arrange to restart on hangup signal */
-#ifdef LOG
if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/')
- syslog(LOG_WARNING, "daemon invoked without full pathname; kill -1 won't work");
-#endif
+ sm_syslog(LOG_WARNING, NOQID,
+ "daemon invoked without full pathname; kill -1 won't work");
setsignal(SIGHUP, sighup);
/* workaround: can't seem to release the signal in the parent */
@@ -949,7 +962,8 @@ main(argc, argv, envp)
break;
case MD_INITALIAS:
- Verbose = TRUE;
+ Verbose = 2;
+ CurEnv->e_errormode = EM_PRINT;
/* fall through... */
case MD_PRINT:
@@ -1088,17 +1102,23 @@ main(argc, argv, envp)
#endif
/* operate in queue directory */
- if (OpMode == MD_TEST)
- /* nothing -- just avoid further if clauses */ ;
- else if (QueueDir == NULL)
+ if (QueueDir == NULL)
{
- syserr("QueueDirectory (Q) option must be set");
- ExitStat = EX_CONFIG;
+ if (OpMode != MD_TEST)
+ {
+ syserr("QueueDirectory (Q) option must be set");
+ ExitStat = EX_CONFIG;
+ }
}
- else if (chdir(QueueDir) < 0)
+ else
{
- syserr("cannot chdir(%s)", QueueDir);
- ExitStat = EX_CONFIG;
+ /* test path to get warning messages */
+ (void) safedirpath(QueueDir, (uid_t) 0, (gid_t) 0, NULL, SFF_ANYFILE);
+ if (OpMode != MD_TEST && chdir(QueueDir) < 0)
+ {
+ syserr("cannot chdir(%s)", QueueDir);
+ ExitStat = EX_CONFIG;
+ }
}
/* check host status directory for validity */
@@ -1226,7 +1246,7 @@ main(argc, argv, envp)
SIGFUNC_DECL intindebug __P((int));
if (isatty(fileno(stdin)))
- Verbose = TRUE;
+ Verbose = 2;
if (Verbose)
{
@@ -1261,7 +1281,6 @@ main(argc, argv, envp)
if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0)
{
- (void) unsetenv("HOSTALIASES");
(void) runqueue(FALSE, Verbose);
finis();
}
@@ -1305,9 +1324,8 @@ main(argc, argv, envp)
if (tTd(0, 1))
strcat(dtype, "+debugging");
-#ifdef LOG
- syslog(LOG_INFO, "starting daemon (%s): %s", Version, dtype + 1);
-#endif
+ sm_syslog(LOG_INFO, NOQID,
+ "starting daemon (%s): %s", Version, dtype + 1);
#ifdef XLA
xla_create_file();
#endif
@@ -1317,8 +1335,14 @@ main(argc, argv, envp)
{
(void) runqueue(TRUE, FALSE);
if (OpMode != MD_DAEMON)
+ {
for (;;)
+ {
pause();
+ if (DoQueueRun)
+ (void) runqueue(TRUE, FALSE);
+ }
+ }
}
# endif /* QUEUE */
dropenvelope(CurEnv, TRUE);
@@ -1402,7 +1426,7 @@ main(argc, argv, envp)
/* collect body for UUCP return */
if (OpMode != MD_VERIFY)
- collect(InChannel, FALSE, FALSE, NULL, CurEnv);
+ collect(InChannel, FALSE, NULL, CurEnv);
finis();
}
@@ -1423,8 +1447,21 @@ main(argc, argv, envp)
CurEnv->e_to = NULL;
if (OpMode != MD_VERIFY || GrabTo)
{
+ long savedflags = CurEnv->e_flags & EF_FATALERRS;
+
CurEnv->e_flags |= EF_GLOBALERRS;
- collect(InChannel, FALSE, FALSE, NULL, CurEnv);
+ CurEnv->e_flags &= ~EF_FATALERRS;
+ collect(InChannel, FALSE, NULL, CurEnv);
+
+ /* bail out if there were fatal errors in collect */
+ if (OpMode != MD_VERIFY && bitset(EF_FATALERRS, CurEnv->e_flags))
+ {
+ CurEnv->e_flags |= EF_CLRQUEUE;
+ finis();
+ /*NOTREACHED*/
+ return -1;
+ }
+ CurEnv->e_flags |= savedflags;
}
errno = 0;
@@ -1443,6 +1480,7 @@ main(argc, argv, envp)
printaddr(&CurEnv->e_from, FALSE);
}
CurEnv->e_to = NULL;
+ CurrentLA = getla();
sendall(CurEnv, SM_DEFAULT);
/*
@@ -1493,6 +1531,13 @@ finis()
if (tTd(2, 9))
printopenfds(FALSE);
+ /* if we fail in finis(), just exit */
+ if (setjmp(TopFrame) != 0)
+ {
+ /* failed -- just give it up */
+ goto forceexit;
+ }
+
/* clean up temp files */
CurEnv->e_to = NULL;
if (CurEnv->e_id != NULL)
@@ -1507,10 +1552,11 @@ finis()
# endif
/* and exit */
-# ifdef LOG
+ forceexit:
if (LogLevel > 78)
- syslog(LOG_DEBUG, "finis, pid=%d", getpid());
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "finis, pid=%d",
+ getpid());
if (ExitStat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET)
ExitStat = EX_OK;
@@ -1540,11 +1586,8 @@ SIGFUNC_DECL
intsig(sig)
int sig;
{
-#ifdef LOG
if (LogLevel > 79)
- syslog(LOG_DEBUG, "%s: interrupt",
- CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id);
-#endif
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt");
FileName = NULL;
unlockqueue(CurEnv);
#ifdef XLA
@@ -1665,11 +1708,10 @@ disconnect(droplev, e)
printf("don't\n");
return;
}
-#ifdef LOG
if (LogLevel > 93)
- syslog(LOG_DEBUG, "%s: disconnect level %d",
- e->e_id == NULL ? "[NOQUEUE]" : e->e_id, droplev);
-#endif
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "disconnect level %d",
+ droplev);
/* be sure we don't get nasty signals */
(void) setsignal(SIGINT, SIG_IGN);
@@ -1678,7 +1720,7 @@ disconnect(droplev, e)
/* we can't communicate with our caller, so.... */
HoldErrs = TRUE;
CurEnv->e_errormode = EM_MAIL;
- Verbose = FALSE;
+ Verbose = 0;
DisConnected = TRUE;
/* all input from /dev/null */
@@ -1719,10 +1761,10 @@ disconnect(droplev, e)
checkfd012("disconnect");
#endif
-# ifdef LOG
if (LogLevel > 71)
- syslog(LOG_DEBUG, "in background, pid=%d", getpid());
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "in background, pid=%d",
+ getpid());
errno = 0;
}
@@ -1822,11 +1864,10 @@ auth_warning(e, msg, va_alist)
vsnprintf(p, SPACELEFT(buf, p), msg, ap);
VA_END;
addheader("X-Authentication-Warning", buf, &e->e_header);
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_INFO, "%s: Authentication-Warning: %.400s",
- e->e_id == NULL ? "[NOQUEUE]" : e->e_id, buf);
-#endif
+ sm_syslog(LOG_INFO, e->e_id,
+ "Authentication-Warning: %.400s",
+ buf);
}
}
/*
@@ -1916,22 +1957,23 @@ void
dumpstate(when)
char *when;
{
-#ifdef LOG
register char *j = macvalue('j', CurEnv);
int rs;
- syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---",
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "--- dumping state on %s: $j = %s ---",
when,
j == NULL ? "<NULL>" : j);
if (j != NULL)
{
if (!wordinclass(j, 'w'))
- syslog(LOG_DEBUG, "*** $j not in $=w ***");
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "*** $j not in $=w ***");
}
- syslog(LOG_DEBUG, "CurChildren = %d", CurChildren);
- syslog(LOG_DEBUG, "--- open file descriptors: ---");
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren);
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---");
printopenfds(TRUE);
- syslog(LOG_DEBUG, "--- connection cache: ---");
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---");
mci_dump_all(TRUE);
rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
if (rs > 0)
@@ -1942,14 +1984,13 @@ dumpstate(when)
pv[0] = NULL;
stat = rewrite(pv, rs, 0, CurEnv);
- syslog(LOG_DEBUG,
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
"--- ruleset debug_dumpstate returns stat %d, pv: ---",
stat);
for (pvp = pv; *pvp != NULL; pvp++)
- syslog(LOG_DEBUG, "%s", *pvp);
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp);
}
- syslog(LOG_DEBUG, "--- end of state dump ---");
-#endif
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---");
}
@@ -1968,31 +2009,24 @@ sighup(sig)
{
if (SaveArgv[0][0] != '/')
{
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_INFO, "could not restart: need full path");
-#endif
+ sm_syslog(LOG_INFO, NOQID, "could not restart: need full path");
exit(EX_OSFILE);
}
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]);
-#endif
+ sm_syslog(LOG_INFO, NOQID, "restarting %s on signal", SaveArgv[0]);
+ alarm(0);
releasesignal(SIGHUP);
if (setgid(RealGid) < 0 || setuid(RealUid) < 0)
{
-#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "could not set[ug]id(%d, %d): %m",
+ sm_syslog(LOG_ALERT, NOQID, "could not set[ug]id(%d, %d): %m",
RealUid, RealGid);
-#endif
exit(EX_OSERR);
}
execv(SaveArgv[0], (ARGV_T) SaveArgv);
-#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "could not exec %s: %m", SaveArgv[0]);
-#endif
+ sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", SaveArgv[0]);
exit(EX_OSFILE);
}
/*
@@ -2285,6 +2319,11 @@ testmodeline(line, e)
printf("Map named \"%s\" not found\n", p);
return;
}
+ if (!bitset(MF_OPEN, map->s_map.map_mflags))
+ {
+ printf("Map named \"%s\" not open\n", p);
+ return;
+ }
printf("map_lookup: %s (%s) ", p, q);
p = (*map->s_map.map_class->map_lookup)
(&map->s_map, q, NULL, &rcode);
diff --git a/usr.sbin/sendmail/src/mime.c b/usr.sbin/sendmail/src/mime.c
index 999c5ab..3e5a610 100644
--- a/usr.sbin/sendmail/src/mime.c
+++ b/usr.sbin/sendmail/src/mime.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 1996 Eric P. Allman
+ * Copyright (c) 1994, 1996-1997 Eric P. Allman
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
@@ -36,7 +36,7 @@
# include <string.h>
#ifndef lint
-static char sccsid[] = "@(#)mime.c 8.54 (Berkeley) 1/14/97";
+static char sccsid[] = "@(#)mime.c 8.59 (Berkeley) 5/6/97";
#endif /* not lint */
/*
@@ -259,10 +259,10 @@ mime8to7(mci, header, e, boundaries, flags)
if (strcasecmp(argv[i].field, "boundary") == 0)
break;
}
- if (i >= argc)
+ if (i >= argc || argv[i].value == NULL)
{
- syserr("mime8to7: Content-Type: \"%s\": missing boundary",
- p);
+ syserr("mime8to7: Content-Type: \"%s\": %s boundary",
+ i >= argc ? "missing" : "bogus", p);
p = "---";
/* avoid bounce loops */
@@ -311,7 +311,7 @@ mime8to7(mci, header, e, boundaries, flags)
bt = mimeboundary(buf, boundaries);
if (bt != MBT_NOTSEP)
break;
- putxline(buf, mci, PXLF_MAPFROM|PXLF_STRIP8BIT);
+ putxline(buf, strlen(buf), mci, PXLF_MAPFROM|PXLF_STRIP8BIT);
if (tTd(43, 99))
printf(" ...%s", buf);
}
@@ -325,7 +325,7 @@ mime8to7(mci, header, e, boundaries, flags)
putline(buf, mci);
if (tTd(43, 35))
printf(" ...%s\n", buf);
- collect(e->e_dfp, FALSE, FALSE, &hdr, e);
+ collect(e->e_dfp, FALSE, &hdr, e);
if (tTd(43, 101))
putline("+++after collect", mci);
putheader(mci, hdr, e);
@@ -346,7 +346,7 @@ mime8to7(mci, header, e, boundaries, flags)
bt = mimeboundary(buf, boundaries);
if (bt != MBT_NOTSEP)
break;
- putxline(buf, mci, PXLF_MAPFROM|PXLF_STRIP8BIT);
+ putxline(buf, strlen(buf), mci, PXLF_MAPFROM|PXLF_STRIP8BIT);
if (tTd(43, 99))
printf(" ...%s", buf);
}
@@ -377,7 +377,7 @@ mime8to7(mci, header, e, boundaries, flags)
putline("", mci);
mci->mci_flags |= MCIF_INMIME;
- collect(e->e_dfp, FALSE, FALSE, &hdr, e);
+ collect(e->e_dfp, FALSE, &hdr, e);
if (tTd(43, 101))
putline("+++after collect", mci);
putheader(mci, hdr, e);
@@ -1048,8 +1048,8 @@ mime7to8(mci, header, e)
if (*--fbufp != '\n' ||
(fbufp > fbuf && *--fbufp != '\r'))
fbufp++;
- *fbufp = '\0';
- putline((char *) fbuf, mci);
+ putxline((char *) fbuf, fbufp - fbuf,
+ mci, PXLF_MAPFROM);
fbufp = fbuf;
}
if (c3 == '=')
@@ -1061,8 +1061,8 @@ mime7to8(mci, header, e)
if (*--fbufp != '\n' ||
(fbufp > fbuf && *--fbufp != '\r'))
fbufp++;
- *fbufp = '\0';
- putline((char *) fbuf, mci);
+ putxline((char *) fbuf, fbufp - fbuf,
+ mci, PXLF_MAPFROM);
fbufp = fbuf;
}
if (c4 == '=')
@@ -1074,8 +1074,8 @@ mime7to8(mci, header, e)
if (*--fbufp != '\n' ||
(fbufp > fbuf && *--fbufp != '\r'))
fbufp++;
- *fbufp = '\0';
- putline((char *) fbuf, mci);
+ putxline((char *) fbuf, fbufp - fbuf,
+ mci, PXLF_MAPFROM);
fbufp = fbuf;
}
}
@@ -1090,7 +1090,9 @@ mime7to8(mci, header, e)
&fbuf[MAXLINE] - fbufp) == 0)
continue;
- putline((char *) fbuf, mci);
+ if (fbufp - fbuf > 0)
+ putxline((char *) fbuf, fbufp - fbuf - 1, mci,
+ PXLF_MAPFROM);
fbufp = fbuf;
}
}
@@ -1099,7 +1101,7 @@ mime7to8(mci, header, e)
if (fbufp > fbuf)
{
*fbufp = '\0';
- putline((char *) fbuf, mci);
+ putxline((char *) fbuf, fbufp - fbuf, mci, PXLF_MAPFROM);
}
if (tTd(43, 3))
printf("\t\t\tmime7to8 => %s to 8bit done\n", cte);
diff --git a/usr.sbin/sendmail/src/parseaddr.c b/usr.sbin/sendmail/src/parseaddr.c
index a10c329..258e0a9 100644
--- a/usr.sbin/sendmail/src/parseaddr.c
+++ b/usr.sbin/sendmail/src/parseaddr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)parseaddr.c 8.115 (Berkeley) 11/24/96";
+static char sccsid[] = "@(#)parseaddr.c 8.128 (Berkeley) 6/14/97";
#endif /* not lint */
# include "sendmail.h"
@@ -220,6 +220,11 @@ invalidaddr(addr, delimptr)
if (savedelim != '\0')
*delimptr = '\0';
}
+ if (strlen(addr) > TOBUFSIZE - 2)
+ {
+ usrerr("553 Address too long (%d bytes max)", TOBUFSIZE - 2);
+ goto failure;
+ }
for (; *addr != '\0'; addr++)
{
if ((*addr & 0340) == 0200)
@@ -233,6 +238,7 @@ invalidaddr(addr, delimptr)
}
setstat(EX_USAGE);
usrerr("553 Address contained invalid control characters");
+failure:
if (delimptr != NULL && savedelim != '\0')
*delimptr = savedelim;
return TRUE;
@@ -756,6 +762,7 @@ rewrite(pvp, ruleset, reclevel, e)
struct match mlist[MAXMATCH]; /* stores match on LHS */
char *npvp[MAXATOM+1]; /* temporary space for rebuild */
extern int callsubr __P((char**, int, ENVELOPE *));
+ extern int sm_strcasecmp __P((char *, char *));
if (OpMode == MD_TEST || tTd(21, 1))
{
@@ -930,7 +937,7 @@ rewrite(pvp, ruleset, reclevel, e)
default:
/* must have exact match */
- if (strcasecmp(rp, ap))
+ if (sm_strcasecmp(rp, ap))
goto backup;
avp++;
break;
@@ -1436,7 +1443,7 @@ map_lookup(map, key, argvect, pstat, e)
map->s_name, key, errno);
if (e->e_message == NULL)
{
- char mbuf[300];
+ char mbuf[320];
snprintf(mbuf, sizeof mbuf,
"%.80s map: lookup (%s): deferred",
@@ -2106,6 +2113,10 @@ remotename(name, m, flags, pstat, e)
** none.
*/
+#define Q_COPYFLAGS (QPRIMARY|QBOGUSSHELL|QUNSAFEADDR|\
+ Q_PINGFLAGS|QHASNOTIFY|\
+ QRELAYED|QEXPANDED|QDELIVERED|QDELAYED)
+
void
maplocaluser(a, sendq, aliaslevel, e)
register ADDRESS *a;
@@ -2127,6 +2138,10 @@ maplocaluser(a, sendq, aliaslevel, e)
if (pvp == NULL)
return;
+ define('h', a->q_host, e);
+ define('u', a->q_user, e);
+ define('z', a->q_home, e);
+
if (rewrite(pvp, 5, 0, e) == EX_TEMPFAIL)
{
a->q_flags |= QQUEUEUP;
@@ -2139,7 +2154,16 @@ maplocaluser(a, sendq, aliaslevel, e)
/* if non-null, mailer destination specified -- has it changed? */
a1 = buildaddr(pvp, NULL, 0, e);
if (a1 == NULL || sameaddr(a, a1))
+ {
+ if (a1 != NULL)
+ free(a1);
return;
+ }
+
+ /* make new address take on flags and print attributes of old */
+ a1->q_flags &= ~Q_COPYFLAGS;
+ a1->q_flags |= a->q_flags & Q_COPYFLAGS;
+ a1->q_paddr = a->q_paddr;
/* mark old address as dead; insert new address */
a->q_flags |= QDONTSEND;
@@ -2324,6 +2348,8 @@ rscheck(rwset, p1, p2, e)
int rsno;
auto ADDRESS a1;
bool saveQuickAbort = QuickAbort;
+ bool saveSuprErrs = SuprErrs;
+ bool saveOnlyOneError = OnlyOneError;
char buf0[MAXLINE];
char pvpbuf[PSBUFSIZE];
extern char MsgBuf[];
@@ -2360,44 +2386,52 @@ rscheck(rwset, p1, p2, e)
}
(void) snprintf(buf, bufsize, "%s", p1);
}
+ SuprErrs = TRUE;
+ OnlyOneError = QuickAbort = FALSE;
pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
+ SuprErrs = saveSuprErrs;
if (pvp == NULL)
{
+ syserr("rscheck: cannot prescan input: \"%s\"",
+ shortenstring(buf, 203));
rstat = EX_DATAERR;
goto finis;
}
(void) rewrite(pvp, rsno, 0, e);
if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET ||
pvp[1] == NULL || strcmp(pvp[1], "error") != 0)
- return EX_OK;
+ {
+ rstat = EX_OK;
+ goto finis;
+ }
/* got an error -- process it */
saveexitstat = ExitStat;
- QuickAbort = FALSE;
(void) buildaddr(pvp, &a1, 0, e);
- QuickAbort = saveQuickAbort;
rstat = ExitStat;
ExitStat = saveexitstat;
-#ifdef LOG
if (LogLevel >= 4)
{
if (p2 == NULL)
- syslog(LOG_NOTICE, "Ruleset %s (%s) rejection: %s",
+ sm_syslog(LOG_NOTICE, e->e_id,
+ "Ruleset %s (%s) rejection: %s",
rwset, p1, MsgBuf);
else
- syslog(LOG_NOTICE, "Ruleset %s (%s, %s) rejection: %s",
+ sm_syslog(LOG_NOTICE, e->e_id,
+ "Ruleset %s (%s, %s) rejection: %s",
rwset, p1, p2, MsgBuf);
}
-#endif
-
- if (QuickAbort)
- longjmp(TopFrame, 2);
- /* clean up */
finis:
+ /* clean up */
+ QuickAbort = saveQuickAbort;
+ OnlyOneError = saveOnlyOneError;
setstat(rstat);
if (buf != buf0)
free(buf);
+
+ if (rstat != EX_OK && (QuickAbort || (OnlyOneError && !HoldErrs)))
+ longjmp(TopFrame, 2);
return rstat;
}
diff --git a/usr.sbin/sendmail/src/readcf.c b/usr.sbin/sendmail/src/readcf.c
index c868136..f050fde 100644
--- a/usr.sbin/sendmail/src/readcf.c
+++ b/usr.sbin/sendmail/src/readcf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)readcf.c 8.184 (Berkeley) 1/14/97";
+static char sccsid[] = "@(#)readcf.c 8.196 (Berkeley) 5/29/97";
#endif /* not lint */
# include "sendmail.h"
@@ -121,7 +121,7 @@ readcf(cfname, safe, e)
FileName = cfname;
LineNumber = 0;
- cf = fopen(cfname, "r");
+ cf = safefopen(cfname, O_RDONLY, 0444, SFF_OPENASROOT|SFF_NOLOCK);
if (cf == NULL)
{
syserr("cannot open");
@@ -145,11 +145,10 @@ readcf(cfname, safe, e)
if (OpMode == MD_DAEMON || OpMode == MD_INITALIAS)
fprintf(stderr, "%s: WARNING: dangerous write permissions\n",
FileName);
-#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_CRIT, "%s: WARNING: dangerous write permissions",
+ sm_syslog(LOG_CRIT, NOQID,
+ "%s: WARNING: dangerous write permissions",
FileName);
-#endif
}
#ifdef XLA
@@ -745,7 +744,7 @@ fileclass(class, filename, fmt, safe, optional)
else
{
pid = -1;
- sff = SFF_REGONLY;
+ sff = SFF_REGONLY|SFF_NOWLINK;
if (safe)
sff |= SFF_OPENASROOT;
f = safefopen(filename, O_RDONLY, 0, sff);
@@ -761,7 +760,7 @@ fileclass(class, filename, fmt, safe, optional)
{
register char *p;
# if SCANF
- char wordbuf[MAXNAME+1];
+ char wordbuf[MAXLINE + 1];
# endif
if (buf[0] == '#')
@@ -1482,14 +1481,30 @@ struct optioninfo
{ "SingleThreadDelivery", O_SINGTHREAD, FALSE },
#define O_RUNASUSER 0x9d
{ "RunAsUser", O_RUNASUSER, FALSE },
-#ifdef _FFR_DSN_RRT
+#if _FFR_DSN_RRT_OPTION
#define O_DSN_RRT 0x9e
{ "RrtImpliesDsn", O_DSN_RRT, FALSE },
#endif
-#ifdef _FFR_PIDFILE_OPT
+#if _FFR_PIDFILE_OPTION
#define O_PIDFILE 0x9f
{ "PidFile", O_PIDFILE, FALSE },
#endif
+#if _FFR_WRITABLE_DIRECTORIES_ARE_FATAL_OPTION
+#define O_WDAF 0xa0
+ { "WritableDirectoriesAreFatal", O_WDAF, FALSE },
+#endif
+#if _FFR_CHOWN_IS_ALWAYS_SAFE_OPTION
+#define O_CIAS 0xa1
+ { "ChownIsAlwaysSafe", O_CIAS, FALSE },
+#endif
+#if _FFR_DONT_PROBE_INTERFACES_OPTION
+#define O_DPI 0xa2
+ { "DontProbeInterfaces", O_DPI, FALSE },
+#endif
+#if _FFR_MAXRCPT_OPTION
+#define O_MAXRCPT 0xa3
+ { "MaxRecipientPerMessage", O_MAXRCPT, FALSE },
+#endif
{ NULL, '\0', FALSE }
};
@@ -1575,9 +1590,9 @@ setoption(opt, val, safe, sticky, e)
}
if (strlen(val) != strlen(o->o_name))
{
- bool oldVerbose = Verbose;
+ int oldVerbose = Verbose;
- Verbose = TRUE;
+ Verbose = 1;
message("Option %s used as abbreviation for %s",
val, o->o_name);
Verbose = oldVerbose;
@@ -2061,7 +2076,7 @@ setoption(opt, val, safe, sticky, e)
break;
case 'v': /* run in verbose mode */
- Verbose = atobool(val);
+ Verbose = atobool(val) ? 1 : 0;
break;
case 'w': /* if we are best MX, try host directly */
@@ -2251,6 +2266,8 @@ setoption(opt, val, safe, sticky, e)
syserr("readcf: option RunAsUser: unknown user %s", val);
else
{
+ if (*p == '\0')
+ RunAsUserName = newstr(val);
RunAsUid = pw->pw_uid;
RunAsGid = pw->pw_gid;
}
@@ -2258,7 +2275,7 @@ setoption(opt, val, safe, sticky, e)
if (*p == '\0')
break;
if (isascii(*p) && isdigit(*p))
- DefGid = atoi(p);
+ RunAsGid = atoi(p);
else
{
register struct group *gr;
@@ -2272,16 +2289,40 @@ setoption(opt, val, safe, sticky, e)
}
break;
-#ifdef _FFR_DSN_RRT
+#if _FFR_DSN_RRT_OPTION
case O_DSN_RRT:
- RrtImpliesDsn = atobool(p);
+ RrtImpliesDsn = atobool(val);
break;
#endif
-#ifdef _FFR_PIDFILE_OPT
+#if _FFR_PIDFILE_OPTION
case O_PIDFILE:
free(PidFile);
- PidFile = newstr(p);
+ PidFile = newstr(val);
+ break;
+#endif
+
+#if _FFR_WRITABLE_DIRECTORIES_ARE_FATAL_OPTION
+ case O_WDAF:
+ FatalWritableDirs = atobool(val);
+ break;
+#endif
+
+#if _FFR_CHOWN_IS_ALWAYS_SAFE_OPTION
+ case O_CIAS:
+ ChownIsAlwaysSafe = atobool(val);
+ break;
+#endif
+
+#if _FFR_DONT_PROBE_INTERFACES_OPTION
+ case O_DPI:
+ DontProbeInterfaces = atobool(val);
+ break;
+#endif
+
+#if _FFR_MAXRCPT_OPTION
+ case O_MAXRCPT:
+ MaxRcptPerMsg = atoi(val);
break;
#endif
diff --git a/usr.sbin/sendmail/src/recipient.c b/usr.sbin/sendmail/src/recipient.c
index 92e6bc3..2076884 100644
--- a/usr.sbin/sendmail/src/recipient.c
+++ b/usr.sbin/sendmail/src/recipient.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)recipient.c 8.118 (Berkeley) 12/1/96";
+static char sccsid[] = "@(#)recipient.c 8.130 (Berkeley) 5/29/97";
#endif /* not lint */
# include "sendmail.h"
@@ -76,7 +76,6 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
{
register char *p;
register ADDRESS *al; /* list of addresses to send to */
- bool firstone; /* set on first address sent */
char delimiter; /* the address delimiter */
int naddrs;
int i;
@@ -105,7 +104,6 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
delimiter = ',';
- firstone = TRUE;
al = NULL;
naddrs = 0;
@@ -185,7 +183,6 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
}
al = a;
- firstone = FALSE;
}
/* arrange to send to everyone on the local send list */
@@ -303,8 +300,12 @@ recipient(a, sendq, aliaslevel, e)
{
a->q_flags |= QBADADDR;
a->q_status = "5.7.1";
- usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs",
- a->q_alias->q_ruser, MyHostName);
+ if (a->q_alias->q_ruser == NULL)
+ usrerr("550 UID %d is an unknown user: cannot mail to programs",
+ a->q_alias->q_uid);
+ else
+ usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs",
+ a->q_alias->q_ruser, MyHostName);
}
else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
{
@@ -378,13 +379,11 @@ recipient(a, sendq, aliaslevel, e)
ret = include(a->q_user, FALSE, a, sendq, aliaslevel, e);
if (transienterror(ret))
{
-#ifdef LOG
if (LogLevel > 2)
- syslog(LOG_ERR, "%s: include %s: transient error: %s",
- e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ sm_syslog(LOG_ERR, e->e_id,
+ "include %s: transient error: %s",
shortenstring(a->q_user, 203),
errstring(ret));
-#endif
a->q_flags |= QQUEUEUP;
a->q_flags &= ~QDONTSEND;
usrerr("451 Cannot open %s: %s",
@@ -416,8 +415,12 @@ recipient(a, sendq, aliaslevel, e)
{
a->q_flags |= QBADADDR;
a->q_status = "5.7.1";
- usrerr("550 User %s@%s doesn't have a valid shell for mailing to files",
- a->q_alias->q_ruser, MyHostName);
+ if (a->q_alias->q_ruser == NULL)
+ usrerr("550 UID %d is an unknown user: cannot mail to files",
+ a->q_alias->q_uid);
+ else
+ usrerr("550 User %s@%s doesn't have a valid shell for mailing to files",
+ a->q_alias->q_ruser, MyHostName);
}
else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
{
@@ -426,6 +429,10 @@ recipient(a, sendq, aliaslevel, e)
usrerr("550 Address %s is unsafe for mailing to files",
a->q_alias->q_paddr);
}
+ else if (strcmp(buf, "/dev/null") == 0)
+ {
+ /* /dev/null is always accepted */
+ }
else if (!writable(buf, a->q_alias, SFF_CREAT))
{
a->q_flags |= QBADADDR;
@@ -451,12 +458,10 @@ recipient(a, sendq, aliaslevel, e)
a->q_flags |= QQUEUEUP;
if (e->e_message == NULL)
e->e_message = newstr("Deferred: user database error");
-# ifdef LOG
if (LogLevel > 8)
- syslog(LOG_INFO, "%s: deferred: udbexpand: %s",
- e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ sm_syslog(LOG_INFO, e->e_id,
+ "deferred: udbexpand: %s",
errstring(errno));
-# endif
message("queued (user database error): %s",
errstring(errno));
e->e_nrcpts++;
@@ -808,7 +813,13 @@ writable(filename, ctladdr, flags)
** File does exist -- check that it is writable.
*/
- if (ctladdr != NULL && geteuid() == 0)
+ if (geteuid() != 0)
+ {
+ euid = geteuid();
+ egid = getegid();
+ uname = NULL;
+ }
+ else if (ctladdr != NULL)
{
euid = ctladdr->q_uid;
egid = ctladdr->q_gid;
@@ -844,6 +855,7 @@ writable(filename, ctladdr, flags)
if (geteuid() == 0 &&
(ctladdr == NULL || !bitset(QGOODUID, ctladdr->q_flags)))
flags |= SFF_SETUIDOK;
+ flags |= SFF_NOLINK;
errno = safefile(filename, euid, egid, uname, flags, S_IWRITE, NULL);
return errno == 0;
@@ -908,25 +920,11 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
char *volatile uname;
int rval = 0;
volatile int sfflags = SFF_REGONLY;
+ register char *p;
+ bool safechown = FALSE;
+ bool safedir = FALSE;
struct stat st;
char buf[MAXLINE];
-#ifdef _POSIX_CHOWN_RESTRICTED
-# if _POSIX_CHOWN_RESTRICTED == -1
-# define safechown FALSE
-# else
-# define safechown TRUE
-# endif
-#else
-# ifdef _PC_CHOWN_RESTRICTED
- bool safechown;
-# else
-# ifdef BSD
-# define safechown TRUE
-# else
-# define safechown FALSE
-# endif
-# endif
-#endif
extern bool chownsafe();
if (tTd(27, 2))
@@ -1000,7 +998,7 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
errno = 0;
/* return pseudo-error code */
- rval = EOPENTIMEOUT;
+ rval = E_SM_OPENTIMEOUT;
goto resetuid;
}
if (TimeOuts.to_fileopen > 0)
@@ -1008,8 +1006,25 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
else
ev = NULL;
- /* the input file must be marked safe */
- rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD, NULL);
+ /* check for writable parent directory */
+ p = strrchr(fname, '/');
+ if (p != NULL)
+ {
+ *p = '\0';
+ if (safedirpath(fname, uid, gid, uname, sfflags|SFF_SAFEDIRPATH) == 0)
+ {
+ /* in safe directory: relax chown & link rules */
+ safedir = TRUE;
+ sfflags |= SFF_NOPATHCHECK;
+ }
+ *p = '/';
+ }
+
+ /* allow links only in unwritable directories */
+ if (!safedir)
+ sfflags |= SFF_NOLINK;
+
+ rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD, &st);
if (rval != 0)
{
/* don't use this :include: file */
@@ -1017,15 +1032,17 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
printf("include: not safe (uid=%d): %s\n",
(int) uid, errstring(rval));
}
- else
+ else if ((fp = fopen(fname, "r")) == NULL)
{
- fp = fopen(fname, "r");
- if (fp == NULL)
- {
- rval = errno;
- if (tTd(27, 4))
- printf("include: open: %s\n", errstring(rval));
- }
+ rval = errno;
+ if (tTd(27, 4))
+ printf("include: open: %s\n", errstring(rval));
+ }
+ else if (filechanged(fname, fileno(fp), &st, sfflags))
+ {
+ rval = E_SM_FILECHANGE;
+ if (tTd(27, 4))
+ printf("include: file changed after open\n");
}
if (ev != NULL)
clrevent(ev);
@@ -1058,7 +1075,7 @@ resetuid:
printf("include: reset uid = %d/%d\n",
(int) getuid(), (int) geteuid());
- if (rval == EOPENTIMEOUT)
+ if (rval == E_SM_OPENTIMEOUT)
usrerr("451 open timeout on %s", fname);
if (fp == NULL)
@@ -1071,9 +1088,14 @@ resetuid:
return rval;
}
-#ifndef safechown
- safechown = chownsafe(fileno(fp));
-#endif
+ /* if path was writable, check to avoid file giveaway tricks */
+ safechown = chownsafe(fileno(fp), safedir);
+ if (tTd(27, 6))
+ printf("include: parent of %s is %s, chown is %ssafe\n",
+ fname,
+ safedir ? "safe" : "dangerous",
+ safechown ? "" : "un");
+
if (ca == NULL && safechown)
{
ctladdr->q_uid = st.st_uid;
@@ -1104,13 +1126,12 @@ resetuid:
sh = "/SENDMAIL/ANY/SHELL/";
if (!usershellok(pw->pw_name, sh))
{
-#ifdef LOG
if (LogLevel >= 12)
- syslog(LOG_INFO, "%s: user %s has bad shell %s, marked %s",
+ sm_syslog(LOG_INFO, e->e_id,
+ "%s: user %s has bad shell %s, marked %s",
shortenstring(fname, 203),
pw->pw_name, sh,
safechown ? "bogus" : "unsafe");
-#endif
if (safechown)
ctladdr->q_flags |= QBOGUSSHELL;
else
@@ -1141,13 +1162,12 @@ resetuid:
if (bitset(S_IWOTH | (UnsafeGroupWrites ? S_IWGRP : 0), st.st_mode))
{
-#ifdef LOG
if (LogLevel >= 12)
- syslog(LOG_INFO, "%s: %s writable %s file, marked unsafe",
+ sm_syslog(LOG_INFO, e->e_id,
+ "%s: %s writable %s file, marked unsafe",
shortenstring(fname, 203),
bitset(S_IWOTH, st.st_mode) ? "world" : "group",
forwarding ? "forward" : ":include:");
-#endif
ctladdr->q_flags |= QUNSAFEADDR;
}
@@ -1184,12 +1204,10 @@ resetuid:
e->e_to = NULL;
message("%s to %s",
forwarding ? "forwarding" : "sending", buf);
-#ifdef LOG
if (forwarding && LogLevel > 9)
- syslog(LOG_INFO, "%s: forward %.200s => %s",
- e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ sm_syslog(LOG_INFO, e->e_id,
+ "forward %.200s => %s",
oldto, shortenstring(buf, 203));
-#endif
nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e);
}
diff --git a/usr.sbin/sendmail/src/savemail.c b/usr.sbin/sendmail/src/savemail.c
index e3cbfa3..894352c 100644
--- a/usr.sbin/sendmail/src/savemail.c
+++ b/usr.sbin/sendmail/src/savemail.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)savemail.c 8.103 (Berkeley) 1/18/97";
+static char sccsid[] = "@(#)savemail.c 8.110 (Berkeley) 4/7/97";
#endif /* not lint */
# include "sendmail.h"
@@ -349,13 +349,13 @@ savemail(e, sendbody)
/* we have a home directory; write dead.letter */
define('z', p, e);
expand("\201z/dead.letter", buf, sizeof buf, e);
- flags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID;
+ flags = SFF_NOLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID;
e->e_to = buf;
if (mailfile(buf, NULL, flags, e) == EX_OK)
{
- bool oldverb = Verbose;
+ int oldverb = Verbose;
- Verbose = TRUE;
+ Verbose = 1;
message("Saved message in %s", buf);
Verbose = oldverb;
state = ESM_DONE;
@@ -383,7 +383,7 @@ savemail(e, sendbody)
snprintf(buf, sizeof buf, "%sdead.letter", _PATH_VARTMP);
- flags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT;
+ flags = SFF_NOLINK|SFF_CREAT|SFF_REGONLY|SFF_OPENASROOT|SFF_MUSTOWN;
if (!writable(buf, NULL, flags) ||
(fp = safefopen(buf, O_WRONLY|O_CREAT|O_APPEND,
FileMode, flags)) == NULL)
@@ -407,15 +407,15 @@ savemail(e, sendbody)
state = ESM_PANIC;
else
{
- bool oldverb = Verbose;
+ int oldverb = Verbose;
- Verbose = TRUE;
+ Verbose = 1;
message("Saved message in %s", buf);
Verbose = oldverb;
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_NOTICE, "Saved message in %s", buf);
-#endif
+ sm_syslog(LOG_NOTICE, e->e_id,
+ "Saved message in %s",
+ buf);
state = ESM_DONE;
}
(void) xfclose(fp, "savemail", buf);
@@ -550,7 +550,6 @@ returntosender(msg, returnq, flags, e)
addheader("To", q->q_paddr, &ee->e_header);
}
-# ifdef LOG
if (LogLevel > 5)
{
if (bitset(EF_RESPONSE|EF_WARNING, e->e_flags))
@@ -559,10 +558,10 @@ returntosender(msg, returnq, flags, e)
p = "postmaster notify";
else
p = "DSN";
- syslog(LOG_INFO, "%s: %s: %s: %s",
- e->e_id, ee->e_id, p, shortenstring(msg, 203));
+ sm_syslog(LOG_INFO, e->e_id,
+ "%s: %s: %s",
+ ee->e_id, p, shortenstring(msg, 203));
}
-# endif
if (SendMIMEErrors)
{
@@ -759,11 +758,15 @@ errbody(mci, e, separator)
{
if (*ErrMsgFile == '/')
{
- xfile = fopen(ErrMsgFile, "r");
+ xfile = safefopen(ErrMsgFile, O_RDONLY, 0444,
+ SFF_ROOTOK|SFF_REGONLY);
if (xfile != NULL)
{
while (fgets(buf, sizeof buf, xfile) != NULL)
{
+#if _FFR_BUG_FIX
+ translate_dollars(buf);
+#endif
expand(buf, buf, sizeof buf, e);
putline(buf, mci);
}
@@ -1223,7 +1226,7 @@ smtptodsn(smtpstat)
return "5.2.2";
case 553: /* Req action not taken: mailbox name not allowed */
- return "5.1.3";
+ return "5.1.0";
case 554: /* Transaction failed */
return "5.0.0";
diff --git a/usr.sbin/sendmail/src/sendmail.8 b/usr.sbin/sendmail/src/sendmail.8
index 601ccd5..67cef7f 100644
--- a/usr.sbin/sendmail/src/sendmail.8
+++ b/usr.sbin/sendmail/src/sendmail.8
@@ -1,3 +1,4 @@
+.\" Copyright (c) 1983, 1997 Eric P. Allman
.\" Copyright (c) 1988, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -29,9 +30,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)sendmail.8 8.11 (Berkeley) 1/16/97
+.\" @(#)sendmail.8 8.12 (Berkeley) 2/1/97
.\"
-.Dd January 16, 1997
+.Dd February 1, 1997
.Dt SENDMAIL 8
.Os BSD 4
.Sh NAME
diff --git a/usr.sbin/sendmail/src/sendmail.h b/usr.sbin/sendmail/src/sendmail.h
index 9c0e3e2..2eb40c8 100644
--- a/usr.sbin/sendmail/src/sendmail.h
+++ b/usr.sbin/sendmail/src/sendmail.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)sendmail.h 8.219 (Berkeley) 1/14/97
+ * @(#)sendmail.h 8.236 (Berkeley) 6/5/97
*/
/*
@@ -41,7 +41,7 @@
# ifdef _DEFINE
# define EXTERN
# ifndef lint
-static char SmailSccsId[] = "@(#)sendmail.h 8.219 1/14/97";
+static char SmailSccsId[] = "@(#)sendmail.h 8.236 6/5/97";
# endif
# else /* _DEFINE */
# define EXTERN extern
@@ -87,6 +87,13 @@ static char SmailSccsId[] = "@(#)sendmail.h 8.219 1/14/97";
# include <netccitt/x25.h>
# endif
+#if NAMED_BIND
+# include <arpa/nameser.h>
+# ifdef NOERROR
+# undef NOERROR /* avoid <sys/streams.h> conflict */
+# endif
+#endif
+
/* forward references for prototypes */
@@ -391,6 +398,7 @@ struct hdrinfo
{
char *hi_field; /* the name of the field */
u_short hi_flags; /* status bits, see below */
+ char *hi_ruleset; /* validity check ruleset */
};
extern struct hdrinfo HdrInfo[];
@@ -726,7 +734,7 @@ MAPCLASS
#define MCF_OPTFILE 0x0008 /* file name is optional */
/* functions */
-extern char *map_rewrite __P((MAP *, char *, int, char **));
+extern char *map_rewrite __P((MAP *, const char *, int, char **));
extern MAP *makemapentry __P((char *));
extern void initmaps __P((bool, ENVELOPE *));
/*
@@ -752,6 +760,7 @@ struct symtab
NAMECANON sv_namecanon; /* canonical name cache */
int sv_macro; /* macro name => id mapping */
int sv_ruleset; /* ruleset index */
+ struct hdrinfo sv_header; /* header metainfo */
char *sv_service[MAXMAPSTACK]; /* service switch */
} s_value;
};
@@ -771,6 +780,7 @@ typedef struct symtab STAB;
# define ST_MACRO 9 /* macro name to id mapping */
# define ST_RULESET 10 /* ruleset index */
# define ST_SERVICE 11 /* service switch entry */
+# define ST_HEADER 12 /* special header flags */
# define ST_MCI 16 /* mailer connection info (offset) */
# define s_class s_value.sv_class
@@ -785,6 +795,7 @@ typedef struct symtab STAB;
# define s_macro s_value.sv_macro
# define s_ruleset s_value.sv_ruleset
# define s_service s_value.sv_service
+# define s_header s_value.sv_header
extern STAB *stab __P((char *, int, int));
extern void stabapply __P((void (*)(STAB *, int), int));
@@ -916,6 +927,7 @@ EXTERN int NoRecipientAction;
#define PRIV_NOVRFY 0x0010 /* disallow VRFY command entirely */
#define PRIV_AUTHWARNINGS 0x0020 /* flag possible authorization probs */
#define PRIV_NORECEIPTS 0x0040 /* disallow return receipts */
+#define PRIV_NOETRN 0x0080 /* disallow ETRN command entirely */
#define PRIV_RESTRICTMAILQ 0x1000 /* restrict mailq command */
#define PRIV_RESTRICTQRUN 0x2000 /* restrict queue run */
#define PRIV_GOAWAY 0x0fff /* don't give no info, anyway, anyhow */
@@ -943,7 +955,7 @@ struct prival
/*
-** Flags passed to safefile.
+** Flags passed to safefile/safedirpath.
*/
#define SFF_ANYFILE 0 /* no special restrictions */
@@ -955,12 +967,25 @@ struct prival
#define SFF_SETUIDOK 0x0020 /* setuid files are ok */
#define SFF_CREAT 0x0040 /* ok to create file if necessary */
#define SFF_REGONLY 0x0080 /* regular files only */
+#define SFF_SAFEDIRPATH 0x0100 /* no writable directories allowed */
+#define SFF_NOHLINK 0x0200 /* file cannot have hard links */
+#define SFF_NOWLINK 0x0400 /* links only in non-writable dirs */
+#define SFF_NOWFILES 0x0800 /* disallow world writable files */
-/* flags that are actually specific to safefopen */
+/* flags that are actually specific to safeopen/safefopen/dfopen */
#define SFF_OPENASROOT 0x1000 /* open as root instead of real user */
+#define SFF_NOLOCK 0x2000 /* don't lock the file */
+
+/* pseudo-flags */
+#define SFF_NOLINK (SFF_NOHLINK|SFF_NOSLINK)
/* functions */
extern int safefile __P((char *, UID_T, GID_T, char *, int, int, struct stat *));
+extern int safedirpath __P((char *, UID_T, GID_T, char *, int));
+extern int safeopen __P((char *, int, int, int));
+extern FILE *safefopen __P((char *, int, int, int));
+extern int dfopen __P((char *, int, int, int));
+extern bool filechanged __P((char *, int, struct stat *, int));
/*
@@ -1077,7 +1102,6 @@ EXTERN bool FromFlag; /* if set, "From" person is explicit */
EXTERN bool MeToo; /* send to the sender also */
EXTERN bool IgnrDot; /* don't let dot end messages */
EXTERN bool SaveFrom; /* save leading "From" lines */
-EXTERN bool Verbose; /* set if blow-by-blow desired */
EXTERN bool GrabTo; /* if set, get recipients from msg */
EXTERN bool SuprErrs; /* set if we are suppressing errors */
EXTERN bool HoldErrs; /* only output errors to transcript */
@@ -1102,6 +1126,7 @@ EXTERN uid_t DefUid; /* default uid to run as */
EXTERN gid_t DefGid; /* default gid to run as */
EXTERN char *DefUser; /* default user to run as (from DefUid) */
EXTERN MODE_T OldUmask; /* umask when sendmail starts up */
+EXTERN int Verbose; /* set if blow-by-blow desired */
EXTERN int Errors; /* set if errors (local to single pass) */
EXTERN int ExitStat; /* exit status code */
EXTERN int LineNumber; /* line number in current input */
@@ -1123,6 +1148,7 @@ EXTERN char *RealHostName; /* name of host we are talking to */
EXTERN char *CurHostName; /* current host we are dealing with */
EXTERN jmp_buf TopFrame; /* branch-to-top-of-loop-on-error frame */
EXTERN bool QuickAbort; /* .... but only if we want a quick abort */
+EXTERN bool OnlyOneError; /* .... or only want to give one SMTP reply */
EXTERN bool LogUsrErrs; /* syslog user errors (e.g., SMTP RCPT cmd) */
EXTERN bool SendMIMEErrors; /* send error messages in MIME format */
EXTERN bool MatchGecos; /* look for user names in gecos field */
@@ -1163,11 +1189,16 @@ EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */
EXTERN int DefaultNotify; /* default DSN notification flags */
EXTERN bool AllowBogusHELO; /* allow syntax errors on HELO command */
EXTERN bool UserSubmission; /* initial (user) mail submission */
+EXTERN char *RunAsUserName; /* user to become for bulk of run */
EXTERN uid_t RunAsUid; /* UID to become for bulk of run */
EXTERN gid_t RunAsGid; /* GID to become for bulk of run */
-#ifdef _FFR_DSN_RRT
+EXTERN int MaxRcptPerMsg; /* max recipients per SMTP message */
+EXTERN bool DoQueueRun; /* non-interrupt time queue run needed */
+#if _FFR_DSN_RRT_OPTION
EXTERN bool RrtImpliesDsn; /* turn Return-Receipt-To: into DSN */
#endif
+EXTERN bool DontProbeInterfaces; /* don't probe interfaces for names */
+EXTERN bool ChownAlwaysSafe; /* treat chown(2) as safe */
EXTERN bool IgnoreHostStatus; /* ignore long term host status files */
EXTERN bool SingleThreadDelivery; /* single thread hosts on delivery */
EXTERN bool UnsafeGroupWrites; /* group-writable files are unsafe */
@@ -1194,6 +1225,7 @@ EXTERN char *QueueLimitSender; /* limit queue runs to this sender */
EXTERN char *QueueLimitId; /* limit queue runs to this id */
EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */
EXTERN char *DoubleBounceAddr; /* where to send double bounces */
+EXTERN bool FatalWritableDirs; /* no writable dirs in map paths */
EXTERN char **ExternalEnviron; /* input environment */
EXTERN char *UserEnviron[MAXUSERENVIRON + 1];
/* saved user environment */
@@ -1249,6 +1281,12 @@ EXTERN u_char tTdvect[100];
*/
+/*
+** The "no queue id" queue id for sm_syslog
+*/
+
+#define NOQID "*~*"
+
/*
** Some in-line functions
@@ -1272,7 +1310,6 @@ EXTERN u_char tTdvect[100];
*/
extern char *xalloc __P((int));
-extern FILE *dfopen __P((char *, int, int));
extern char *sfgets __P((char *, int, FILE *, time_t, char *));
extern char *queuename __P((ENVELOPE *, int));
extern time_t curtime __P(());
@@ -1295,7 +1332,6 @@ extern void rebuildaliases __P((MAP *, bool));
extern void readaliases __P((MAP *, FILE *, bool, bool));
extern void finis __P(());
extern void setsender __P((char *, ENVELOPE *, char **, int, bool));
-extern FILE *safefopen __P((char *, int, int, int));
extern void xputs __P((const char *));
extern void logsender __P((ENVELOPE *, char *));
extern void smtprset __P((MAILER *, MCI *, ENVELOPE *));
@@ -1303,7 +1339,7 @@ extern void smtpquit __P((MAILER *, MCI *, ENVELOPE *));
extern void setuserenv __P((const char *, const char *));
extern char *getextenv __P((const char *));
extern void disconnect __P((int, ENVELOPE *));
-extern void putxline __P((char *, MCI *, int));
+extern void putxline __P((char *, size_t, MCI *, int));
extern void dumpfd __P((int, bool, bool));
extern void makemailer __P((char *));
extern void putfromline __P((MCI *, ENVELOPE *));
@@ -1328,7 +1364,6 @@ extern void proc_list_clear __P((void));
extern void buffer_errors __P((void));
extern void flush_errors __P((bool));
extern void putline __P((char *, MCI *));
-extern void putxline __P((char *, MCI *, int));
extern bool xtextok __P((char *));
extern char *xtextify __P((char *, char *));
extern char *xuntextify __P((char *));
@@ -1341,7 +1376,7 @@ extern int endmailer __P((MCI *, ENVELOPE *, char **));
extern void fixcrlf __P((char *, bool));
extern int dofork __P((void));
extern void initsys __P((ENVELOPE *));
-extern void collect __P((FILE *, bool, bool, HDR **, ENVELOPE *));
+extern void collect __P((FILE *, bool, HDR **, ENVELOPE *));
extern void stripquotes __P((char *));
extern int include __P((char *, bool, ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern void unlockqueue __P((ENVELOPE *));
@@ -1385,6 +1420,7 @@ extern void usrerr(const char *, ...);
extern void message(const char *, ...);
extern void nmessage(const char *, ...);
extern void setproctitle(const char *fmt, ...);
+extern void sm_syslog(int, const char *, const char *, ...);
#else
extern void auth_warning();
extern void syserr();
@@ -1392,6 +1428,7 @@ extern void usrerr();
extern void message();
extern void nmessage();
extern void setproctitle();
+extern void sm_syslog();
#endif
#if !HASSNPRINTF
diff --git a/usr.sbin/sendmail/src/srvrsmtp.c b/usr.sbin/sendmail/src/srvrsmtp.c
index 1195d8a..fa39e68 100644
--- a/usr.sbin/sendmail/src/srvrsmtp.c
+++ b/usr.sbin/sendmail/src/srvrsmtp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#if SMTP
-static char sccsid[] = "@(#)srvrsmtp.c 8.136 (Berkeley) 1/17/97 (with SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.146 (Berkeley) 6/11/97 (with SMTP)";
#else
-static char sccsid[] = "@(#)srvrsmtp.c 8.136 (Berkeley) 1/17/97 (without SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.146 (Berkeley) 6/11/97 (without SMTP)";
#endif
#endif /* not lint */
@@ -153,6 +153,7 @@ smtp(nullserver, e)
volatile int n_noop = 0; /* count of NOOP/VERB/ONEX etc cmds */
volatile int n_helo = 0; /* count of HELO/EHLO commands */
bool ok;
+ int lognullconnection = TRUE;
char inp[MAXLINE];
char cmdbuf[MAXLINE];
extern ENVELOPE BlankEnvelope;
@@ -160,7 +161,7 @@ smtp(nullserver, e)
extern void settime __P((ENVELOPE *));
extern bool enoughdiskspace __P((long));
extern int runinchild __P((char *, ENVELOPE *));
- extern void checksmtpattack __P((volatile int *, int, char *));
+ extern void checksmtpattack __P((volatile int *, int, char *, ENVELOPE *));
if (fileno(OutChannel) != fileno(stdout))
{
@@ -177,11 +178,12 @@ smtp(nullserver, e)
CurSmtpClient = CurHostName;
setproctitle("server %s startup", CurSmtpClient);
-#if defined(LOG) && DAEMON
+#if DAEMON
if (LogLevel > 11)
{
/* log connection information */
- syslog(LOG_INFO, "SMTP connect from %.100s (%.100s)",
+ sm_syslog(LOG_INFO, NOQID,
+ "SMTP connect from %.100s (%.100s)",
CurSmtpClient, anynet_ntoa(&RealHostAddr));
}
#endif
@@ -231,7 +233,9 @@ smtp(nullserver, e)
}
QuickAbort = FALSE;
HoldErrs = FALSE;
+ SuprErrs = FALSE;
LogUsrErrs = FALSE;
+ OnlyOneError = TRUE;
e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
/* setup for the read */
@@ -252,11 +256,10 @@ smtp(nullserver, e)
disconnect(1, e);
message("421 %s Lost input channel from %s",
MyHostName, CurSmtpClient);
-#ifdef LOG
if (LogLevel > (gotmail ? 1 : 19))
- syslog(LOG_NOTICE, "lost input channel from %.100s",
+ sm_syslog(LOG_NOTICE, e->e_id,
+ "lost input channel from %.100s",
CurSmtpClient);
-#endif
if (InChild)
ExitStat = EX_QUIT;
finis();
@@ -269,10 +272,10 @@ smtp(nullserver, e)
if (e->e_xfp != NULL)
fprintf(e->e_xfp, "<<< %s\n", inp);
-#ifdef LOG
if (LogLevel >= 15)
- syslog(LOG_INFO, "<-- %s", inp);
-#endif
+ sm_syslog(LOG_INFO, e->e_id,
+ "<-- %s",
+ inp);
if (e->e_id == NULL)
setproctitle("%s: %.80s", CurSmtpClient, inp);
@@ -324,7 +327,7 @@ smtp(nullserver, e)
default:
if (++badcommands > MAXBADCOMMANDS)
sleep(1);
- message("550 Access denied");
+ usrerr("550 Access denied");
continue;
}
}
@@ -332,6 +335,15 @@ smtp(nullserver, e)
/* non-null server */
switch (c->cmdcode)
{
+ case CMDMAIL:
+ case CMDEXPN:
+ case CMDVRFY:
+ case CMDETRN:
+ lognullconnection = FALSE;
+ }
+
+ switch (c->cmdcode)
+ {
case CMDHELO: /* hello -- introduce yourself */
case CMDEHLO: /* extended hello */
if (c->cmdcode == CMDEHLO)
@@ -346,12 +358,12 @@ smtp(nullserver, e)
}
/* avoid denial-of-service */
- checksmtpattack(&n_helo, MAXHELOCOMMANDS, "HELO/EHLO");
+ checksmtpattack(&n_helo, MAXHELOCOMMANDS, "HELO/EHLO", e);
/* check for duplicate HELO/EHLO per RFC 1651 4.2 */
if (gothello)
{
- message("503 %s Duplicate HELO/EHLO",
+ usrerr("503 %s Duplicate HELO/EHLO",
MyHostName);
break;
}
@@ -359,7 +371,7 @@ smtp(nullserver, e)
/* check for valid domain name (re 1123 5.2.5) */
if (*p == '\0' && !AllowBogusHELO)
{
- message("501 %s requires domain address",
+ usrerr("501 %s requires domain address",
cmdbuf);
break;
}
@@ -384,7 +396,7 @@ smtp(nullserver, e)
if (*q != '\0')
{
if (!AllowBogusHELO)
- message("501 Invalid domain name");
+ usrerr("501 Invalid domain name");
else
{
message("250 %s Invalid domain name, accepting anyway",
@@ -442,13 +454,13 @@ smtp(nullserver, e)
if (bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
{
- message("503 Polite people say HELO first");
+ usrerr("503 Polite people say HELO first");
break;
}
}
if (gotmail)
{
- message("503 Sender already specified");
+ usrerr("503 Sender already specified");
if (InChild)
finis();
break;
@@ -578,7 +590,7 @@ smtp(nullserver, e)
if (!enoughdiskspace(e->e_msgsize))
{
- message("452 Insufficient disk space; try again later");
+ usrerr("452 Insufficient disk space; try again later");
break;
}
message("250 Sender ok");
@@ -600,6 +612,13 @@ smtp(nullserver, e)
QuickAbort = TRUE;
LogUsrErrs = TRUE;
+ /* limit flooding of our machine */
+ if (MaxRcptPerMsg > 0 && nrcpts >= MaxRcptPerMsg)
+ {
+ usrerr("450 Too many recipients");
+ break;
+ }
+
if (e->e_sendmode != SM_DELIVER)
e->e_flags |= EF_VRFYONLY;
@@ -674,21 +693,20 @@ smtp(nullserver, e)
else
{
/* punt -- should keep message in ADDRESS.... */
- message("550 Addressee unknown");
+ usrerr("550 Addressee unknown");
}
- e->e_to = NULL;
break;
case CMDDATA: /* data -- text of mail */
SmtpPhase = "server DATA";
if (!gotmail)
{
- message("503 Need MAIL command");
+ usrerr("503 Need MAIL command");
break;
}
else if (nrcpts <= 0)
{
- message("503 Need RCPT (recipient)");
+ usrerr("503 Need RCPT (recipient)");
break;
}
@@ -713,7 +731,7 @@ smtp(nullserver, e)
/* collect the text of the message */
SmtpPhase = "collect";
buffer_errors();
- collect(InChannel, TRUE, doublequeue, NULL, e);
+ collect(InChannel, TRUE, NULL, e);
flush_errors(TRUE);
if (Errors != 0)
goto abortmessage;
@@ -785,7 +803,10 @@ smtp(nullserver, e)
break;
case CMDRSET: /* rset -- reset state */
- message("250 Reset state");
+ if (tTd(94, 100))
+ message("451 Test failure");
+ else
+ message("250 Reset state");
/* arrange to ignore any current send list */
e->e_sendqueue = NULL;
@@ -795,6 +816,7 @@ smtp(nullserver, e)
/* clean up a bit */
gotmail = FALSE;
+ SuprErrs = TRUE;
dropenvelope(e, TRUE);
CurEnv = e = newenvelope(e, CurEnv);
break;
@@ -802,7 +824,7 @@ smtp(nullserver, e)
case CMDVRFY: /* vrfy -- verify address */
case CMDEXPN: /* expn -- expand address */
checksmtpattack(&nverifies, MAXVRFYCOMMANDS,
- c->cmdcode == CMDVRFY ? "VRFY" : "EXPN");
+ c->cmdcode == CMDVRFY ? "VRFY" : "EXPN", e);
vrfy = c->cmdcode == CMDVRFY;
if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN,
PrivacyFlags))
@@ -811,39 +833,35 @@ smtp(nullserver, e)
message("252 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
else
message("502 Sorry, we do not allow this operation");
-#ifdef LOG
if (LogLevel > 5)
- syslog(LOG_INFO, "%.100s: %s [rejected]",
+ sm_syslog(LOG_INFO, e->e_id,
+ "%.100s: %s [rejected]",
CurSmtpClient,
shortenstring(inp, 203));
-#endif
break;
}
else if (!gothello &&
bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
PrivacyFlags))
{
- message("503 I demand that you introduce yourself first");
+ usrerr("503 I demand that you introduce yourself first");
break;
}
if (runinchild(vrfy ? "SMTP-VRFY" : "SMTP-EXPN", e) > 0)
break;
-#ifdef LOG
if (LogLevel > 5)
- syslog(LOG_INFO, "%.100s: %s",
+ sm_syslog(LOG_INFO, e->e_id,
+ "%.100s: %s",
CurSmtpClient,
shortenstring(inp, 203));
-#endif
vrfyqueue = NULL;
- QuickAbort = TRUE;
if (vrfy)
e->e_flags |= EF_VRFYONLY;
while (*p != '\0' && isascii(*p) && isspace(*p))
p++;
if (*p == '\0')
{
- message("501 Argument required");
- Errors++;
+ usrerr("501 Argument required");
}
else
{
@@ -857,7 +875,7 @@ smtp(nullserver, e)
}
if (vrfyqueue == NULL)
{
- message("554 Nothing to %s", vrfy ? "VRFY" : "EXPN");
+ usrerr("554 Nothing to %s", vrfy ? "VRFY" : "EXPN");
}
while (vrfyqueue != NULL)
{
@@ -878,24 +896,23 @@ smtp(nullserver, e)
case CMDETRN: /* etrn -- force queue flush */
if (strlen(p) <= 0)
{
- message("500 Parameter required");
+ usrerr("500 Parameter required");
break;
}
/* crude way to avoid denial-of-service attacks */
- checksmtpattack(&n_etrn, MAXETRNCOMMANDS, "ETRN");
+ checksmtpattack(&n_etrn, MAXETRNCOMMANDS, "ETRN", e);
id = p;
if (*id == '@')
id++;
else
*--id = '@';
-#ifdef LOG
if (LogLevel > 5)
- syslog(LOG_INFO, "%.100s: ETRN %s",
+ sm_syslog(LOG_INFO, e->e_id,
+ "%.100s: ETRN %s",
CurSmtpClient,
shortenstring(id, 203));
-#endif
QueueLimitRecipient = id;
ok = runqueue(TRUE, TRUE);
QueueLimitRecipient = NULL;
@@ -908,7 +925,7 @@ smtp(nullserver, e)
break;
case CMDNOOP: /* noop -- do nothing */
- checksmtpattack(&n_noop, MAXNOOPCOMMANDS, "NOOP");
+ checksmtpattack(&n_noop, MAXNOOPCOMMANDS, "NOOP", e);
message("250 OK");
break;
@@ -924,6 +941,10 @@ doquit:
if (InChild)
ExitStat = EX_QUIT;
+ if (lognullconnection && LogLevel > 5)
+ sm_syslog(LOG_INFO, NULL,
+ "Null connection from %.100s",
+ CurSmtpClient);
finis();
case CMDVERB: /* set verbose mode */
@@ -933,20 +954,20 @@ doquit:
message("502 Verbose unavailable");
break;
}
- checksmtpattack(&n_noop, MAXNOOPCOMMANDS, "VERB");
- Verbose = TRUE;
+ checksmtpattack(&n_noop, MAXNOOPCOMMANDS, "VERB", e);
+ Verbose = 1;
e->e_sendmode = SM_DELIVER;
message("250 Verbose mode");
break;
case CMDONEX: /* doing one transaction only */
- checksmtpattack(&n_noop, MAXNOOPCOMMANDS, "ONEX");
+ checksmtpattack(&n_noop, MAXNOOPCOMMANDS, "ONEX", e);
OneXact = TRUE;
message("250 Only one transaction");
break;
case CMDXUSR: /* initial (user) submission */
- checksmtpattack(&n_noop, MAXNOOPCOMMANDS, "XUSR");
+ checksmtpattack(&n_noop, MAXNOOPCOMMANDS, "XUSR", e);
UserSubmission = TRUE;
message("250 Initial submission");
break;
@@ -968,13 +989,11 @@ doquit:
case CMDDBGDEBUG: /* set debug mode */
# endif /* SMTPDEBUG */
case CMDLOGBOGUS: /* bogus command */
-# ifdef LOG
if (LogLevel > 0)
- syslog(LOG_CRIT,
+ sm_syslog(LOG_CRIT, e->e_id,
"\"%s\" command from %.100s (%.100s)",
c->cmdname, CurSmtpClient,
anynet_ntoa(&RealHostAddr));
-# endif
/* FALL THROUGH */
case CMDERROR: /* unknown command */
@@ -985,7 +1004,8 @@ doquit:
goto doquit;
}
- message("500 Command unrecognized");
+ usrerr("500 Command unrecognized: \"%s\"",
+ shortenstring(inp, 203));
break;
default:
@@ -1003,6 +1023,7 @@ doquit:
** maxcount -- maximum value for this counter before we
** slow down.
** cname -- command name for logging.
+** e -- the current envelope.
**
** Returns:
** none.
@@ -1012,20 +1033,20 @@ doquit:
*/
void
-checksmtpattack(pcounter, maxcount, cname)
+checksmtpattack(pcounter, maxcount, cname, e)
volatile int *pcounter;
int maxcount;
char *cname;
+ ENVELOPE *e;
{
if (++(*pcounter) >= maxcount)
{
-#ifdef LOG
if (*pcounter == maxcount && LogLevel > 5)
{
- syslog(LOG_INFO, "%.100s: %.40s attack?",
+ sm_syslog(LOG_INFO, e->e_id,
+ "%.100s: %.40s attack?",
CurSmtpClient, cname);
}
-#endif
sleep(*pcounter / maxcount);
}
}
@@ -1065,9 +1086,8 @@ skipword(p, w)
if (*p != ':')
{
syntax:
- message("501 Syntax error in parameters scanning \"%s\"",
+ usrerr("501 Syntax error in parameters scanning \"%s\"",
shortenstring(firstp, 203));
- Errors++;
return (NULL);
}
*p++ = '\0';
@@ -1411,7 +1431,8 @@ help(topic)
extern char Version[];
- if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)
+ if (HelpFile == NULL ||
+ (hf = safefopen(HelpFile, O_RDONLY, 0444, SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK)) == NULL)
{
/* no help */
errno = 0;
diff --git a/usr.sbin/sendmail/src/udb.c b/usr.sbin/sendmail/src/udb.c
index af4c298..51c6873 100644
--- a/usr.sbin/sendmail/src/udb.c
+++ b/usr.sbin/sendmail/src/udb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#if USERDB
-static char sccsid [] = "@(#)udb.c 8.47 (Berkeley) 12/6/96 (with USERDB)";
+static char sccsid [] = "@(#)udb.c 8.51 (Berkeley) 5/29/97 (with USERDB)";
#else
-static char sccsid [] = "@(#)udb.c 8.47 (Berkeley) 12/6/96 (without USERDB)";
+static char sccsid [] = "@(#)udb.c 8.51 (Berkeley) 5/29/97 (without USERDB)";
#endif
#endif
@@ -120,7 +120,7 @@ struct option
char *val;
};
-extern int _udbx_init __P((void));
+extern int _udbx_init __P((ENVELOPE *));
/*
** UDBEXPAND -- look up user in database and expand
**
@@ -173,7 +173,7 @@ udbexpand(a, sendq, aliaslevel, e)
/* on first call, locate the database */
if (!UdbInitialized)
{
- if (_udbx_init() == EX_TEMPFAIL)
+ if (_udbx_init(e) == EX_TEMPFAIL)
return EX_TEMPFAIL;
}
@@ -259,14 +259,19 @@ udbexpand(a, sendq, aliaslevel, e)
breakout = TRUE;
if (info.size >= userleft - 1)
{
- char *nuser = xalloc(usersize + MEMCHUNKSIZE);
+ char *nuser;
+ int size = MEMCHUNKSIZE;
+
+ if (info.size > MEMCHUNKSIZE)
+ size = info.size;
+ nuser = xalloc(usersize + size);
bcopy(user, nuser, usersize);
if (user != userbuf)
free(user);
user = nuser;
- usersize += MEMCHUNKSIZE;
- userleft += MEMCHUNKSIZE;
+ usersize += size;
+ userleft += size;
}
p = &user[strlen(user)];
if (p != user)
@@ -287,12 +292,11 @@ udbexpand(a, sendq, aliaslevel, e)
break;
message("expanded to %s", user);
-#ifdef LOG
if (LogLevel >= 10)
- syslog(LOG_INFO, "%s: expand %.100s => %s",
- e->e_id, e->e_to,
+ sm_syslog(LOG_INFO, e->e_id,
+ "expand %.100s => %s",
+ e->e_to,
shortenstring(user, 203));
-#endif
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
@@ -417,12 +421,11 @@ udbexpand(a, sendq, aliaslevel, e)
user[info.size] = '\0';
message("hesioded to %s", user);
-#ifdef LOG
if (LogLevel >= 10)
- syslog(LOG_INFO, "%s: hesiod %.100s => %s",
- e->e_id, e->e_to,
+ sm_syslog(LOG_INFO, e->e_id,
+ "hesiod %.100s => %s",
+ e->e_to,
shortenstring(user, 203));
-#endif
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
@@ -539,7 +542,7 @@ udbmatch(user, field)
if (!UdbInitialized)
{
- if (_udbx_init() == EX_TEMPFAIL)
+ if (_udbx_init(CurEnv) == EX_TEMPFAIL)
return NULL;
}
@@ -552,7 +555,10 @@ udbmatch(user, field)
return NULL;
/* long names can never match and are a pain to deal with */
- if ((strlen(user) + strlen(field)) > sizeof keybuf - 4)
+ i = strlen(field);
+ if (i < sizeof "maildrop")
+ i = sizeof "maildrop";
+ if ((strlen(user) + i) > sizeof keybuf - 4)
return NULL;
/* names beginning with colons indicate metadata */
@@ -785,7 +791,7 @@ udb_map_lookup(map, name, av, statp)
** _UDBX_INIT -- parse the UDB specification, opening any valid entries.
**
** Parameters:
-** none.
+** e -- the current envelope.
**
** Returns:
** EX_TEMPFAIL -- if it appeared it couldn't get hold of a
@@ -800,7 +806,8 @@ udb_map_lookup(map, name, av, statp)
#define MAXUDBOPTS 27
int
-_udbx_init()
+_udbx_init(e)
+ ENVELOPE *e;
{
register char *p;
register struct udbent *up;
@@ -957,19 +964,18 @@ _udbx_init()
{
int saveerrno = errno;
- printf("dbopen(%s): %s",
+ printf("dbopen(%s): %s\n",
up->udb_dbname,
errstring(errno));
errno = saveerrno;
}
if (errno != ENOENT && errno != EACCES)
{
-#ifdef LOG
if (LogLevel > 2)
- syslog(LOG_ERR, "dbopen(%s): %s",
+ sm_syslog(LOG_ERR, e->e_id,
+ "dbopen(%s): %s",
up->udb_dbname,
errstring(errno));
-#endif
up->udb_type = UDB_EOLIST;
if (up->udb_dbname != spec)
free(up->udb_dbname);
diff --git a/usr.sbin/sendmail/src/usersmtp.c b/usr.sbin/sendmail/src/usersmtp.c
index 23d1348..8529497 100644
--- a/usr.sbin/sendmail/src/usersmtp.c
+++ b/usr.sbin/sendmail/src/usersmtp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#if SMTP
-static char sccsid[] = "@(#)usersmtp.c 8.80 (Berkeley) 1/18/97 (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.87 (Berkeley) 6/3/97 (with SMTP)";
#else
-static char sccsid[] = "@(#)usersmtp.c 8.80 (Berkeley) 1/18/97 (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.87 (Berkeley) 6/3/97 (without SMTP)";
#endif
#endif /* not lint */
@@ -389,7 +389,7 @@ smtpmailfrom(m, mci, e)
!bitset(EF_DONT_MIME, e->e_flags) &&
!bitnset(M_8BITS, m->m_flags))
bodytype = "8BITMIME";
- if (bodytype != NULL)
+ if (bodytype != NULL && strlen(bodytype) + 7 < l)
{
strcat(optbuf, " BODY=");
strcat(optbuf, bodytype);
@@ -524,6 +524,8 @@ smtpmailfrom(m, mci, e)
{
/* exceeded storage allocation */
mci_setstat(mci, EX_NOTSTICKY, "5.2.2", SmtpReplyBuffer);
+ if (bitset(MCIF_SIZE, mci->mci_flags))
+ e->e_flags |= EF_NO_BODY_RETN;
return EX_UNAVAILABLE;
}
else if (REPLYTYPE(r) == 5)
@@ -533,14 +535,13 @@ smtpmailfrom(m, mci, e)
return EX_UNAVAILABLE;
}
-#ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_CRIT, "%s: %.100s: SMTP MAIL protocol error: %s",
- e->e_id, mci->mci_host,
+ sm_syslog(LOG_CRIT, e->e_id,
+ "%.100s: SMTP MAIL protocol error: %s",
+ mci->mci_host,
shortenstring(SmtpReplyBuffer, 403));
}
-#endif
/* protocol error -- close up */
mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
@@ -651,14 +652,13 @@ smtprcpt(to, m, mci, e)
return EX_UNAVAILABLE;
}
-#ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_CRIT, "%s: %.100s: SMTP RCPT protocol error: %s",
- e->e_id, mci->mci_host,
+ sm_syslog(LOG_CRIT, e->e_id,
+ "%.100s: SMTP RCPT protocol error: %s",
+ mci->mci_host,
shortenstring(SmtpReplyBuffer, 403));
}
-#endif
mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
return EX_PROTOCOL;
@@ -718,14 +718,13 @@ smtpdata(m, mci, e)
}
else if (r != 354)
{
-#ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-1 protocol error: %s",
- e->e_id, mci->mci_host,
+ sm_syslog(LOG_CRIT, e->e_id,
+ "%.100s: SMTP DATA-1 protocol error: %s",
+ mci->mci_host,
shortenstring(SmtpReplyBuffer, 403));
}
-#endif
smtprset(m, mci, e);
mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
return (EX_PROTOCOL);
@@ -800,8 +799,6 @@ smtpdata(m, mci, e)
xstat = EX_NOTSTICKY;
if (r == 452)
rstat = EX_TEMPFAIL;
- else if (r == 552)
- rstat = EX_UNAVAILABLE;
else if (REPLYTYPE(r) == 4)
rstat = xstat = EX_TEMPFAIL;
else if (REPLYCLASS(r) != 5)
@@ -809,7 +806,7 @@ smtpdata(m, mci, e)
else if (REPLYTYPE(r) == 2)
rstat = xstat = EX_OK;
else if (REPLYTYPE(r) == 5)
- rstat = xstat = EX_UNAVAILABLE;
+ rstat = EX_UNAVAILABLE;
else
rstat = EX_PROTOCOL;
mci_setstat(mci, xstat, smtptodsn(r), SmtpReplyBuffer);
@@ -818,14 +815,13 @@ smtpdata(m, mci, e)
e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
if (rstat != EX_PROTOCOL)
return rstat;
-#ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-2 protocol error: %s",
- e->e_id, mci->mci_host,
+ sm_syslog(LOG_CRIT, e->e_id,
+ "%.100s: SMTP DATA-2 protocol error: %s",
+ mci->mci_host,
shortenstring(SmtpReplyBuffer, 403));
}
-#endif
return rstat;
}
@@ -877,14 +873,13 @@ smtpgetstat(m, mci, e)
else if (REPLYTYPE(r) == 5)
stat = EX_UNAVAILABLE;
mci_setstat(mci, stat, smtptodsn(r), SmtpReplyBuffer);
-#ifdef LOG
if (LogLevel > 1 && stat == EX_PROTOCOL)
{
- syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-3 protocol error: %s",
- e->e_id, mci->mci_host,
+ sm_syslog(LOG_CRIT, e->e_id,
+ "%.100s: SMTP DATA-3 protocol error: %s",
+ mci->mci_host,
shortenstring(SmtpReplyBuffer, 403));
}
-#endif
return stat;
}
@@ -929,10 +924,7 @@ smtpquit(m, mci, e)
(void) reply(m, mci, e, TimeOuts.to_quit, NULL);
SuprErrs = oldSuprErrs;
if (mci->mci_state == MCIS_CLOSED)
- {
- SuprErrs = oldSuprErrs;
return;
- }
}
/* now actually close the connection and pick up the zombie */
@@ -1025,7 +1017,8 @@ reply(m, mci, e, timeout, pfunc)
** Read the input line, being careful not to hang.
*/
- for (bufp = SmtpReplyBuffer;; bufp = junkbuf)
+ bufp = SmtpReplyBuffer;
+ for (;;)
{
register char *p;
extern time_t curtime();
@@ -1120,26 +1113,32 @@ reply(m, mci, e, timeout, pfunc)
if (Verbose)
nmessage("050 %s", bufp);
+ /* ignore improperly formated input */
+ if (!(isascii(bufp[0]) && isdigit(bufp[0])) ||
+ !(isascii(bufp[1]) && isdigit(bufp[1])) ||
+ !(isascii(bufp[2]) && isdigit(bufp[2])) ||
+ !(bufp[3] == ' ' || bufp[3] == '-'))
+ continue;
+
/* process the line */
if (pfunc != NULL)
(*pfunc)(bufp, firstline, m, mci, e);
firstline = FALSE;
- /* if continuation is required, we can go on */
- if (bufp[3] == '-')
- continue;
-
- /* ignore improperly formated input */
- if (!(isascii(bufp[0]) && isdigit(bufp[0])))
- continue;
-
/* decode the reply code */
r = atoi(bufp);
/* extra semantics: 0xx codes are "informational" */
- if (r >= 100)
+ if (r < 100)
+ continue;
+
+ /* if no continuation lines, return this line */
+ if (bufp[3] != '-')
break;
+
+ /* first line of real reply -- ignore rest */
+ bufp = junkbuf;
}
/*
diff --git a/usr.sbin/sendmail/src/util.c b/usr.sbin/sendmail/src/util.c
index 242b615..5e5e7af 100644
--- a/usr.sbin/sendmail/src/util.c
+++ b/usr.sbin/sendmail/src/util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)util.c 8.115 (Berkeley) 1/5/97";
+static char sccsid[] = "@(#)util.c 8.129 (Berkeley) 6/11/97";
#endif /* not lint */
# include "sendmail.h"
@@ -449,352 +449,6 @@ buildfname(gecos, login, buf, buflen)
*bp = '\0';
}
/*
-** SAFEFILE -- return true if a file exists and is safe for a user.
-**
-** Parameters:
-** fn -- filename to check.
-** uid -- user id to compare against.
-** gid -- group id to compare against.
-** uname -- user name to compare against (used for group
-** sets).
-** flags -- modifiers:
-** SFF_MUSTOWN -- "uid" must own this file.
-** SFF_NOSLINK -- file cannot be a symbolic link.
-** mode -- mode bits that must match.
-** st -- if set, points to a stat structure that will
-** get the stat info for the file.
-**
-** Returns:
-** 0 if fn exists, is owned by uid, and matches mode.
-** An errno otherwise. The actual errno is cleared.
-**
-** Side Effects:
-** none.
-*/
-
-#include <grp.h>
-
-#ifndef S_IXOTH
-# define S_IXOTH (S_IEXEC >> 6)
-#endif
-
-#ifndef S_IXGRP
-# define S_IXGRP (S_IEXEC >> 3)
-#endif
-
-#ifndef S_IXUSR
-# define S_IXUSR (S_IEXEC)
-#endif
-
-#define ST_MODE_NOFILE 0171147 /* unlikely to occur */
-
-int
-safefile(fn, uid, gid, uname, flags, mode, st)
- char *fn;
- UID_T uid;
- GID_T gid;
- char *uname;
- int flags;
- int mode;
- struct stat *st;
-{
- register char *p;
- register struct group *gr = NULL;
- int file_errno = 0;
- struct stat stbuf;
- struct stat fstbuf;
-
- if (tTd(44, 4))
- printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n",
- fn, (int) uid, (int) gid, flags, mode);
- errno = 0;
- if (st == NULL)
- st = &fstbuf;
-
- /* first check to see if the file exists at all */
-#ifdef HASLSTAT
- if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st)
- : stat(fn, st)) < 0)
-#else
- if (stat(fn, st) < 0)
-#endif
- {
- file_errno = errno;
- }
- else if (bitset(SFF_SETUIDOK, flags) &&
- !bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode) &&
- S_ISREG(st->st_mode))
- {
- /*
- ** If final file is setuid, run as the owner of that
- ** file. Gotta be careful not to reveal anything too
- ** soon here!
- */
-
-#ifdef SUID_ROOT_FILES_OK
- if (bitset(S_ISUID, st->st_mode))
-#else
- if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0)
-#endif
- {
- uid = st->st_uid;
- uname = NULL;
- }
-#ifdef SUID_ROOT_FILES_OK
- if (bitset(S_ISGID, st->st_mode))
-#else
- if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0)
-#endif
- gid = st->st_gid;
- }
-
- if (!bitset(SFF_NOPATHCHECK, flags) ||
- (uid == 0 && !bitset(SFF_ROOTOK, flags)))
- {
- /* check the path to the file for acceptability */
- for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/')
- {
- *p = '\0';
- if (stat(fn, &stbuf) < 0)
- break;
- if (uid == 0 && bitset(S_IWGRP|S_IWOTH, stbuf.st_mode))
- message("051 WARNING: writable directory %s",
- fn);
- if (uid == 0 && !bitset(SFF_ROOTOK, flags))
- {
- if (bitset(S_IXOTH, stbuf.st_mode))
- continue;
- break;
- }
- if (stbuf.st_uid == uid &&
- bitset(S_IXUSR, stbuf.st_mode))
- continue;
- if (stbuf.st_gid == gid &&
- bitset(S_IXGRP, stbuf.st_mode))
- continue;
-#ifndef NO_GROUP_SET
- if (uname != NULL && !DontInitGroups &&
- ((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
- (gr = getgrgid(stbuf.st_gid)) != NULL))
- {
- register char **gp;
-
- for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++)
- if (strcmp(*gp, uname) == 0)
- break;
- if (gp != NULL && *gp != NULL &&
- bitset(S_IXGRP, stbuf.st_mode))
- continue;
- }
-#endif
- if (!bitset(S_IXOTH, stbuf.st_mode))
- break;
- }
- if (p != NULL)
- {
- int ret = errno;
-
- if (ret == 0)
- ret = EACCES;
- if (tTd(44, 4))
- printf("\t[dir %s] %s\n", fn, errstring(ret));
- *p = '/';
- return ret;
- }
- }
-
- /*
- ** If the target file doesn't exist, check the directory to
- ** ensure that it is writable by this user.
- */
-
- if (file_errno != 0)
- {
- int ret = file_errno;
-
- if (tTd(44, 4))
- printf("\t%s\n", errstring(ret));
-
- errno = 0;
- if (!bitset(SFF_CREAT, flags))
- return ret;
-
- /* check to see if legal to create the file */
- p = strrchr(fn, '/');
- if (p == NULL)
- return ENOTDIR;
- *p = '\0';
- if (stat(fn, &stbuf) >= 0)
- {
- int md = S_IWRITE|S_IEXEC;
- if (stbuf.st_uid != uid)
- md >>= 6;
- if ((stbuf.st_mode & md) != md)
- errno = EACCES;
- }
- ret = errno;
- if (tTd(44, 4))
- printf("\t[final dir %s uid %d mode %lo] %s\n",
- fn, (int) stbuf.st_uid, (u_long) stbuf.st_mode,
- errstring(ret));
- *p = '/';
- st->st_mode = ST_MODE_NOFILE;
- return ret;
- }
-
-#ifdef S_ISLNK
- if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode))
- {
- if (tTd(44, 4))
- printf("\t[slink mode %o]\tEPERM\n", st->st_mode);
- return EPERM;
- }
-#endif
- if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode))
- {
- if (tTd(44, 4))
- printf("\t[non-reg mode %o]\tEPERM\n", st->st_mode);
- return EPERM;
- }
- if (bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) &&
- bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode))
- {
- if (tTd(44, 4))
- printf("\t[exec bits %o]\tEPERM]\n", st->st_mode);
- return EPERM;
- }
- if (st->st_nlink > 1)
- {
- if (tTd(44, 4))
- printf("\t[link count %d]\tEPERM\n", st->st_nlink);
- return EPERM;
- }
-
- if (uid == 0 && bitset(SFF_OPENASROOT, flags))
- ;
- else if (uid == 0 && !bitset(SFF_ROOTOK, flags))
- mode >>= 6;
- else if (st->st_uid != uid)
- {
- mode >>= 3;
- if (st->st_gid == gid)
- ;
-#ifndef NO_GROUP_SET
- else if (uname != NULL && !DontInitGroups &&
- ((gr != NULL && gr->gr_gid == st->st_gid) ||
- (gr = getgrgid(st->st_gid)) != NULL))
- {
- register char **gp;
-
- for (gp = gr->gr_mem; *gp != NULL; gp++)
- if (strcmp(*gp, uname) == 0)
- break;
- if (*gp == NULL)
- mode >>= 3;
- }
-#endif
- else
- mode >>= 3;
- }
- if (tTd(44, 4))
- printf("\t[uid %d, nlink %d, stat %lo, mode %lo] ",
- (int) st->st_uid, (int) st->st_nlink,
- (u_long) st->st_mode, (u_long) mode);
- if ((st->st_uid == uid || st->st_uid == 0 ||
- !bitset(SFF_MUSTOWN, flags)) &&
- (st->st_mode & mode) == mode)
- {
- if (tTd(44, 4))
- printf("\tOK\n");
- return 0;
- }
- if (tTd(44, 4))
- printf("\tEACCES\n");
- return EACCES;
-}
- /*
-** SAFEFOPEN -- do a file open with extra checking
-**
-** Parameters:
-** fn -- the file name to open.
-** omode -- the open-style mode flags.
-** cmode -- the create-style mode flags.
-** sff -- safefile flags.
-**
-** Returns:
-** Same as fopen.
-*/
-
-#ifndef O_ACCMODE
-# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
-#endif
-
-FILE *
-safefopen(fn, omode, cmode, sff)
- char *fn;
- int omode;
- int cmode;
- int sff;
-{
- int rval;
- FILE *fp;
- int smode;
- struct stat stb, sta;
-
- if (bitset(O_CREAT, omode))
- sff |= SFF_CREAT;
- smode = 0;
- switch (omode & O_ACCMODE)
- {
- case O_RDONLY:
- smode = S_IREAD;
- break;
-
- case O_WRONLY:
- smode = S_IWRITE;
- break;
-
- case O_RDWR:
- smode = S_IREAD|S_IWRITE;
- break;
-
- default:
- smode = 0;
- break;
- }
- if (bitset(SFF_OPENASROOT, sff))
- rval = safefile(fn, 0, 0, NULL, sff, smode, &stb);
- else
- rval = safefile(fn, RealUid, RealGid, RealUserName,
- sff, smode, &stb);
- if (rval != 0)
- {
- errno = rval;
- return NULL;
- }
- if (stb.st_mode == ST_MODE_NOFILE)
- omode |= O_EXCL;
-
- fp = dfopen(fn, omode, cmode);
- if (fp == NULL)
- return NULL;
- if (bitset(O_EXCL, omode))
- return fp;
- if (fstat(fileno(fp), &sta) < 0 ||
- sta.st_nlink != stb.st_nlink ||
- sta.st_dev != stb.st_dev ||
- sta.st_ino != stb.st_ino ||
- sta.st_uid != stb.st_uid ||
- sta.st_gid != stb.st_gid)
- {
- syserr("554 cannot open: file %s changed after open", fn);
- fclose(fp);
- errno = EPERM;
- return NULL;
- }
- return fp;
-}
- /*
** FIXCRLF -- fix <CR><LF> in line.
**
** Looks for the <CR><LF> combination and turns it into the
@@ -830,80 +484,6 @@ fixcrlf(line, stripnl)
*p = '\0';
}
/*
-** DFOPEN -- determined file open
-**
-** This routine has the semantics of fopen, except that it will
-** keep trying a few times to make this happen. The idea is that
-** on very loaded systems, we may run out of resources (inodes,
-** whatever), so this tries to get around it.
-*/
-
-struct omodes
-{
- int mask;
- int mode;
- char *farg;
-} OpenModes[] =
-{
- { O_ACCMODE, O_RDONLY, "r" },
- { O_ACCMODE|O_APPEND, O_WRONLY, "w" },
- { O_ACCMODE|O_APPEND, O_WRONLY|O_APPEND, "a" },
- { O_TRUNC, 0, "w+" },
- { O_APPEND, O_APPEND, "a+" },
- { 0, 0, "r+" },
-};
-
-FILE *
-dfopen(filename, omode, cmode)
- char *filename;
- int omode;
- int cmode;
-{
- register int tries;
- int fd;
- register struct omodes *om;
- struct stat st;
-
- for (om = OpenModes; om->mask != 0; om++)
- if ((omode & om->mask) == om->mode)
- break;
-
- for (tries = 0; tries < 10; tries++)
- {
- sleep((unsigned) (10 * tries));
- errno = 0;
- fd = open(filename, omode, cmode);
- if (fd >= 0)
- break;
- switch (errno)
- {
- case ENFILE: /* system file table full */
- case EINTR: /* interrupted syscall */
-#ifdef ETXTBSY
- case ETXTBSY: /* Apollo: net file locked */
-#endif
- continue;
- }
- break;
- }
- if (fd >= 0 && fstat(fd, &st) >= 0 && S_ISREG(st.st_mode))
- {
- int locktype;
-
- /* lock the file to avoid accidental conflicts */
- if ((omode & O_ACCMODE) != O_RDONLY)
- locktype = LOCK_EX;
- else
- locktype = LOCK_SH;
- (void) lockfile(fd, filename, NULL, locktype);
- errno = 0;
- }
- if (fd < 0)
- return NULL;
- else
- return fdopen(fd, om->farg);
-}
- /*
** PUTLINE -- put a line like fputs obeying SMTP conventions
**
** This routine always guarantees outputing a newline (or CRLF,
@@ -925,7 +505,7 @@ putline(l, mci)
register char *l;
register MCI *mci;
{
- putxline(l, mci, PXLF_MAPFROM);
+ putxline(l, strlen(l), mci, PXLF_MAPFROM);
}
/*
** PUTXLINE -- putline with flags bits.
@@ -935,6 +515,7 @@ putline(l, mci)
**
** Parameters:
** l -- line to put.
+** len -- the length of the line.
** mci -- the mailer connection information.
** pxflags -- flag bits:
** PXLF_MAPFROM -- map From_ to >From_.
@@ -948,12 +529,13 @@ putline(l, mci)
*/
void
-putxline(l, mci, pxflags)
+putxline(l, len, mci, pxflags)
register char *l;
+ size_t len;
register MCI *mci;
int pxflags;
{
- register char *p;
+ register char *p, *end;
register char svchar;
int slop = 0;
@@ -966,12 +548,13 @@ putxline(l, mci, pxflags)
*p = svchar &~ 0200;
}
+ end = l + len;
do
{
/* find the end of the line */
- p = strchr(l, '\n');
+ p = memchr(l, '\n', end - l);
if (p == NULL)
- p = &l[strlen(l)];
+ p = end;
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%05d >>> ", (int) getpid());
@@ -1005,8 +588,12 @@ putxline(l, mci, pxflags)
fputs(mci->mci_mailer->m_eol, mci->mci_out);
(void) putc(' ', mci->mci_out);
if (TrafficLogFile != NULL)
- fprintf(TrafficLogFile, "%s!\n%05d >>> ",
- l, (int) getpid());
+ {
+ for ( ; l < q; ++l)
+ (void) putc(*l, TrafficLogFile);
+ fprintf(TrafficLogFile, "!\n%05d >>> ",
+ (int) getpid());
+ }
*q = svchar;
l = q;
slop = 1;
@@ -1029,10 +616,14 @@ putxline(l, mci, pxflags)
if (TrafficLogFile != NULL)
(void) putc('>', TrafficLogFile);
}
- if (TrafficLogFile != NULL)
- fprintf(TrafficLogFile, "%.*s\n", p - l, l);
for ( ; l < p; ++l)
+ {
+ if (TrafficLogFile != NULL)
+ (void) putc(*l, TrafficLogFile);
(void) putc(*l, mci->mci_out);
+ }
+ if (TrafficLogFile != NULL)
+ (void) putc('\n', TrafficLogFile);
fputs(mci->mci_mailer->m_eol, mci->mci_out);
if (*l == '\n')
{
@@ -1043,7 +634,7 @@ putxline(l, mci, pxflags)
(void) putc(' ', TrafficLogFile);
}
}
- } while (l[0] != '\0');
+ } while (l < end);
}
/*
** XUNLINK -- unlink a file, doing logging as appropriate.
@@ -1064,16 +655,16 @@ xunlink(f)
{
register int i;
-# ifdef LOG
if (LogLevel > 98)
- syslog(LOG_DEBUG, "%s: unlink %s", CurEnv->e_id, f);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "unlink %s",
+ f);
i = unlink(f);
-# ifdef LOG
if (i < 0 && LogLevel > 97)
- syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "%s: unlink-fail %d",
+ f, errno);
}
/*
** XFCLOSE -- close a file, doing logging as appropriate.
@@ -1147,20 +738,19 @@ sfgets(buf, siz, fp, timeout, during)
{
if (setjmp(CtxReadTimeout) != 0)
{
-# ifdef LOG
if (LogLevel > 1)
- syslog(LOG_NOTICE,
+ sm_syslog(LOG_NOTICE, CurEnv->e_id,
"timeout waiting for input from %.100s during %s",
CurHostName ? CurHostName : "local",
during);
-# endif
errno = 0;
- usrerr("451 timeout waiting for input during %s",
- during);
buf[0] = '\0';
#if XDEBUG
checkfd012(during);
#endif
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%05d <<< [TIMEOUT]\n",
+ (int) getpid());
return (NULL);
}
ev = setevent(timeout, readtimeout, 0);
@@ -1365,46 +955,6 @@ atooct(s)
return (i);
}
/*
-** WAITFOR -- wait for a particular process id.
-**
-** Parameters:
-** pid -- process id to wait for.
-**
-** Returns:
-** status of pid.
-** -1 if pid never shows up.
-**
-** Side Effects:
-** none.
-*/
-
-int
-waitfor(pid)
- pid_t pid;
-{
-#ifdef WAITUNION
- union wait st;
-#else
- auto int st;
-#endif
- pid_t i;
-
- do
- {
- errno = 0;
- i = wait(&st);
- if (i > 0)
- proc_list_drop(i);
- } while ((i >= 0 || errno == EINTR) && i != pid);
- if (i < 0)
- return -1;
-#ifdef WAITUNION
- return st.w_status;
-#else
- return st;
-#endif
-}
- /*
** BITINTERSECT -- tell if two bitmaps intersect
**
** Parameters:
@@ -1606,7 +1156,9 @@ checkfds(where)
continue;
if (printhdr)
{
- syslog(LOG_DEBUG, "%s: changed fds:", where);
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "%s: changed fds:",
+ where);
printhdr = FALSE;
}
dumpfd(fd, TRUE, TRUE);
@@ -1772,11 +1324,10 @@ defprint:
}
printit:
-#ifdef LOG
if (logit)
- syslog(LOG_DEBUG, "%.800s", buf);
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "%.800s", buf);
else
-#endif
printf("%s\n", buf);
}
/*
@@ -2084,10 +1635,8 @@ cleanstrcpy(t, f, l)
register char *f;
int l;
{
-#ifdef LOG
/* check for newlines and log if necessary */
(void) denlstring(f, TRUE, TRUE);
-#endif
l--;
while (l > 0 && *f != '\0')
@@ -2146,20 +1695,23 @@ denlstring(s, strict, logattacks)
for (p = bp; (p = strchr(p, '\n')) != NULL; )
*p++ = ' ';
-#ifdef LOG
if (logattacks)
{
- syslog(LOG_NOTICE, "POSSIBLE ATTACK from %.100s: newline in string \"%s\"",
+ sm_syslog(LOG_NOTICE, CurEnv->e_id,
+ "POSSIBLE ATTACK from %.100s: newline in string \"%s\"",
RealHostName == NULL ? "[UNKNOWN]" : RealHostName,
shortenstring(bp, 203));
}
-#endif
return bp;
}
/*
** PATH_IS_DIR -- check to see if file exists and is a directory.
**
+** There are some additional checks for security violations in
+** here. This routine is intended to be used for the host status
+** support.
+**
** Parameters:
** pathname -- pathname to check for directory-ness.
** createflag -- if set, create directory if needed.
@@ -2176,7 +1728,11 @@ path_is_dir(pathname, createflag)
{
struct stat statbuf;
+#if HASLSTAT
+ if (lstat(pathname, &statbuf) < 0)
+#else
if (stat(pathname, &statbuf) < 0)
+#endif
{
if (errno != ENOENT || !createflag)
return FALSE;
@@ -2189,6 +1745,14 @@ path_is_dir(pathname, createflag)
errno = ENOTDIR;
return FALSE;
}
+
+ /* security: don't allow writable directories */
+ if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode))
+ {
+ errno = EACCES;
+ return FALSE;
+ }
+
return TRUE;
}
/*
@@ -2320,11 +1884,10 @@ proc_list_probe()
continue;
if (kill(ProcListVec[i], 0) < 0)
{
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_DEBUG, "proc_list_probe: lost pid %d",
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "proc_list_probe: lost pid %d",
ProcListVec[i]);
-#endif
ProcListVec[i] = NO_PID;
CurChildren--;
}
@@ -2332,3 +1895,119 @@ proc_list_probe()
if (CurChildren < 0)
CurChildren = 0;
}
+ /*
+** SM_STRCASECMP -- 8-bit clean version of strcasecmp
+**
+** Thank you, vendors, for making this all necessary.
+*/
+
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison. The mappings are
+ * based upon ascii character sequences.
+ */
+static const u_char charmap[] = {
+ 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
+ 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
+ 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
+ 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
+ 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
+ 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
+ 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
+ 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
+ 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
+ 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
+ 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
+ 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
+ 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
+ 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
+};
+
+int
+sm_strcasecmp(s1, s2)
+ const char *s1, *s2;
+{
+ register const u_char *cm = charmap,
+ *us1 = (const u_char *)s1,
+ *us2 = (const u_char *)s2;
+
+ while (cm[*us1] == cm[*us2++])
+ if (*us1++ == '\0')
+ return (0);
+ return (cm[*us1] - cm[*--us2]);
+}
+
+int
+sm_strncasecmp(s1, s2, n)
+ const char *s1, *s2;
+ register size_t n;
+{
+ if (n != 0) {
+ register const u_char *cm = charmap,
+ *us1 = (const u_char *)s1,
+ *us2 = (const u_char *)s2;
+
+ do {
+ if (cm[*us1] != cm[*us2++])
+ return (cm[*us1] - cm[*--us2]);
+ if (*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+ return (0);
+}
OpenPOWER on IntegriCloud