summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src')
-rw-r--r--usr.sbin/sendmail/src/Makefile8
-rw-r--r--usr.sbin/sendmail/src/READ_ME71
-rw-r--r--usr.sbin/sendmail/src/TRACEFLAGS3
-rw-r--r--usr.sbin/sendmail/src/alias.c50
-rw-r--r--usr.sbin/sendmail/src/aliases.5107
-rw-r--r--usr.sbin/sendmail/src/arpadate.c4
-rw-r--r--usr.sbin/sendmail/src/clock.c47
-rw-r--r--usr.sbin/sendmail/src/collect.c39
-rw-r--r--usr.sbin/sendmail/src/conf.c839
-rw-r--r--usr.sbin/sendmail/src/conf.h141
-rw-r--r--usr.sbin/sendmail/src/convtime.c4
-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/envelope.c39
-rw-r--r--usr.sbin/sendmail/src/err.c91
-rw-r--r--usr.sbin/sendmail/src/headers.c155
-rw-r--r--usr.sbin/sendmail/src/ldap_map.h6
-rw-r--r--usr.sbin/sendmail/src/macro.c4
-rw-r--r--usr.sbin/sendmail/src/mailq.189
-rw-r--r--usr.sbin/sendmail/src/main.c193
-rw-r--r--usr.sbin/sendmail/src/makesendmail15
-rw-r--r--usr.sbin/sendmail/src/map.c361
-rw-r--r--usr.sbin/sendmail/src/mci.c54
-rw-r--r--usr.sbin/sendmail/src/mime.c36
-rw-r--r--usr.sbin/sendmail/src/newaliases.169
-rw-r--r--usr.sbin/sendmail/src/parseaddr.c64
-rw-r--r--usr.sbin/sendmail/src/queue.c242
-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/safefile.c686
-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/sendmail.hf4
-rw-r--r--usr.sbin/sendmail/src/srvrsmtp.c139
-rw-r--r--usr.sbin/sendmail/src/stab.c29
-rw-r--r--usr.sbin/sendmail/src/stats.c7
-rw-r--r--usr.sbin/sendmail/src/sysexits.c4
-rw-r--r--usr.sbin/sendmail/src/trace.c4
-rw-r--r--usr.sbin/sendmail/src/udb.c54
-rw-r--r--usr.sbin/sendmail/src/useful.h6
-rw-r--r--usr.sbin/sendmail/src/usersmtp.c79
-rw-r--r--usr.sbin/sendmail/src/util.c669
-rw-r--r--usr.sbin/sendmail/src/version.c4
45 files changed, 3469 insertions, 1706 deletions
diff --git a/usr.sbin/sendmail/src/Makefile b/usr.sbin/sendmail/src/Makefile
index 57a7df0b3911e..0be76ad3ac7a7 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 #
@@ -21,9 +21,9 @@ CFLAGS+=-I${.CURDIR} ${DBMDEF} -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=
LDADD=
MAN1= mailq.0 newaliases.0
diff --git a/usr.sbin/sendmail/src/READ_ME b/usr.sbin/sendmail/src/READ_ME
index 88fa68a33c76a..8046d41ac2999 100644
--- a/usr.sbin/sendmail/src/READ_ME
+++ b/usr.sbin/sendmail/src/READ_ME
@@ -1,4 +1,4 @@
-# Copyright (c) 1983, 1995, 1996 Eric P. Allman
+# Copyright (c) 1983, 1995-1997 Eric P. Allman
# Copyright (c) 1988 The Regents of the University of California.
# All rights reserved.
#
@@ -30,7 +30,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# @(#)READ_ME 8.135 (Berkeley) 1/21/97
+# @(#)READ_ME 8.142 (Berkeley) 6/3/97
#
This directory contains the source files for sendmail.
@@ -149,7 +149,7 @@ The options are:
NEWDB The new Berkeley DB package. Some systems (e.g., BSD/OS and
Digital UNIX 4.0) have this package pre-installed. If your
system does not have NEWDB installed, get the latest version
- from FTP.CS.Berkeley.EDU in /ucb/4bsd/db.tar.gz (or db.tar.Z).
+ from FTP://ftp.sleepycat.com/db/packages/db.1.85.tar.gz.
DO NOT use the version from the Net2 distribution. If you are
still running BSD/386 1.x, you will also need to define
OLD_NEWDB.
@@ -273,14 +273,14 @@ HASSETREUID Define this if you have setreuid(2) ***AND*** root can
security, since sendmail doesn't have to read .forward
and :include: files as root. There are certain attacks
that may be unpreventable without this call.
-USESETEUID Define this to 1 if you have seteuid(2) if you have a seteuid
- system call that will allow root to set only the effective
- user id to an arbitrary value ***AND*** you have saved user
- ids. This is preferable to HASSETREUID if these conditions
- are fulfilled. These are the semantics of the to-be-released
- revision of Posix.1. The test program ../test/t_seteuid.c
- will try this out on your system. If you define both
- HASSETREUID and USESETEUID, the former is ignored.
+USESETEUID Define this to 1 if you have a seteuid(2) system call that
+ will allow root to set only the effective user id to an
+ arbitrary value ***AND*** you have saved user ids. This is
+ preferable to HASSETREUID if these conditions are fulfilled.
+ These are the semantics of the to-be-released revision of
+ Posix.1. The test program ../test/t_seteuid.c will try
+ this out on your system. If you define both HASSETREUID
+ and USESETEUID, the former is ignored.
HASLSTAT Define this if you have symbolic links (and thus the
lstat(2) system call). This improves security. Unlike
most other options, this one is on by default, so you
@@ -295,6 +295,9 @@ HASULIMIT Define this if you have the ulimit(2) syscall (System V
HASWAITPID Define this if you have the waitpid(2) syscall.
HASGETDTABLESIZE
Define this if you have the getdtablesize(2) syscall.
+USESTRERROR Define this if you have the libc strerror function (which
+ should be declared in <errno.h>), and it should be used
+ instead of sys_errlist.
NEEDGETOPT Define this if you need a reimplementation of getopt(3).
On some systems, getopt does very odd things if called
to scan the arguments twice. This flag will ask sendmail
@@ -396,7 +399,7 @@ SFS_TYPE Encodes how your kernel can locate the amount of free
<sys/vfs.h>, <sys/mount.h>, or <sys/statfs.h> respectively,
or SFS_STATVFS (6) if you have the two-argument statvfs(2)
call. The default if nothing is defined is SFS_NONE.
-SFS_BAVAIL with SFS_4ARGS hou can also set SFS_BAVAIL to the field name
+SFS_BAVAIL with SFS_4ARGS you can also set SFS_BAVAIL to the field name
in the statfs structure that holds the useful information;
this defaults to f_bavail.
SPT_TYPE Encodes how your system can display what a process is doing
@@ -409,6 +412,10 @@ SPT_TYPE Encodes how your system can display what a process is doing
SPT_PSTAT (3) -- Use the PSTAT_SETCMD option to pstat(2)
to set the process title; this is used by HP-UX.
SPT_PSSTRINGS (4) -- Use the magic PS_STRINGS pointer (4.4BSD).
+ SPT_SYSMIPS (5) -- Use sysmips() supported by NEWS-OS 6.
+ SPT_SCO (6) -- Write kernel u. area.
+ SPT_CHANGEARGV (7) -- Write pointers to our own strings into
+ the existing argv vector.
SPT_PADCHAR Character used to pad the process title; if undefined,
the space character (0x20) is used. This is ignored if
SPT_TYPE != SPT_REUSEARGV
@@ -441,6 +448,15 @@ NAMELISTMASK If defined, values returned by nlist(3) are masked
0x7fffffff to strip off the top bit.
BSD4_4_SOCKADDR If defined, socket addresses have an sa_len field that
defines the length of this address.
+SAFENFSPATHCONF Set this to 1 if and only if you have verified that a
+ pathconf(2) call with _PC_CHOWN_RESTRICTED argument on an
+ NFS filesystem where the underlying system allows users to
+ give away files to other users returns <= 0. Be sure you
+ try both on NFS V2 and V3. Some systems assume that their
+ local policy apply to NFS servers -- this is a bad
+ assumption! The test/t_pathconf.c program will try this
+ for you -- you have to run it in a directory that is
+ mounted from a server that allows file giveaway.
@@ -521,8 +537,7 @@ MATCHGECOS Permit fuzzy matching of user names against the full
MIME8TO7 If non-zero, include 8 to 7 bit MIME conversions. This
also controls advertisement of 8BITMIME in the ESMTP
startup dialogue.
-MIME7TO8 If non-zero, include 7 to 8 bit MIME conversions. Not yet
- implemented.
+MIME7TO8 If non-zero, include 7 to 8 bit MIME conversions.
HES_GETMAILHOST Define this to 1 if you are using Hesiod with the
hes_getmailhost() routine. This is included with the MIT
Hesiod distribution, but not with the DEC Hesiod distribution.
@@ -791,13 +806,6 @@ Solaris 2.6 (SunOS 5.6)
incompatible snprintf(3s) calls. This problem is fixed in sendmail
8.8.5.
-Ultrix
- By default, the IDENT protocol is turned off on Ultrix. If you
- are running Ultrix 4.4 or later, or if you have included patch
- CXO-8919 for Ultrix 4.2 or 4.3 to fix the TCP problem, you can turn
- IDENT on in the configuration file by setting the "ident" timeout
- to 30 seconds.
-
Solaris 2.5.1 (SunOS 5.5.1)
Apparently patch 103663-01 installs a new /usr/include/resolv.h
file that defines the __P macro without checking to see if it is
@@ -815,6 +823,13 @@ Solaris 2.5.1 (SunOS 5.5.1)
... And then file a bug report with Sun.
+Ultrix
+ By default, the IDENT protocol is turned off on Ultrix. If you
+ are running Ultrix 4.4 or later, or if you have included patch
+ CXO-8919 for Ultrix 4.2 or 4.3 to fix the TCP problem, you can turn
+ IDENT on in the configuration file by setting the "ident" timeout
+ to 30 seconds.
+
OSF/1
If you are compiling on OSF/1 (DEC Alpha), you must use
-L/usr/shlib (otherwise it core dumps on startup). You may also
@@ -1279,15 +1294,6 @@ LDAP
It requires the ldap and lber libraries from the Umich Ldap3.2
release.
- - KNOWN BUGS: It does not work under Digital Unix 3.2c, with gcc and
- ldap3.2 or ldap3.3. It dumps core after attempting to take strlen
- of a garbage string pointer in the lber libraries routine
- ber_printf.
-
- The string pointer in question is set to 0x50000000, when the
- program crashes. If anyone recognizes where this magic number comes
- from that would be really helpful.
-
I've tested the software on Solaris.2.4 with gcc and on NeXTStep3.2
and it runs without problems. If you have any questions, please
send them along.
@@ -1384,11 +1390,14 @@ main.c The main routine to sendmail. This file also
contains some miscellaneous routines.
map.c Support for database maps.
mci.c Routines that handle mail connection information caching.
+mime.c MIME conversion routines.
parseaddr.c The routines which do address parsing.
queue.c Routines to implement message queueing.
readcf.c The routine that reads the configuration file and
translates it to internal form.
recipient.c Routines that manipulate the recipient list.
+safefile.c Routines to do careful checking of file modes and permissions
+ when opening or creating files.
savemail.c Routines which save the letter on processing errors.
sendmail.h Main header file for sendmail.
srvrsmtp.c Routines to implement server SMTP.
@@ -1407,4 +1416,4 @@ version.c The version number and information about this
Eric Allman
-(Version 8.135, last update 1/21/97 07:47:02)
+(Version 8.142, last update 6/3/97 11:34:09)
diff --git a/usr.sbin/sendmail/src/TRACEFLAGS b/usr.sbin/sendmail/src/TRACEFLAGS
index a5b25656e76a6..e9d4818356fdd 100644
--- a/usr.sbin/sendmail/src/TRACEFLAGS
+++ b/usr.sbin/sendmail/src/TRACEFLAGS
@@ -52,7 +52,7 @@
42 mci.c mci_get
43 mime.c mime8to7
44 recipient.c writeable
-44 util.c safefile
+44 safefile.c safefile, safedirpath, filechanged
45 envelope.c setsender
46 envelope.c openxscript
49 conf.c checkcompat
@@ -70,4 +70,5 @@
80 content length
81 sun remote mode
91 mci.c syslogging of MCI cache information
+94 srvrsmtp.c cause commands to fail (for protocol testing)
99 main.c avoid backgrounding (no printed output)
diff --git a/usr.sbin/sendmail/src/alias.c b/usr.sbin/sendmail/src/alias.c
index b09a85db5dcec..cebd805c1a682 100644
--- a/usr.sbin/sendmail/src/alias.c
+++ b/usr.sbin/sendmail/src/alias.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.
*
@@ -35,7 +35,7 @@
# include "sendmail.h"
#ifndef lint
-static char sccsid[] = "@(#)alias.c 8.67 (Berkeley) 1/18/97";
+static char sccsid[] = "@(#)alias.c 8.73 (Berkeley) 5/8/97";
#endif /* not lint */
@@ -74,7 +74,6 @@ alias(a, sendq, aliaslevel, e)
register ENVELOPE *e;
{
register char *p;
- int naliases;
char *owner;
auto int stat = EX_OK;
char obuf[MAXNAME + 7];
@@ -125,12 +124,10 @@ alias(a, sendq, aliaslevel, e)
return;
}
message("aliased to %s", shortenstring(p, 203));
-#ifdef LOG
if (LogLevel > 9)
- syslog(LOG_INFO, "%s: alias %.100s => %s",
- e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ sm_syslog(LOG_INFO, e->e_id,
+ "alias %.100s => %s",
a->q_paddr, shortenstring(p, 203));
-#endif
a->q_flags &= ~QSELFREF;
if (tTd(27, 5))
{
@@ -138,7 +135,7 @@ alias(a, sendq, aliaslevel, e)
printaddr(a, FALSE);
}
a->q_flags |= QDONTSEND;
- naliases = sendtolist(p, a, sendq, aliaslevel + 1, e);
+ (void) sendtolist(p, a, sendq, aliaslevel + 1, e);
if (bitset(QSELFREF, a->q_flags))
a->q_flags &= ~QDONTSEND;
@@ -279,7 +276,7 @@ setalias(spec)
else
{
class = "implicit";
- map->map_mflags = MF_OPTIONAL|MF_INCLNULL;
+ map->map_mflags = MF_INCLNULL;
}
/* find end of spec */
@@ -423,11 +420,10 @@ aliaswait(map, ext, isopen)
}
else
{
-#ifdef LOG
if (LogLevel > 3)
- syslog(LOG_INFO, "alias database %s out of date",
+ sm_syslog(LOG_INFO, NOQID,
+ "alias database %s out of date",
buf);
-#endif /* LOG */
message("Warning: alias database %s out of date", buf);
}
}
@@ -456,6 +452,7 @@ rebuildaliases(map, automatic)
{
FILE *af;
bool nolock = FALSE;
+ int sff = SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK|SFF_NOWLINK|SFF_NOWFILES;
sigfunc_t oldsigint, oldsigquit;
#ifdef SIGTSTP
sigfunc_t oldsigtstp;
@@ -465,12 +462,12 @@ rebuildaliases(map, automatic)
return;
/* try to lock the source file */
- if ((af = fopen(map->map_file, "r+")) == NULL)
+ if ((af = safefopen(map->map_file, O_RDWR, 0, sff)) == NULL)
{
struct stat stb;
if ((errno != EACCES && errno != EROFS) || automatic ||
- (af = fopen(map->map_file, "r")) == NULL)
+ (af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL)
{
int saveerr = errno;
@@ -517,14 +514,13 @@ rebuildaliases(map, automatic)
if (map->map_class->map_open(map, O_RDWR))
{
-#ifdef LOG
if (LogLevel > 7)
{
- syslog(LOG_NOTICE, "alias database %s %srebuilt by %s",
+ sm_syslog(LOG_NOTICE, NOQID,
+ "alias database %s %srebuilt by %s",
map->map_file, automatic ? "auto" : "",
username());
}
-#endif /* LOG */
map->map_mflags |= MF_OPEN|MF_WRITABLE;
readaliases(map, af, !automatic, TRUE);
}
@@ -605,6 +601,15 @@ readaliases(map, af, announcestats, logstats)
LineNumber++;
p = strchr(line, '\n');
+#if _FFR_BACKSLASH_IN_ALIASES
+ while (p != NULL && p > line && p[-1] == '\\')
+ {
+ p--;
+ if (fgets(p, SPACELEFT(line, p), af) == NULL)
+ break;
+ p = strchr(p, '\n');
+ }
+#endif
if (p != NULL)
*p = '\0';
else if (!feof(af))
@@ -762,11 +767,10 @@ readaliases(map, af, announcestats, logstats)
if (Verbose || announcestats)
message("%s: %d aliases, longest %d bytes, %d bytes total",
map->map_file, naliases, longest, bytes);
-# ifdef LOG
if (LogLevel > 7 && logstats)
- syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total",
+ sm_syslog(LOG_INFO, NOQID,
+ "%s: %d aliases, longest %d bytes, %d bytes total",
map->map_file, naliases, longest, bytes);
-# endif /* LOG */
}
/*
** FORWARD -- Try to forward mail
@@ -846,12 +850,10 @@ forward(user, sendq, aliaslevel, e)
got_transient = TRUE;
if (tTd(27, 2))
printf("forward: transient error on %s\n", buf);
-#ifdef LOG
if (LogLevel > 2)
- syslog(LOG_ERR, "%s: forward %s: transient error: %s",
- e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ sm_syslog(LOG_ERR, e->e_id,
+ "forward %s: transient error: %s",
buf, errstring(err));
-#endif
}
}
if (pp == NULL && got_transient)
diff --git a/usr.sbin/sendmail/src/aliases.5 b/usr.sbin/sendmail/src/aliases.5
new file mode 100644
index 0000000000000..351946750f66a
--- /dev/null
+++ b/usr.sbin/sendmail/src/aliases.5
@@ -0,0 +1,107 @@
+.\" Copyright (c) 1983, 1997 Eric P. Allman
+.\" Copyright (c) 1985, 1991, 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.
+.\"
+.\" @(#)aliases.5 8.3 (Berkeley) 2/1/97
+.\"
+.Dd February 1, 1997
+.Dt ALIASES 5
+.Os BSD 4
+.Sh NAME
+.Nm aliases
+.Nd aliases file for sendmail
+.Sh SYNOPSIS
+.Nm aliases
+.Sh DESCRIPTION
+This file describes user
+.Tn ID
+aliases used by
+.Pa /usr/sbin/sendmail .
+The file resides in
+.Pa /etc
+and
+is formatted as a series of lines of the form
+.Bd -filled -offset indent
+name: name_1, name2, name_3, . . .
+.Ed
+.Pp
+The
+.Em name
+is the name to alias, and the
+.Em name_n
+are the aliases for that name.
+Lines beginning with white space are continuation lines.
+Lines beginning with
+.Ql #
+are comments.
+.Pp
+Aliasing occurs only on local names.
+Loops can not occur, since no message will be sent to any person more than once.
+.Pp
+After aliasing has been done, local and valid recipients who have a
+.Dq Pa .forward
+file in their home directory have messages forwarded to the
+list of users defined in that file.
+.Pp
+This is only the raw data file; the actual aliasing information is
+placed into a binary format in the file
+.Pa /etc/aliases.db
+using the program
+.Xr newaliases 1 .
+A
+.Xr newaliases
+command should be executed each time the aliases file is changed for the
+change to take effect.
+.Sh SEE ALSO
+.Xr newaliases 1 ,
+.Xr dbopen 3 ,
+.Xr dbm 3 ,
+.Xr sendmail 8
+.Rs
+.%T "SENDMAIL Installation and Operation Guide"
+.Re
+.Rs
+.%T "SENDMAIL An Internetwork Mail Router"
+.Re
+.Sh BUGS
+If you have compiled
+.Xr sendmail
+with DBM support instead of NEWDB,
+you may have encountered problems in
+.Xr dbm 3
+restricting a single alias to about 1000 bytes of information.
+You can get longer aliases by ``chaining''; that is, make the last name in
+the alias be a dummy name which is a continuation alias.
+.Sh HISTORY
+The
+.Nm
+file format appeared in
+.Bx 4.0 .
diff --git a/usr.sbin/sendmail/src/arpadate.c b/usr.sbin/sendmail/src/arpadate.c
index 418fd262e5557..f289020424adb 100644
--- a/usr.sbin/sendmail/src/arpadate.c
+++ b/usr.sbin/sendmail/src/arpadate.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[] = "@(#)arpadate.c 8.6 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)arpadate.c 8.7 (Berkeley) 2/1/97";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/clock.c b/usr.sbin/sendmail/src/clock.c
index 5639f44051794..6940b297894e1 100644
--- a/usr.sbin/sendmail/src/clock.c
+++ b/usr.sbin/sendmail/src/clock.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[] = "@(#)clock.c 8.18 (Berkeley) 12/31/96";
+static char sccsid[] = "@(#)clock.c 8.24 (Berkeley) 4/19/97";
#endif /* not lint */
# include "sendmail.h"
@@ -60,7 +60,9 @@ static char sccsid[] = "@(#)clock.c 8.18 (Berkeley) 12/31/96";
** none.
*/
-static SIGFUNC_DECL tick __P((int));
+EVENT *FreeEventList; /* list of free events */
+
+static SIGFUNC_DECL tick __P((int));
EVENT *
setevent(intvl, func, arg)
@@ -71,6 +73,7 @@ setevent(intvl, func, arg)
register EVENT **evp;
register EVENT *ev;
auto time_t now;
+ int wasblocked;
if (intvl <= 0)
{
@@ -78,7 +81,7 @@ setevent(intvl, func, arg)
return (NULL);
}
- (void) setsignal(SIGALRM, SIG_IGN);
+ wasblocked = blocksignal(SIGALRM);
(void) time(&now);
/* search event queue for correct position */
@@ -89,7 +92,11 @@ setevent(intvl, func, arg)
}
/* insert new event */
- ev = (EVENT *) xalloc(sizeof *ev);
+ ev = FreeEventList;
+ if (ev == NULL)
+ ev = (EVENT *) xalloc(sizeof *ev);
+ else
+ FreeEventList = ev->ev_link;
ev->ev_time = now + intvl;
ev->ev_func = func;
ev->ev_arg = arg;
@@ -101,7 +108,11 @@ setevent(intvl, func, arg)
printf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n",
intvl, now + intvl, (u_long) func, arg, (u_long) ev);
- tick(0);
+ setsignal(SIGALRM, tick);
+ intvl = EventQueue->ev_time - now;
+ (void) alarm((unsigned) intvl < 1 ? 1 : intvl);
+ if (wasblocked == 0)
+ (void) releasesignal(SIGALRM);
return (ev);
}
/*
@@ -122,6 +133,7 @@ clrevent(ev)
register EVENT *ev;
{
register EVENT **evp;
+ int wasblocked;
if (tTd(5, 5))
printf("clrevent: ev=%lx\n", (u_long) ev);
@@ -129,7 +141,7 @@ clrevent(ev)
return;
/* find the parent event */
- (void) setsignal(SIGALRM, SIG_IGN);
+ wasblocked = blocksignal(SIGALRM);
for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
{
if (*evp == ev)
@@ -140,16 +152,22 @@ clrevent(ev)
if (*evp != NULL)
{
*evp = ev->ev_link;
- free((char *) ev);
+ ev->ev_link = FreeEventList;
+ FreeEventList = ev;
}
/* restore clocks and pick up anything spare */
- tick(0);
+ if (wasblocked == 0)
+ releasesignal(SIGALRM);
+ if (EventQueue != NULL)
+ kill(getpid(), SIGALRM);
}
/*
** TICK -- take a clock tick
**
** Called by the alarm clock. This routine runs events as needed.
+** Always called as a signal handler, so we assume that SIGALRM
+** has been blocked.
**
** Parameters:
** One that is ignored; for compatibility with signal handlers.
@@ -170,13 +188,14 @@ tick(arg)
int mypid = getpid();
int olderrno = errno;
- (void) setsignal(SIGALRM, SIG_IGN);
(void) alarm(0);
now = curtime();
if (tTd(5, 4))
printf("tick: now=%ld\n", now);
+ /* reset signal in case System V semantics */
+ (void) setsignal(SIGALRM, tick);
while ((ev = EventQueue) != NULL &&
(ev->ev_time <= now || ev->ev_pid != mypid))
{
@@ -196,7 +215,8 @@ tick(arg)
f = ev->ev_func;
arg = ev->ev_arg;
pid = ev->ev_pid;
- free((char *) ev);
+ ev->ev_link = FreeEventList;
+ FreeEventList = ev;
if (pid != getpid())
continue;
if (EventQueue != NULL)
@@ -207,17 +227,12 @@ tick(arg)
(void) alarm(3);
}
- /* restore signals so that we can take ticks while in ev_func */
- (void) setsignal(SIGALRM, tick);
- (void) releasesignal(SIGALRM);
-
/* call ev_func */
errno = olderrno;
(*f)(arg);
(void) alarm(0);
now = curtime();
}
- (void) setsignal(SIGALRM, tick);
if (EventQueue != NULL)
(void) alarm((unsigned) (EventQueue->ev_time - now));
errno = olderrno;
diff --git a/usr.sbin/sendmail/src/collect.c b/usr.sbin/sendmail/src/collect.c
index 660521cf8c710..219a47f7b8b0a 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;
{
@@ -94,7 +91,7 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
volatile bool ignrdot = smtpmode ? FALSE : IgnrDot;
volatile time_t dbto = smtpmode ? TimeOuts.to_datablock : 0;
register char *volatile bp;
- volatile int c = '\0';
+ volatile int c = EOF;
volatile bool inputerr = FALSE;
bool headeronly;
char *volatile buf;
@@ -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 e172a78c5cfa4..e9a5d250ee4c1 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,48 +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, 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;
-}
- /*
** SETUPMAILERS -- initialize default mailers
*/
@@ -368,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
@@ -1062,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;
@@ -1525,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));
}
@@ -1557,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);
}
@@ -1699,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)
{
@@ -1783,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
@@ -1913,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;
}
}
@@ -2036,16 +1994,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");
@@ -2059,7 +2020,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;
@@ -2083,6 +2044,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;
@@ -2105,24 +2067,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;
}
@@ -2130,11 +2090,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;
}
@@ -2147,11 +2106,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;
}
}
@@ -2180,6 +2138,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
@@ -2204,7 +2163,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
@@ -2253,7 +2212,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.
*/
@@ -2355,11 +2314,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:
@@ -2387,12 +2400,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);
@@ -2406,7 +2417,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
@@ -2880,12 +2898,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...
*
@@ -2897,10 +2913,12 @@ vsprintf(s, fmt, ap)
**************************************************************/
/*static char _id[] = "$Id: snprintf.c,v 1.2 1995/10/09 11:19:47 roberto Exp $";*/
-static void dopr();
-static char *end;
+static void sm_dopr();
+static char *DoprEnd;
static int SnprfOverflow;
+#if !HASSNPRINTF
+
/* VARARGS3 */
int
# ifdef __STDC__
@@ -2932,19 +2950,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));
@@ -2952,9 +2973,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;
@@ -2968,30 +2990,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 );
@@ -2999,64 +3026,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;
}
@@ -3069,7 +3110,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)
@@ -3078,13 +3119,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;
}
}
@@ -3101,50 +3142,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;
}
}
@@ -3166,20 +3207,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
**
@@ -3434,7 +3471,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;
@@ -3483,15 +3520,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;
}
}
@@ -3597,7 +3631,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;
}
@@ -3627,6 +3661,7 @@ lockfile(fd, filename, ext, type)
char *ext;
int type;
{
+ int i;
# if !HASFLOCK
int action;
struct flock lfd;
@@ -3651,7 +3686,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");
@@ -3697,7 +3734,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");
@@ -3728,53 +3767,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
@@ -3783,15 +3842,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
}
/*
@@ -4028,11 +4086,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
@@ -4385,7 +4442,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>
@@ -4398,19 +4455,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))
@@ -4435,7 +4511,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)
@@ -4456,12 +4531,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);
@@ -4484,18 +4559,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;
}
@@ -4520,7 +4598,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
}
/*
@@ -4553,7 +4790,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);
@@ -4613,7 +4850,7 @@ char *CompileOptions[] =
#if LDAPMAP
"LDAPMAP",
#endif
-#ifdef LOG
+#if LOG
"LOG",
#endif
#if MATCHGECOS
@@ -4695,6 +4932,9 @@ char *CompileOptions[] =
char *OsCompileOptions[] =
{
+#if BOGUS_O_EXCL
+ "BOGUS_O_EXCL",
+#endif
#if HASFCHMOD
"HASFCHMOD",
#endif
@@ -4731,6 +4971,9 @@ char *OsCompileOptions[] =
#if HASSNPRINTF
"HASSNPRINTF",
#endif
+#if HASSTRERROR
+ "HASSTRERROR",
+#endif
#if HASULIMIT
"HASULIMIT",
#endif
@@ -4758,12 +5001,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 595ed433e0a04..bf81bbfa3421a 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,10 +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
@@ -737,7 +755,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 */
@@ -761,6 +779,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
**
@@ -1066,6 +1128,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
@@ -1117,10 +1180,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
@@ -1829,7 +1894,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.
*/
@@ -1930,12 +1995,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
@@ -1957,6 +2031,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.
@@ -1966,7 +2047,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 */
@@ -1978,16 +2068,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
/*
@@ -2133,7 +2215,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
@@ -2182,3 +2264,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/convtime.c b/usr.sbin/sendmail/src/convtime.c
index 65994f88758a2..5ca1b39149e73 100644
--- a/usr.sbin/sendmail/src/convtime.c
+++ b/usr.sbin/sendmail/src/convtime.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[] = "@(#)convtime.c 8.8 (Berkeley) 11/24/96";
+static char sccsid[] = "@(#)convtime.c 8.9 (Berkeley) 2/1/97";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/daemon.c b/usr.sbin/sendmail/src/daemon.c
index bd8a9146de2eb..41f1a7286d777 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 97a1050552acf..c98c4bcbca981 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 92036518b4728..802ae6cbd33e8 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/envelope.c b/usr.sbin/sendmail/src/envelope.c
index c5e98f7e3f149..4dc07ae7fc339 100644
--- a/usr.sbin/sendmail/src/envelope.c
+++ b/usr.sbin/sendmail/src/envelope.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[] = "@(#)envelope.c 8.101 (Berkeley) 12/16/96";
+static char sccsid[] = "@(#)envelope.c 8.104 (Berkeley) 6/3/97";
#endif /* not lint */
#include "sendmail.h"
@@ -121,12 +121,10 @@ dropenvelope(e, fulldrop)
}
}
-#ifdef LOG
if (LogLevel > 84)
- syslog(LOG_DEBUG, "%s: dropenvelope, e_flags=0x%x, OpMode=%c, pid=%d",
- id == NULL ? "[NOQUEUE]" : id,
+ sm_syslog(LOG_DEBUG, id,
+ "dropenvelope, e_flags=0x%x, OpMode=%c, pid=%d",
e->e_flags, OpMode, getpid());
-#endif
/* we must have an id to remove disk files */
if (id == NULL)
@@ -168,8 +166,9 @@ dropenvelope(e, fulldrop)
queueit = TRUE;
#if XDEBUG
else if (bitset(QQUEUEUP, q->q_flags))
- syslog(LOG_DEBUG, "dropenvelope: %s: q_flags = %x, paddr = %s",
- e->e_id, q->q_flags, q->q_paddr);
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "dropenvelope: q_flags = %x, paddr = %s",
+ q->q_flags, q->q_paddr);
#endif
/* see if a notification is needed */
@@ -296,6 +295,8 @@ dropenvelope(e, fulldrop)
{
auto ADDRESS *rlist = NULL;
+ if (tTd(50, 8))
+ printf("dropenvelope(%s): sending return receipt\n", id);
e->e_flags |= EF_SENDRECEIPT;
(void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
(void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
@@ -310,6 +311,8 @@ dropenvelope(e, fulldrop)
{
extern void savemail __P((ENVELOPE *, bool));
+ if (tTd(50, 8))
+ printf("dropenvelope(%s): saving mail\n", id);
savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
}
@@ -323,6 +326,8 @@ dropenvelope(e, fulldrop)
{
auto ADDRESS *rlist = NULL;
+ if (tTd(50, 8))
+ printf("dropenvelope(%s): sending postmaster copy\n", id);
(void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e);
(void) returntosender(e->e_message, rlist, RTSF_PM_BOUNCE, e);
}
@@ -332,6 +337,9 @@ dropenvelope(e, fulldrop)
*/
simpledrop:
+ if (tTd(50, 8))
+ printf("dropenvelope(%s): at simpledrop, queueit=%d\n",
+ id, queueit);
if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
{
if (tTd(50, 1))
@@ -345,10 +353,8 @@ simpledrop:
xunlink(queuename(e, 'd'));
xunlink(queuename(e, 'q'));
-#ifdef LOG
if (LogLevel > 10)
- syslog(LOG_INFO, "%s: done", id);
-#endif
+ sm_syslog(LOG_INFO, id, "done");
}
else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
{
@@ -360,6 +366,8 @@ simpledrop:
}
/* now unlock the job */
+ if (tTd(50, 8))
+ printf("dropenvelope(%s): unlocking job\n", id);
closexscript(e);
unlockqueue(e);
@@ -698,7 +706,6 @@ setsender(from, e, delimptr, delimchar, internal)
e->e_from.q_mailer == InclMailer)
{
/* log garbage addresses for traceback */
-# ifdef LOG
if (from != NULL && LogLevel > 2)
{
char *p;
@@ -716,11 +723,10 @@ setsender(from, e, delimptr, delimchar, internal)
MAXNAME, host);
p = ebuf;
}
- syslog(LOG_NOTICE,
+ sm_syslog(LOG_NOTICE, e->e_id,
"setsender: %s: invalid or unparseable, received from %s",
shortenstring(from, 83), p);
}
-# endif /* LOG */
if (from != NULL)
{
if (!bitset(QBADADDR, e->e_from.q_flags))
@@ -838,11 +844,10 @@ setsender(from, e, delimptr, delimchar, internal)
if (pvp == NULL)
{
/* don't need to give error -- prescan did that already */
-# ifdef LOG
if (LogLevel > 2)
- syslog(LOG_NOTICE, "cannot prescan from (%s)",
+ sm_syslog(LOG_NOTICE, e->e_id,
+ "cannot prescan from (%s)",
shortenstring(from, 203));
-# endif
finis();
}
(void) rewrite(pvp, 3, 0, e);
diff --git a/usr.sbin/sendmail/src/err.c b/usr.sbin/sendmail/src/err.c
index 2e0f0b91004dd..5bec0884d02af 100644
--- a/usr.sbin/sendmail/src/err.c
+++ b/usr.sbin/sendmail/src/err.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[] = "@(#)err.c 8.52 (Berkeley) 12/1/96";
+static char sccsid[] = "@(#)err.c 8.62 (Berkeley) 6/5/97";
#endif /* not lint */
# include "sendmail.h"
@@ -42,8 +42,7 @@ static char sccsid[] = "@(#)err.c 8.52 (Berkeley) 12/1/96";
/*
** SYSERR -- Print error message.
**
-** Prints an error message via printf to the diagnostic
-** output. If LOG is defined, it logs it also.
+** Prints an error message via printf to the diagnostic output.
**
** If the first character of the syserr message is `!' it will
** log this as an ALERT message and exit immediately. This can
@@ -90,16 +89,17 @@ syserr(fmt, va_alist)
register char *p;
int olderrno = errno;
bool panic;
-#ifdef LOG
char *uname;
struct passwd *pw;
char ubuf[80];
-#endif
VA_LOCAL_DECL
panic = *fmt == '!';
if (panic)
+ {
fmt++;
+ HoldErrs = FALSE;
+ }
/* format and output the error message */
if (olderrno == 0)
@@ -130,7 +130,6 @@ syserr(fmt, va_alist)
printf("syserr: ExitStat = %d\n", ExitStat);
}
-# ifdef LOG
pw = sm_getpwuid(getuid());
if (pw != NULL)
uname = pw->pw_name;
@@ -141,10 +140,9 @@ syserr(fmt, va_alist)
}
if (LogLevel > 0)
- syslog(panic ? LOG_ALERT : LOG_CRIT, "%s: SYSERR(%s): %.900s",
- CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+ sm_syslog(panic ? LOG_ALERT : LOG_CRIT, CurEnv->e_id,
+ "SYSERR(%s): %.900s",
uname, &MsgBuf[4]);
-# endif /* LOG */
switch (olderrno)
{
case EBADF:
@@ -180,7 +178,7 @@ syserr(fmt, va_alist)
exit(EX_OSERR);
}
errno = 0;
- if (QuickAbort)
+ if (QuickAbort || (OnlyOneError && !HoldErrs))
longjmp(TopFrame, 2);
}
/*
@@ -251,14 +249,12 @@ usrerr(fmt, va_alist)
puterrmsg(MsgBuf);
-# ifdef LOG
if (LogLevel > 3 && LogUsrErrs)
- syslog(LOG_NOTICE, "%s: %.900s",
- CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+ sm_syslog(LOG_NOTICE, CurEnv->e_id,
+ "%.900s",
&MsgBuf[4]);
-# endif /* LOG */
- if (QuickAbort)
+ if (QuickAbort || (OnlyOneError && !HoldErrs))
longjmp(TopFrame, 1);
}
/*
@@ -404,10 +400,10 @@ putoutmsg(msg, holdmsg, heldmsg)
if (!heldmsg && CurEnv->e_xfp != NULL && strchr("45", msg[0]) != NULL)
fprintf(CurEnv->e_xfp, "%s\n", msg);
-#ifdef LOG
if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
- syslog(LOG_INFO, "--> %s%s", msg, holdmsg ? " (held)" : "");
-#endif
+ sm_syslog(LOG_INFO, CurEnv->e_id,
+ "--> %s%s",
+ msg, holdmsg ? " (held)" : "");
if (msgcode == '8')
msg[0] = '0';
@@ -450,14 +446,11 @@ putoutmsg(msg, holdmsg, heldmsg)
/* can't call syserr, 'cause we are using MsgBuf */
HoldErrs = TRUE;
-#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_CRIT,
- "%s: SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
- CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+ sm_syslog(LOG_CRIT, CurEnv->e_id,
+ "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
CurHostName == NULL ? "NO-HOST" : CurHostName,
shortenstring(msg, 203), errstring(errno));
-#endif
}
/*
** PUTERRMSG -- like putoutmsg, but does special processing for error messages
@@ -522,7 +515,6 @@ fmtmsg(eb, to, num, eno, fmt, ap)
va_list ap;
{
char del;
- char *meb;
int l;
int spaceleft = sizeof MsgBuf;
@@ -559,8 +551,6 @@ fmtmsg(eb, to, num, eno, fmt, ap)
*eb++ &= 0177;
}
- meb = eb;
-
/* output the message */
(void) vsnprintf(eb, spaceleft, fmt, ap);
spaceleft -= strlen(eb);
@@ -627,7 +617,7 @@ errstring(errnum)
char *dnsmsg;
char *bp;
static char buf[MAXLINE];
-# ifndef ERRLIST_PREDEFINED
+# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
extern char *sys_errlist[];
extern int sys_nerr;
# endif
@@ -648,7 +638,11 @@ errstring(errnum)
case ETIMEDOUT:
case ECONNRESET:
bp = buf;
+#if HASSTRERROR
+ snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum));
+#else
snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]);
+#endif
bp += strlen(bp);
if (CurHostName != NULL)
{
@@ -690,9 +684,6 @@ errstring(errnum)
return (buf);
# endif
- case EOPENTIMEOUT:
- return "Timeout on file open";
-
# if NAMED_BIND
case HOST_NOT_FOUND + E_DNSBASE:
dnsmsg = "host not found";
@@ -714,6 +705,40 @@ errstring(errnum)
case EPERM:
/* SunOS gives "Not owner" -- this is the POSIX message */
return "Operation not permitted";
+
+ /*
+ ** Error messages used internally in sendmail.
+ */
+
+ 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 (dnsmsg != NULL)
@@ -731,9 +756,13 @@ errstring(errnum)
return buf;
}
+#if HASSTRERROR
+ return strerror(errnum);
+#else
if (errnum > 0 && errnum < sys_nerr)
return (sys_errlist[errnum]);
(void) snprintf(buf, sizeof buf, "Error %d", errnum);
return (buf);
+#endif
}
diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c
index d40d95f470a8e..a4ece010dded7 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/ldap_map.h b/usr.sbin/sendmail/src/ldap_map.h
index 488589b7f5a96..dd85da3073b5a 100644
--- a/usr.sbin/sendmail/src/ldap_map.h
+++ b/usr.sbin/sendmail/src/ldap_map.h
@@ -5,12 +5,14 @@
** Please go to him for support -- since I (Eric) don't run LDAP, I
** can't help you at all.
**
-** @(#)ldap_map.h 8.2 (Berkeley) 5/22/96
+** @(#)ldap_map.h 8.4 (Berkeley) 6/3/97
*/
#ifndef _LDAP_MAP_H
#define _LDAP_MAP_H
+#include <sys/time.h>
+
struct ldap_map_struct
{
/* needed for ldap_open */
@@ -33,7 +35,7 @@ struct ldap_map_struct
char *base;
int scope;
char *filter;
- char *attr;
+ char *attr[2];
int attrsonly;
struct timeval timeout;
LDAPMessage *res;
diff --git a/usr.sbin/sendmail/src/macro.c b/usr.sbin/sendmail/src/macro.c
index e31d0deb21cbc..0f31d11f3b44c 100644
--- a/usr.sbin/sendmail/src/macro.c
+++ b/usr.sbin/sendmail/src/macro.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[] = "@(#)macro.c 8.17 (Berkeley) 5/13/96";
+static char sccsid[] = "@(#)macro.c 8.18 (Berkeley) 2/1/97";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/mailq.1 b/usr.sbin/sendmail/src/mailq.1
new file mode 100644
index 0000000000000..b489f31b2c31d
--- /dev/null
+++ b/usr.sbin/sendmail/src/mailq.1
@@ -0,0 +1,89 @@
+.\" Copyright (c) 1983, 1997 Eric P. Allman
+.\" Copyright (c) 1985, 1990, 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.
+.\"
+.\" @(#)mailq.1 8.5 (Berkeley) 2/1/97
+.\"
+.Dd February 1, 1997
+.Dt MAILQ 1
+.Os BSD 4
+.Sh NAME
+.Nm mailq
+.Nd print the mail queue
+.Sh SYNOPSIS
+.Nm mailq
+.Op Fl v
+.Sh DESCRIPTION
+.Nm Mailq
+prints a summary of the mail messages queued for future delivery.
+.Pp
+The first line printed for each message
+shows the internal identifier used on this host
+for the message,
+the size of the message in bytes,
+the date and time the message was accepted into the queue,
+and the envelope sender of the message.
+The second line shows the error message that caused this message
+to be retained in the queue;
+it will not be present if the message is being processed
+for the first time.
+The following lines show message recipients,
+one per line.
+.Pp
+.Nm Mailq
+is identical to
+.Dq Li "sendmail -bp" .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl v
+Print verbose information.
+This adds the priority of the message and
+a single character indicator (``+'' or blank)
+indicating whether a warning message has been sent
+on the first line of the message.
+Additionally, extra lines may be intermixed with the recipients
+indicating the ``controlling user'' information;
+this shows who will own any programs that are executed
+on behalf of this message
+and the name of the alias this command expanded from, if any.
+.El
+.Pp
+The
+.Nm mailq
+utility exits 0 on success, and >0 if an error occurs.
+.Sh SEE ALSO
+.Xr sendmail 8
+.Sh HISTORY
+The
+.Nm mailq
+command appeared in
+.Bx 4.0 .
diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c
index 3c30fb3e61738..880b181ca25f2 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/makesendmail b/usr.sbin/sendmail/src/makesendmail
index 838d89199712e..a28e2f4cc4e25 100644
--- a/usr.sbin/sendmail/src/makesendmail
+++ b/usr.sbin/sendmail/src/makesendmail
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 1993, 1996 Eric P. Allman
+# Copyright (c) 1993, 1996-1997 Eric P. Allman
# Copyright (c) 1993 The Regents of the University of California.
# All rights reserved.
#
@@ -32,7 +32,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# @(#)makesendmail 8.42 (Berkeley) 11/10/96
+# @(#)makesendmail 8.45 (Berkeley) 4/12/97
#
#
@@ -115,6 +115,16 @@ then
# old versions of SCO UNIX set uname -s the same as uname -n
os=SCO_SV
fi
+if [ "$os" = "$node" -a "$rel" = 4.0 -a "$arch" = "3360,3430-R" ]
+then
+ # AT&T/NCR Machines also set uname -s == uname -n
+ if [ -d /usr/sadm/sysadm/add-ons/WIN-TCP ]
+ then
+ os=NCR.MP-RAS.2.x
+ else
+ os=NCR.MP-RAS.3.x
+ fi
+fi
case $os
in
@@ -133,6 +143,7 @@ in
os="UXPDS"
rel=`uname -v | sed -e 's/\(V.*\)L.*/\1/'`
fi;;
+ SINIX-?) os=SINIX;;
esac
# get "base part" of operating system release
diff --git a/usr.sbin/sendmail/src/map.c b/usr.sbin/sendmail/src/map.c
index 3d40d62e511b4..e0a0fd2408849 100644
--- a/usr.sbin/sendmail/src/map.c
+++ b/usr.sbin/sendmail/src/map.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1992, 1995, 1996 Eric P. Allman.
+ * Copyright (c) 1992, 1995-1997 Eric P. Allman.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)map.c 8.147 (Berkeley) 1/17/97";
+static char sccsid[] = "@(#)map.c 8.168 (Berkeley) 6/14/97";
#endif /* not lint */
#include "sendmail.h"
@@ -107,11 +107,23 @@ static char sccsid[] = "@(#)map.c 8.147 (Berkeley) 1/17/97";
extern bool aliaswait __P((MAP *, char *, int));
extern bool extract_canonname __P((char *, char *, char[], int));
-#if O_EXLOCK && HASFLOCK
+#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
# define LOCK_ON_OPEN 1 /* we can open/create a locked file */
#else
# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */
#endif
+
+#ifndef O_LEAVELOCKED
+# if O_SHLOCK
+# define O_LEAVELOCKED O_SHLOCK
+# else
+# define O_LEAVELOCKED 0x1000
+# endif
+#endif
+
+#ifndef O_ACCMODE
+# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
+#endif
/*
** MAP_PARSEARGS -- parse config line arguments for database lookup
**
@@ -284,7 +296,7 @@ map_parseargs(map, ap)
char *
map_rewrite(map, s, slen, av)
register MAP *map;
- register char *s;
+ register const char *s;
int slen;
char **av;
{
@@ -314,14 +326,15 @@ map_rewrite(map, s, slen, av)
i = len = slen;
if (av != NULL)
{
- bp = s;
- for (i = slen; --i >= 0 && (c = *bp++) != 0; )
+ const char *sp = s;
+
+ for (i = slen; --i >= 0 && (c = *sp++) != 0; )
{
if (c != '%')
continue;
if (--i < 0)
break;
- c = *bp++;
+ c = *sp++;
if (!(isascii(c) && isdigit(c)))
continue;
for (avp = av; --c >= '0' && *avp != NULL; avp++)
@@ -675,11 +688,9 @@ extract_canonname(name, line, cbuf, cbuflen)
int i;
char *p;
bool found = FALSE;
- int l;
extern char *get_column __P((char *, int, char, char *, int));
cbuf[0] = '\0';
- l = cbuflen;
if (line[0] == '#')
return FALSE;
@@ -733,11 +744,49 @@ ndbm_map_open(map, mode)
register DBM *dbm;
struct stat st;
int fd;
+ int sff;
+ int ret;
+ int smode = S_IREAD;
+ char dirfile[MAXNAME + 1];
+ char pagfile[MAXNAME + 1];
+ struct stat std, stp;
if (tTd(38, 2))
printf("ndbm_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
map->map_lockfd = -1;
+ mode &= O_ACCMODE;
+
+ /* do initial file and directory checks */
+ snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file);
+ snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file);
+ sff = SFF_ROOTOK|SFF_REGONLY|SFF_CREAT;
+ if (mode == O_RDWR)
+ {
+ sff |= SFF_NOLINK;
+ smode = S_IWRITE;
+ }
+ else
+ {
+ sff |= SFF_NOWLINK;
+ }
+ if (FatalWritableDirs)
+ sff |= SFF_SAFEDIRPATH;
+ if ((ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName,
+ sff, smode, &std)) != 0 ||
+ (ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName,
+ sff, smode, &stp)) != 0)
+ {
+ /* cannot open this map */
+ if (tTd(38, 2))
+ printf("\tunsafe map file: %d\n", ret);
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("dbm map \"%s\": unsafe map file %s",
+ map->map_mname, map->map_file);
+ return FALSE;
+ }
+ if (std.st_mode == ST_MODE_NOFILE)
+ mode |= O_EXCL;
#if LOCK_ON_OPEN
if (mode == O_RDONLY)
@@ -745,12 +794,14 @@ ndbm_map_open(map, mode)
else
mode |= O_CREAT|O_TRUNC|O_EXLOCK;
#else
- if (mode == O_RDWR)
+ if ((mode & O_ACCMODE) == O_RDWR)
{
# if NOFTRUNCATE
/*
** Warning: race condition. Try to lock the file as
** quickly as possible after opening it.
+ ** This may also have security problems on some systems,
+ ** but there isn't anything we can do about it.
*/
mode |= O_CREAT|O_TRUNC;
@@ -763,13 +814,11 @@ ndbm_map_open(map, mode)
int dirfd;
int pagfd;
- char dirfile[MAXNAME + 1];
- char pagfile[MAXNAME + 1];
- snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file);
- snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file);
- dirfd = open(dirfile, mode|O_CREAT, DBMMODE);
- pagfd = open(pagfile, mode|O_CREAT, DBMMODE);
+ dirfd = safeopen(dirfile, mode|O_CREAT, DBMMODE,
+ SFF_NOLINK|SFF_CREAT|SFF_OPENASROOT);
+ pagfd = safeopen(pagfile, mode|O_CREAT, DBMMODE,
+ SFF_NOLINK|SFF_CREAT|SFF_OPENASROOT);
if (dirfd < 0 || pagfd < 0)
{
@@ -779,9 +828,6 @@ ndbm_map_open(map, mode)
close(pagfd);
return FALSE;
}
- if (!lockfile(dirfd, map->map_file, ".dir", LOCK_EX))
- syserr("ndbm_map_open: cannot lock %s.dir",
- map->map_file);
if (ftruncate(dirfd, (off_t) 0) < 0)
syserr("ndbm_map_open: cannot truncate %s.dir",
map->map_file);
@@ -805,8 +851,25 @@ ndbm_map_open(map, mode)
return TRUE;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("Cannot open DBM database %s", map->map_file);
+#if !LOCK_ON_OPEN && !NOFTRUNCATE
+ if (map->map_lockfd >= 0)
+ close(map->map_lockfd);
+#endif
+ return FALSE;
+ }
+ if (filechanged(dirfile, dbm_dirfno(dbm), &std, sff) ||
+ filechanged(pagfile, dbm_pagfno(dbm), &stp, sff))
+ {
+ syserr("ndbm_map_open(%s): file changed after open",
+ map->map_file);
+ dbm_close(dbm);
+#if !LOCK_ON_OPEN && !NOFTRUNCATE
+ if (map->map_lockfd >= 0)
+ close(map->map_lockfd);
+#endif
return FALSE;
}
+
map->map_db1 = (void *) dbm;
fd = dbm_dirfno((DBM *) map->map_db1);
if (mode == O_RDONLY)
@@ -1036,7 +1099,7 @@ ndbm_map_close(map)
** be pokey about it. That's hard to do.
*/
-extern bool db_map_open __P((MAP *, int, DBTYPE, const void *));
+extern bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *));
/* these should be K line arguments */
#ifndef DB_CACHE_SIZE
@@ -1059,7 +1122,7 @@ bt_map_open(map, mode)
bzero(&btinfo, sizeof btinfo);
btinfo.cachesize = DB_CACHE_SIZE;
- return db_map_open(map, mode, DB_BTREE, &btinfo);
+ return db_map_open(map, mode, "btree", DB_BTREE, &btinfo);
}
bool
@@ -1076,32 +1139,65 @@ hash_map_open(map, mode)
bzero(&hinfo, sizeof hinfo);
hinfo.nelem = DB_HASH_NELEM;
hinfo.cachesize = DB_CACHE_SIZE;
- return db_map_open(map, mode, DB_HASH, &hinfo);
+ return db_map_open(map, mode, "hash", DB_HASH, &hinfo);
}
bool
-db_map_open(map, mode, dbtype, openinfo)
+db_map_open(map, mode, mapclassname, dbtype, openinfo)
MAP *map;
int mode;
+ char *mapclassname;
DBTYPE dbtype;
const void *openinfo;
{
DB *db;
int i;
int omode;
+ int smode = S_IREAD;
int fd;
+ int sff;
int saveerrno;
+ bool leavelocked = bitset(O_LEAVELOCKED, mode);
struct stat st;
char buf[MAXNAME + 1];
+ /* do initial file and directory checks */
snprintf(buf, sizeof buf - 3, "%s", map->map_file);
i = strlen(buf);
if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
(void) strcat(buf, ".db");
- map->map_lockfd = -1;
+ mode &= O_ACCMODE;
omode = mode;
+ sff = SFF_ROOTOK|SFF_REGONLY|SFF_CREAT;
+ if (mode == O_RDWR)
+ {
+ sff |= SFF_NOLINK;
+ smode = S_IWRITE;
+ }
+ else
+ {
+ sff |= SFF_NOWLINK;
+ }
+ if (FatalWritableDirs)
+ sff |= SFF_SAFEDIRPATH;
+ if ((i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName,
+ sff, smode, &st)) != 0)
+ {
+ /* cannot open this map */
+ if (tTd(38, 2))
+ printf("\tunsafe map file: %d\n", i);
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("%s map \"%s\": unsafe map file %s",
+ mapclassname, map->map_mname, map->map_file);
+ return FALSE;
+ }
+ if (st.st_mode == ST_MODE_NOFILE)
+ omode |= O_EXCL;
+
+ map->map_lockfd = -1;
+
#if LOCK_ON_OPEN
if (mode == O_RDWR)
omode |= O_CREAT|O_TRUNC|O_EXLOCK;
@@ -1139,7 +1235,7 @@ db_map_open(map, mode, dbtype, openinfo)
saveerrno = errno;
#if !LOCK_ON_OPEN
- if (mode == O_RDWR)
+ if (leavelocked || mode == O_RDWR)
map->map_lockfd = fd;
else
(void) close(fd);
@@ -1152,7 +1248,23 @@ db_map_open(map, mode, dbtype, openinfo)
return TRUE;
errno = saveerrno;
if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("Cannot open DB database %s", map->map_file);
+ syserr("Cannot open %s database %s",
+ mapclassname, map->map_file);
+#if !LOCK_ON_OPEN
+ if (map->map_lockfd >= 0)
+ (void) close(map->map_lockfd);
+#endif
+ return FALSE;
+ }
+
+ if (filechanged(buf, db->fd(db), &st, sff))
+ {
+ syserr("db_map_open(%s): file changed after open", buf);
+ db->close(db);
+#if !LOCK_ON_OPEN
+ if (map->map_lockfd >= 0)
+ close(map->map_lockfd);
+#endif
return FALSE;
}
@@ -1161,7 +1273,7 @@ db_map_open(map, mode, dbtype, openinfo)
#if !OLD_NEWDB
fd = db->fd(db);
# if LOCK_ON_OPEN
- if (fd >= 0 && mode == O_RDONLY)
+ if (fd >= 0 && mode == O_RDONLY && !leavelocked)
{
(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
}
@@ -1203,6 +1315,7 @@ db_map_lookup(map, name, av, statp)
int st;
int saveerrno;
int fd;
+ struct stat stbuf;
char keybuf[MAXNAME + 1];
if (tTd(38, 20))
@@ -1220,8 +1333,41 @@ db_map_lookup(map, name, av, statp)
#if !OLD_NEWDB
fd = db->fd(db);
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
- (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
+ (void) lockfile(fd, map->map_file, ".db", LOCK_SH);
+ if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
+ {
+ /* Reopen the database to sync the cache */
+ int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
+ : O_RDONLY;
+
+ map->map_class->map_close(map);
+ map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
+ omode |= O_LEAVELOCKED;
+ if (map->map_class->map_open(map, omode))
+ {
+ map->map_mflags |= MF_OPEN;
+ if ((omode && O_ACCMODE) == O_RDWR)
+ map->map_mflags |= MF_WRITABLE;
+ db = (DB *) map->map_db2;
+ fd = db->fd(db);
+ }
+ else
+ {
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ {
+ extern MAPCLASS BogusMapClass;
+
+ *statp = EX_TEMPFAIL;
+ map->map_class = &BogusMapClass;
+ map->map_mflags |= MF_OPEN;
+ syserr("Cannot reopen DB database %s",
+ map->map_file);
+ }
+ return NULL;
+ }
+ }
#endif
+
st = 1;
if (bitset(MF_TRY0NULL, map->map_mflags))
{
@@ -1392,6 +1538,7 @@ nis_map_open(map, mode)
printf("nis_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
+ mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
/* issue a pseudo-error message */
@@ -1581,6 +1728,8 @@ nis_getcanonname(name, hbsize, statp)
*statp = EX_UNAVAILABLE;
return FALSE;
}
+ if (vsize >= sizeof host_record)
+ vsize = sizeof host_record - 1;
strncpy(host_record, vp, vsize);
host_record[vsize] = '\0';
if (tTd(38, 44))
@@ -1637,6 +1786,7 @@ nisplus_map_open(map, mode)
printf("nisplus_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
+ mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
errno = ENODEV;
@@ -1657,15 +1807,17 @@ nisplus_map_open(map, mode)
map->map_file, map->map_domain);
}
if (!PARTIAL_NAME(map->map_file))
+ {
map->map_domain = newstr("");
-
- /* check to see if this map actually exists */
- if (PARTIAL_NAME(map->map_file))
+ snprintf(qbuf, sizeof qbuf, "%s", map->map_file);
+ }
+ else
+ {
+ /* check to see if this map actually exists */
snprintf(qbuf, sizeof qbuf, "%s.%s",
map->map_file, map->map_domain);
- else
- strcpy(qbuf, map->map_file);
-
+ }
+
retry_cnt = 0;
while (res == NULL || res->status != NIS_SUCCESS)
{
@@ -1769,10 +1921,11 @@ nisplus_map_lookup(map, name, av, statp)
char **av;
int *statp;
{
- char *vp;
+ char *p;
auto int vsize;
- int buflen;
- char search_key[MAXNAME + 1];
+ char *skp;
+ int skleft;
+ char search_key[MAXNAME + 4];
char qbuf[MAXLINE + NIS_MAXNAMELEN];
nis_result *result;
@@ -1791,11 +1944,40 @@ nisplus_map_lookup(map, name, av, statp)
}
}
- buflen = strlen(name);
- if (buflen > sizeof search_key - 1)
- buflen = sizeof search_key - 1;
- bcopy(name, search_key, buflen);
- search_key[buflen] = '\0';
+ /*
+ ** Copy the name to the key buffer, escaping double quote characters
+ ** by doubling them and quoting "]" and "," to avoid having the
+ ** NIS+ parser choke on them.
+ */
+
+ skleft = sizeof search_key - 4;
+ skp = search_key;
+ for (p = name; *p != '\0' && skleft > 0; p++)
+ {
+ switch (*p)
+ {
+ case ']':
+ case ',':
+ /* quote the character */
+ *skp++ = '"';
+ *skp++ = *p;
+ *skp++ = '"';
+ skleft -= 3;
+ break;
+
+ case '"':
+ /* double the quote */
+ *skp++ = '"';
+ skleft--;
+ /* fall through... */
+
+ default:
+ *skp++ = *p;
+ skleft--;
+ break;
+ }
+ }
+ *skp = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(search_key);
@@ -1819,7 +2001,7 @@ nisplus_map_lookup(map, name, av, statp)
if ((count = NIS_RES_NUMOBJ(result)) != 1)
{
if (LogLevel > 10)
- syslog(LOG_WARNING,
+ sm_syslog(LOG_WARNING, CurEnv->e_id,
"%s: lookup error, expected 1 entry, got %d",
map->map_file, count);
@@ -1829,18 +2011,18 @@ nisplus_map_lookup(map, name, av, statp)
name, count);
}
- vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
+ p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
/* set the length of the result */
- if (vp == NULL)
- vp = "";
- vsize = strlen(vp);
+ if (p == NULL)
+ p = "";
+ vsize = strlen(p);
if (tTd(38, 20))
printf("nisplus_map_lookup(%s), found %s\n",
- name, vp);
+ name, p);
if (bitset(MF_MATCHONLY, map->map_mflags))
str = map_rewrite(map, name, strlen(name), NULL);
else
- str = map_rewrite(map, vp, vsize, av);
+ str = map_rewrite(map, p, vsize, av);
nis_freeresult(result);
*statp = EX_OK;
return str;
@@ -1923,12 +2105,10 @@ nisplus_getcanonname(name, hbsize, statp)
if ((count = NIS_RES_NUMOBJ(result)) != 1)
{
-#ifdef LOG
if (LogLevel > 10)
- syslog(LOG_WARNING,
+ sm_syslog(LOG_WARNING, CurEnv->e_id,
"nisplus_getcanonname: lookup error, expected 1 entry, got %d",
count);
-#endif
/* ignore second entry */
if (tTd(38, 20))
@@ -2031,6 +2211,7 @@ ldap_map_open(map, mode)
if (tTd(38, 2))
printf("ldap_map_open(%s, %d)\n", map->map_mname, mode);
+ mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
/* issue a pseudo-error message */
@@ -2207,7 +2388,7 @@ ldap_map_lookup(map, name, av, statp)
snprintf(filter, sizeof filter, lmap->filter, keybuf);
if (ldap_search_st(lmap->ld, lmap->base,lmap->scope,filter,
- &(lmap->attr), lmap->attrsonly, &(lmap->timeout),
+ lmap->attr, lmap->attrsonly, &(lmap->timeout),
&(lmap->res)) != LDAP_SUCCESS)
{
/* try close/opening map */
@@ -2219,7 +2400,7 @@ ldap_map_lookup(map, name, av, statp)
goto quick_exit;
}
if (ldap_search_st(lmap->ld, lmap->base, lmap->scope, filter,
- &(lmap->attr), lmap->attrsonly,
+ lmap->attr, lmap->attrsonly,
&(lmap->timeout), &(lmap->res))
!= LDAP_SUCCESS)
{
@@ -2243,7 +2424,7 @@ ldap_map_lookup(map, name, av, statp)
}
/* Need to build the args for map_rewrite here */
- attr_values = ldap_get_values(lmap->ld,entry,lmap->attr);
+ attr_values = ldap_get_values(lmap->ld,entry,lmap->attr[0]);
if (attr_values == NULL)
{
/* bad things happened */
@@ -2258,12 +2439,10 @@ ldap_map_lookup(map, name, av, statp)
vp = attr_values[0];
vsize = strlen(vp);
-# ifdef LOG
if (LogLevel > 9)
- syslog(LOG_INFO, "%s: ldap %.100s => %s",
- CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+ sm_syslog(LOG_INFO, CurEnv->e_id,
+ "ldap %.100s => %s",
name, vp);
-# endif
if (bitset(MF_MATCHONLY, map->map_mflags))
result = map_rewrite(map, name, strlen(name), NULL);
else
@@ -2398,7 +2577,8 @@ ldap_map_parseargs(map,args)
case 'v': /* attr to return */
while (isascii(*++p) && isspace(*p))
continue;
- lmap->attr = p;
+ lmap->attr[0] = p;
+ lmap->attr[1] = NULL;
break;
/* args stolen from ldapsearch.c */
@@ -2538,8 +2718,8 @@ ldap_map_parseargs(map,args)
return FALSE;
}
}
- if (lmap->attr != NULL)
- lmap->attr = newstr(ldap_map_dequote(lmap->attr));
+ if (lmap->attr[0] != NULL)
+ lmap->attr[0] = newstr(ldap_map_dequote(lmap->attr[0]));
else
{
if (!bitset(MCF_OPTFILE, map->map_class->map_cflags))
@@ -2690,6 +2870,7 @@ ni_map_open(map, mode)
if (tTd(38, 2))
printf("ni_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
+ mode &= O_ACCMODE;
if (*map->map_file == '\0')
map->map_file = NETINFO_DEFAULT_DIR;
@@ -2970,6 +3151,8 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar)
** This code donated by Sun Microsystems.
*/
+#define map_sff map_lockfd /* overload field */
+
/*
** TEXT_MAP_OPEN -- open text table
@@ -2980,12 +3163,14 @@ text_map_open(map, mode)
MAP *map;
int mode;
{
- struct stat sbuf;
+ int sff;
+ int i;
if (tTd(38, 2))
printf("text_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
+ mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
errno = ENODEV;
@@ -3005,33 +3190,22 @@ text_map_open(map, mode)
map->map_mname);
return FALSE;
}
- /* check to see if this map actually accessable */
- if (access(map->map_file, R_OK) <0)
+
+ sff = SFF_ROOTOK|SFF_REGONLY|SFF_NOWLINK;
+ if (FatalWritableDirs)
+ sff |= SFF_SAFEDIRPATH;
+ if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName,
+ sff, S_IRUSR, NULL)) != 0)
{
+ /* cannot open this map */
if (tTd(38, 2))
- printf("text_map_open(%s, %s): cannot access: %s\n",
- map->map_mname, map->map_file, errstring(errno));
+ printf("\tunsafe map file: %d\n", i);
if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("text map \"%s\": cannot access file %s",
+ syserr("text map \"%s\": unsafe map file %s",
map->map_mname, map->map_file);
return FALSE;
}
- /* check to see if this map actually exist */
- if (stat(map->map_file, &sbuf) <0)
- {
- syserr("text_map_open(%s, %s): cannot stat",
- map->map_mname, map->map_file);
- return FALSE;
- }
-
- if (!S_ISREG(sbuf.st_mode))
- {
- syserr("text map \"%s\": %s is not a regular file",
- map->map_mname, map->map_file);
- return FALSE;
- }
-
if (map->map_keycolnm == NULL)
map->map_keycolno = 0;
else
@@ -3070,6 +3244,7 @@ text_map_open(map, mode)
printf("%c\n", map->map_coldelim);
}
+ map->map_sff = sff;
return TRUE;
}
@@ -3088,13 +3263,14 @@ text_map_lookup(map, name, av, statp)
char *vp;
auto int vsize;
int buflen;
- char search_key[MAXNAME + 1];
- char linebuf[MAXLINE];
FILE *f;
- char buf[MAXNAME + 1];
char delim;
int key_idx;
bool found_it;
+ int sff = map->map_sff;
+ char search_key[MAXNAME + 1];
+ char linebuf[MAXLINE];
+ char buf[MAXNAME + 1];
extern char *get_column __P((char *, int, char, char *, int));
found_it = FALSE;
@@ -3109,7 +3285,7 @@ text_map_lookup(map, name, av, statp)
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(search_key);
- f = fopen(map->map_file, "r");
+ f = safefopen(map->map_file, O_RDONLY, FileMode, sff);
if (f == NULL)
{
map->map_mflags &= ~(MF_VALID|MF_OPEN);
@@ -3166,7 +3342,6 @@ text_getcanonname(name, hbsize, statp)
char linebuf[MAXLINE];
char cbuf[MAXNAME + 1];
char nbuf[MAXNAME + 1];
- extern char *get_column __P((char *, int, char, char *, int));
if (tTd(38, 20))
printf("text_getcanonname(%s)\n", name);
@@ -3272,19 +3447,24 @@ stab_map_open(map, mode)
int mode;
{
FILE *af;
+ int sff;
struct stat st;
if (tTd(38, 2))
printf("stab_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
+ mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
errno = ENODEV;
return FALSE;
}
- af = fopen(map->map_file, "r");
+ sff = SFF_ROOTOK|SFF_REGONLY|SFF_NOWLINK;
+ if (FatalWritableDirs)
+ sff |= SFF_SAFEDIRPATH;
+ af = safefopen(map->map_file, O_RDONLY, 0444, sff);
if (af == NULL)
return FALSE;
readaliases(map, af, FALSE, FALSE);
@@ -3365,6 +3545,7 @@ impl_map_open(map, mode)
printf("impl_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
+ mode &= O_ACCMODE;
#ifdef NEWDB
map->map_mflags |= MF_IMPL_HASH;
if (hash_map_open(map, mode))
@@ -3447,6 +3628,7 @@ user_map_open(map, mode)
printf("user_map_open(%s, %d)\n",
map->map_mname, mode);
+ mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
/* issue a pseudo-error message */
@@ -3768,6 +3950,7 @@ switch_map_open(map, mode)
printf("switch_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
+ mode &= O_ACCMODE;
nmaps = switch_map_find(map->map_file, maptype, map->map_return);
if (tTd(38, 19))
{
diff --git a/usr.sbin/sendmail/src/mci.c b/usr.sbin/sendmail/src/mci.c
index a81e61de2c7b0..f8ba789ff8a05 100644
--- a/usr.sbin/sendmail/src/mci.c
+++ b/usr.sbin/sendmail/src/mci.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996 Eric P. Allman
+ * Copyright (c) 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[] = "@(#)mci.c 8.54 (Berkeley) 12/1/96";
+static char sccsid[] = "@(#)mci.c 8.62 (Berkeley) 5/29/97";
#endif /* not lint */
#include "sendmail.h"
@@ -116,12 +116,10 @@ mci_cache(mci)
if (tTd(42, 5))
printf("mci_cache: caching %lx (%s) in slot %d\n",
(u_long) mci, mci->mci_host, mcislot - MciCache);
-#ifdef LOG
if (tTd(91, 100))
- syslog(LOG_DEBUG, "%s: mci_cache: caching %x (%.100s) in slot %d",
- CurEnv->e_id ? CurEnv->e_id : "NOQUEUE",
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "mci_cache: caching %x (%.100s) in slot %d",
mci, mci->mci_host, mcislot - MciCache);
-#endif
*mcislot = mci;
mci->mci_flags |= MCIF_CACHED;
@@ -216,12 +214,10 @@ mci_uncache(mcislot, doquit)
if (tTd(42, 5))
printf("mci_uncache: uncaching %lx (%s) from slot %d (%d)\n",
(u_long) mci, mci->mci_host, mcislot - MciCache, doquit);
-#ifdef LOG
if (tTd(91, 100))
- syslog(LOG_DEBUG, "%s: mci_uncache: uncaching %x (%.100s) from slot %d (%d)",
- CurEnv->e_id ? CurEnv->e_id : "NOQUEUE",
+ sm_syslog(LOG_DEBUG, CurEnv->e_id,
+ "mci_uncache: uncaching %x (%.100s) from slot %d (%d)",
mci, mci->mci_host, mcislot - MciCache, doquit);
-#endif
#if SMTP
if (doquit)
@@ -485,11 +481,9 @@ mci_dump(mci, logit)
mci->mci_host == NULL ? "NULL" : mci->mci_host,
ctime(&mci->mci_lastuse));
printit:
-#ifdef LOG
if (logit)
- syslog(LOG_DEBUG, "%.1000s", buf);
+ sm_syslog(LOG_DEBUG, CurEnv->e_id, "%.1000s", buf);
else
-#endif
printf("%s\n", buf);
}
/*
@@ -577,8 +571,8 @@ mci_lock_host_statfile(mci)
goto cleanup;
}
- if ((mci->mci_statfile = fopen(fname, "r+")) == NULL)
- mci->mci_statfile = fopen(fname, "w");
+ mci->mci_statfile = safefopen(fname, O_RDWR|O_CREAT, FileMode,
+ SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_CREAT);
if (mci->mci_statfile == NULL)
{
@@ -699,7 +693,8 @@ mci_load_persistent(mci)
goto cleanup;
}
- fp = fopen(fname, "r");
+ fp = safefopen(fname, O_RDONLY, FileMode,
+ SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY);
if (fp == NULL)
{
/* I can't think of any reason this should ever happen */
@@ -744,6 +739,7 @@ mci_read_persistent(fp, mci)
{
int ver;
register char *p;
+ int saveLineNumber = LineNumber;
char buf[MAXLINE];
if (fp == NULL)
@@ -763,8 +759,10 @@ mci_read_persistent(fp, mci)
rewind(fp);
ver = -1;
+ LineNumber = 0;
while (fgets(buf, sizeof buf, fp) != NULL)
{
+ LineNumber++;
p = strchr(buf, '\n');
if (p != NULL)
*p = '\0';
@@ -806,9 +804,11 @@ mci_read_persistent(fp, mci)
default:
syserr("Unknown host status line \"%s\"", buf);
+ LineNumber = saveLineNumber;
return -1;
}
}
+ LineNumber = saveLineNumber;
if (ver < 0)
return -1;
return 0;
@@ -1053,7 +1053,8 @@ mci_print_persistent(pathname, hostname)
printf(" -------------- Hostname --------------- How long ago ---------Results---------\n");
}
- fp = fopen(pathname, "r+");
+ fp = safefopen(pathname, O_RDWR, FileMode,
+ SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY);
if (fp == NULL)
{
@@ -1063,16 +1064,19 @@ mci_print_persistent(pathname, hostname)
return 0;
}
+ FileName = pathname;
bzero(&mcib, sizeof mcib);
if (mci_read_persistent(fp, &mcib) < 0)
{
syserr("%s: could not read status file", pathname);
fclose(fp);
+ FileName = NULL;
return 0;
}
locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB);
fclose(fp);
+ FileName = NULL;
printf("%c%-39s %12s ",
locked ? '*' : ' ', hostname,
@@ -1193,13 +1197,22 @@ mci_generate_persistent_path(host, path, pathlen, createflag)
*/
if (host == NULL)
+ {
syserr("mci_generate_persistent_path: null host");
+ return -1;
+ }
if (path == NULL)
+ {
syserr("mci_generate_persistent_path: null path");
+ return -1;
+ }
if (tTd(56, 80))
printf("mci_generate_persistent_path(%s): ", host);
+ if (*host == '\0')
+ return -1;
+
/* make certain this is not a bracketed host number */
if (strlen(host) > sizeof t_host - 1)
return -1;
@@ -1214,16 +1227,19 @@ mci_generate_persistent_path(host, path, pathlen, createflag)
*/
elem = t_host + strlen(t_host);
- while (elem > t_host && (elem[-1] == '.' || elem[-1] == ']'))
+ while (elem > t_host &&
+ (elem[-1] == '.' || (host[0] == '[' && elem[-1] == ']')))
*--elem = '\0';
/* check for what will be the final length of the path */
len = strlen(HostStatDir) + 2;
for (p = (char *) host; *p != '\0'; p++)
{
- if (*p == '|' || *p != '.')
+ if (*p == '|' || *p == '.')
len++;
len++;
+ if (p[0] == '.' && p[1] == '.')
+ return -1;
}
if (len > pathlen)
return -1;
diff --git a/usr.sbin/sendmail/src/mime.c b/usr.sbin/sendmail/src/mime.c
index 999c5ab589763..3e5a610bb39fc 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/newaliases.1 b/usr.sbin/sendmail/src/newaliases.1
new file mode 100644
index 0000000000000..7168c1303f42d
--- /dev/null
+++ b/usr.sbin/sendmail/src/newaliases.1
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1983, 1997 Eric P. Allman
+.\" Copyright (c) 1985, 1990, 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.
+.\"
+.\" @(#)newaliases.1 8.5 (Berkeley) 2/1/97
+.\"
+.Dd February 1, 1997
+.Dt NEWALIASES 1
+.Os BSD 4
+.Sh NAME
+.Nm newaliases
+.Nd rebuild the data base for the mail aliases file
+.Sh SYNOPSIS
+.Nm newaliases
+.Sh DESCRIPTION
+.Nm Newaliases
+rebuilds the random access data base for the mail aliases file
+.Pa /etc/aliases .
+It must be run each time this file is changed in order
+for the change to take effect.
+.Pp
+.Nm Newaliases
+is identical to
+.Dq Li "sendmail -bi" .
+.Pp
+The
+.Nm newaliases
+utility exits 0 on success, and >0 if an error occurs.
+.Sh FILES
+.Bl -tag -width /etc/aliases -compact
+.It Pa /etc/aliases
+The mail aliases file
+.El
+.Sh SEE ALSO
+.Xr aliases 5 ,
+.Xr sendmail 8
+.Sh HISTORY
+The
+.Nm newaliases
+command appeared in
+.Bx 4.0 .
diff --git a/usr.sbin/sendmail/src/parseaddr.c b/usr.sbin/sendmail/src/parseaddr.c
index a10c329ffa808..258e0a9f6abf4 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/queue.c b/usr.sbin/sendmail/src/queue.c
index 2afa73dcf744b..13965de01be2a 100644
--- a/usr.sbin/sendmail/src/queue.c
+++ b/usr.sbin/sendmail/src/queue.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 QUEUE
-static char sccsid[] = "@(#)queue.c 8.153 (Berkeley) 1/14/97 (with queueing)";
+static char sccsid[] = "@(#)queue.c 8.169 (Berkeley) 6/14/97 (with queueing)";
#else
-static char sccsid[] = "@(#)queue.c 8.153 (Berkeley) 1/14/97 (without queueing)";
+static char sccsid[] = "@(#)queue.c 8.169 (Berkeley) 6/14/97 (without queueing)";
#endif
#endif /* not lint */
@@ -99,7 +99,8 @@ queueup(e, announce)
register char *p;
MAILER nullmailer;
MCI mcibuf;
- char buf[MAXLINE], tf[MAXLINE];
+ char tf[MAXQFNAME];
+ char buf[MAXLINE];
extern void printctladdr __P((ADDRESS *, FILE *));
/*
@@ -125,21 +126,19 @@ queueup(e, announce)
{
if (errno != EEXIST)
break;
-#ifdef LOG
if (LogLevel > 0 && (i % 32) == 0)
- syslog(LOG_ALERT, "queueup: cannot create %s, uid=%d: %s",
+ sm_syslog(LOG_ALERT, e->e_id,
+ "queueup: cannot create %s, uid=%d: %s",
tf, geteuid(), errstring(errno));
-#endif
}
else
{
if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB))
break;
-#ifdef LOG
else if (LogLevel > 0 && (i % 32) == 0)
- syslog(LOG_ALERT, "queueup: cannot lock %s: %s",
+ sm_syslog(LOG_ALERT, e->e_id,
+ "queueup: cannot lock %s: %s",
tf, errstring(errno));
-#endif
close(fd);
}
@@ -192,7 +191,7 @@ queueup(e, announce)
if (!bitset(EF_HAS_DF, e->e_flags))
{
register FILE *dfp = NULL;
- char dfname[20];
+ char dfname[MAXQFNAME];
struct stat stbuf;
strcpy(dfname, queuename(e, 'd'));
@@ -247,6 +246,11 @@ queueup(e, announce)
if (e->e_bodytype != NULL)
fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE));
+#if _FFR_SAVE_CHARSET
+ if (e->e_charset != NULL)
+ fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE));
+#endif
+
/* message from envelope, if it exists */
if (e->e_message != NULL)
fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE));
@@ -296,9 +300,9 @@ queueup(e, announce)
{
#if XDEBUG
if (bitset(QQUEUEUP, q->q_flags))
- syslog(LOG_DEBUG,
- "dropenvelope: %s: q_flags = %x, paddr = %s",
- e->e_id, q->q_flags, q->q_paddr);
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "dropenvelope: q_flags = %x, paddr = %s",
+ q->q_flags, q->q_paddr);
#endif
continue;
}
@@ -453,11 +457,9 @@ queueup(e, announce)
errno = 0;
e->e_flags |= EF_INQUEUE;
-# ifdef LOG
/* save log info */
if (LogLevel > 79)
- syslog(LOG_DEBUG, "%s: queueup, qf=%s", e->e_id, qf);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf);
if (tTd(40, 1))
printf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
@@ -537,6 +539,7 @@ printctladdr(a, tfp)
*/
ENVELOPE QueueEnvelope; /* the queue run envelope */
+extern int get_num_procs_online __P((void));
bool
runqueue(forkflag, verbose)
@@ -546,30 +549,45 @@ runqueue(forkflag, verbose)
register ENVELOPE *e;
int njobs;
int sequenceno = 0;
+ time_t current_la_time;
extern ENVELOPE BlankEnvelope;
extern void clrdaemon __P((void));
- extern void runqueueevent __P((bool));
+ extern void runqueueevent __P((void));
extern void drop_privileges __P((void));
+ DoQueueRun = FALSE;
+
/*
** If no work will ever be selected, don't even bother reading
** the queue.
*/
CurrentLA = getla(); /* get load average */
+ current_la_time = curtime();
- if (CurrentLA >= QueueLA)
+ if (shouldqueue(WkRecipFact, current_la_time))
{
char *msg = "Skipping queue run -- load average too high";
if (verbose)
message("458 %s\n", msg);
-#ifdef LOG
if (LogLevel > 8)
- syslog(LOG_INFO, "runqueue: %s", msg);
-#endif
+ sm_syslog(LOG_INFO, NOQID,
+ "runqueue: %s",
+ msg);
if (forkflag && QueueIntvl != 0)
- (void) setevent(QueueIntvl, runqueueevent, TRUE);
+ (void) setevent(QueueIntvl, runqueueevent, 0);
+ return FALSE;
+ }
+
+ /*
+ ** See if we already have too many children.
+ */
+
+ if (forkflag && QueueIntvl != 0 &&
+ MaxChildren > 0 && CurChildren >= MaxChildren)
+ {
+ (void) setevent(QueueIntvl, runqueueevent, 0);
return FALSE;
}
@@ -596,12 +614,12 @@ runqueue(forkflag, verbose)
if (verbose)
message("458 %s: %s\n", msg, err);
-#ifdef LOG
if (LogLevel > 8)
- syslog(LOG_INFO, "runqueue: %s: %s", msg, err);
-#endif
+ sm_syslog(LOG_INFO, NOQID,
+ "runqueue: %s: %s",
+ msg, err);
if (QueueIntvl != 0)
- (void) setevent(QueueIntvl, runqueueevent, TRUE);
+ (void) setevent(QueueIntvl, runqueueevent, 0);
(void) releasesignal(SIGCHLD);
return FALSE;
}
@@ -617,7 +635,7 @@ runqueue(forkflag, verbose)
releasesignal(SIGCHLD);
#endif /* SIGCHLD */
if (QueueIntvl != 0)
- (void) setevent(QueueIntvl, runqueueevent, TRUE);
+ (void) setevent(QueueIntvl, runqueueevent, 0);
return TRUE;
}
/* child -- double fork and clean up signals */
@@ -634,11 +652,10 @@ runqueue(forkflag, verbose)
setproctitle("running queue: %s", QueueDir);
-# ifdef LOG
if (LogLevel > 69)
- syslog(LOG_DEBUG, "runqueue %s, pid=%d, forkflag=%d",
+ sm_syslog(LOG_DEBUG, NOQID,
+ "runqueue %s, pid=%d, forkflag=%d",
QueueDir, getpid(), forkflag);
-# endif /* LOG */
/*
** Release any resources used by the daemon code.
@@ -665,7 +682,10 @@ runqueue(forkflag, verbose)
/* make sure we have disconnected from parent */
if (forkflag)
+ {
disconnect(1, e);
+ OnlyOneError = QuickAbort = FALSE;
+ }
/*
** Make sure the alias database is open.
@@ -705,17 +725,52 @@ runqueue(forkflag, verbose)
/*
** Ignore jobs that are too expensive for the moment.
+ **
+ ** Get new load average every 30 seconds.
*/
+ if (current_la_time < curtime() - 30)
+ {
+ CurrentLA = getla();
+ current_la_time = curtime();
+ }
+ if (shouldqueue(WkRecipFact, current_la_time))
+ {
+ char *msg = "Aborting queue run: load average too high";
+
+ if (Verbose)
+ message("%s", msg);
+ if (LogLevel > 8)
+ sm_syslog(LOG_INFO, NOQID,
+ "runqueue: %s",
+ msg);
+ break;
+ }
sequenceno++;
if (shouldqueue(w->w_pri, w->w_ctime))
{
if (Verbose)
- {
message("");
+ if (QueueSortOrder == QS_BYPRIORITY)
+ {
+ if (Verbose)
+ message("Skipping %s (sequence %d of %d) and flushing rest of queue",
+ w->w_name + 2,
+ sequenceno,
+ njobs);
+ if (LogLevel > 8)
+ sm_syslog(LOG_INFO, NOQID,
+ "runqueue: Flushing queue from %s (pri %ld, LA %d, %d of %d)",
+ w->w_name + 2,
+ w->w_pri,
+ CurrentLA,
+ sequenceno,
+ njobs);
+ break;
+ }
+ else if (Verbose)
message("Skipping %s (sequence %d of %d)",
w->w_name + 2, sequenceno, njobs);
- }
}
else
{
@@ -752,10 +807,9 @@ runqueue(forkflag, verbose)
*/
void
-runqueueevent(forkflag)
- bool forkflag;
+runqueueevent()
{
- (void) runqueue(forkflag, FALSE);
+ DoQueueRun = TRUE;
}
/*
** ORDERQ -- order the work queue.
@@ -843,6 +897,9 @@ orderq(doall)
if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
continue;
+ if (strlen(d->d_name) > MAXQFNAME)
+ continue;
+
if (QueueLimitId != NULL &&
!strcontainedin(QueueLimitId, d->d_name))
continue;
@@ -866,11 +923,10 @@ orderq(doall)
{
if (Verbose)
printf("orderq: bogus qf name %s\n", d->d_name);
-# ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "orderq: bogus qf name %s",
+ sm_syslog(LOG_ALERT, NOQID,
+ "orderq: bogus qf name %s",
d->d_name);
-# endif
if (strlen(d->d_name) > (SIZE_T) MAXNAME)
d->d_name[MAXNAME] = '\0';
strcpy(lbuf, d->d_name);
@@ -883,11 +939,10 @@ orderq(doall)
/* open control file (if not too many files) */
if (++wn >= MaxQueueRun && MaxQueueRun > 0)
{
-# ifdef LOG
if (wn == MaxQueueRun && LogLevel > 0)
- syslog(LOG_ALERT, "WorkList for %s maxed out at %d",
- QueueDir, MaxQueueRun);
-# endif
+ sm_syslog(LOG_ALERT, NOQID,
+ "WorkList for %s maxed out at %d",
+ QueueDir, MaxQueueRun);
continue;
}
if (wn >= WorkListSize)
@@ -930,8 +985,20 @@ orderq(doall)
while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
{
int qfver = 0;
+ char *p;
+ int c;
extern bool strcontainedin();
+ p = strchr(lbuf, '\n');
+ if (p != NULL)
+ *p = '\0';
+ else
+ {
+ /* flush rest of overly long line */
+ while ((c = getc(cf)) != EOF && c != '\n')
+ continue;
+ }
+
switch (lbuf[0])
{
case 'V':
@@ -1140,18 +1207,18 @@ grow_wlist()
{
WorkListSize = newsize;
WorkList = newlist;
-# ifdef LOG
if (LogLevel > 1)
{
- syslog(LOG_NOTICE, "grew WorkList for %s to %d",
- QueueDir, WorkListSize);
+ sm_syslog(LOG_NOTICE, NOQID,
+ "grew WorkList for %s to %d",
+ QueueDir, WorkListSize);
}
}
else if (LogLevel > 0)
{
- syslog(LOG_ALERT, "FAILED to grow WorkList for %s to %d",
- QueueDir, newsize);
-# endif
+ sm_syslog(LOG_ALERT, NOQID,
+ "FAILED to grow WorkList for %s to %d",
+ QueueDir, newsize);
}
}
if (tTd(41, 1))
@@ -1347,6 +1414,11 @@ dowork(id, forkflag, requeueflag, e)
/* parent -- clean out connection cache */
mci_flush(FALSE, NULL);
}
+ else
+ {
+ /* child -- error messages to the transcript */
+ QuickAbort = OnlyOneError = FALSE;
+ }
}
else
{
@@ -1378,11 +1450,10 @@ dowork(id, forkflag, requeueflag, e)
OpMode = MD_DELIVER;
}
setproctitle("%s: from queue", id);
-# ifdef LOG
if (LogLevel > 76)
- syslog(LOG_DEBUG, "%s: dowork, pid=%d", e->e_id,
- getpid());
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "dowork, pid=%d",
+ getpid());
/* don't use the headers from sendmail.cf... */
e->e_header = NULL;
@@ -1443,7 +1514,7 @@ readqf(e)
register char *p;
char *orcpt = NULL;
bool nomore = FALSE;
- char qf[20];
+ char qf[MAXQFNAME];
char buf[MAXLINE];
extern ADDRESS *setctluser __P((char *, int));
@@ -1468,10 +1539,8 @@ readqf(e)
/* being processed by another queuer */
if (Verbose || tTd(40, 8))
printf("%s: locked\n", e->e_id);
-# ifdef LOG
if (LogLevel > 19)
- syslog(LOG_DEBUG, "%s: locked", e->e_id);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id, "locked");
(void) fclose(qfp);
return FALSE;
}
@@ -1493,13 +1562,12 @@ readqf(e)
if ((st.st_uid != geteuid() && geteuid() != RealUid) ||
bitset(S_IWOTH|S_IWGRP, st.st_mode))
{
-# ifdef LOG
if (LogLevel > 0)
{
- syslog(LOG_ALERT, "%s: bogus queue file, uid=%d, mode=%o",
- e->e_id, st.st_uid, st.st_mode);
+ sm_syslog(LOG_ALERT, e->e_id,
+ "bogus queue file, uid=%d, mode=%o",
+ st.st_uid, st.st_mode);
}
-# endif /* LOG */
if (tTd(40, 8))
printf("readqf(%s): bogus file\n", qf);
loseqfile(e, "bogus file uid in mqueue");
@@ -1509,11 +1577,14 @@ readqf(e)
if (st.st_size == 0)
{
- /* must be a bogus file -- just remove it */
- qf[0] = 'd';
- (void) unlink(qf);
- qf[0] = 'q';
- (void) unlink(qf);
+ /* must be a bogus file -- if also old, just remove it */
+ if (st.st_ctime + 10 * 60 < curtime())
+ {
+ qf[0] = 'd';
+ (void) unlink(qf);
+ qf[0] = 'q';
+ (void) unlink(qf);
+ }
fclose(qfp);
return FALSE;
}
@@ -1636,6 +1707,7 @@ readqf(e)
hdrsize += strlen(&bp[1]);
break;
+ case 'L': /* Solaris Content-Length: */
case 'M': /* message */
/* ignore this; we want a new message next time */
break;
@@ -1648,6 +1720,12 @@ readqf(e)
e->e_bodytype = newstr(&bp[1]);
break;
+#if _FFR_SAVE_CHARSET
+ case 'X': /* character set */
+ e->e_charset = newstr(&bp[1]);
+ break;
+#endif
+
case 'D': /* data file name */
/* obsolete -- ignore */
break;
@@ -1669,7 +1747,7 @@ readqf(e)
/* if this has been tried recently, let it be */
if (e->e_ntries > 0 &&
- (curtime() - e->e_dtime) < MinQueueAge)
+ curtime() < e->e_dtime + MinQueueAge)
{
char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
extern void unlockqueue();
@@ -1677,11 +1755,10 @@ readqf(e)
if (Verbose || tTd(40, 8))
printf("%s: too young (%s)\n",
e->e_id, howlong);
-#ifdef LOG
if (LogLevel > 19)
- syslog(LOG_DEBUG, "%s: too young (%s)",
- e->e_id, howlong);
-#endif
+ sm_syslog(LOG_DEBUG, e->e_id,
+ "too young (%s)",
+ howlong);
e->e_id = NULL;
unlockqueue(e);
return FALSE;
@@ -1822,7 +1899,7 @@ printqueue()
struct stat st;
# ifdef NGROUPS_MAX
int n;
- GIDSET_T gidset[NGROUPS_MAX];
+ extern GIDSET_T InitialGidSet[NGROUPS_MAX];
# endif
if (stat(QueueDir, &st) < 0)
@@ -1831,10 +1908,10 @@ printqueue()
return;
}
# ifdef NGROUPS_MAX
- n = getgroups(NGROUPS_MAX, gidset);
+ n = NGROUPS_MAX;
while (--n >= 0)
{
- if (gidset[n] == st.st_gid)
+ if (InitialGidSet[n] == st.st_gid)
break;
}
if (n < 0 && RealGid != st.st_gid)
@@ -2037,7 +2114,7 @@ queuename(e, type)
if (e->e_id == NULL)
{
- char qf[20];
+ char qf[MAXQFNAME];
/* find a unique id */
if (pid != getpid())
@@ -2100,10 +2177,8 @@ queuename(e, type)
printf(" lockfd=");
dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
}
-# ifdef LOG
if (LogLevel > 93)
- syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
}
if (type == '\0')
@@ -2144,10 +2219,8 @@ unlockqueue(e)
return;
/* remove the transcript */
-# ifdef LOG
if (LogLevel > 87)
- syslog(LOG_DEBUG, "%s: unlock", e->e_id);
-# endif /* LOG */
+ sm_syslog(LOG_DEBUG, e->e_id, "unlock");
if (!tTd(51, 104))
xunlink(queuename(e, 'x'));
@@ -2252,7 +2325,7 @@ loseqfile(e, why)
char *why;
{
char *p;
- char buf[40];
+ char buf[MAXQFNAME];
if (e == NULL || e->e_id == NULL)
return;
@@ -2262,8 +2335,7 @@ loseqfile(e, why)
p = queuename(e, 'Q');
if (rename(buf, p) < 0)
syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid());
-#ifdef LOG
else if (LogLevel > 0)
- syslog(LOG_ALERT, "Losing %s: %s", buf, why);
-#endif
+ sm_syslog(LOG_ALERT, e->e_id,
+ "Losing %s: %s", buf, why);
}
diff --git a/usr.sbin/sendmail/src/readcf.c b/usr.sbin/sendmail/src/readcf.c
index ca0100f1c4fff..23470e3ae40a9 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 92e6bc379c195..2076884f09035 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/safefile.c b/usr.sbin/sendmail/src/safefile.c
new file mode 100644
index 0000000000000..08660347cafef
--- /dev/null
+++ b/usr.sbin/sendmail/src/safefile.c
@@ -0,0 +1,686 @@
+/*
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
+ * Copyright (c) 1988, 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)safefile.c 8.12 (Berkeley) 6/14/97";
+#endif /* not lint */
+
+# include "sendmail.h"
+ /*
+** 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
+
+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;
+ bool checkpath;
+ struct stat stbuf;
+ struct stat fstbuf;
+ char fbuf[MAXPATHLEN + 1];
+
+ 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;
+ if (strlen(fn) > sizeof fbuf - 1)
+ {
+ if (tTd(44, 4))
+ printf("\tpathname too long\n");
+ return ENAMETOOLONG;
+ }
+ strcpy(fbuf, fn);
+ fn = fbuf;
+
+ /* 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;
+ }
+
+ checkpath = !bitset(SFF_NOPATHCHECK, flags) ||
+ (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags));
+ if (bitset(SFF_NOWLINK, flags) && !bitset(SFF_SAFEDIRPATH, flags))
+ {
+ int ret;
+
+ /* check the directory */
+ p = strrchr(fn, '/');
+ if (p == NULL)
+ {
+ ret = safedirpath(".", uid, gid, uname, flags|SFF_SAFEDIRPATH);
+ }
+ else
+ {
+ *p = '\0';
+ ret = safedirpath(fn, uid, gid, uname, flags|SFF_SAFEDIRPATH);
+ *p = '/';
+ }
+ if (ret == 0)
+ {
+ /* directory is safe */
+ checkpath = FALSE;
+ }
+ else
+ {
+ /* directory is writable: disallow links */
+ flags |= SFF_NOLINK;
+ }
+ }
+
+ if (checkpath)
+ {
+ int ret;
+
+ p = strrchr(fn, '/');
+ if (p == NULL)
+ {
+ ret = safedirpath(".", uid, gid, uname, flags);
+ }
+ else
+ {
+ *p = '\0';
+ ret = safedirpath(fn, uid, gid, uname, flags);
+ *p = '/';
+ }
+ if (ret != 0)
+ 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;
+ char *dir = fn;
+
+ if (tTd(44, 4))
+ printf("\t%s\n", errstring(ret));
+
+ errno = 0;
+ if (!bitset(SFF_CREAT, flags) || file_errno != ENOENT)
+ return ret;
+
+ /* check to see if legal to create the file */
+ p = strrchr(dir, '/');
+ if (p == NULL)
+ dir = ".";
+ else if (p == dir)
+ dir = "/";
+ else
+ *p = '\0';
+ if (stat(dir, &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",
+ dir, (int) stbuf.st_uid, (u_long) stbuf.st_mode,
+ errstring(ret));
+ if (p != NULL)
+ *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]\tE_SM_NOSLINK\n",
+ st->st_mode);
+ return E_SM_NOSLINK;
+ }
+#endif
+ if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[non-reg mode %o]\tE_SM_REGONLY\n",
+ st->st_mode);
+ return E_SM_REGONLY;
+ }
+ if (bitset(SFF_NOWFILES, flags) &&
+ bitset(S_IWOTH | (UnsafeGroupWrites ? S_IWGRP : 0), st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[write bits %o]\tE_SM_%cWFILE\n",
+ st->st_mode,
+ bitset(S_IWOTH, st->st_mode) ? 'W' : 'G');
+ return bitset(S_IWOTH, st->st_mode) ? E_SM_WWFILE : E_SM_GWFILE;
+ }
+ 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]\tE_SM_ISEXEC]\n",
+ st->st_mode);
+ return E_SM_ISEXEC;
+ }
+ if (bitset(SFF_NOHLINK, flags) && st->st_nlink != 1)
+ {
+ if (tTd(44, 4))
+ printf("\t[link count %d]\tE_SM_NOHLINK\n",
+ st->st_nlink);
+ return E_SM_NOHLINK;
+ }
+
+ 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;
+}
+ /*
+** SAFEDIRPATH -- check to make sure a path to a directory is safe
+**
+** Safe means not writable and owned by the right folks.
+**
+** 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_ROOTOK -- ok to use root permissions to open.
+** SFF_SAFEDIRPATH -- writable directories are considered
+** to be fatal errors.
+**
+** Returns:
+** 0 -- if the directory path is "safe".
+** else -- an error number associated with the path.
+*/
+
+int
+safedirpath(fn, uid, gid, uname, flags)
+ char *fn;
+ UID_T uid;
+ GID_T gid;
+ char *uname;
+ int flags;
+{
+ char *p;
+ register struct group *gr = NULL;
+ int ret = 0;
+ struct stat stbuf;
+
+ /* special case root directory */
+ if (*fn == '\0')
+ fn = "/";
+
+ if (tTd(44, 4))
+ printf("safedirpath(%s, uid=%ld, gid=%ld, flags=%x):\n",
+ fn, (long) uid, (long) gid, flags);
+
+ p = fn;
+ do
+ {
+ if (*p == '\0')
+ *p = '/';
+ p = strchr(++p, '/');
+ if (p != NULL)
+ *p = '\0';
+ if (stat(fn, &stbuf) < 0)
+ {
+ ret = errno;
+ break;
+ }
+ if ((uid == 0 || bitset(SFF_SAFEDIRPATH, flags)) &&
+ bitset(S_IWGRP|S_IWOTH, stbuf.st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[dir %s] mode %o\n",
+ fn, stbuf.st_mode);
+ if (bitset(SFF_SAFEDIRPATH, flags))
+ {
+ if (bitset(S_IWOTH, stbuf.st_mode))
+ ret = E_SM_WWDIR;
+ else
+ ret = E_SM_GWDIR;
+ break;
+ }
+ if (Verbose > 1)
+ message("051 WARNING: writable directory %s", fn);
+ }
+ if (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags))
+ {
+ if (bitset(S_IXOTH, stbuf.st_mode))
+ continue;
+ ret = EACCES;
+ 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))
+ {
+ ret = EACCES;
+ break;
+ }
+ } while (p != NULL);
+ if (ret != 0 && tTd(44, 4))
+ printf("\t[dir %s] %s\n", fn, errstring(ret));
+ if (p != NULL)
+ *p = '/';
+ return ret;
+}
+ /*
+** SAFEOPEN -- 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 open.
+*/
+
+#ifndef O_ACCMODE
+# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
+#endif
+
+int
+safeopen(fn, omode, cmode, sff)
+ char *fn;
+ int omode;
+ int cmode;
+ int sff;
+{
+ int rval;
+ int fd;
+ int smode;
+ struct stat stb;
+
+ 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, RunAsUid, RunAsGid, RunAsUserName,
+ sff, smode, &stb);
+ else
+ rval = safefile(fn, RealUid, RealGid, RealUserName,
+ sff, smode, &stb);
+ if (rval != 0)
+ {
+ errno = rval;
+ return -1;
+ }
+ if (stb.st_mode == ST_MODE_NOFILE)
+ omode |= O_EXCL;
+
+ fd = dfopen(fn, omode, cmode, sff);
+ if (fd < 0)
+ return fd;
+ if (filechanged(fn, fd, &stb, sff))
+ {
+ syserr("554 cannot open: file %s changed after open", fn);
+ close(fd);
+ errno = E_SM_FILECHANGE;
+ return -1;
+ }
+ return fd;
+}
+ /*
+** 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.
+*/
+
+FILE *
+safefopen(fn, omode, cmode, sff)
+ char *fn;
+ int omode;
+ int cmode;
+ int sff;
+{
+ int fd;
+ FILE *fp;
+ char *fmode;
+
+ switch (omode & O_ACCMODE)
+ {
+ case O_RDONLY:
+ fmode = "r";
+ break;
+
+ case O_WRONLY:
+ if (bitset(O_APPEND, omode))
+ fmode = "a";
+ else
+ fmode = "w";
+ break;
+
+ case O_RDWR:
+ if (bitset(O_TRUNC, omode))
+ fmode = "w+";
+ else if (bitset(O_APPEND, omode))
+ fmode = "a+";
+ else
+ fmode = "r+";
+ break;
+
+ default:
+ syserr("safefopen: unknown omode %o", omode);
+ fmode = "x";
+ }
+ fd = safeopen(fn, omode, cmode, sff);
+ if (fd < 0)
+ return NULL;
+ fp = fdopen(fd, fmode);
+ if (fp != NULL)
+ return fp;
+ (void) close(fd);
+ return NULL;
+}
+ /*
+** FILECHANGED -- check to see if file changed after being opened
+**
+** Parameters:
+** fn -- pathname of file to check.
+** fd -- file descriptor to check.
+** stb -- stat structure from before open.
+** sff -- safe file flags.
+**
+** Returns:
+** TRUE -- if a problem was detected.
+** FALSE -- if this file is still the same.
+*/
+
+bool
+filechanged(fn, fd, stb, sff)
+ char *fn;
+ int fd;
+ struct stat *stb;
+ int sff;
+{
+ struct stat sta;
+
+ if (stb->st_mode == ST_MODE_NOFILE)
+ {
+#if HASLSTAT && BOGUS_O_EXCL
+ /* only necessary if exclusive open follows symbolic links */
+ if (lstat(fn, stb) < 0 || stb->st_nlink != 1)
+ return TRUE;
+#else
+ return FALSE;
+#endif
+ }
+ if (fstat(fd, &sta) < 0)
+ return TRUE;
+
+ if (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)
+ {
+ if (tTd(44, 8))
+ {
+ printf("File changed after opening:\n");
+ printf(" nlink = %ld/%ld\n",
+ (long) stb->st_nlink, (long) sta.st_nlink);
+ printf(" dev = %ld/%ld\n",
+ (long) stb->st_dev, (long) sta.st_dev);
+ printf(" ino = %ld/%ld\n",
+ (long) stb->st_ino, (long) sta.st_ino);
+ printf(" uid = %ld/%ld\n",
+ (long) stb->st_uid, (long) sta.st_uid);
+ printf(" gid = %ld/%ld\n",
+ (long) stb->st_gid, (long) sta.st_gid);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+ /*
+** DFOPEN -- determined file open
+**
+** This routine has the semantics of open, 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.
+*/
+
+int
+dfopen(filename, omode, cmode, sff)
+ char *filename;
+ int omode;
+ int cmode;
+ int sff;
+{
+ register int tries;
+ int fd;
+ struct stat st;
+
+ 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 (!bitset(SFF_NOLOCK, sff) &&
+ 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;
+ }
+ return fd;
+}
diff --git a/usr.sbin/sendmail/src/savemail.c b/usr.sbin/sendmail/src/savemail.c
index 0d949f8749ebf..9cabcfa4b4460 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 81a4440f11aac..9a0a687f87638 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 9c0e3e2b4ef62..2eb40c8d6a987 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/sendmail.hf b/usr.sbin/sendmail/src/sendmail.hf
index add62c1ae6de5..7ab6d6139e18c 100644
--- a/usr.sbin/sendmail/src/sendmail.hf
+++ b/usr.sbin/sendmail/src/sendmail.hf
@@ -1,9 +1,9 @@
cpyr
-cpyr Copyright (c) 1983, 1995, 1996 Eric P. Allman
+cpyr Copyright (c) 1983, 1995-1997 Eric P. Allman
cpyr Copyright (c) 1988, 1993
cpyr The Regents of the University of California. All rights reserved.
cpyr
-cpyr @(#)sendmail.hf 8.11 (Berkeley) 9/11/96
+cpyr @(#)sendmail.hf 8.12 (Berkeley) 2/1/97
cpyr
smtp Topics:
smtp HELO EHLO MAIL RCPT DATA
diff --git a/usr.sbin/sendmail/src/srvrsmtp.c b/usr.sbin/sendmail/src/srvrsmtp.c
index 83bd46389a92d..ca40a75c1c689 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/stab.c b/usr.sbin/sendmail/src/stab.c
index a9d8736a27089..7d480b901331e 100644
--- a/usr.sbin/sendmail/src/stab.c
+++ b/usr.sbin/sendmail/src/stab.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[] = "@(#)stab.c 8.10 (Berkeley) 11/23/96";
+static char sccsid[] = "@(#)stab.c 8.13 (Berkeley) 4/19/97";
#endif /* not lint */
# include "sendmail.h"
@@ -131,11 +131,7 @@ stab(name, type, op)
printf("entered\n");
/* determine size of new entry */
-#ifdef _FFR_MEMORY_MISER
- if (type >= ST_MCI)
- len = sizeof s->s_mci;
- else
- len = -1;
+#if _FFR_MEMORY_MISER
switch (type)
{
case ST_CLASS:
@@ -180,11 +176,20 @@ stab(name, type, op)
case ST_SERVICE:
len = sizeof s->s_service;
break;
- }
- if (len < 0)
- {
- syserr("stab: unknown symbol type %d", type);
- len = sizeof s->s_value;
+
+ case ST_HEADER:
+ len = sizeof s->s_header;
+ break;
+
+ default:
+ if (type >= ST_MCI)
+ len = sizeof s->s_mci;
+ else
+ {
+ syserr("stab: unknown symbol type %d", type);
+ len = sizeof s->s_value;
+ }
+ break;
}
len += sizeof *s - sizeof s->s_value;
#else
diff --git a/usr.sbin/sendmail/src/stats.c b/usr.sbin/sendmail/src/stats.c
index 6d3aaedca4db0..cb0f9dd761dbe 100644
--- a/usr.sbin/sendmail/src/stats.c
+++ b/usr.sbin/sendmail/src/stats.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[] = "@(#)stats.c 8.6 (Berkeley) 2/21/96";
+static char sccsid[] = "@(#)stats.c 8.11 (Berkeley) 4/9/97";
#endif /* not lint */
# include "sendmail.h"
@@ -97,13 +97,12 @@ poststats(sfile)
(void) time(&Stat.stat_itime);
Stat.stat_size = sizeof Stat;
- fd = open(sfile, O_RDWR);
+ fd = safeopen(sfile, O_RDWR, 0644, SFF_REGONLY|SFF_NOLINK|SFF_OPENASROOT);
if (fd < 0)
{
errno = 0;
return;
}
- (void) lockfile(fd, sfile, NULL, LOCK_EX);
if (read(fd, (char *) &stat, sizeof stat) == sizeof stat &&
stat.stat_size == sizeof stat)
{
diff --git a/usr.sbin/sendmail/src/sysexits.c b/usr.sbin/sendmail/src/sysexits.c
index cc1022a14e7d2..36955363ebeb8 100644
--- a/usr.sbin/sendmail/src/sysexits.c
+++ b/usr.sbin/sendmail/src/sysexits.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[] = "@(#)sysexits.c 8.6 (Berkeley) 2/21/96";
+static char sccsid[] = "@(#)sysexits.c 8.7 (Berkeley) 2/1/97";
#endif /* not lint */
#include <sendmail.h>
diff --git a/usr.sbin/sendmail/src/trace.c b/usr.sbin/sendmail/src/trace.c
index 380ecb5654008..49a1ae0148661 100644
--- a/usr.sbin/sendmail/src/trace.c
+++ b/usr.sbin/sendmail/src/trace.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[] = "@(#)trace.c 8.5 (Berkeley) 2/21/96";
+static char sccsid[] = "@(#)trace.c 8.6 (Berkeley) 2/1/97";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/udb.c b/usr.sbin/sendmail/src/udb.c
index bb54ee8eb5a7c..cf77bdca376de 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/useful.h b/usr.sbin/sendmail/src/useful.h
index 309a0df9db0fa..59182febc15c8 100644
--- a/usr.sbin/sendmail/src/useful.h
+++ b/usr.sbin/sendmail/src/useful.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 1996 Eric P. Allman
+ * Copyright (c) 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -31,15 +31,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)useful.h 8.5 (Berkeley) 2/21/96
+ * @(#)useful.h 8.7 (Berkeley) 5/29/97
*/
# include <sys/types.h>
/* support for bool type */
typedef int bool;
+#ifndef TRUE
# define TRUE 1
# define FALSE 0
+#endif
# ifndef NULL
# define NULL 0
diff --git a/usr.sbin/sendmail/src/usersmtp.c b/usr.sbin/sendmail/src/usersmtp.c
index d98841a85387c..475a0dc2aa25c 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 dbe76552394a6..98435f3aa7fef 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);
+}
diff --git a/usr.sbin/sendmail/src/version.c b/usr.sbin/sendmail/src/version.c
index a6b4f168ce1e7..6f6ffad0c8eab 100644
--- a/usr.sbin/sendmail/src/version.c
+++ b/usr.sbin/sendmail/src/version.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)version.c 8.8.5.3 (Berkeley) 1/21/97";
+static char sccsid[] = "@(#)version.c 8.8.6.1 (Berkeley) 6/14/97";
#endif /* not lint */
-char Version[] = "8.8.5";
+char Version[] = "8.8.6";