summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src
diff options
context:
space:
mode:
authorgshapiro <gshapiro@FreeBSD.org>2004-08-01 01:04:57 +0000
committergshapiro <gshapiro@FreeBSD.org>2004-08-01 01:04:57 +0000
commit1fc446a819a244515d9461fa50d34ee191414d6f (patch)
treef6477ae85b00ee6d58b086b0d1d597dd9a403391 /contrib/sendmail/src
parent238623a0204c90e8d61dbde7b3b499a5036f2e5d (diff)
downloadFreeBSD-src-1fc446a819a244515d9461fa50d34ee191414d6f.zip
FreeBSD-src-1fc446a819a244515d9461fa50d34ee191414d6f.tar.gz
Import sendmail 8.13.1
Diffstat (limited to 'contrib/sendmail/src')
-rw-r--r--contrib/sendmail/src/Makefile.m44
-rw-r--r--contrib/sendmail/src/README43
-rw-r--r--contrib/sendmail/src/SECURITY2
-rw-r--r--contrib/sendmail/src/TRACEFLAGS16
-rw-r--r--contrib/sendmail/src/TUNING2
-rw-r--r--contrib/sendmail/src/alias.c4
-rw-r--r--contrib/sendmail/src/aliases.515
-rw-r--r--contrib/sendmail/src/bf.c7
-rw-r--r--contrib/sendmail/src/collect.c31
-rw-r--r--contrib/sendmail/src/conf.c276
-rw-r--r--contrib/sendmail/src/conf.h12
-rw-r--r--contrib/sendmail/src/control.c2
-rw-r--r--contrib/sendmail/src/daemon.c120
-rw-r--r--contrib/sendmail/src/deliver.c209
-rw-r--r--contrib/sendmail/src/domain.c108
-rw-r--r--contrib/sendmail/src/envelope.c40
-rw-r--r--contrib/sendmail/src/err.c6
-rw-r--r--contrib/sendmail/src/headers.c206
-rw-r--r--contrib/sendmail/src/macro.c18
-rw-r--r--contrib/sendmail/src/mailq.118
-rw-r--r--contrib/sendmail/src/main.c191
-rw-r--r--contrib/sendmail/src/map.c1189
-rw-r--r--contrib/sendmail/src/mci.c16
-rw-r--r--contrib/sendmail/src/milter.c403
-rw-r--r--contrib/sendmail/src/mime.c12
-rw-r--r--contrib/sendmail/src/parseaddr.c178
-rw-r--r--contrib/sendmail/src/queue.c375
-rw-r--r--contrib/sendmail/src/ratectrl.c534
-rw-r--r--contrib/sendmail/src/readcf.c231
-rw-r--r--contrib/sendmail/src/recipient.c45
-rw-r--r--contrib/sendmail/src/sasl.c4
-rw-r--r--contrib/sendmail/src/savemail.c15
-rw-r--r--contrib/sendmail/src/sendmail.822
-rw-r--r--contrib/sendmail/src/sendmail.h232
-rw-r--r--contrib/sendmail/src/sfsasl.c16
-rw-r--r--contrib/sendmail/src/sm_resolve.c2
-rw-r--r--contrib/sendmail/src/srvrsmtp.c620
-rw-r--r--contrib/sendmail/src/stab.c8
-rw-r--r--contrib/sendmail/src/stats.c6
-rw-r--r--contrib/sendmail/src/sysexits.c2
-rw-r--r--contrib/sendmail/src/tls.c142
-rw-r--r--contrib/sendmail/src/trace.c2
-rw-r--r--contrib/sendmail/src/udb.c10
-rw-r--r--contrib/sendmail/src/usersmtp.c63
-rw-r--r--contrib/sendmail/src/util.c221
-rw-r--r--contrib/sendmail/src/version.c4
46 files changed, 3674 insertions, 2008 deletions
diff --git a/contrib/sendmail/src/Makefile.m4 b/contrib/sendmail/src/Makefile.m4
index 1100dea..5cf0f78 100644
--- a/contrib/sendmail/src/Makefile.m4
+++ b/contrib/sendmail/src/Makefile.m4
@@ -1,11 +1,11 @@
-dnl $Id: Makefile.m4,v 8.91.2.4 2002/09/09 02:48:54 gshapiro Exp $
+dnl $Id: Makefile.m4,v 8.96 2003/08/08 20:31:17 ca Exp $
include(confBUILDTOOLSDIR`/M4/switch.m4')
define(`confREQUIRE_LIBSM', `true')
bldPRODUCT_START(`executable', `sendmail')
define(`bldBIN_TYPE', `G')
define(`bldINSTALL_DIR', `')
-define(`bldSOURCES', `main.c alias.c arpadate.c bf.c collect.c conf.c control.c convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c macro.c map.c mci.c milter.c mime.c parseaddr.c queue.c readcf.c recipient.c sasl.c savemail.c sfsasl.c shmticklib.c sm_resolve.c srvrsmtp.c stab.c stats.c sysexits.c timers.c tls.c trace.c udb.c usersmtp.c util.c version.c ')
+define(`bldSOURCES', `main.c alias.c arpadate.c bf.c collect.c conf.c control.c convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c macro.c map.c mci.c milter.c mime.c parseaddr.c queue.c ratectrl.c readcf.c recipient.c sasl.c savemail.c sfsasl.c shmticklib.c sm_resolve.c srvrsmtp.c stab.c stats.c sysexits.c timers.c tls.c trace.c udb.c usersmtp.c util.c version.c ')
PREPENDDEF(`confENVDEF', `confMAPDEF')
bldPUSH_SMLIB(`sm')
bldPUSH_SMLIB(`smutil')
diff --git a/contrib/sendmail/src/README b/contrib/sendmail/src/README
index e0af96b..b2e11c4 100644
--- a/contrib/sendmail/src/README
+++ b/contrib/sendmail/src/README
@@ -1,4 +1,4 @@
-# Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+# Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
# All rights reserved.
# Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
# Copyright (c) 1988
@@ -9,7 +9,7 @@
# the sendmail distribution.
#
#
-# $Id: README,v 8.355.2.16 2004/01/08 21:54:55 ca Exp $
+# $Id: README,v 8.384 2004/07/26 18:03:55 ca Exp $
#
This directory contains the source files for sendmail(TM).
@@ -127,6 +127,8 @@ DNSMAP DNS map support. Requires NAMED_BIND.
PH_MAP PH map support. You will need the libphclient library from
the nph package (http://www-dev.cites.uiuc.edu/ph/nph/).
MAP_NSD nsd map support (IRIX 6.5 and later).
+SOCKETMAP Support for a trivial query protocol over UNIX domain or TCP
+ sockets.
>>> NOTE WELL for NEWDB support: If you want to get ndbm support, for
>>> Berkeley DB versions under 2.0, it is CRITICAL that you remove
@@ -180,6 +182,15 @@ addresses, so "^[0-9]+$" would match this. By using such a map in a
check_* rule-set, you can block a certain range of addresses that would
otherwise be considered valid.
+The socket map uses a simple request/reply protocol over TCP or
+UNIX domain sockets to query an external server. Both requests and
+replies are text based and encoded as netstrings. The socket map
+uses the same syntax as milters the specify the remote endpoint,
+e.g.:
+
+Ksocket mySocketMap inet:12345@127.0.0.1
+
+See doc/op/op.me for details.
+---------------+
| COMPILE FLAGS |
@@ -287,6 +298,8 @@ HASURANDOMDEV Define this if your system has /dev/urandom(4).
HASSTRERROR Define this if you have the libc strerror(3) function (which
should be declared in <errno.h>), and it should be used
instead of sys_errlist.
+HASCLOSEFROM Define this if your system has closefrom(3).
+HASFDWALK Define this if your system has fdwalk(3).
SM_CONF_GETOPT Define this as 0 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
@@ -481,6 +494,11 @@ USE_DOUBLE_FORK By default this is on (1). Set it to 0 to suppress the
ALLOW_255 Do not convert (char)0xff to (char)0x7f in headers etc.
This can also be done at runtime with the command line
option -d82.101.
+NEEDINTERRNO Set this if <errno.h> does not declare errno, i.e., if an
+ application needs to use
+ extern int errno;
+USE_TTYPATH Set this to 1 to enable ErrorMode=write.
+USESYSCTL Use sysctl(3) to determine the number of CPUs in a system.
+-----------------------+
@@ -604,8 +622,11 @@ STARTTLS Enables SMTP STARTTLS (RFC 2487). This requires OpenSSL
See STARTTLS COMPILATION AND CONFIGURATION for further
information.
TLS_NO_RSA Turn off support for RSA algorithms in STARTTLS.
-MILTER Turn on support for external filters using the Milter API.
- See libmilter/README for more information.
+MILTER Turn on support for external filters using the Milter API;
+ this option is set by default, to turn it off use
+ APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER')
+ in devtools/Site/site.config.m4 (see devtools/README).
+ See libmilter/README for more information about milter.
REQUIRES_DIR_FSYNC Turn on support for file systems that require to
call fsync() for a directory if the meta-data in it has
been changed. This should be turned on at least for older
@@ -1303,12 +1324,12 @@ Linux
Something broke between versions 0.99.13 and 0.99.14 of Linux: the
flock() system call gives errors. If you are running .14, you must
not use flock. You can do this with -DHASFLOCK=0. We have also
- been getting complaints since version 2.4.X was released. Unless
- the bug is fixed before sendmail 8.13 is shipped, 8.13 will change
- the default locking method to fcntl() for Linux kernel version 2.4
- and later. Be sure to update other sendmail related programs to
- match locking techniques (some examples, besides makemap and
- mail.local, include procmail, mailx, mutt, elm, etc).
+ been getting complaints since version 2.4.X was released.
+ sendmail 8.13 has changed the default locking method to fcntl()
+ for Linux kernel version 2.4 and later. Be sure to update other
+ sendmail related programs to match locking techniques (some
+ examples, besides makemap and mail.local, include procmail, mailx,
+ mutt, elm, etc).
Around the inclusion of bind-4.9.3 & Linux libc-4.6.20, the
initialization of the _res structure changed. If /etc/hosts.conf
@@ -1802,4 +1823,4 @@ util.c Some general purpose routines used by sendmail.
version.c The version number and information about this
version of sendmail.
-(Version $Revision: 8.355.2.16 $, last update $Date: 2004/01/08 21:54:55 $ )
+(Version $Revision: 8.384 $, last update $Date: 2004/07/26 18:03:55 $ )
diff --git a/contrib/sendmail/src/SECURITY b/contrib/sendmail/src/SECURITY
index 71b4643..0445e44 100644
--- a/contrib/sendmail/src/SECURITY
+++ b/contrib/sendmail/src/SECURITY
@@ -5,7 +5,7 @@
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
-# $Id: SECURITY,v 1.50.2.1 2002/09/23 21:28:48 ca Exp $
+# $Id: SECURITY,v 1.51 2002/09/23 21:29:18 ca Exp $
#
This file gives some hints how to configure and run sendmail for
diff --git a/contrib/sendmail/src/TRACEFLAGS b/contrib/sendmail/src/TRACEFLAGS
index 1d7d28b..9927922 100644
--- a/contrib/sendmail/src/TRACEFLAGS
+++ b/contrib/sendmail/src/TRACEFLAGS
@@ -1,4 +1,4 @@
-# $Id: TRACEFLAGS,v 8.37.2.4 2003/06/13 21:59:45 lijian Exp $
+# $Id: TRACEFLAGS,v 8.42 2003/06/13 22:29:11 lijian Exp $
0, 4 main.c main canonical name, UUCP node name, a.k.a.s
0, 15 main.c main print configuration
0, 44 util.c printav print address of each string
@@ -75,15 +75,13 @@
63 queue.c runqueue process watching
64 multiple Milter
65 main.c permission checks
-#if _FFR_ADAPTIVE_EOL
-66 srvrsmtp.c conformance checks
-#endif /* _FFR_ADAPTIVE_EOL */
-#if _FFR_QUEUE_SCHED_DBG
-69 queue.c scheduling
-#endif /* _FFR_QUEUE_SCHED_DBG */
-#if _FFR_QUARANTINE
+#if _FFR_ADAPTIVE_EOL
+66 srvrsmtp.c conformance checks
+#endif /* _FFR_ADAPTIVE_EOL */
+#if _FFR_QUEUE_SCHED_DBG
+69 queue.c scheduling
+#endif /* _FFR_QUEUE_SCHED_DBG */
70 queue.c quarantining
-#endif /* _FFR_QUARANTINE */
71,>99 milter.c quarantine on errors
80 content length
81 sun remote mode
diff --git a/contrib/sendmail/src/TUNING b/contrib/sendmail/src/TUNING
index 61121cb..6ccff9a 100644
--- a/contrib/sendmail/src/TUNING
+++ b/contrib/sendmail/src/TUNING
@@ -5,7 +5,7 @@
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
-# $Id: TUNING,v 1.18.4.1 2003/02/07 18:19:51 ca Exp $
+# $Id: TUNING,v 1.19 2003/01/25 23:06:02 ca Exp $
#
********************************************
diff --git a/contrib/sendmail/src/alias.c b/contrib/sendmail/src/alias.c
index c944388..3c05212 100644
--- a/contrib/sendmail/src/alias.c
+++ b/contrib/sendmail/src/alias.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: alias.c,v 8.214.2.2 2003/10/06 20:43:29 ca Exp $")
+SM_RCSID("@(#)$Id: alias.c,v 8.217 2003/07/28 17:47:18 ca Exp $")
#define SEPARATOR ':'
# define ALIAS_SPEC_SEPARATORS " ,/:"
@@ -139,7 +139,7 @@ alias(a, sendq, aliaslevel, e)
if (tTd(27, 5))
{
sm_dprintf("alias: QS_EXPANDED ");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
a->q_state = QS_EXPANDED;
diff --git a/contrib/sendmail/src/aliases.5 b/contrib/sendmail/src/aliases.5
index 62b5dfb..32fb50c 100644
--- a/contrib/sendmail/src/aliases.5
+++ b/contrib/sendmail/src/aliases.5
@@ -9,9 +9,9 @@
.\" the sendmail distribution.
.\"
.\"
-.\" $Id: aliases.5,v 8.17 2000/12/14 23:09:46 gshapiro Exp $
+.\" $Id: aliases.5,v 8.19 2004/07/12 05:39:21 ca Exp $
.\"
-.TH ALIASES 5 "$Date: 2000/12/14 23:09:46 $"
+.TH ALIASES 5 "$Date: 2004/07/12 05:39:21 $"
.SH NAME
aliases
\- aliases file for sendmail
@@ -78,6 +78,17 @@ are comments.
Aliasing occurs only on local names.
Loops can not occur, since no message will be sent to any person more than once.
.PP
+If an alias is found for
+.IR name ,
+sendmail then checks for an alias for
+.IR owner-name .
+If it is found and the result of the lookup expands to a single
+address, the envelope sender address of the message is rewritten to
+that address.
+If it is found and the result expands to more than one address, the
+envelope sender address is changed to
+.IR owner-name .
+.PP
After aliasing has been done, local and valid recipients who have a
``.forward''
file in their home directory have messages forwarded to the
diff --git a/contrib/sendmail/src/bf.c b/contrib/sendmail/src/bf.c
index 4e672b9..211ed02 100644
--- a/contrib/sendmail/src/bf.c
+++ b/contrib/sendmail/src/bf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2002, 2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -18,7 +18,7 @@
*/
#include <sm/gen.h>
-SM_RCSID("@(#)$Id: bf.c,v 8.54.2.3 2003/09/03 19:58:26 ca Exp $")
+SM_RCSID("@(#)$Id: bf.c,v 8.60 2004/04/14 18:12:49 ca Exp $")
#include <sys/types.h>
#include <sys/stat.h>
@@ -701,7 +701,8 @@ sm_bfcommit(fp)
/* Clear umask as bf_filemode are the true perms */
omask = umask(0);
- retval = OPEN(bfp->bf_filename, O_RDWR | O_CREAT | O_EXCL,
+ retval = OPEN(bfp->bf_filename,
+ O_RDWR | O_CREAT | O_EXCL | QF_O_EXTRA,
bfp->bf_filemode, bfp->bf_flags);
save_errno = errno;
(void) umask(omask);
diff --git a/contrib/sendmail/src/collect.c b/contrib/sendmail/src/collect.c
index 20a2c1c..392941b 100644
--- a/contrib/sendmail/src/collect.c
+++ b/contrib/sendmail/src/collect.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,10 +13,9 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: collect.c,v 8.242.2.8 2003/07/08 01:16:35 ca Exp $")
+SM_RCSID("@(#)$Id: collect.c,v 8.254 2004/04/05 18:41:38 ca Exp $")
static void collecttimeout __P((time_t));
-static void dferror __P((SM_FILE_T *volatile, char *, ENVELOPE *));
static void eatfrom __P((char *volatile, ENVELOPE *));
static void collect_doheader __P((ENVELOPE *));
static SM_FILE_T *collect_dfopen __P((ENVELOPE *));
@@ -724,7 +723,9 @@ readerr:
finis(true, true, ExitStat);
/* NOTREACHED */
}
- else if (SuperSafe != SAFE_REALLY)
+ else if (SuperSafe == SAFE_NO ||
+ SuperSafe == SAFE_INTERACTIVE ||
+ (SuperSafe == SAFE_REALLY_POSTMILTER && smtpmode))
{
/* skip next few clauses */
/* EMPTY */
@@ -743,7 +744,7 @@ readerr:
if (stat(dfile, &st) < 0)
st.st_size = -1;
errno = EEXIST;
- syserr("@collect: bfcommit(%s): already on disk, size = %ld",
+ syserr("@collect: bfcommit(%s): already on disk, size=%ld",
dfile, (long) st.st_size);
dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
if (dfd >= 0)
@@ -754,8 +755,14 @@ readerr:
flush_errors(true);
finis(save_errno != EEXIST, true, ExitStat);
}
- else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) >= 0 &&
- fsync(afd) < 0)
+ else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
+ {
+ dferror(df, "sm_io_getinfo", e);
+ flush_errors(true);
+ finis(true, true, ExitStat);
+ /* NOTREACHED */
+ }
+ else if (fsync(afd) < 0)
{
dferror(df, "fsync", e);
flush_errors(true);
@@ -873,7 +880,7 @@ readerr:
{
char *dfname = queuename(e, DATAFL_LETTER);
if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
- SM_IO_RDONLY, NULL)) == NULL)
+ SM_IO_RDONLY_B, NULL)) == NULL)
{
/* we haven't acked receipt yet, so just chuck this */
syserr("@Cannot reopen %s", dfname);
@@ -896,10 +903,6 @@ readerr:
e->e_msgpriority = e->e_msgsize
- e->e_class * WkClassFact
+ e->e_nrcpts * WkRecipFact;
- if (tTd(90, 1))
- sm_syslog(LOG_INFO, e->e_id,
- "collect: at end: msgsize=%ld, msgpriority=%ld",
- e->e_msgsize, e->e_msgpriority);
markstats(e, (ADDRESS *) NULL, STATS_NORMAL);
}
}
@@ -958,7 +961,7 @@ collecttimeout(timeout)
** Arranges for following output to go elsewhere.
*/
-static void
+void
dferror(df, msg, e)
SM_FILE_T *volatile df;
char *msg;
@@ -989,7 +992,7 @@ dferror(df, msg, e)
< 0)
st.st_size = 0;
(void) sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, dfname,
- SM_IO_WRONLY, NULL, df);
+ SM_IO_WRONLY_B, NULL, df);
if (st.st_size <= 0)
(void) sm_io_fprintf(df, SM_TIME_DEFAULT,
"\n*** Mail could not be accepted");
diff --git a/contrib/sendmail/src/conf.c b/contrib/sendmail/src/conf.c
index 56a8404..5f91e45 100644
--- a/contrib/sendmail/src/conf.c
+++ b/contrib/sendmail/src/conf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: conf.c,v 8.972.2.54 2004/01/08 21:54:55 ca Exp $")
+SM_RCSID("@(#)$Id: conf.c,v 8.1047 2004/07/14 21:54:23 ca Exp $")
#include <sendmail/pathnames.h>
#if NEWDB
@@ -81,6 +81,7 @@ struct hdrinfo HdrInfo[] =
{ "errors-to", H_FROM|H_ERRORSTO, NULL },
{ "full-name", H_ACHECK, NULL },
{ "return-receipt-to", H_RECEIPTTO, NULL },
+ { "delivery-receipt-to", H_RECEIPTTO, NULL },
{ "disposition-notification-to", H_FROM, NULL },
/* destination fields */
@@ -259,9 +260,7 @@ setdefaults(e)
WkClassFact = 1800L; /* option z */
WkTimeFact = 90000L; /* option Z */
QueueFactor = WkRecipFact * 20; /* option q */
-#if _FFR_QUARANTINE
QueueMode = QM_NORMAL; /* what queue items to act upon */
-#endif /* _FFR_QUARANTINE */
FileMode = (RealUid != geteuid()) ? 0644 : 0600;
/* option F */
QueueFileMode = (RealUid != geteuid()) ? 0644 : 0600;
@@ -338,6 +337,7 @@ setdefaults(e)
FastSplit = 1;
#if SASL
AuthMechanisms = newstr(AUTH_MECHANISMS);
+ AuthRealm = NULL;
MaxSLBits = INT_MAX;
#endif /* SASL */
#if STARTTLS
@@ -368,12 +368,11 @@ setdefaults(e)
#if MILTER
InputFilters[0] = NULL;
#endif /* MILTER */
-#if _FFR_REJECT_LOG
RejectLogInterval = 3 HOURS;
-#endif /* _FFR_REJECT_LOG */
-#if _FFR_REQ_DIR_FSYNC_OPT
+#if REQUIRES_DIR_FSYNC
RequiresDirfsync = true;
-#endif /* _FFR_REQ_DIR_FSYNC_OPT */
+#endif /* REQUIRES_DIR_FSYNC */
+ ConnectionRateWindowSize = 60;
setupmaps();
setupqueues();
setupmailers();
@@ -640,6 +639,13 @@ setupmaps()
dequote_init, null_map_open, null_map_close,
arith_map_lookup, null_map_store);
+#if SOCKETMAP
+ /* arbitrary daemons */
+ MAPDEF("socket", NULL, MCF_ALIASOK,
+ map_parseargs, socket_map_open, socket_map_close,
+ socket_map_lookup, null_map_store);
+#endif /* SOCKETMAP */
+
if (tTd(38, 2))
{
/* bogus map -- always return tempfail */
@@ -1492,7 +1498,6 @@ getla()
double avenrun[3];
# endif /* LA_TYPE == LA_SHORT */
# endif /* LA_TYPE == LA_INT */
- extern int errno;
extern off_t lseek();
if (kmem < 0)
@@ -1600,7 +1605,6 @@ getla()
int j;
static int kmem = -1;
long avenrun[3];
- extern int errno;
struct mioc_rksym mirk;
if (kmem < 0)
@@ -1828,6 +1832,12 @@ getla()
# include <sys/sysmp.h>
+# ifdef _UNICOSMP
+# define CAST_SYSMP(x) (x)
+# else /* _UNICOSMP */
+# define CAST_SYSMP(x) ((x) & 0x7fffffff)
+# endif /* _UNICOSMP */
+
int
getla(void)
{
@@ -1857,7 +1867,8 @@ getla(void)
}
}
- if (lseek(kmem, (sysmp(MP_KERNADDR, MPKA_AVENRUN) & 0x7fffffff), SEEK_SET) == -1 ||
+ if (lseek(kmem, CAST_SYSMP(sysmp(MP_KERNADDR, MPKA_AVENRUN)), SEEK_SET)
+ == -1 ||
read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
{
if (tTd(3, 1))
@@ -2193,16 +2204,16 @@ refuseconnections(name, e, d, active)
{
static time_t lastconn[MAXDAEMONS];
static int conncnt[MAXDAEMONS];
-#if _FFR_REJECT_LOG
static time_t firstrejtime[MAXDAEMONS];
static time_t nextlogtime[MAXDAEMONS];
-#endif /* _FFR_REJECT_LOG */
#if XLA
if (!xla_smtp_ok())
return true;
#endif /* XLA */
+ SM_ASSERT(d >= 0);
+ SM_ASSERT(d < MAXDAEMONS);
if (ConnRateThrottle > 0)
{
time_t now;
@@ -2234,16 +2245,13 @@ refuseconnections(name, e, d, active)
sm_getla();
if (RefuseLA > 0 && CurrentLA >= RefuseLA)
{
-# if _FFR_REJECT_LOG
time_t now;
-# define R2_MSG_LA "have been rejecting connections on daemon %s for %s"
-# endif /* _FFR_REJECT_LOG */
# define R_MSG_LA "rejecting connections on daemon %s: load average: %d"
+# define R2_MSG_LA "have been rejecting connections on daemon %s for %s"
sm_setproctitle(true, e, R_MSG_LA, name, CurrentLA);
if (LogLevel > 8)
sm_syslog(LOG_NOTICE, NOQID, R_MSG_LA, name, CurrentLA);
-# if _FFR_REJECT_LOG
now = curtime();
if (firstrejtime[d] == 0)
{
@@ -2256,13 +2264,10 @@ refuseconnections(name, e, d, active)
pintvl(now - firstrejtime[d], true));
nextlogtime[d] = now + RejectLogInterval;
}
-# endif /* _FFR_REJECT_LOG */
return true;
}
-# if _FFR_REJECT_LOG
else
firstrejtime[d] = 0;
-# endif /* _FFR_REJECT_LOG */
if (DelayLA > 0 && CurrentLA >= DelayLA)
{
@@ -3968,6 +3973,7 @@ validate_connection(sap, hostname, e)
sm_dprintf("validate_connection(%s, %s)\n",
hostname, anynet_ntoa(sap));
+ connection_rate_check(sap, e);
if (rscheck("check_relay", hostname, anynet_ntoa(sap),
e, RSF_RMCOMM|RSF_COUNT, 3, NULL, NOQID) != EX_OK)
{
@@ -5155,6 +5161,80 @@ get_num_procs_online()
return nproc;
}
/*
+** SM_CLOSEFROM -- close file descriptors
+**
+** Parameters:
+** lowest -- first fd to close
+** highest -- last fd + 1 to close
+**
+** Returns:
+** none
+*/
+
+void
+sm_closefrom(lowest, highest)
+ int lowest, highest;
+{
+#if HASCLOSEFROM
+ closefrom(lowest);
+#else /* HASCLOSEFROM */
+ int i;
+
+ for (i = lowest; i < highest; i++)
+ (void) close(i);
+#endif /* HASCLOSEFROM */
+}
+#if HASFDWALK
+/*
+** CLOSEFD_WALK -- walk fd's arranging to close them
+** Callback for fdwalk()
+**
+** Parameters:
+** lowest -- first fd to arrange to be closed
+** fd -- fd to arrange to be closed
+**
+** Returns:
+** zero
+*/
+
+static int
+closefd_walk(lowest, fd)
+ void *lowest;
+ int fd;
+{
+ if (fd >= *(int *)lowest)
+ (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+ return 0;
+}
+#endif /* HASFDWALK */
+/*
+** SM_CLOSE_ON_EXEC -- arrange for file descriptors to be closed
+**
+** Parameters:
+** lowest -- first fd to arrange to be closed
+** highest -- last fd + 1 to arrange to be closed
+**
+** Returns:
+** none
+*/
+
+void
+sm_close_on_exec(highest, lowest)
+ int highest, lowest;
+{
+#if HASFDWALK
+ (void) fdwalk(closefd_walk, &lowest);
+#else /* HASFDWALK */
+ int i, j;
+
+ for (i = lowest; i < highest; i++)
+ {
+ if ((j = fcntl(i, F_GETFD, 0)) != -1)
+ (void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
+ }
+#endif /* HASFDWALK */
+}
+/*
** SEED_RANDOM -- seed the random number generator
**
** Parameters:
@@ -5536,6 +5616,9 @@ link(source, target)
char *CompileOptions[] =
{
+#if ALLOW_255
+ "ALLOW_255",
+#endif /* ALLOW_255 */
#if NAMED_BIND
# if DNSMAP
"DNSMAP",
@@ -5638,6 +5721,9 @@ char *CompileOptions[] =
#if SMTPDEBUG
"SMTPDEBUG",
#endif /* SMTPDEBUG */
+#if SOCKETMAP
+ "SOCKETMAP",
+#endif /* SOCKETMAP */
#if STARTTLS
"STARTTLS",
#endif /* STARTTLS */
@@ -5659,6 +5745,9 @@ char *CompileOptions[] =
#if USE_LDAP_INIT
"USE_LDAP_INIT",
#endif /* USE_LDAP_INIT */
+#if USE_TTYPATH
+ "USE_TTYPATH",
+#endif /* USE_TTYPATH */
#if XDEBUG
"XDEBUG",
#endif /* XDEBUG */
@@ -5678,9 +5767,6 @@ char *OsCompileOptions[] =
#if ADDRCONFIG_IS_BROKEN
"ADDRCONFIG_IS_BROKEN",
#endif /* ADDRCONFIG_IS_BROKEN */
-#if ALLOW_255
- "ALLOW_255",
-#endif /* ALLOW_255 */
#ifdef AUTO_NETINFO_HOSTS
"AUTO_NETINFO_HOSTS",
#endif /* AUTO_NETINFO_HOSTS */
@@ -5702,12 +5788,18 @@ char *OsCompileOptions[] =
#if FAST_PID_RECYCLE
"FAST_PID_RECYCLE",
#endif /* FAST_PID_RECYCLE */
+#if HASCLOSEFROM
+ "HASCLOSEFROM",
+#endif /* HASCLOSEFROM */
#if HASFCHOWN
"HASFCHOWN",
#endif /* HASFCHOWN */
#if HASFCHMOD
"HASFCHMOD",
#endif /* HASFCHMOD */
+#if HASFDWALK
+ "HASFDWALK",
+#endif /* HASFDWALK */
#if HASFLOCK
"HASFLOCK",
#endif /* HASFLOCK */
@@ -5885,20 +5977,11 @@ char *OsCompileOptions[] =
char *FFRCompileOptions[] =
{
-#if _FFR_ADAPTIVE_EOL
- /* tries to be smart about \r\n versus \n from broken clients */
- /* known to be broken, do not use */
- "_FFR_ADAPTIVE_EOL",
-#endif /* _FFR_ADAPTIVE_EOL */
#if _FFR_ALLOW_SASLINFO
/* DefaultAuthInfo can be specified by user. */
- /* DefaultAuthInfo doesn't really work in 8.12 anymore. */
+ /* DefaultAuthInfo doesn't really work in 8.13 anymore. */
"_FFR_ALLOW_SASLINFO",
#endif /* _FFR_ALLOW_SASLINFO */
-#if _FFR_ALLOW_S0_ERROR_4XX
- /* Allow for tempfail from S0 (ruleset 0). */
- "_FFR_ALLOW_S0_ERROR_4XX",
-#endif /* _FFR_ALLOW_S0_ERROR_4XX */
#if _FFR_BESTMX_BETTER_TRUNCATION
/* Better truncation of list of MX records for dns map. */
"_FFR_BESTMX_BETTER_TRUNCATION",
@@ -5911,19 +5994,10 @@ char *FFRCompileOptions[] =
"_FFR_BLOCK_PROXIES",
#endif /* _FFR_BLOCK_PROXIES */
-#if _FFR_CACHE_LPC
- /* Cache connections to LCP based mailers */
-/* Christophe Wolfhugel of France Telecom Oleane */
- "_FFR_CACHE_LPC",
-#endif /* _FFR_CACHE_LPC */
#if _FFR_CATCH_BROKEN_MTAS
/* Deal with MTAs that send a reply during the DATA phase. */
"_FFR_CATCH_BROKEN_MTAS",
#endif /* _FFR_CATCH_BROKEN_MTAS */
-#if _FFR_CATCH_LONG_STRINGS
- /* Report long address strings instead of silently ignoring them. */
- "_FFR_CATCH_LONG_STRINGS",
-#endif /* _FFR_CATCH_LONG_STRINGS */
#if _FFR_CHECK_EOM
/* Enable check_eom ruleset */
"_FFR_CHECK_EOM",
@@ -5940,6 +6014,10 @@ char *FFRCompileOptions[] =
/* Extended daemon status. */
"_FFR_CONTROL_MSTAT",
#endif /* _FFR_CONTROL_MSTAT */
+#if _FFR_CRLPATH
+ /* CRLPath; needs documentation; Al Smith */
+ "_FFR_CRLPATH",
+#endif /* _FFR_CRLPATH */
#if _FFR_DAEMON_NETUNIX
/* Allow local (not just TCP) socket connection to server. */
"_FFR_DAEMON_NETUNIX",
@@ -5978,11 +6056,6 @@ char *FFRCompileOptions[] =
/* Enable DontLockFilesForRead option. */
"_FFR_DONTLOCKFILESFORREAD_OPTION",
#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */
-#if _FFR_DONT_STOP_LOOKING
- /* Continue with DNS lookups on ECONNREFUSED and TRY_AGAIN. */
-/* Noted by Neil Rickert of Northern Illinois University */
- "_FFR_DONT_STOP_LOOKING",
-#endif /* _FFR_DONT_STOP_LOOKING */
#if _FFR_DOTTED_USERNAMES
/* Allow usernames with '.' */
"_FFR_DOTTED_USERNAMES",
@@ -6033,6 +6106,10 @@ char *FFRCompileOptions[] =
/* Set 'h' in {addr_type} for headers. */
"_FFR_HDR_TYPE",
#endif /* _FFR_HDR_TYPE */
+#if _FFR_HELONAME
+ /* option to set heloname; Nik Clayton of FreeBSD */
+ "_FFR_HELONAME",
+#endif /* _FFR_HELONAME */
#if _FFR_HPUX_NSSWITCH
/* Use nsswitch on HP-UX */
"_FFR_HPUX_NSSWITCH",
@@ -6045,19 +6122,16 @@ char *FFRCompileOptions[] =
/* Ignore extensions offered in response to HELO */
"_FFR_IGNORE_EXT_ON_HELO",
#endif /* _FFR_IGNORE_EXT_ON_HELO */
-#if _FFR_LDAP_RECURSION
- /* Support LDAP recursion in LDAP responses */
-/* Andrew Baucom */
- "_FFR_LDAP_RECURSION",
-#endif /* _FFR_LDAP_RECURSION */
-#if _FFR_LDAP_SETVERSION
- /* New LDAP map option for setting LDAP protocol version */
- "_FFR_LDAP_SETVERSION",
-#endif /* _FFR_LDAP_SETVERSION */
-#if _FFR_LDAP_URI
- /* Support LDAP URI form of specifying host/port (and allows ldaps) */
- "_FFR_LDAP_URI",
-#endif /* _FFR_LDAP_URI */
+#if _FFR_MAXDATASIZE
+ /*
+ ** It is possible that a header is larger than MILTER_CHUNK_SIZE,
+ ** hence this shouldn't be used as limit for milter communication.
+ ** see also libmilter/comm.c
+ ** Gurusamy Sarathy of ActiveState
+ */
+
+ "_FFR_MAXDATASIZE"
+#endif /* _FFR_MAXDATASIZE */
#if _FFR_MAX_FORWARD_ENTRIES
/* Try to limit number of .forward entries */
/* (doesn't work) */
@@ -6068,24 +6142,20 @@ char *FFRCompileOptions[] =
/* Limit sleep(2) time in libsm/clock.c */
"_FFR_MAX_SLEEP_TIME",
#endif /* _FFR_MAX_SLEEP_TIME */
-#if _FFR_MESSAGEID_MACRO
- /* stick the message ID header's value in a macro */
- "_FFR_MESSAGEID_MACRO",
-#endif /* _FFR_MESSAGEID_MACRO */
-#if MILTER
-# if _FFR_MILTER_421
- /* If a filter returns 421, close the SMTP connection */
- "_FFR_MILTER_421",
-# endif /* _FFR_MILTER_421 */
-# if _FFR_MILTER_MACROS_EOM
- /* Add an EOM macro set for milter */
- "_FFR_MILTER_MACROS_EOM",
-# endif /* _FFR_MILTER_MACROS_EOM */
-# if _FFR_MILTER_PERDAEMON
- /* Per DaemonPortOptions InputMailFilter lists */
- "_FFR_MILTER_PERDAEMON",
-# endif /* _FFR_MILTER_PERDAEMON */
-#endif /* MILTER */
+#if _FFR_MILTER_NAGLE
+ /* milter: turn off Nagle ("cork" on Linux) */
+ /* John Gardiner Myers of Proofpoint */
+ "_FFR_MILTER_NAGLE ",
+#endif /* _FFR_MILTER_NAGLE */
+#if _FFR_MILTER_NOHDR_RESP
+ /* milter: no response expected when sending headers */
+ /* John Gardiner Myers of Proofpoint */
+ "_FFR_MILTER_NOHDR_RESP",
+#endif /* _FFR_MILTER_NOHDR_RESP */
+#if _FFR_MIME7TO8_OLD
+ /* Old mime7to8 code, the new is broken for at least one example. */
+ "_FFR_MIME7TO8_OLD",
+#endif /* _FFR_MAX_SLEEP_TIME */
#if _FFR_NODELAYDSN_ON_HOLD
/* Do not issue a DELAY DSN for mailers that use the hold flag. */
/* Steven Pitzl */
@@ -6095,10 +6165,6 @@ char *FFRCompileOptions[] =
/* Disable PIPELINING, delay client if used. */
"_FFR_NO_PIPE",
#endif /* _FFR_NO_PIPE */
-#if _FFR_QUARANTINE
- /* Quarantine items in the queue */
- "_FFR_QUARANTINE",
-#endif /* _FFR_QUARANTINE */
#if _FFR_QUEUEDELAY
/* Exponential queue delay; disabled in 8.13 since it isn't used. */
"_FFR_QUEUEDELAY",
@@ -6112,16 +6178,6 @@ char *FFRCompileOptions[] =
/* Define {queue} macro. */
"_FFR_QUEUE_MACRO",
#endif /* _FFR_QUEUE_MACRO */
-#if _FFR_QUEUERETURN_DSN
- /*
- ** Provide an option for different Timeout.queue{warn,return} for
- ** DSN messages. These days, queues are filled with bounces for
- ** spam that will never make it to the sender and therefore slow
- ** down queue runs until they timeout.
- */
-
- "_FFR_QUEUERETURN_DSN",
-#endif /* _FFR_QUEUERETURN_DSN */
#if _FFR_QUEUE_RUN_PARANOIA
/* Additional checks when doing queue runs. */
"_FFR_QUEUE_RUN_PARANOIA",
@@ -6139,30 +6195,14 @@ char *FFRCompileOptions[] =
"_FFR_REDIRECTEMPTY",
#endif /* _FFR_REDIRECTEMPTY */
-#if _FFR_REJECT_LOG
- /* Log when we start/stop rejecting connections due to load, etc */
- "_FFR_REJECT_LOG",
-#endif /* _FFR_REJECT_LOG */
-#if _FFR_REQ_DIR_FSYNC_OPT
- /* Add cf option to fsync() directories */
- "_FFR_REQ_DIR_FSYNC_OPT",
-#endif /* _FFR_REQ_DIR_FSYNC_OPT */
#if _FFR_RESET_MACRO_GLOBALS
/* Allow macro 'j' to be set dynamically via rulesets. */
"_FFR_RESET_MACRO_GLOBALS",
#endif /* _FFR_RESET_MACRO_GLOBALS */
-#if _FFR_RESPOND_ALL
- /* in vacation: respond to every message, not just once per interval */
- "_FFR_RESPOND_ALL",
-#endif /* _FFR_RESPOND_ALL */
#if _FFR_RHS
/* Random shuffle for queue sorting. */
"_FFR_RHS",
#endif /* _FFR_RHS */
-#if _FFR_SASL_OPT_M
- /* Support SASL's SASL_SEC_MUTUAL_AUTH option */
- "_FFR_SASL_OPT_M",
-#endif /* _FFR_SASL_OPT_M */
#if _FFR_SELECT_SHM
/* Auto-select of shared memory key */
"_FFR_SELECT_SHM",
@@ -6171,18 +6211,14 @@ char *FFRCompileOptions[] =
/* Donated code (unused). */
"_FFR_SHM_STATUS",
#endif /* _FFR_SHM_STATUS */
+#if _FFR_SKIP_DOMAINS
+ /* process every N'th domain instead of every N'th message */
+ "_FFR_SKIP_DOMAINS"
+#endif /* _FFR_SKIP_DOMAINS */
#if _FFR_SLEEP_USE_SELECT
/* Use select(2) in libsm/clock.c to emulate sleep(2) */
"_FFR_SLEEP_USE_SELECT ",
#endif /* _FFR_SLEEP_USE_SELECT */
-#if _FFR_SMFI_OPENSOCKET
- /* libmilter: smfi_opensocket() to force the socket open early */
- "_FFR_SMFI_OPENSOCKET",
-#endif /* _FFR_SMFI_OPENSOCKET */
-#if _FFR_SMTP_SSL
- /* Support for smtps (SMTP over SSL) */
- "_FFR_SMTP_SSL",
-#endif /* _FFR_SMTP_SSL */
#if _FFR_SOFT_BOUNCE
/* Turn all errors into temporary errors. */
"_FFR_SOFT_BOUNCE",
@@ -6199,14 +6235,6 @@ char *FFRCompileOptions[] =
/* Chris Adams of HiWAAY Informations Services */
"_FFR_SPT_ALIGN",
#endif /* _FFR_SPT_ALIGN */
-#if _FFR_STRIPBACKSL
- /*
- ** Strip backslash from addresses (so sender doesn't
- ** decide to ignore forward)
- */
-
- "_FFR_STRIPBACKSL",
-#endif /* _FFR_STRIPBACKSL */
#if _FFR_TIMERS
/* Donated code (unused). */
"_FFR_TIMERS",
diff --git a/contrib/sendmail/src/conf.h b/contrib/sendmail/src/conf.h
index 0675c2d..77577c4 100644
--- a/contrib/sendmail/src/conf.h
+++ b/contrib/sendmail/src/conf.h
@@ -10,7 +10,7 @@
* the sendmail distribution.
*
*
- * $Id: conf.h,v 8.563.2.3 2002/10/31 03:28:36 ca Exp $
+ * $Id: conf.h,v 8.567 2004/07/23 20:45:01 gshapiro Exp $
*/
/*
@@ -145,6 +145,16 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
# define DBMMODE 0640
#endif /* ! DBMMODE */
+/*
+** Value which means a uid or gid value should not change
+*/
+
+#ifndef NO_UID
+# define NO_UID -1
+#endif /* ! NO_UID */
+#ifndef NO_GID
+# define NO_GID -1
+#endif /* ! NO_GID */
/**********************************************************************
** Compilation options.
diff --git a/contrib/sendmail/src/control.c b/contrib/sendmail/src/control.c
index d93f0cf..60eab3c 100644
--- a/contrib/sendmail/src/control.c
+++ b/contrib/sendmail/src/control.c
@@ -10,7 +10,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: control.c,v 8.118.4.8 2003/06/24 17:45:27 ca Exp $")
+SM_RCSID("@(#)$Id: control.c,v 8.125 2003/06/24 17:46:06 ca Exp $")
#include <sm/fdset.h>
diff --git a/contrib/sendmail/src/daemon.c b/contrib/sendmail/src/daemon.c
index 88c55cd..c593901 100644
--- a/contrib/sendmail/src/daemon.c
+++ b/contrib/sendmail/src/daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: daemon.c,v 8.613.2.20 2003/11/25 19:02:24 ca Exp $")
+SM_RCSID("@(#)$Id: daemon.c,v 8.649 2004/07/14 21:57:52 ca Exp $")
#if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__)
# define USE_SOCK_STREAM 1
@@ -74,10 +74,8 @@ struct daemon
char *d_mflags; /* flags for use in macro */
char *d_name; /* user-supplied name */
#if MILTER
-# if _FFR_MILTER_PERDAEMON
char *d_inputfilterlist;
struct milter *d_inputfilters[MAXFILTERS];
-# endif /* _FFR_MILTER_PERDAEMON */
#endif /* MILTER */
};
@@ -212,7 +210,7 @@ getrequests(e)
#endif /* XDEBUG */
/* Add parent process as first item */
- proc_list_add(CurrentPid, "Sendmail daemon", PROC_DAEMON, 0, -1);
+ proc_list_add(CurrentPid, "Sendmail daemon", PROC_DAEMON, 0, -1, NULL);
if (tTd(15, 1))
{
@@ -280,6 +278,7 @@ getrequests(e)
/* May have been sleeping above, check again */
CHECK_RESTART;
+
getrequests_checkdiskspace(e);
#if XDEBUG
@@ -490,6 +489,21 @@ getrequests(e)
if (t < 0)
{
errno = save_errno;
+
+ /* let's ignore these temporary errors */
+ if (save_errno == EINTR
+#ifdef EAGAIN
+ || save_errno == EAGAIN
+#endif /* EAGAIN */
+#ifdef ECONNABORTED
+ || save_errno == ECONNABORTED
+#endif /* ECONNABORTED */
+#ifdef EWOULDBLOCK
+ || save_errno == EWOULDBLOCK
+#endif /* EWOULDBLOCK */
+ )
+ continue;
+
syserr("getrequests: accept");
/* arrange to re-open the socket next time around */
@@ -568,6 +582,16 @@ getrequests(e)
}
/*
+ ** If connection rate is exceeded here, connection shall be
+ ** refused later by a new call after fork() by the
+ ** validate_connection() function. Closing the connection
+ ** at this point violates RFC 2821.
+ ** Do NOT remove this call, its side effects are needed.
+ */
+
+ connection_rate_check(&RealHostAddr, NULL);
+
+ /*
** Create a subprocess to process the mail.
*/
@@ -594,13 +618,13 @@ getrequests(e)
#if NAMED_BIND
/*
- ** Update MX records for FallBackMX.
+ ** Update MX records for FallbackMX.
** Let's hope this is fast otherwise we screw up the
** response time.
*/
- if (FallBackMX != NULL)
- (void) getfallbackmxrr(FallBackMX);
+ if (FallbackMX != NULL)
+ (void) getfallbackmxrr(FallbackMX);
#endif /* NAMED_BIND */
if (tTd(93, 100))
@@ -655,6 +679,7 @@ getrequests(e)
ShutdownRequest = NULL;
PendingSignal = 0;
CurrentPid = getpid();
+ close_sendmail_pid();
(void) sm_releasesignal(SIGALRM);
(void) sm_releasesignal(SIGCHLD);
@@ -697,7 +722,7 @@ getrequests(e)
/* Add control socket process */
proc_list_add(CurrentPid,
"console socket child",
- PROC_CONTROL_CHILD, 0, -1);
+ PROC_CONTROL_CHILD, 0, -1, NULL);
}
else
{
@@ -708,7 +733,7 @@ getrequests(e)
/* Add parent process as first child item */
proc_list_add(CurrentPid, "daemon child",
- PROC_DAEMON_CHILD, 0, -1);
+ PROC_DAEMON_CHILD, 0, -1, NULL);
/* don't schedule queue runs if ETRN */
QueueIntvl = 0;
@@ -759,21 +784,23 @@ getrequests(e)
h_errno == TRY_AGAIN ? "TEMP" : "FAIL");
}
else
+ {
macdefine(&BlankEnvelope.e_macro, A_PERM,
- macid("{client_resolve}"), "OK");
+ macid("{client_resolve}"), "OK");
+ }
sm_setproctitle(true, e, "startup with %s", p);
markstats(e, NULL, STATS_CONNECT);
if ((inchannel = sm_io_open(SmFtStdiofd,
SM_TIME_DEFAULT,
(void *) &t,
- SM_IO_RDONLY,
+ SM_IO_RDONLY_B,
NULL)) == NULL ||
(t = dup(t)) < 0 ||
(outchannel = sm_io_open(SmFtStdiofd,
SM_TIME_DEFAULT,
(void *) &t,
- SM_IO_WRONLY,
+ SM_IO_WRONLY_B,
NULL)) == NULL)
{
syserr("cannot open SMTP server channel, fd=%d",
@@ -856,14 +883,15 @@ getrequests(e)
{
(void) sm_snprintf(status, sizeof status,
"control socket server child");
- proc_list_add(pid, status, PROC_CONTROL, 0, -1);
+ proc_list_add(pid, status, PROC_CONTROL, 0, -1, NULL);
}
else
{
(void) sm_snprintf(status, sizeof status,
"SMTP server child for %s",
anynet_ntoa(&RealHostAddr));
- proc_list_add(pid, status, PROC_DAEMON, 0, -1);
+ proc_list_add(pid, status, PROC_DAEMON, 0, -1,
+ &RealHostAddr);
}
(void) sm_releasesignal(SIGCHLD);
@@ -888,7 +916,6 @@ getrequests(e)
sm_dprintf("getreq: returning\n");
#if MILTER
-# if _FFR_MILTER_PERDAEMON
/* set the filters for this daemon */
if (Daemons[curdaemon].d_inputfilterlist != NULL)
{
@@ -902,7 +929,6 @@ getrequests(e)
if (i < MAXFILTERS)
InputFilters[i] = NULL;
}
-# endif /* _FFR_MILTER_PERDAEMON */
#endif /* MILTER */
return &Daemons[curdaemon].d_flags;
}
@@ -1465,11 +1491,9 @@ setsockaddroptions(p, d)
break;
#if MILTER
-# if _FFR_MILTER_PERDAEMON
case 'I':
d->d_inputfilterlist = v;
break;
-# endif /* _FFR_MILTER_PERDAEMON */
#endif /* MILTER */
case 'P': /* port */
@@ -1711,9 +1735,7 @@ static struct dflags DaemonFlags[] =
{ "IFNHELO", D_IFNHELO },
{ "FQMAIL", D_FQMAIL },
{ "FQRCPT", D_FQRCPT },
-#if _FFR_SMTP_SSL
{ "SMTPS", D_SMTPS },
-#endif /* _FFR_SMTP_SSL */
{ "UNQUALOK", D_UNQUALOK },
{ "NOAUTH", D_NOAUTH },
{ "NOCANON", D_NOCANON },
@@ -1738,15 +1760,13 @@ printdaemonflags(d)
if (!bitnset(df->d_flag, d->d_flags))
continue;
if (first)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "<%s",
- df->d_name);
+ sm_dprintf("<%s", df->d_name);
else
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ",%s",
- df->d_name);
+ sm_dprintf(",%s", df->d_name);
first = false;
}
if (!first)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ">");
+ sm_dprintf(">");
}
bool
@@ -1761,10 +1781,8 @@ setdaemonoptions(p)
setsockaddroptions(p, &Daemons[NDaemons]);
#if MILTER
-# if _FFR_MILTER_PERDAEMON
if (Daemons[NDaemons].d_inputfilterlist != NULL)
Daemons[NDaemons].d_inputfilterlist = newstr(Daemons[NDaemons].d_inputfilterlist);
-# endif /* _FFR_MILTER_PERDAEMON */
#endif /* MILTER */
if (Daemons[NDaemons].d_name != NULL)
@@ -1929,7 +1947,6 @@ chkclientmodifiers(flag)
}
#if MILTER
-# if _FFR_MILTER_PERDAEMON
/*
** SETUP_DAEMON_FILTERS -- Parse per-socket filters
**
@@ -1961,7 +1978,6 @@ setup_daemon_milters()
}
}
}
-# endif /* _FFR_MILTER_PERDAEMON */
#endif /* MILTER */
/*
** MAKECONNECTION -- make a connection to an SMTP socket on a machine.
@@ -2673,11 +2689,11 @@ nextaddr:
mci->mci_out = NULL;
if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
(void *) &s,
- SM_IO_WRONLY, NULL)) == NULL ||
+ SM_IO_WRONLY_B, NULL)) == NULL ||
(s = dup(s)) < 0 ||
(mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
(void *) &s,
- SM_IO_RDONLY, NULL)) == NULL)
+ SM_IO_RDONLY_B, NULL)) == NULL)
{
save_errno = errno;
syserr("cannot open SMTP client channel, fd=%d", s);
@@ -2746,6 +2762,13 @@ nextaddr:
macdefine(&BlankEnvelope.e_macro, A_PERM,
macid("{if_family_out}"), NULL);
}
+
+#if _FFR_HELONAME
+ /* Use the configured HeloName as appropriate */
+ if (HeloName != NULL && HeloName[0] != '\0')
+ mci->mci_heloname = newstr(HeloName);
+#endif /* _FFR_HELONAME */
+
mci_setstat(mci, EX_OK, NULL, NULL);
return EX_OK;
}
@@ -2795,7 +2818,8 @@ makeconnection_ds(mux_path, mci)
if (rval != 0)
{
- syserr("makeconnection_ds: unsafe domain socket");
+ syserr("makeconnection_ds: unsafe domain socket %s",
+ mux_path);
mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL);
errno = rval;
return EX_TEMPFAIL;
@@ -2807,7 +2831,8 @@ makeconnection_ds(mux_path, mci)
if (strlen(mux_path) >= sizeof unix_addr.sun_path)
{
- syserr("makeconnection_ds: domain socket name too long");
+ syserr("makeconnection_ds: domain socket name %s too long",
+ mux_path);
/* XXX why TEMPFAIL but 5.x.y ? */
mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL);
@@ -2822,7 +2847,8 @@ makeconnection_ds(mux_path, mci)
if (sock == -1)
{
save_errno = errno;
- syserr("makeconnection_ds: could not create domain socket");
+ syserr("makeconnection_ds: could not create domain socket %s",
+ mux_path);
mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
errno = save_errno;
return EX_TEMPFAIL;
@@ -2843,11 +2869,11 @@ makeconnection_ds(mux_path, mci)
/* connection ok, put it into canonical form */
mci->mci_out = NULL;
if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
- (void *) &sock, SM_IO_WRONLY, NULL))
+ (void *) &sock, SM_IO_WRONLY_B, NULL))
== NULL
|| (sock = dup(sock)) < 0 ||
(mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
- (void *) &sock, SM_IO_RDONLY, NULL))
+ (void *) &sock, SM_IO_RDONLY_B, NULL))
== NULL)
{
save_errno = errno;
@@ -2891,8 +2917,8 @@ shutdown_daemon()
ShutdownRequest = NULL;
PendingSignal = 0;
- if (LogLevel > 79)
- sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt (%s)",
+ if (LogLevel > 9)
+ sm_syslog(LOG_INFO, CurEnv->e_id, "stopping daemon, reason=%s",
reason == NULL ? "implicit call" : reason);
FileName = NULL;
@@ -2964,7 +2990,6 @@ void
restart_daemon()
{
bool drop;
- int i;
int save_errno;
char *reason;
sigfunc_t ignore, oalrm, ousr1;
@@ -2996,6 +3021,9 @@ restart_daemon()
cleanup_shm(DaemonPid == getpid());
#endif /* SM_CONF_SHM */
+ /* close locked pid file */
+ close_sendmail_pid();
+
/*
** Want to drop to the user who started the process in all cases
** *but* when running as "smmsp" for the clientmqueue queue run
@@ -3016,14 +3044,7 @@ restart_daemon()
/* NOTREACHED */
}
- /* arrange for all the files to be closed */
- for (i = 3; i < DtableSize; i++)
- {
- register int j;
-
- if ((j = fcntl(i, F_GETFD, 0)) != -1)
- (void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
- }
+ sm_close_on_exec(STDERR_FILENO + 1, DtableSize);
/*
** Need to allow signals before execve() to make them "harmless".
@@ -3340,6 +3361,7 @@ getauthinfo(fd, may_be_forged)
hp = sm_gethostbyname(RealHostName, family);
if (hp == NULL)
{
+ /* XXX: Could be a temporary error on forward lookup */
*may_be_forged = true;
}
else
@@ -3826,7 +3848,7 @@ host_map_lookup(map, name, av, statp)
return NULL;
if (s->s_namecanon.nc_cname == NULL)
{
- syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d",
+ syserr("host_map_lookup(%s): bogus NULL cache entry, errno=%d, h_errno=%d",
name,
s->s_namecanon.nc_errno,
s->s_namecanon.nc_herrno);
diff --git a/contrib/sendmail/src/deliver.c b/contrib/sendmail/src/deliver.c
index eb98f83..5839cbe 100644
--- a/contrib/sendmail/src/deliver.c
+++ b/contrib/sendmail/src/deliver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -14,7 +14,7 @@
#include <sendmail.h>
#include <sys/time.h>
-SM_RCSID("@(#)$Id: deliver.c,v 8.940.2.20 2003/09/26 18:26:19 ca Exp $")
+SM_RCSID("@(#)$Id: deliver.c,v 8.976 2004/07/23 20:45:01 gshapiro Exp $")
#if HASSETUSERCONTEXT
# include <login_cap.h>
@@ -123,11 +123,11 @@ sendall(e, mode)
{
sm_dprintf("\n===== SENDALL: mode %c, id %s, e_from ",
mode, e->e_id);
- printaddr(&e->e_from, false);
+ printaddr(sm_debug_file(), &e->e_from, false);
sm_dprintf("\te_flags = ");
printenvflags(e);
sm_dprintf("sendqueue:\n");
- printaddr(e->e_sendqueue, true);
+ printaddr(sm_debug_file(), e->e_sendqueue, true);
}
/*
@@ -184,7 +184,7 @@ sendall(e, mode)
if (tTd(13, 5))
{
sm_dprintf("sendall: QS_SENDER ");
- printaddr(&e->e_from, false);
+ printaddr(sm_debug_file(), &e->e_from, false);
}
e->e_from.q_state = QS_SENDER;
(void) recipient(&e->e_from, &e->e_sendqueue, 0, e);
@@ -215,7 +215,7 @@ sendall(e, mode)
if (tTd(13, 25))
{
sm_dprintf("\nAfter first owner pass, sendq =\n");
- printaddr(e->e_sendqueue, true);
+ printaddr(sm_debug_file(), e->e_sendqueue, true);
}
owner = "";
@@ -233,7 +233,7 @@ sendall(e, mode)
if (tTd(13, 30))
{
sm_dprintf("Checking ");
- printaddr(q, false);
+ printaddr(sm_debug_file(), q, false);
}
if (QS_IS_DEAD(q->q_state))
{
@@ -244,7 +244,7 @@ sendall(e, mode)
if (tTd(13, 29) && !tTd(13, 30))
{
sm_dprintf("Checking ");
- printaddr(q, false);
+ printaddr(sm_debug_file(), q, false);
}
if (q->q_owner != NULL)
@@ -304,8 +304,8 @@ sendall(e, mode)
** set, send directly to the fallback MX host.
*/
- if (FallBackMX != NULL &&
- !wordinclass(FallBackMX, 'w') &&
+ if (FallbackMX != NULL &&
+ !wordinclass(FallbackMX, 'w') &&
mode != SM_VERIFY &&
!bitnset(M_NOMX, m->m_flags) &&
strcmp(m->m_mailer, "[IPC]") == 0 &&
@@ -316,11 +316,11 @@ sendall(e, mode)
char *p;
if (tTd(13, 30))
- sm_dprintf(" ... FallBackMX\n");
+ sm_dprintf(" ... FallbackMX\n");
- len = strlen(FallBackMX) + 1;
+ len = strlen(FallbackMX) + 1;
p = sm_rpool_malloc_x(e->e_rpool, len);
- (void) sm_strlcpy(p, FallBackMX, len);
+ (void) sm_strlcpy(p, FallbackMX, len);
q->q_state = QS_OK;
q->q_host = p;
}
@@ -359,7 +359,6 @@ sendall(e, mode)
q->q_state = QS_QUEUEUP;
expensive = true;
}
-#if _FFR_QUARANTINE
else if (QueueMode != QM_QUARANTINE &&
e->e_quarmsg != NULL)
{
@@ -369,7 +368,6 @@ sendall(e, mode)
q->q_state = QS_QUEUEUP;
expensive = true;
}
-#endif /* _FFR_QUARANTINE */
else
{
if (tTd(13, 30))
@@ -407,7 +405,7 @@ sendall(e, mode)
if (tTd(13, 5))
{
sm_dprintf("sendall(split): QS_SENDER ");
- printaddr(&ee->e_from, false);
+ printaddr(sm_debug_file(), &ee->e_from, false);
}
ee->e_from.q_state = QS_SENDER;
ee->e_dfp = NULL;
@@ -418,11 +416,9 @@ sendall(e, mode)
ee->e_errormode = EM_MAIL;
ee->e_sibling = splitenv;
ee->e_statmsg = NULL;
-#if _FFR_QUARANTINE
if (e->e_quarmsg != NULL)
ee->e_quarmsg = sm_rpool_strdup_x(ee->e_rpool,
e->e_quarmsg);
-#endif /* _FFR_QUARANTINE */
splitenv = ee;
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
@@ -485,7 +481,7 @@ sendall(e, mode)
if (tTd(13, 5))
{
sm_dprintf("sendall(owner): QS_SENDER ");
- printaddr(&e->e_from, false);
+ printaddr(sm_debug_file(), &e->e_from, false);
}
e->e_from.q_state = QS_SENDER;
e->e_errormode = EM_MAIL;
@@ -517,7 +513,9 @@ sendall(e, mode)
}
if ((WILL_BE_QUEUED(mode) || mode == SM_FORK ||
- (mode != SM_VERIFY && SuperSafe == SAFE_REALLY)) &&
+ (mode != SM_VERIFY &&
+ (SuperSafe == SAFE_REALLY ||
+ SuperSafe == SAFE_REALLY_POSTMILTER))) &&
(!bitset(EF_INQUEUE, e->e_flags) || splitenv != NULL))
{
bool msync;
@@ -555,12 +553,12 @@ sendall(e, mode)
sm_dprintf("\n================ Final Send Queue(s) =====================\n");
sm_dprintf("\n *** Envelope %s, e_from=%s ***\n",
e->e_id, e->e_from.q_paddr);
- printaddr(e->e_sendqueue, true);
+ printaddr(sm_debug_file(), e->e_sendqueue, true);
for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
{
sm_dprintf("\n *** Envelope %s, e_from=%s ***\n",
ee->e_id, ee->e_from.q_paddr);
- printaddr(ee->e_sendqueue, true);
+ printaddr(sm_debug_file(), ee->e_sendqueue, true);
}
sm_dprintf("==========================================================\n\n");
}
@@ -623,6 +621,7 @@ sendall(e, mode)
/* and save qid for reacquisition */
ee->e_id = qid;
}
+
#endif /* !HASFLOCK */
/*
@@ -953,10 +952,8 @@ sync_dir(filename, panic)
char *dirp;
char dir[MAXPATHLEN];
-#if _FFR_REQ_DIR_FSYNC_OPT
if (!RequiresDirfsync)
return;
-#endif /* _FFR_REQ_DIR_FSYNC_OPT */
/* filesystems which require the directory be synced */
dirp = strrchr(filename, '/');
@@ -1180,6 +1177,50 @@ coloncmp(a, b)
return ret;
}
+
+/*
+** SHOULD_TRY_FBSH -- Should try FallbackSmartHost?
+**
+** Parameters:
+** e -- envelope
+** tried_fallbacksmarthost -- has been tried already? (in/out)
+** hostbuf -- buffer for hostname (expand FallbackSmartHost) (out)
+** hbsz -- size of hostbuf
+** status -- current delivery status
+**
+** Returns:
+** true iff FallbackSmartHost should be tried.
+*/
+
+static bool
+should_try_fbsh(e, tried_fallbacksmarthost, hostbuf, hbsz, status)
+ ENVELOPE *e;
+ bool *tried_fallbacksmarthost;
+ char *hostbuf;
+ size_t hbsz;
+ int status;
+{
+ /*
+ ** If the host was not found and a FallbackSmartHost is defined
+ ** (and we have not yet tried it), then make one last try with
+ ** it as the host.
+ */
+
+ if (status == EX_NOHOST && FallbackSmartHost != NULL &&
+ !*tried_fallbacksmarthost)
+ {
+ *tried_fallbacksmarthost = true;
+ expand(FallbackSmartHost, hostbuf, hbsz, e);
+ if (!wordinclass(hostbuf, 'w'))
+ {
+ if (tTd(11, 1))
+ sm_dprintf("one last try with FallbackSmartHost %s\n",
+ hostbuf);
+ return true;
+ }
+ }
+ return false;
+}
/*
** DELIVER -- Deliver a message to a list of addresses.
**
@@ -1241,13 +1282,6 @@ coloncmp(a, b)
** The standard input is passed off to someone.
*/
-#ifndef NO_UID
-# define NO_UID -1
-#endif /* ! NO_UID */
-#ifndef NO_GID
-# define NO_GID -1
-#endif /* ! NO_GID */
-
static int
deliver(e, firstto)
register ENVELOPE *e;
@@ -1284,9 +1318,7 @@ deliver(e, firstto)
bool anyok; /* at least one address was OK */
SM_NONVOLATILE bool goodmxfound = false; /* at least one MX was OK */
bool ovr;
-#if _FFR_QUARANTINE
bool quarantine;
-#endif /* _FFR_QUARANTINE */
int strsize;
int rcptcount;
int ret;
@@ -1327,6 +1359,7 @@ deliver(e, firstto)
if (bitset(EF_RESPONSE, e->e_flags))
{
macdefine(&e->e_macro, A_PERM, macid("{client_name}"), "");
+ macdefine(&e->e_macro, A_PERM, macid("{client_ptr}"), "");
macdefine(&e->e_macro, A_PERM, macid("{client_addr}"), "");
macdefine(&e->e_macro, A_PERM, macid("{client_port}"), "");
macdefine(&e->e_macro, A_PERM, macid("{client_resolve}"), "");
@@ -1369,6 +1402,10 @@ deliver(e, firstto)
pvp = pv;
*pvp++ = m->m_argv[0];
+ /* ignore long term host status information if mailer flag W is set */
+ if (bitnset(M_NOHOSTSTAT, m->m_flags))
+ IgnoreHostStatus = true;
+
/* insert -f or -r flag as appropriate */
if (FromFlag &&
(bitnset(M_FOPT, m->m_flags) ||
@@ -1507,7 +1544,7 @@ deliver(e, firstto)
if (tTd(10, 1))
{
sm_dprintf("\nsend to ");
- printaddr(to, false);
+ printaddr(sm_debug_file(), to, false);
}
/* compute effective uid/gid when sending */
@@ -1521,7 +1558,7 @@ deliver(e, firstto)
if (tTd(10, 2))
{
sm_dprintf("ctladdr=");
- printaddr(ctladdr, false);
+ printaddr(sm_debug_file(), ctladdr, false);
}
user = to->q_user;
@@ -1555,9 +1592,7 @@ deliver(e, firstto)
ovr = true;
/* do config file checking of compatibility */
-#if _FFR_QUARANTINE
quarantine = (e->e_quarmsg != NULL);
-#endif /* _FFR_QUARANTINE */
rcode = rscheck("check_compat", e->e_from.q_paddr, to->q_paddr,
e, RSF_RMCOMM|RSF_COUNT, 3, NULL,
e->e_id);
@@ -1577,7 +1612,6 @@ deliver(e, firstto)
NULL, ctladdr, xstart, e, to);
continue;
}
-#if _FFR_QUARANTINE
if (!quarantine && e->e_quarmsg != NULL)
{
/*
@@ -1590,13 +1624,12 @@ deliver(e, firstto)
macdefine(&e->e_macro, A_PERM,
macid("{quarantine}"), "");
}
-#endif /* _FFR_QUARANTINE */
if (bitset(EF_DISCARD, e->e_flags))
{
if (tTd(10, 5))
{
sm_dprintf("deliver: discarding recipient ");
- printaddr(to, false);
+ printaddr(sm_debug_file(), to, false);
}
/* pretend the message was sent */
@@ -1624,7 +1657,7 @@ deliver(e, firstto)
stripquotes(user);
stripquotes(host);
}
-#if _FFR_STRIPBACKSL
+
/*
** Strip one leading backslash if requested and the
** next character is alphanumerical (the latter can
@@ -1633,7 +1666,6 @@ deliver(e, firstto)
if (bitnset(M_STRIPBACKSL, m->m_flags) && user[0] == '\\')
stripbackslash(user);
-#endif /* _FFR_STRIPBACKSL */
/* hack attack -- delivermail compatibility */
if (m == ProgMailer && *user == '|')
@@ -1827,7 +1859,7 @@ deliver(e, firstto)
if (tTd(11, 1))
{
sm_dprintf("openmailer:");
- printav(pv);
+ printav(sm_debug_file(), pv);
}
errno = 0;
SM_SET_H_ERRNO(0);
@@ -1879,7 +1911,6 @@ deliver(e, firstto)
/* check for Local Person Communication -- not for mortals!!! */
if (strcmp(m->m_mailer, "[LPC]") == 0)
{
-#if _FFR_CACHE_LPC
if (clever)
{
/* flush any expired connections */
@@ -1913,13 +1944,6 @@ deliver(e, firstto)
}
else
mci->mci_state = MCIS_OPEN;
-#else /* _FFR_CACHE_LPC */
- mci = mci_new(e->e_rpool);
- mci->mci_in = smioin;
- mci->mci_out = smioout;
- mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN;
- mci->mci_mailer = m;
-#endif /* _FFR_CACHE_LPC */
}
else if (strcmp(m->m_mailer, "[IPC]") == 0)
{
@@ -1989,6 +2013,7 @@ tryhost:
char sep = ':';
char *endp;
static char hostbuf[MAXNAME + 1];
+ bool tried_fallbacksmarthost = false;
# if NETINET6
if (*mxhosts[hostnum] == '[')
@@ -2040,6 +2065,7 @@ tryhost:
if (endp != NULL)
*endp = sep;
+ one_last_try:
/* see if we already know that this host is fried */
CurHostName = hostbuf;
mci = mci_get(hostbuf, m);
@@ -2050,7 +2076,7 @@ tryhost:
if (tTd(11, 1))
{
sm_dprintf("openmailer: ");
- mci_dump(mci, false);
+ mci_dump(sm_debug_file(), mci, false);
}
CurHostName = mci->mci_host;
if (bitnset(M_LMTP, m->m_flags))
@@ -2069,6 +2095,13 @@ tryhost:
{
if (mci->mci_exitstat == EX_TEMPFAIL)
goodmxfound = true;
+
+ /* Try FallbackSmartHost? */
+ if (should_try_fbsh(e, &tried_fallbacksmarthost,
+ hostbuf, sizeof hostbuf,
+ mci->mci_exitstat))
+ goto one_last_try;
+
continue;
}
@@ -2121,9 +2154,9 @@ tryhost:
{
int h;
# if NAMED_BIND
- extern int NumFallBackMXHosts;
+ extern int NumFallbackMXHosts;
# else /* NAMED_BIND */
- const int NumFallBackMXHosts = 0;
+ const int NumFallbackMXHosts = 0;
# endif /* NAMED_BIND */
if (hostnum < nummxhosts && LogLevel > 9)
@@ -2131,11 +2164,11 @@ tryhost:
"Timeout.to_aconnect occurred before exhausting all addresses");
/* turn off timeout if fallback available */
- if (NumFallBackMXHosts > 0)
+ if (NumFallbackMXHosts > 0)
enough = 0;
/* skip to a fallback MX host */
- h = nummxhosts - NumFallBackMXHosts;
+ h = nummxhosts - NumFallbackMXHosts;
if (hostnum < h)
hostnum = h;
}
@@ -2155,6 +2188,11 @@ tryhost:
}
else
{
+ /* Try FallbackSmartHost? */
+ if (should_try_fbsh(e, &tried_fallbacksmarthost,
+ hostbuf, sizeof hostbuf, i))
+ goto one_last_try;
+
if (tTd(11, 1))
sm_dprintf("openmailer: makeconnection => stat=%d, errno=%d\n",
i, errno);
@@ -2320,7 +2358,6 @@ tryhost:
}
else if (pid == 0)
{
- int i;
int save_errno;
int sff;
int new_euid = NO_UID;
@@ -2396,7 +2433,12 @@ tryhost:
/* reset group id */
if (bitnset(M_SPECIFIC_UID, m->m_flags))
- new_gid = m->m_gid;
+ {
+ if (m->m_gid == NO_GID)
+ new_gid = RunAsGid;
+ else
+ new_gid = m->m_gid;
+ }
else if (bitset(S_ISGID, stb.st_mode))
new_gid = stb.st_gid;
else if (ctladdr != NULL && ctladdr->q_gid != 0)
@@ -2455,7 +2497,7 @@ tryhost:
exit(EX_TEMPFAIL);
}
}
- if (m->m_gid == 0)
+ if (m->m_gid == NO_GID)
new_gid = DefGid;
else
new_gid = m->m_gid;
@@ -2507,7 +2549,10 @@ tryhost:
sm_mbdb_terminate();
if (bitnset(M_SPECIFIC_UID, m->m_flags))
{
- new_euid = m->m_uid;
+ if (m->m_uid == NO_UID)
+ new_euid = RunAsUid;
+ else
+ new_euid = m->m_uid;
/*
** Undo the effects of the uid change in main
@@ -2537,7 +2582,7 @@ tryhost:
new_ruid = stb.st_uid;
else if (ctladdr != NULL && ctladdr->q_uid != 0)
new_ruid = ctladdr->q_uid;
- else if (m->m_uid != 0)
+ else if (m->m_uid != NO_UID)
new_ruid = m->m_uid;
else
new_ruid = DefUid;
@@ -2679,14 +2724,7 @@ tryhost:
(void) close(mpvect[0]);
/* arrange for all the files to be closed */
- for (i = 3; i < DtableSize; i++)
- {
- register int j;
-
- if ((j = fcntl(i, F_GETFD, 0)) != -1)
- (void) fcntl(i, F_SETFD,
- j | FD_CLOEXEC);
- }
+ sm_close_on_exec(STDERR_FILENO + 1, DtableSize);
# if !_FFR_USE_SETLOGIN
/* run disconnected from terminal */
@@ -2743,7 +2781,7 @@ tryhost:
mci->mci_pid = pid;
(void) close(mpvect[0]);
mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
- (void *) &(mpvect[1]), SM_IO_WRONLY,
+ (void *) &(mpvect[1]), SM_IO_WRONLY_B,
NULL);
if (mci->mci_out == NULL)
{
@@ -2758,7 +2796,7 @@ tryhost:
(void) close(rpvect[1]);
mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
- (void *) &(rpvect[0]), SM_IO_RDONLY,
+ (void *) &(rpvect[0]), SM_IO_RDONLY_B,
NULL);
if (mci->mci_in == NULL)
{
@@ -3118,7 +3156,7 @@ reconnect: /* after switching to an encrypted connection */
/* avoid bogus error msg */
mci->mci_errno = 0;
rcode = EX_TEMPFAIL;
- mci_setstat(mci, rcode, "4.7.1", p);
+ mci_setstat(mci, rcode, "4.3.0", p);
/*
** hack to get the error message into
@@ -3162,7 +3200,7 @@ do_transfer:
if (tTd(11, 1))
{
sm_dprintf("openmailer: ");
- mci_dump(mci, false);
+ mci_dump(sm_debug_file(), mci, false);
}
#if _FFR_CLIENT_SIZE
@@ -3208,7 +3246,7 @@ do_transfer:
syserr("554 5.3.5 deliver: mci=%lx rcode=%d errno=%d state=%d sig=%s",
(unsigned long) mci, rcode, errno,
mci->mci_state, firstsig);
- mci_dump_all(true);
+ mci_dump_all(smioout, true);
rcode = EX_SOFTWARE;
}
else if (nummxhosts > hostnum)
@@ -4197,7 +4235,6 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e)
anynet_ntoa(&CurHostAddr));
}
}
-#if _FFR_QUARANTINE
else if (strcmp(status, "quarantined") == 0)
{
if (e->e_quarmsg != NULL)
@@ -4205,7 +4242,6 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e)
", quarantine=%s",
shortenstring(e->e_quarmsg, 40));
}
-#endif /* _FFR_QUARANTINE */
else if (strcmp(status, "queued") != 0)
{
p = macvalue('h', e);
@@ -4344,7 +4380,6 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e)
" [%.100s]",
anynet_ntoa(&CurHostAddr));
}
-#if _FFR_QUARANTINE
else if (strcmp(status, "quarantined") == 0)
{
if (e->e_quarmsg != NULL)
@@ -4352,7 +4387,6 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e)
", quarantine=%.100s",
e->e_quarmsg);
}
-#endif /* _FFR_QUARANTINE */
else if (strcmp(status, "queued") != 0)
{
p = macvalue('h', e);
@@ -5036,7 +5070,7 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
if (tTd(11, 1))
{
sm_dprintf("mailfile %s\n ctladdr=", filename);
- printaddr(ctladdr, false);
+ printaddr(sm_debug_file(), ctladdr, false);
}
if (mailer == NULL)
@@ -5226,7 +5260,10 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
if (bitnset(M_SPECIFIC_UID, mailer->m_flags))
{
RealUserName = NULL;
- RealUid = mailer->m_uid;
+ if (mailer->m_uid == NO_UID)
+ RealUid = RunAsUid;
+ else
+ RealUid = mailer->m_uid;
if (RunAsUid != 0 && RealUid != RunAsUid)
{
/* Only root can change the uid */
@@ -5248,7 +5285,7 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
RealUserName = ctladdr->q_user;
RealUid = ctladdr->q_uid;
}
- else if (mailer != NULL && mailer->m_uid != 0)
+ else if (mailer != NULL && mailer->m_uid != NO_UID)
{
RealUserName = DefUser;
RealUid = mailer->m_uid;
@@ -5262,7 +5299,10 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
/* select a new group to run as */
if (bitnset(M_SPECIFIC_UID, mailer->m_flags))
{
- RealGid = mailer->m_gid;
+ if (mailer->m_gid == NO_GID)
+ RealGid = RunAsGid;
+ else
+ RealGid = mailer->m_gid;
if (RunAsUid != 0 &&
(RealGid != getgid() ||
RealGid != getegid()))
@@ -5291,7 +5331,7 @@ mailfile(filename, mailer, ctladdr, sfflags, e)
}
else if (ctladdr != NULL && ctladdr->q_uid != 0)
RealGid = ctladdr->q_gid;
- else if (mailer != NULL && mailer->m_gid != 0)
+ else if (mailer != NULL && mailer->m_gid != NO_GID)
RealGid = mailer->m_gid;
else
RealGid = DefGid;
@@ -6014,7 +6054,8 @@ starttls(m, mci, e)
smtpmessage("STARTTLS", m, mci);
/* get the reply */
- smtpresult = reply(m, mci, e, TimeOuts.to_starttls, NULL, NULL);
+ smtpresult = reply(m, mci, e, TimeOuts.to_starttls, NULL, NULL,
+ XS_STARTTLS);
/* check return code from server */
if (smtpresult == 454)
diff --git a/contrib/sendmail/src/domain.c b/contrib/sendmail/src/domain.c
index f4a8810..dd24272 100644
--- a/contrib/sendmail/src/domain.c
+++ b/contrib/sendmail/src/domain.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1986, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -14,9 +14,9 @@
#include <sendmail.h>
#if NAMED_BIND
-SM_RCSID("@(#)$Id: domain.c,v 8.181.2.9 2003/08/11 23:23:40 gshapiro Exp $ (with name server)")
+SM_RCSID("@(#)$Id: domain.c,v 8.194 2004/01/14 01:47:34 ca Exp $ (with name server)")
#else /* NAMED_BIND */
-SM_RCSID("@(#)$Id: domain.c,v 8.181.2.9 2003/08/11 23:23:40 gshapiro Exp $ (without name server)")
+SM_RCSID("@(#)$Id: domain.c,v 8.194 2004/01/14 01:47:34 ca Exp $ (without name server)")
#endif /* NAMED_BIND */
#if NAMED_BIND
@@ -76,7 +76,6 @@ static char MXHostBuf[MXHOSTBUFSIZE];
# define RES_UNC_T unsigned char *
# endif /* defined(__RES) && (__RES >= 19940415) */
-static char *gethostalias __P((char *));
static int mxrand __P((char *));
static int fallbackmxrr __P((int, unsigned short *, char **));
@@ -96,11 +95,11 @@ static int fallbackmxrr __P((int, unsigned short *, char **));
** number of MX records.
**
** Side Effects:
-** Populates NumFallBackMXHosts and fbhosts.
+** Populates NumFallbackMXHosts and fbhosts.
** Sets renewal time (based on TTL).
*/
-int NumFallBackMXHosts = 0; /* Number of fallback MX hosts (after MX expansion) */
+int NumFallbackMXHosts = 0; /* Number of fallback MX hosts (after MX expansion) */
static char *fbhosts[MAXMXHOSTS + 1];
int
@@ -116,27 +115,27 @@ getfallbackmxrr(host)
if (host == NULL || *host == '\0')
return 0;
#endif /* 0 */
- if (NumFallBackMXHosts > 0 && renew > curtime())
- return NumFallBackMXHosts;
+ if (NumFallbackMXHosts > 0 && renew > curtime())
+ return NumFallbackMXHosts;
if (host[0] == '[')
{
fbhosts[0] = host;
- NumFallBackMXHosts = 1;
+ NumFallbackMXHosts = 1;
}
else
{
/* free old data */
- for (i = 0; i < NumFallBackMXHosts; i++)
+ for (i = 0; i < NumFallbackMXHosts; i++)
sm_free(fbhosts[i]);
/* get new data */
- NumFallBackMXHosts = getmxrr(host, fbhosts, NULL, false,
+ NumFallbackMXHosts = getmxrr(host, fbhosts, NULL, false,
&rcode, false, &ttl);
renew = curtime() + ttl;
- for (i = 0; i < NumFallBackMXHosts; i++)
+ for (i = 0; i < NumFallbackMXHosts; i++)
fbhosts[i] = newstr(fbhosts[i]);
}
- return NumFallBackMXHosts;
+ return NumFallbackMXHosts;
}
/*
@@ -151,7 +150,7 @@ getfallbackmxrr(host)
** new number of MX records.
**
** Side Effects:
-** If FallBackMX was set, it appends the MX records for
+** If FallbackMX was set, it appends the MX records for
** that host to mxhosts (and modifies prefs accordingly).
*/
@@ -163,7 +162,7 @@ fallbackmxrr(nmx, prefs, mxhosts)
{
int i;
- for (i = 0; i < NumFallBackMXHosts && nmx < MAXMXHOSTS; i++)
+ for (i = 0; i < NumFallbackMXHosts && nmx < MAXMXHOSTS; i++)
{
if (nmx > 0)
prefs[nmx] = prefs[nmx - 1] + 1;
@@ -221,7 +220,7 @@ getmxrr(host, mxhosts, mxprefs, droplocalhost, rcode, tryfallback, pttl)
bool seenlocal = false;
unsigned short pref, type;
unsigned short localpref = 256;
- char *fallbackMX = FallBackMX;
+ char *fallbackMX = FallbackMX;
bool trycanon = false;
unsigned short *prefs;
int (*resfunc)();
@@ -342,7 +341,7 @@ getmxrr(host, mxhosts, mxprefs, droplocalhost, rcode, tryfallback, pttl)
ancount = ntohs((unsigned short) hp->ancount);
/* See RFC 1035 for layout of RRs. */
- /* XXX leave room for FallBackMX ? */
+ /* XXX leave room for FallbackMX ? */
while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS - 1)
{
if ((n = dn_expand((unsigned char *)&answer, eom, cp,
@@ -805,7 +804,6 @@ dns_getcanonname(host, hbsize, trymx, statp, pttl)
int qtype;
int initial;
int loopcnt;
- char *xp;
char nbuf[SM_MAX(MAXPACKET, MAXDNAME*2+2)];
char *searchlist[MAXDNSRCH + 2];
@@ -840,24 +838,6 @@ cnameloop:
n++;
/*
- ** If this is a simple name, determine whether it matches an
- ** alias in the file defined by the environment variable HOSTALIASES.
- */
-
- if (n == 0 && (xp = gethostalias(host)) != NULL)
- {
- if (loopcnt++ > MAXCNAMEDEPTH)
- {
- syserr("loop in ${HOSTALIASES} file");
- }
- else
- {
- (void) sm_strlcpy(host, xp, hbsize);
- goto cnameloop;
- }
- }
-
- /*
** Build the search list.
** If there is at least one dot in name, start with a null
** domain to search the unmodified name first.
@@ -933,14 +913,12 @@ cnameloop:
*/
SM_SET_H_ERRNO(TRY_AGAIN);
-# if _FFR_DONT_STOP_LOOKING
if (**dp == '\0')
{
if (*statp == EX_OK)
*statp = EX_TEMPFAIL;
goto nexttype;
}
-# endif /* _FFR_DONT_STOP_LOOKING */
*statp = EX_TEMPFAIL;
if (WorkAroundBrokenAAAA)
@@ -962,9 +940,7 @@ cnameloop:
return false;
}
-# if _FFR_DONT_STOP_LOOKING
nexttype:
-# endif /* _FFR_DONT_STOP_LOOKING */
if (h_errno != HOST_NOT_FOUND)
{
/* might have another type of interest */
@@ -1189,56 +1165,4 @@ nexttype:
*pttl = ttl;
return true;
}
-
-static char *
-gethostalias(host)
- char *host;
-{
- char *fname;
- SM_FILE_T *fp;
- register char *p = NULL;
- long sff = SFF_REGONLY;
- char buf[MAXLINE];
- static char hbuf[MAXDNAME];
-
- if (ResNoAliases)
- return NULL;
- if (DontLockReadFiles)
- sff |= SFF_NOLOCK;
- fname = getenv("HOSTALIASES");
- if (fname == NULL ||
- (fp = safefopen(fname, O_RDONLY, 0, sff)) == NULL)
- return NULL;
- while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
- {
- for (p = buf; p != '\0' && !(isascii(*p) && isspace(*p)); p++)
- continue;
- if (*p == 0)
- {
- /* syntax error */
- continue;
- }
- *p++ = '\0';
- if (sm_strcasecmp(buf, host) == 0)
- break;
- }
-
- if (sm_io_eof(fp))
- {
- /* no match */
- (void) sm_io_close(fp, SM_TIME_DEFAULT);
- return NULL;
- }
- (void) sm_io_close(fp, SM_TIME_DEFAULT);
-
- /* got a match; extract the equivalent name */
- while (*p != '\0' && isascii(*p) && isspace(*p))
- p++;
- host = p;
- while (*p != '\0' && !(isascii(*p) && isspace(*p)))
- p++;
- *p = '\0';
- (void) sm_strlcpy(hbuf, host, sizeof hbuf);
- return hbuf;
-}
#endif /* NAMED_BIND */
diff --git a/contrib/sendmail/src/envelope.c b/contrib/sendmail/src/envelope.c
index c29871f..1aedd3e 100644
--- a/contrib/sendmail/src/envelope.c
+++ b/contrib/sendmail/src/envelope.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: envelope.c,v 8.282.2.2 2002/12/04 15:44:08 ca Exp $")
+SM_RCSID("@(#)$Id: envelope.c,v 8.293 2004/02/18 00:46:18 gshapiro Exp $")
/*
** CLRSESSENVELOPE -- clear session oriented data in an envelope
@@ -101,7 +101,6 @@ newenvelope(e, parent, rpool)
if (parent != NULL)
{
e->e_msgpriority = parent->e_msgsize;
-#if _FFR_QUARANTINE
if (parent->e_quarmsg == NULL)
{
e->e_quarmsg = NULL;
@@ -115,7 +114,6 @@ newenvelope(e, parent, rpool)
macdefine(&e->e_macro, A_PERM,
macid("{quarantine}"), e->e_quarmsg);
}
-#endif /* _FFR_QUARANTINE */
}
e->e_puthdr = putheader;
e->e_putbody = putbody;
@@ -176,13 +174,13 @@ dropenvelope(e, fulldrop, split)
if (tTd(50, 1))
{
sm_dprintf("dropenvelope %p: id=", e);
- xputs(e->e_id);
+ xputs(sm_debug_file(), e->e_id);
sm_dprintf(", flags=");
printenvflags(e);
if (tTd(50, 10))
{
sm_dprintf("sendq=");
- printaddr(e->e_sendqueue, true);
+ printaddr(sm_debug_file(), e->e_sendqueue, true);
}
}
@@ -507,7 +505,6 @@ simpledrop:
}
if (!panic)
(void) xunlink(queuename(e, DATAFL_LETTER));
-#if _FFR_QUARANTINE
if (panic && QueueMode == QM_LOST)
{
/*
@@ -518,7 +515,6 @@ simpledrop:
/* EMPTY */
}
else
-#endif /* _FFR_QUARANTINE */
if (xunlink(queuename(e, ANYQFL_LETTER)) == 0)
{
/* add to available space in filesystem */
@@ -655,11 +651,9 @@ clearenvelope(e, fullclear, rpool)
*e = BlankEnvelope;
e->e_message = NULL;
-#if _FFR_QUARANTINE
e->e_qfletter = '\0';
e->e_quarmsg = NULL;
macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
-#endif /* _FFR_QUARANTINE */
/*
** Copy the macro table.
@@ -732,13 +726,7 @@ initsys(e)
openxscript(e);
e->e_ctime = curtime();
-#if _FFR_QUARANTINE
e->e_qfletter = '\0';
-#endif /* _FFR_QUARANTINE */
-#if _FFR_QUEUEDELAY
- e->e_queuealg = QueueAlg;
- e->e_queuedelay = QueueInitDelay;
-#endif /* _FFR_QUEUEDELAY */
/*
** Set OutChannel to something useful if stdout isn't it.
@@ -807,6 +795,8 @@ settime(e)
register struct tm *tm;
now = curtime();
+ (void) sm_snprintf(buf, sizeof buf, "%ld", (long) now);
+ macdefine(&e->e_macro, A_TEMP, macid("{time}"), buf);
tm = gmtime(&now);
(void) sm_snprintf(buf, sizeof buf, "%04d%02d%02d%02d%02d",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
@@ -1044,7 +1034,7 @@ setsender(from, e, delimptr, delimchar, internal)
if (tTd(45, 5))
{
sm_dprintf("setsender: QS_SENDER ");
- printaddr(&e->e_from, false);
+ printaddr(sm_debug_file(), &e->e_from, false);
}
SuprErrs = false;
@@ -1140,7 +1130,7 @@ setsender(from, e, delimptr, delimchar, internal)
** links in the net.
*/
- pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL);
+ pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL, false);
if (pvp == NULL)
{
/* don't need to give error -- prescan did that already */
@@ -1180,15 +1170,17 @@ setsender(from, e, delimptr, delimchar, internal)
/* strip off to the last "@" sign */
for (lastat = NULL; *pvp != NULL; pvp++)
+ {
if (strcmp(*pvp, "@") == 0)
lastat = pvp;
+ }
if (lastat != NULL)
{
e->e_fromdomain = copyplist(lastat, true, e->e_rpool);
if (tTd(45, 3))
{
sm_dprintf("Saving from domain: ");
- printav(e->e_fromdomain);
+ printav(sm_debug_file(), e->e_fromdomain);
}
}
}
@@ -1249,19 +1241,17 @@ printenvflags(e)
register struct eflags *ef;
bool first = true;
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%lx", e->e_flags);
+ sm_dprintf("%lx", e->e_flags);
for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
{
if (!bitset(ef->ef_bit, e->e_flags))
continue;
if (first)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "<%s",
- ef->ef_name);
+ sm_dprintf("<%s", ef->ef_name);
else
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ",%s",
- ef->ef_name);
+ sm_dprintf(",%s", ef->ef_name);
first = false;
}
if (!first)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ">\n");
+ sm_dprintf(">\n");
}
diff --git a/contrib/sendmail/src/err.c b/contrib/sendmail/src/err.c
index 484af9e..5a0b5b1 100644
--- a/contrib/sendmail/src/err.c
+++ b/contrib/sendmail/src/err.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: err.c,v 8.189 2002/01/09 18:52:30 ca Exp $")
+SM_RCSID("@(#)$Id: err.c,v 8.191 2003/01/10 02:16:46 ca Exp $")
#if LDAPMAP
# include <lber.h>
@@ -238,7 +238,7 @@ syserr(fmt, va_alist)
case ESTALE:
#endif /* ESTALE */
printopenfds(true);
- mci_dump_all(true);
+ mci_dump_all(smioout, true);
break;
}
if (panic)
diff --git a/contrib/sendmail/src/headers.c b/contrib/sendmail/src/headers.c
index 8012b51..12a567d 100644
--- a/contrib/sendmail/src/headers.c
+++ b/contrib/sendmail/src/headers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,8 +13,9 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: headers.c,v 8.266.4.9 2003/10/30 00:17:22 gshapiro Exp $")
+SM_RCSID("@(#)$Id: headers.c,v 8.286 2004/07/08 17:57:32 ca Exp $")
+static HDR *allocheader __P((char *, char *, int, SM_RPOOL_T *));
static size_t fix_mime_header __P((HDR *, ENVELOPE *));
static int priencode __P((char *));
static void put_vanilla_header __P((HDR *, char *, MCI *));
@@ -87,7 +88,7 @@ chompheader(line, pflag, hdrp, e)
if (tTd(31, 6))
{
sm_dprintf("chompheader: ");
- xputs(line);
+ xputs(sm_debug_file(), line);
sm_dprintf("\n");
}
@@ -291,11 +292,12 @@ hse:
int rscheckflags;
char *rs;
- /* no ruleset? look for default */
- rs = hi->hi_ruleset;
rscheckflags = RSF_COUNT;
if (!bitset(hi->hi_flags, H_FROM|H_RCPT))
rscheckflags |= RSF_UNSTRUCTURED;
+
+ /* no ruleset? look for default */
+ rs = hi->hi_ruleset;
if (rs == NULL)
{
s = stab("*", ST_HEADER, ST_FIND);
@@ -357,17 +359,10 @@ hse:
(void) sm_snprintf(qval, sizeof qval, "%d", k);
macdefine(&e->e_macro, A_TEMP, macid("{hdrlen}"), qval);
#if _FFR_HDR_TYPE
- /*
- ** XXX: h isn't set yet
- ** If we really want to be precise then we have
- ** to lookup the header (see below).
- ** It's probably not worth the effort.
- */
-
- if (bitset(H_FROM, h->h_flags))
+ if (bitset(H_FROM, hi->hi_flags))
macdefine(&e->e_macro, A_PERM,
macid("{addr_type}"), "h s");
- else if (bitset(H_RCPT, h->h_flags))
+ else if (bitset(H_RCPT, hi->hi_flags))
macdefine(&e->e_macro, A_PERM,
macid("{addr_type}"), "h r");
else
@@ -466,6 +461,44 @@ hse:
return h->h_flags;
}
/*
+** ALLOCHEADER -- allocate a header entry
+**
+** Parameters:
+** field -- the name of the header field.
+** value -- the value of the field.
+** flags -- flags to add to h_flags.
+** rp -- resource pool for allocations
+**
+** Returns:
+** Pointer to a newly allocated and populated HDR.
+*/
+
+static HDR *
+allocheader(field, value, flags, rp)
+ char *field;
+ char *value;
+ int flags;
+ SM_RPOOL_T *rp;
+{
+ HDR *h;
+ STAB *s;
+
+ /* find info struct */
+ s = stab(field, ST_HEADER, ST_FIND);
+
+ /* allocate space for new header */
+ h = (HDR *) sm_rpool_malloc_x(rp, sizeof *h);
+ h->h_field = field;
+ h->h_value = sm_rpool_strdup_x(rp, value);
+ h->h_flags = flags;
+ if (s != NULL)
+ h->h_flags |= s->s_header.hi_flags;
+ clrbitmap(h->h_mflags);
+ h->h_macro = '\0';
+
+ return h;
+}
+/*
** ADDHEADER -- add a header entry to the end of the queue.
**
** This bypasses the special checking of chompheader.
@@ -491,13 +524,9 @@ addheader(field, value, flags, e)
ENVELOPE *e;
{
register HDR *h;
- STAB *s;
HDR **hp;
HDR **hdrlist = &e->e_header;
- /* find info struct */
- 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)
{
@@ -506,18 +535,65 @@ addheader(field, value, flags, e)
}
/* allocate space for new header */
- h = (HDR *) sm_rpool_malloc_x(e->e_rpool, sizeof *h);
- h->h_field = field;
- h->h_value = sm_rpool_strdup_x(e->e_rpool, value);
+ h = allocheader(field, value, flags, e->e_rpool);
h->h_link = *hp;
- h->h_flags = flags;
- if (s != NULL)
- h->h_flags |= s->s_header.hi_flags;
- clrbitmap(h->h_mflags);
- h->h_macro = '\0';
*hp = h;
}
/*
+** INSHEADER -- insert a header entry at the specified index
+**
+** This bypasses the special checking of chompheader.
+**
+** Parameters:
+** idx -- index into the header list at which to insert
+** field -- the name of the header field.
+** value -- the value of the field.
+** flags -- flags to add to h_flags.
+** e -- envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** inserts the field on the list of headers for this envelope.
+*/
+
+void
+insheader(idx, field, value, flags, e)
+ int idx;
+ char *field;
+ char *value;
+ int flags;
+ ENVELOPE *e;
+{
+ HDR *h, *srch, *last = NULL;
+
+ /* allocate space for new header */
+ h = allocheader(field, value, flags, e->e_rpool);
+
+ /* find insertion position */
+ for (srch = e->e_header; srch != NULL && idx > 0;
+ srch = srch->h_link, idx--)
+ last = srch;
+
+ if (e->e_header == NULL)
+ {
+ e->e_header = h;
+ h->h_link = NULL;
+ }
+ else if (srch == NULL)
+ {
+ SM_ASSERT(last != NULL);
+ last->h_link = h;
+ h->h_link = NULL;
+ }
+ else
+ {
+ h->h_link = srch->h_link;
+ srch->h_link = h;
+ }
+}
+/*
** HVALUE -- return value of a header.
**
** Only "real" fields (i.e., ones that have not been supplied
@@ -673,7 +749,7 @@ eatheader(e, full, log)
if (tTd(32, 1))
{
sm_dprintf("(");
- xputs(h->h_value);
+ xputs(sm_debug_file(), h->h_value);
sm_dprintf(") ");
}
expand(h->h_value, buf, sizeof buf, e);
@@ -688,7 +764,7 @@ eatheader(e, full, log)
}
if (tTd(32, 1))
{
- xputs(h->h_value);
+ xputs(sm_debug_file(), h->h_value);
sm_dprintf("\n");
}
@@ -730,10 +806,8 @@ eatheader(e, full, log)
e->e_msgid = h->h_value;
while (isascii(*e->e_msgid) && isspace(*e->e_msgid))
e->e_msgid++;
-#if _FFR_MESSAGEID_MACRO
macdefine(&e->e_macro, A_PERM, macid("{msg_id}"),
- e->e_msgid);
-#endif /* _FFR_MESSAGEID_MACRO */
+ e->e_msgid);
}
}
if (tTd(32, 1))
@@ -766,6 +840,60 @@ eatheader(e, full, log)
+ e->e_nrcpts * WkRecipFact;
}
+ /* check for DSN to properly set e_timeoutclass */
+ p = hvalue("content-type", e->e_header);
+ if (p != NULL)
+ {
+ bool oldsupr;
+ char **pvp;
+ char pvpbuf[MAXLINE];
+ extern unsigned char MimeTokenTab[256];
+
+ /* tokenize header */
+ oldsupr = SuprErrs;
+ SuprErrs = true;
+ pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
+ MimeTokenTab, false);
+ SuprErrs = oldsupr;
+
+ /* Check if multipart/report */
+ if (pvp != NULL && pvp[0] != NULL &&
+ pvp[1] != NULL && pvp[2] != NULL &&
+ sm_strcasecmp(*pvp++, "multipart") == 0 &&
+ strcmp(*pvp++, "/") == 0 &&
+ sm_strcasecmp(*pvp++, "report") == 0)
+ {
+ /* Look for report-type=delivery-status */
+ while (*pvp != NULL)
+ {
+ /* skip to semicolon separator */
+ while (*pvp != NULL && strcmp(*pvp, ";") != 0)
+ pvp++;
+
+ /* skip semicolon */
+ if (*pvp++ == NULL || *pvp == NULL)
+ break;
+
+ /* look for report-type */
+ if (sm_strcasecmp(*pvp++, "report-type") != 0)
+ continue;
+
+ /* skip equal */
+ if (*pvp == NULL || strcmp(*pvp, "=") != 0)
+ continue;
+
+ /* check value */
+ if (*++pvp != NULL &&
+ sm_strcasecmp(*pvp,
+ "delivery-status") == 0)
+ e->e_timeoutclass = TOC_DSN;
+
+ /* found report-type, no need to continue */
+ break;
+ }
+ }
+ }
+
/* message timeout priority */
p = hvalue("priority", e->e_header);
if (p != NULL)
@@ -777,15 +905,11 @@ eatheader(e, full, log)
e->e_timeoutclass = TOC_NORMAL;
else if (sm_strcasecmp(p, "non-urgent") == 0)
e->e_timeoutclass = TOC_NONURGENT;
-#if _FFR_QUEUERETURN_DSN
else if (bitset(EF_RESPONSE, e->e_flags))
e->e_timeoutclass = TOC_DSN;
-#endif /* _FFR_QUEUERETURN_DSN */
}
-#if _FFR_QUEUERETURN_DSN
else if (bitset(EF_RESPONSE, e->e_flags))
e->e_timeoutclass = TOC_DSN;
-#endif /* _FFR_QUEUERETURN_DSN */
/* date message originated */
p = hvalue("posted-date", e->e_header);
@@ -1239,12 +1363,8 @@ crackaddr(addr, e)
{
c = *q++;
if (quoteit && c == '"')
- {
SM_APPEND_CHAR('\\');
- SM_APPEND_CHAR(c);
- }
- else
- SM_APPEND_CHAR(c);
+ SM_APPEND_CHAR(c);
}
if (quoteit)
{
@@ -1406,7 +1526,7 @@ crackaddr(addr, e)
if (tTd(33, 1))
{
sm_dprintf("crackaddr=>`");
- xputs(buf);
+ xputs(sm_debug_file(), buf);
sm_dprintf("'\n");
}
return buf;
@@ -1459,7 +1579,7 @@ putheader(mci, hdr, e, flags)
if (tTd(34, 11))
{
sm_dprintf(" %s: ", h->h_field);
- xputs(p);
+ xputs(sm_debug_file(), p);
}
/* Skip empty headers */
@@ -1813,7 +1933,7 @@ commaize(h, p, oldstyle, mci, e)
char pvpbuf[PSBUFSIZE];
res = prescan(p, oldstyle ? ' ' : ',', pvpbuf,
- sizeof pvpbuf, &oldp, NULL);
+ sizeof pvpbuf, &oldp, NULL, false);
p = oldp;
#if _FFR_IGNORE_BOGUS_ADDR
/* ignore addresses that can't be parsed */
diff --git a/contrib/sendmail/src/macro.c b/contrib/sendmail/src/macro.c
index fc7a2c2..af8f6d5 100644
--- a/contrib/sendmail/src/macro.c
+++ b/contrib/sendmail/src/macro.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2001, 2003 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: macro.c,v 8.86 2001/09/11 04:05:14 gshapiro Exp $")
+SM_RCSID("@(#)$Id: macro.c,v 8.88 2003/09/05 23:11:18 ca Exp $")
#if MAXMACROID != (BITMAPBITS - 1)
ERROR Read the comment in conf.h
@@ -130,7 +130,7 @@ expand(s, buf, bufsize, e)
if (tTd(35, 24))
{
sm_dprintf("expand(");
- xputs(s);
+ xputs(sm_debug_file(), s);
sm_dprintf(")\n");
}
@@ -223,7 +223,7 @@ expand(s, buf, bufsize, e)
if (tTd(35, 24))
{
sm_dprintf("expand ==> ");
- xputs(xbuf);
+ xputs(sm_debug_file(), xbuf);
sm_dprintf("\n");
}
@@ -305,7 +305,7 @@ macdefine(mac, vclass, id, value)
{
sm_dprintf("%sdefine(%s as ",
mac->mac_table[id] == NULL ? "" : "re", macname(id));
- xputs(value);
+ xputs(sm_debug_file(), value);
sm_dprintf(")\n");
}
@@ -325,7 +325,11 @@ macdefine(mac, vclass, id, value)
}
else
{
+#if SM_HEAP_CHECK
newvalue = sm_strdup_tagged_x(value, file, line, 0);
+#else /* SM_HEAP_CHECK */
+ newvalue = sm_strdup_x(value);
+#endif /* SM_HEAP_CHECK */
setbitn(id, mac->mac_allocated);
}
mac->mac_table[id] = newvalue;
@@ -377,7 +381,7 @@ macset(mac, i, value)
if (tTd(35, 9))
{
sm_dprintf("macset(%s as ", macname(i));
- xputs(value);
+ xputs(sm_debug_file(), value);
sm_dprintf(")\n");
}
mac->mac_table[i] = value;
@@ -487,7 +491,7 @@ macid_parse(p, ep)
if (tTd(35, 14))
{
sm_dprintf("macid(");
- xputs(p);
+ xputs(sm_debug_file(), p);
sm_dprintf(") => ");
}
diff --git a/contrib/sendmail/src/mailq.1 b/contrib/sendmail/src/mailq.1
index 1eb234e..f67a9dd 100644
--- a/contrib/sendmail/src/mailq.1
+++ b/contrib/sendmail/src/mailq.1
@@ -9,9 +9,9 @@
.\" the sendmail distribution.
.\"
.\"
-.\" $Id: mailq.1,v 8.19.2.1 2002/09/26 23:03:39 gshapiro Exp $
+.\" $Id: mailq.1,v 8.20 2002/06/27 22:47:34 gshapiro Exp $
.\"
-.TH MAILQ 1 "$Date: 2002/09/26 23:03:39 $"
+.TH MAILQ 1 "$Date: 2002/06/27 22:47:34 $"
.SH NAME
mailq
\- print the mail queue
@@ -55,6 +55,13 @@ Show the mail submission queue specified in
instead of the MTA queue specified in
.IR /etc/mail/sendmail.cf .
.TP
+.B \-qL
+Show the "lost" items in the mail queue instead of the normal queue items.
+.TP
+.B \-qQ
+Show the quarantined items in the mail queue instead of the normal queue
+items.
+.TP
\fB\-q\fR[\fI!\fR]I substr
Limit processed jobs to those containing
.I substr
@@ -62,6 +69,13 @@ as a substring of the queue id or not when
.I !
is specified.
.TP
+\fB\-q\fR[\fI!\fR]Q substr
+Limit processed jobs to quarantined jobs containing
+.I substr
+as a substring of the quarantine reason or not when
+.I !
+is specified.
+.TP
\fB\-q\fR[\fI!\fR]R substr
Limit processed jobs to those containing
.I substr
diff --git a/contrib/sendmail/src/main.c b/contrib/sendmail/src/main.c
index 0d8c0ce..f274ad8 100644
--- a/contrib/sendmail/src/main.c
+++ b/contrib/sendmail/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -18,14 +18,14 @@
#ifndef lint
SM_UNUSED(static char copyright[]) =
-"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\
+"@(#) Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.\n\
All rights reserved.\n\
Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.\n\
Copyright (c) 1988, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* ! lint */
-SM_RCSID("@(#)$Id: main.c,v 8.887.2.29 2003/11/07 00:09:31 ca Exp $")
+SM_RCSID("@(#)$Id: main.c,v 8.939 2004/06/17 16:39:21 ca Exp $")
#if NETINET || NETINET6
@@ -175,15 +175,14 @@ main(argc, argv, envp)
char *sysloglabel = NULL; /* label for syslog */
char *conffile = NULL; /* name of .cf file */
char *queuegroup = NULL; /* queue group to process */
-#if _FFR_QUARANTINE
char *quarantining = NULL; /* quarantine queue items? */
-#endif /* _FFR_QUARANTINE */
bool extraprivs;
bool forged, negate;
bool queuepersistent = false; /* queue runner process runs forever */
bool foregroundqueue = false; /* queue run in foreground */
bool save_val; /* to save some bool var. */
int cftype; /* which cf file to use? */
+ SM_FILE_T *smdebug;
static time_t starttime = 0; /* when was process started */
struct stat traf_st; /* for TrafficLog FIFO check */
char buf[MAXLINE];
@@ -268,14 +267,9 @@ main(argc, argv, envp)
if (errno != 0)
fill_errno = errno;
- i = DtableSize;
- while (--i > 0)
- {
- if (i != STDIN_FILENO && i != STDOUT_FILENO &&
- i != STDERR_FILENO)
- (void) close(i);
- }
+ sm_closefrom(STDERR_FILENO + 1, DtableSize);
errno = 0;
+ smdebug = NULL;
#if LOG
# ifndef SM_LOG_STR
@@ -371,27 +365,15 @@ main(argc, argv, envp)
else if (strcmp(p, "purgestat") == 0)
OpMode = MD_PURGESTAT;
-#if _FFR_QUARANTINE
-# if defined(__osf__) || defined(_AIX3)
-# define OPTIONS "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:xQ:"
-# endif /* defined(__osf__) || defined(_AIX3) */
-# if defined(sony_news)
-# define OPTIONS "A:B:b:C:cd:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:q:R:r:sTtV:vX:Q:"
-# endif /* defined(sony_news) */
-# ifndef OPTIONS
-# define OPTIONS "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:Q:"
-# endif /* ! OPTIONS */
-#else /* _FFR_QUARANTINE */
-# if defined(__osf__) || defined(_AIX3)
-# define OPTIONS "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:x"
-# endif /* defined(__osf__) || defined(_AIX3) */
-# if defined(sony_news)
-# define OPTIONS "A:B:b:C:cd:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:q:R:r:sTtV:vX:"
-# endif /* defined(sony_news) */
-# ifndef OPTIONS
-# define OPTIONS "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:"
-# endif /* ! OPTIONS */
-#endif /* _FFR_QUARANTINE */
+#if defined(__osf__) || defined(_AIX3)
+# define OPTIONS "A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:x"
+#endif /* defined(__osf__) || defined(_AIX3) */
+#if defined(sony_news)
+# define OPTIONS "A:B:b:C:cD:d:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:"
+#endif /* defined(sony_news) */
+#ifndef OPTIONS
+# define OPTIONS "A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:"
+#endif /* ! OPTIONS */
/* Set to 0 to allow -b; need to check optarg before using it! */
opterr = 0;
@@ -431,10 +413,31 @@ main(argc, argv, envp)
}
break;
+ case 'D':
+ if (debug)
+ {
+ errno = 0;
+ syserr("-D file must be before -d");
+ ExitStat = EX_USAGE;
+ break;
+ }
+ dp = drop_privileges(true);
+ setstat(dp);
+ smdebug = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
+ optarg, SM_IO_APPEND, NULL);
+ if (smdebug == NULL)
+ {
+ syserr("cannot open %s", optarg);
+ ExitStat = EX_CANTCREAT;
+ break;
+ }
+ sm_debug_setfile(smdebug);
+ break;
+
case 'd':
debug = true;
tTflag(optarg);
- (void) sm_io_setvbuf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_setvbuf(sm_debug_file(), SM_TIME_DEFAULT,
(char *) NULL, SM_IO_NBF,
SM_IO_BUFSIZ);
break;
@@ -451,16 +454,14 @@ main(argc, argv, envp)
(char) j);
return EX_USAGE;
}
- j = SM_MIN(strlen(optarg), 24) + 1;
+ j = SM_MIN(strlen(optarg), 32) + 1;
sysloglabel = xalloc(j);
(void) sm_strlcpy(sysloglabel, optarg, j);
SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) +
SL_FUDGE + j;
break;
-#if _FFR_QUARANTINE
case 'Q':
-#endif /* _FFR_QUARANTINE */
case 'q':
/* just check if it is there */
queuerun = true;
@@ -474,6 +475,7 @@ main(argc, argv, envp)
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"WARNING: Can not use -d with -q. Disabling debugging.\n");
+ sm_debug_close();
sm_debug_setfile(NULL);
(void) memset(tTdvect, '\0', sizeof tTdvect);
}
@@ -667,8 +669,6 @@ main(argc, argv, envp)
else
_res.options &= ~RES_DEBUG;
# ifdef RES_NOALIASES
- if (bitset(RES_NOALIASES, _res.options))
- ResNoAliases = true;
_res.options |= RES_NOALIASES;
# endif /* RES_NOALIASES */
TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry;
@@ -701,23 +701,8 @@ main(argc, argv, envp)
setclass('w', jbuf);
p = strchr(jbuf, '.');
- if (p != NULL)
- {
- if (p[1] != '\0')
- {
- macdefine(&BlankEnvelope.e_macro, A_TEMP, 'm',
- &p[1]);
- }
- while (p != NULL && strchr(&p[1], '.') != NULL)
- {
- *p = '\0';
- if (tTd(0, 4))
- sm_dprintf("\ta.k.a.: %s\n", jbuf);
- setclass('w', jbuf);
- *p++ = '.';
- p = strchr(p, '.');
- }
- }
+ if (p != NULL && p[1] != '\0')
+ macdefine(&BlankEnvelope.e_macro, A_TEMP, 'm', &p[1]);
if (uname(&utsname) >= 0)
p = utsname.nodename;
@@ -806,9 +791,7 @@ main(argc, argv, envp)
QueueLimitRecipient = (QUEUE_CHAR *) NULL;
QueueLimitSender = (QUEUE_CHAR *) NULL;
QueueLimitId = (QUEUE_CHAR *) NULL;
-#if _FFR_QUARANTINE
QueueLimitQuarantine = (QUEUE_CHAR *) NULL;
-#endif /* _FFR_QUARANTINE */
/*
** Crack argv.
@@ -842,6 +825,7 @@ main(argc, argv, envp)
safecf = false;
break;
+ case 'D':
case 'd': /* debugging */
/* already done */
break;
@@ -957,7 +941,6 @@ main(argc, argv, envp)
}
break;
-#if _FFR_QUARANTINE
case 'Q': /* change quarantining on queued items */
/* sanity check */
if (OpMode != MD_DELIVER &&
@@ -975,7 +958,6 @@ main(argc, argv, envp)
quarantining = newstr(optarg);
break;
-#endif /* _FFR_QUARANTINE */
case 'q': /* run queue files at intervals */
/* sanity check */
@@ -1049,7 +1031,6 @@ main(argc, argv, envp)
foregroundqueue = true;
break;
-#if _FFR_QUARANTINE
case 'Q': /* Limit by quarantine message */
if (optarg[1] != '\0')
{
@@ -1065,7 +1046,6 @@ main(argc, argv, envp)
case 'L': /* act on lost items */
QueueMode = QM_LOST;
break;
-#endif /* _FFR_QUARANTINE */
case 'p': /* Persistent queue */
queuepersistent = true;
@@ -1308,8 +1288,8 @@ main(argc, argv, envp)
}
#if NAMED_BIND
- if (FallBackMX != NULL)
- (void) getfallbackmxrr(FallBackMX);
+ if (FallbackMX != NULL)
+ (void) getfallbackmxrr(FallbackMX);
#endif /* NAMED_BIND */
if (SuperSafe == SAFE_INTERACTIVE && CurEnv->e_sendmode != SM_DELIVER)
@@ -1418,13 +1398,13 @@ main(argc, argv, envp)
{
sm_dprintf("\n============ SYSTEM IDENTITY (after readcf) ============");
sm_dprintf("\n (short domain name) $w = ");
- xputs(macvalue('w', &BlankEnvelope));
+ xputs(sm_debug_file(), macvalue('w', &BlankEnvelope));
sm_dprintf("\n (canonical domain name) $j = ");
- xputs(macvalue('j', &BlankEnvelope));
+ xputs(sm_debug_file(), macvalue('j', &BlankEnvelope));
sm_dprintf("\n (subdomain name) $m = ");
- xputs(macvalue('m', &BlankEnvelope));
+ xputs(sm_debug_file(), macvalue('m', &BlankEnvelope));
sm_dprintf("\n (node name) $k = ");
- xputs(macvalue('k', &BlankEnvelope));
+ xputs(sm_debug_file(), macvalue('k', &BlankEnvelope));
sm_dprintf("\n========================================================\n\n");
}
@@ -1459,10 +1439,6 @@ main(argc, argv, envp)
if (DefaultNotify == 0)
DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
- /* be sure we don't pick up bogus HOSTALIASES environment variable */
- if (OpMode == MD_QUEUERUN && RealUid != 0)
- (void) unsetenv("HOSTALIASES");
-
/* check for sane configuration level */
if (ConfigLevel > MAXCONFIGLEVEL)
{
@@ -1495,14 +1471,14 @@ main(argc, argv, envp)
switch (OpMode)
{
case MD_QUEUERUN:
-#if _FFR_QUARANTINE
if (quarantining != NULL)
action = "quarantine jobs";
else
-#endif /* _FFR_QUARANTINE */
- /* Normal users can do a single queue run */
- if (QueueIntvl == 0)
- break;
+ {
+ /* Normal users can do a single queue run */
+ if (QueueIntvl == 0)
+ break;
+ }
/* but not persistent queue runners */
if (action == NULL)
@@ -1757,7 +1733,7 @@ main(argc, argv, envp)
else
PSTRSET(MyHostName, jbuf);
if (strchr(MyHostName, '.') == NULL)
- message("WARNING: local host name (%s) is not qualified; fix $j in config file",
+ message("WARNING: local host name (%s) is not qualified; see cf/README: WHO AM I?",
MyHostName);
/* make certain that this name is part of the $=w class */
@@ -1917,9 +1893,7 @@ main(argc, argv, envp)
if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
{
milter_config(InputFilterList, InputFilters, MAXFILTERS);
-# if _FFR_MILTER_PERDAEMON
setup_daemon_milters();
-# endif /* _FFR_MILTER_PERDAEMON */
}
#endif /* MILTER */
@@ -1991,7 +1965,6 @@ main(argc, argv, envp)
/* NOTREACHED */
break;
-#if _FFR_QUARANTINE
case MD_QUEUERUN:
/* only handle quarantining here */
if (quarantining == NULL)
@@ -2009,7 +1982,6 @@ main(argc, argv, envp)
quarantine_queue(quarantining, qgrp);
finis(false, true, EX_OK);
break;
-#endif /* _FFR_QUARANTINE */
case MD_HOSTSTAT:
(void) sm_signal(SIGPIPE, sigpipe);
@@ -2056,7 +2028,7 @@ main(argc, argv, envp)
for (i = 0; i < MAXMAILERS; i++)
{
if (Mailer[i] != NULL)
- printmailer(Mailer[i]);
+ printmailer(sm_debug_file(), Mailer[i]);
}
}
@@ -2286,7 +2258,7 @@ main(argc, argv, envp)
if (OpMode == MD_SMTP)
{
proc_list_add(CurrentPid, "Sendmail SMTP Agent",
- PROC_DAEMON, 0, -1);
+ PROC_DAEMON, 0, -1, NULL);
/* clean up background delivery children */
(void) sm_signal(SIGCHLD, reapchild);
@@ -2385,6 +2357,13 @@ main(argc, argv, envp)
if (OpMode != MD_DAEMON && queuepersistent)
{
+ /*
+ ** Write the pid to file
+ ** XXX Overwrites sendmail.pid
+ */
+
+ log_sendmail_pid(&MainEnvelope);
+
/* set the title to make it easier to find */
sm_setproctitle(true, CurEnv, "Queue control");
(void) sm_signal(SIGCHLD, SIG_DFL);
@@ -2488,7 +2467,9 @@ main(argc, argv, envp)
for (;;)
{
(void) pause();
+
CHECK_RESTART;
+
if (doqueuerun())
(void) runqueue(true, false,
false, false);
@@ -2554,6 +2535,8 @@ main(argc, argv, envp)
else
macdefine(&BlankEnvelope.e_macro, A_PERM,
macid("{client_name}"), RealHostName);
+ macdefine(&BlankEnvelope.e_macro, A_PERM,
+ macid("{client_ptr}"), RealHostName);
macdefine(&BlankEnvelope.e_macro, A_TEMP,
macid("{client_addr}"), anynet_ntoa(&RealHostAddr));
sm_getla();
@@ -2584,8 +2567,9 @@ main(argc, argv, envp)
/* validate the connection */
HoldErrs = true;
nullserver = validate_connection(&RealHostAddr,
- RealHostName,
- &MainEnvelope);
+ macvalue(macid("{client_name}"),
+ &MainEnvelope),
+ &MainEnvelope);
HoldErrs = false;
}
else if (p_flags == NULL)
@@ -2785,11 +2769,9 @@ main(argc, argv, envp)
sm_dprintf("From person = \"%s\"\n",
MainEnvelope.e_from.q_paddr);
-#if _FFR_QUARANTINE
/* Check if quarantining stats should be updated */
if (MainEnvelope.e_quarmsg != NULL)
markstats(&MainEnvelope, NULL, STATS_QUARANTINE);
-#endif /* _FFR_QUARANTINE */
/*
** Actually send everything.
@@ -2813,7 +2795,7 @@ main(argc, argv, envp)
if (tTd(1, 5))
{
sm_dprintf("main[%d]: QS_SENDER ", i);
- printaddr(&e->e_from, false);
+ printaddr(sm_debug_file(), &e->e_from, false);
}
e->e_to = NULL;
sm_getla();
@@ -2881,6 +2863,7 @@ finis(drop, cleanup, exitstat)
bool cleanup;
volatile int exitstat;
{
+ char pidpath[MAXPATHLEN];
/* Still want to process new timeouts added below */
sm_clear_events();
@@ -2953,6 +2936,16 @@ finis(drop, cleanup, exitstat)
cleanup_shm(DaemonPid == getpid());
#endif /* SM_CONF_SHM */
+ /* close locked pid file */
+ close_sendmail_pid();
+
+ if (DaemonPid == getpid() || PidFilePid == getpid())
+ {
+ /* blow away the pid file */
+ expand(PidFile, pidpath, sizeof pidpath, CurEnv);
+ (void) unlink(pidpath);
+ }
+
/* reset uid for process accounting */
endpwent();
sm_mbdb_terminate();
@@ -3309,7 +3302,6 @@ obsolete(argv)
if (ap[0] != '-' || ap[1] == '-')
return;
-#if _FFR_QUARANTINE
/* Don't allow users to use "-Q." or "-Q ." */
if ((ap[1] == 'Q' && ap[2] == '.') ||
(ap[1] == 'Q' && argv[1] != NULL &&
@@ -3319,7 +3311,6 @@ obsolete(argv)
"Can not use -Q.\n");
exit(EX_USAGE);
}
-#endif /* _FFR_QUARANTINE */
/* skip over options that do have a value */
op = strchr(OPTIONS, ap[1]);
@@ -3347,11 +3338,9 @@ obsolete(argv)
if (ap[1] == 'q' && ap[2] == '\0')
*argv = "-q0";
-#if _FFR_QUARANTINE
/* If -Q doesn't have an argument, disable quarantining */
if (ap[1] == 'Q' && ap[2] == '\0')
*argv = "-Q.";
-#endif /* _FFR_QUARANTINE */
/* if -d doesn't have an argument, use 0-99.1 */
if (ap[1] == 'd' && ap[2] == '\0')
@@ -3531,7 +3520,7 @@ dumpstate(when)
sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---");
printopenfds(true);
sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---");
- mci_dump_all(true);
+ mci_dump_all(smioout, true);
rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
if (rs > 0)
{
@@ -3999,7 +3988,7 @@ testmodeline(line, e)
s = rw->r_lhs;
while (*s != NULL)
{
- xputs(*s++);
+ xputs(smioout, *s++);
(void) sm_io_putc(smioout,
SM_TIME_DEFAULT, ' ');
}
@@ -4010,7 +3999,7 @@ testmodeline(line, e)
s = rw->r_rhs;
while (*s != NULL)
{
- xputs(*s++);
+ xputs(smioout, *s++);
(void) sm_io_putc(smioout,
SM_TIME_DEFAULT, ' ');
}
@@ -4023,7 +4012,7 @@ testmodeline(line, e)
for (i = 0; i < MAXMAILERS; i++)
{
if (Mailer[i] != NULL)
- printmailer(Mailer[i]);
+ printmailer(smioout, Mailer[i]);
}
break;
@@ -4075,7 +4064,7 @@ testmodeline(line, e)
"Undefined\n");
else
{
- xputs(p);
+ xputs(smioout, p);
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"\n");
}
@@ -4292,7 +4281,7 @@ testmodeline(line, e)
q = crackaddr(p, e);
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Cracked address = ");
- xputs(q);
+ xputs(smioout, q);
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"\nParsing %s %s address\n",
bitset(RF_HEADERADDR, tryflags) ?
@@ -4344,8 +4333,8 @@ testmodeline(line, e)
register char **pvp;
char pvpbuf[PSBUFSIZE];
- pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf,
- &delimptr, ConfigLevel >= 9 ? TokTypeNoC : NULL);
+ pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf, &delimptr,
+ ConfigLevel >= 9 ? TokTypeNoC : NULL, false);
if (pvp == NULL)
continue;
p = q;
diff --git a/contrib/sendmail/src/map.c b/contrib/sendmail/src/map.c
index 8362327..ad9fa70 100644
--- a/contrib/sendmail/src/map.c
+++ b/contrib/sendmail/src/map.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: map.c,v 8.645.2.10 2003/07/24 18:24:17 ca Exp $")
+SM_RCSID("@(#)$Id: map.c,v 8.664 2004/06/28 17:46:13 ca Exp $")
#if LDAPMAP
# include <sm/ldap.h>
@@ -66,6 +66,12 @@ static bool nis_getcanonname __P((char *, int, int *));
static bool ni_getcanonname __P((char *, int, int *));
#endif /* NETINFO */
static bool text_getcanonname __P((char *, int, int *));
+#if SOCKETMAP
+static STAB *socket_map_findconn __P((const char*));
+
+/* XXX arbitrary limit for sanity */
+# define SOCKETMAP_MAXL 1000000
+#endif /* SOCKETMAP */
/* default error message for trying to open a map in write mode */
#ifdef ENOSYS
@@ -3307,6 +3313,7 @@ ldapmap_open(map, mode)
{
SM_LDAP_STRUCT *lmap;
STAB *s;
+ char *id;
if (tTd(38, 2))
sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode);
@@ -3342,6 +3349,13 @@ ldapmap_open(map, mode)
if (tTd(38, 2))
sm_dprintf("opening new connection\n");
+ if (lmap->ldap_host != NULL)
+ id = lmap->ldap_host;
+ else if (lmap->ldap_uri != NULL)
+ id = lmap->ldap_uri;
+ else
+ id = "localhost";
+
/* No connection yet, connect */
if (!sm_ldap_start(map->map_mname, lmap))
{
@@ -3350,31 +3364,31 @@ ldapmap_open(map, mode)
if (LogLevel > 1)
sm_syslog(LOG_NOTICE, CurEnv->e_id,
"timeout conning to LDAP server %.100s",
- lmap->ldap_target == NULL ? "localhost" : lmap->ldap_target);
+ id);
}
if (!bitset(MF_OPTIONAL, map->map_mflags))
{
if (bitset(MF_NODEFER, map->map_mflags))
+ {
syserr("%s failed to %s in map %s",
# if USE_LDAP_INIT
"ldap_init/ldap_bind",
# else /* USE_LDAP_INIT */
"ldap_open",
# endif /* USE_LDAP_INIT */
- lmap->ldap_target == NULL ? "localhost"
- : lmap->ldap_target,
- map->map_mname);
+ id, map->map_mname);
+ }
else
+ {
syserr("451 4.3.5 %s failed to %s in map %s",
# if USE_LDAP_INIT
"ldap_init/ldap_bind",
# else /* USE_LDAP_INIT */
"ldap_open",
# endif /* USE_LDAP_INIT */
- lmap->ldap_target == NULL ? "localhost"
- : lmap->ldap_target,
- map->map_mname);
+ id, map->map_mname);
+ }
}
return false;
}
@@ -3470,19 +3484,14 @@ ldapmap_lookup(map, name, av, statp)
char **av;
int *statp;
{
-# if _FFR_LDAP_RECURSION
+ int flags;
int plen = 0;
int psize = 0;
-# else /* _FFR_LDAP_RECURSION */
- int entries = 0;
- int i;
- int ret;
- int vsize;
-# endif /* _FFR_LDAP_RECURSION */
int msgid;
int save_errno;
char *vp, *p;
char *result = NULL;
+ SM_RPOOL_T *rpool;
SM_LDAP_STRUCT *lmap = NULL;
char keybuf[MAXNAME + 1];
@@ -3537,391 +3546,37 @@ ldapmap_lookup(map, name, av, statp)
*statp = EX_NOTFOUND;
vp = NULL;
-# if _FFR_LDAP_RECURSION
- {
- int flags;
- SM_RPOOL_T *rpool;
-
- flags = 0;
- if (bitset(MF_SINGLEMATCH, map->map_mflags))
- flags |= SM_LDAP_SINGLEMATCH;
- if (bitset(MF_MATCHONLY, map->map_mflags))
- flags |= SM_LDAP_MATCHONLY;
-
- /* Create an rpool for search related memory usage */
- rpool = sm_rpool_new_x(NULL);
+ flags = 0;
+ if (bitset(MF_SINGLEMATCH, map->map_mflags))
+ flags |= SM_LDAP_SINGLEMATCH;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ flags |= SM_LDAP_MATCHONLY;
- p = NULL;
- *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim,
- rpool, &p, &plen, &psize, NULL);
- save_errno = errno;
+ /* Create an rpool for search related memory usage */
+ rpool = sm_rpool_new_x(NULL);
- /* Copy result so rpool can be freed */
- if (*statp == EX_OK && p != NULL)
- vp = newstr(p);
- sm_rpool_free(rpool);
+ p = NULL;
+ *statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim,
+ rpool, &p, &plen, &psize, NULL);
+ save_errno = errno;
- /* need to restart LDAP connection? */
- if (*statp == EX_RESTART)
- {
- *statp = EX_TEMPFAIL;
- ldapmap_close(map);
- }
+ /* Copy result so rpool can be freed */
+ if (*statp == EX_OK && p != NULL)
+ vp = newstr(p);
+ sm_rpool_free(rpool);
- errno = save_errno;
- if (*statp != EX_OK && *statp != EX_NOTFOUND)
- {
- if (!bitset(MF_OPTIONAL, map->map_mflags))
- {
- if (bitset(MF_NODEFER, map->map_mflags))
- syserr("Error getting LDAP results in map %s",
- map->map_mname);
- else
- syserr("451 4.3.5 Error getting LDAP results in map %s",
- map->map_mname);
- }
- errno = save_errno;
- return NULL;
- }
- }
-# else /* _FFR_LDAP_RECURSION */
-
- /* Get results */
- while ((ret = ldap_result(lmap->ldap_ld, msgid, 0,
- (lmap->ldap_timeout.tv_sec == 0 ? NULL :
- &(lmap->ldap_timeout)),
- &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY)
+ /* need to restart LDAP connection? */
+ if (*statp == EX_RESTART)
{
- LDAPMessage *entry;
-
- if (bitset(MF_SINGLEMATCH, map->map_mflags))
- {
- entries += ldap_count_entries(lmap->ldap_ld,
- lmap->ldap_res);
- if (entries > 1)
- {
- *statp = EX_NOTFOUND;
- if (lmap->ldap_res != NULL)
- {
- ldap_msgfree(lmap->ldap_res);
- lmap->ldap_res = NULL;
- }
- (void) ldap_abandon(lmap->ldap_ld, msgid);
- if (vp != NULL)
- sm_free(vp); /* XXX */
- if (tTd(38, 25))
- sm_dprintf("ldap search found multiple on a single match query\n");
- return NULL;
- }
- }
-
- /* If we don't want multiple values and we have one, break */
- if (map->map_coldelim == '\0' && vp != NULL)
- break;
-
- /* Cycle through all entries */
- for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res);
- entry != NULL;
- entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res))
- {
- BerElement *ber;
- char *attr;
- char **vals = NULL;
-
- /*
- ** If matching only and found an entry,
- ** no need to spin through attributes
- */
-
- if (*statp == EX_OK &&
- bitset(MF_MATCHONLY, map->map_mflags))
- continue;
-
-# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
- /*
- ** Reset value to prevent lingering
- ** LDAP_DECODING_ERROR due to
- ** OpenLDAP 1.X's hack (see below)
- */
-
- lmap->ldap_ld->ld_errno = LDAP_SUCCESS;
-# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
-
- for (attr = ldap_first_attribute(lmap->ldap_ld, entry,
- &ber);
- attr != NULL;
- attr = ldap_next_attribute(lmap->ldap_ld, entry,
- ber))
- {
- char *tmp, *vp_tmp;
-
- if (lmap->ldap_attrsonly == LDAPMAP_FALSE)
- {
- vals = ldap_get_values(lmap->ldap_ld,
- entry,
- attr);
- if (vals == NULL)
- {
- save_errno = sm_ldap_geterrno(lmap->ldap_ld);
- if (save_errno == LDAP_SUCCESS)
- {
- ldap_memfree(attr);
- continue;
- }
-
- /* Must be an error */
- save_errno += E_LDAPBASE;
- if (!bitset(MF_OPTIONAL,
- map->map_mflags))
- {
- errno = save_errno;
- if (bitset(MF_NODEFER,
- map->map_mflags))
- syserr("Error getting LDAP values in map %s",
- map->map_mname);
- else
- syserr("451 4.3.5 Error getting LDAP values in map %s",
- map->map_mname);
- }
- *statp = EX_TEMPFAIL;
- ldap_memfree(attr);
- if (lmap->ldap_res != NULL)
- {
- ldap_msgfree(lmap->ldap_res);
- lmap->ldap_res = NULL;
- }
- (void) ldap_abandon(lmap->ldap_ld,
- msgid);
- if (vp != NULL)
- sm_free(vp); /* XXX */
- errno = save_errno;
- return NULL;
- }
- }
-
- *statp = EX_OK;
-
-# if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
- /*
- ** Reset value to prevent lingering
- ** LDAP_DECODING_ERROR due to
- ** OpenLDAP 1.X's hack (see below)
- */
-
- lmap->ldap_ld->ld_errno = LDAP_SUCCESS;
-# endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
-
- /*
- ** If matching only,
- ** no need to spin through entries
- */
-
- if (bitset(MF_MATCHONLY, map->map_mflags))
- {
- if (lmap->ldap_attrsonly == LDAPMAP_FALSE)
- ldap_value_free(vals);
-
- ldap_memfree(attr);
- continue;
- }
-
- /*
- ** If we don't want multiple values,
- ** return first found.
- */
-
- if (map->map_coldelim == '\0')
- {
- if (lmap->ldap_attrsonly == LDAPMAP_TRUE)
- {
- vp = newstr(attr);
- ldap_memfree(attr);
- break;
- }
-
- if (vals[0] == NULL)
- {
- ldap_value_free(vals);
- ldap_memfree(attr);
- continue;
- }
-
- vsize = strlen(vals[0]) + 1;
- if (lmap->ldap_attrsep != '\0')
- vsize += strlen(attr) + 1;
- vp = xalloc(vsize);
- if (lmap->ldap_attrsep != '\0')
- sm_snprintf(vp, vsize,
- "%s%c%s",
- attr,
- lmap->ldap_attrsep,
- vals[0]);
- else
- sm_strlcpy(vp, vals[0], vsize);
- ldap_value_free(vals);
- ldap_memfree(attr);
- break;
- }
-
- /* attributes only */
- if (lmap->ldap_attrsonly == LDAPMAP_TRUE)
- {
- if (vp == NULL)
- vp = newstr(attr);
- else
- {
- vsize = strlen(vp) +
- strlen(attr) + 2;
- tmp = xalloc(vsize);
- (void) sm_snprintf(tmp,
- vsize, "%s%c%s",
- vp, map->map_coldelim,
- attr);
- sm_free(vp); /* XXX */
- vp = tmp;
- }
- ldap_memfree(attr);
- continue;
- }
-
- /*
- ** If there is more than one,
- ** munge then into a map_coldelim
- ** separated string
- */
-
- vsize = 0;
- for (i = 0; vals[i] != NULL; i++)
- {
- vsize += strlen(vals[i]) + 1;
- if (lmap->ldap_attrsep != '\0')
- vsize += strlen(attr) + 1;
- }
- vp_tmp = xalloc(vsize);
- *vp_tmp = '\0';
-
- p = vp_tmp;
- for (i = 0; vals[i] != NULL; i++)
- {
- if (lmap->ldap_attrsep != '\0')
- {
- p += sm_strlcpy(p, attr,
- vsize - (p - vp_tmp));
- if (p >= vp_tmp + vsize)
- syserr("ldapmap_lookup: Internal error: buffer too small for LDAP values");
- *p++ = lmap->ldap_attrsep;
- }
- p += sm_strlcpy(p, vals[i],
- vsize - (p - vp_tmp));
- if (p >= vp_tmp + vsize)
- syserr("ldapmap_lookup: Internal error: buffer too small for LDAP values");
- if (vals[i + 1] != NULL)
- *p++ = map->map_coldelim;
- }
-
- ldap_value_free(vals);
- ldap_memfree(attr);
- if (vp == NULL)
- {
- vp = vp_tmp;
- continue;
- }
- vsize = strlen(vp) + strlen(vp_tmp) + 2;
- tmp = xalloc(vsize);
- (void) sm_snprintf(tmp, vsize, "%s%c%s",
- vp, map->map_coldelim, vp_tmp);
-
- sm_free(vp); /* XXX */
- sm_free(vp_tmp); /* XXX */
- vp = tmp;
- }
- save_errno = sm_ldap_geterrno(lmap->ldap_ld);
-
- /*
- ** We check errno != LDAP_DECODING_ERROR since
- ** OpenLDAP 1.X has a very ugly *undocumented*
- ** hack of returning this error code from
- ** ldap_next_attribute() if the library freed the
- ** ber attribute. See:
- ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html
- */
-
- if (save_errno != LDAP_SUCCESS &&
- save_errno != LDAP_DECODING_ERROR)
- {
- /* Must be an error */
- save_errno += E_LDAPBASE;
- if (!bitset(MF_OPTIONAL, map->map_mflags))
- {
- errno = save_errno;
- if (bitset(MF_NODEFER, map->map_mflags))
- syserr("Error getting LDAP attributes in map %s",
- map->map_mname);
- else
- syserr("451 4.3.5 Error getting LDAP attributes in map %s",
- map->map_mname);
- }
- *statp = EX_TEMPFAIL;
- if (lmap->ldap_res != NULL)
- {
- ldap_msgfree(lmap->ldap_res);
- lmap->ldap_res = NULL;
- }
- (void) ldap_abandon(lmap->ldap_ld, msgid);
- if (vp != NULL)
- sm_free(vp); /* XXX */
- errno = save_errno;
- return NULL;
- }
-
- /* We don't want multiple values and we have one */
- if (map->map_coldelim == '\0' && vp != NULL)
- break;
- }
- save_errno = sm_ldap_geterrno(lmap->ldap_ld);
- if (save_errno != LDAP_SUCCESS &&
- save_errno != LDAP_DECODING_ERROR)
- {
- /* Must be an error */
- save_errno += E_LDAPBASE;
- if (!bitset(MF_OPTIONAL, map->map_mflags))
- {
- errno = save_errno;
- if (bitset(MF_NODEFER, map->map_mflags))
- syserr("Error getting LDAP entries in map %s",
- map->map_mname);
- else
- syserr("451 4.3.5 Error getting LDAP entries in map %s",
- map->map_mname);
- }
- *statp = EX_TEMPFAIL;
- if (lmap->ldap_res != NULL)
- {
- ldap_msgfree(lmap->ldap_res);
- lmap->ldap_res = NULL;
- }
- (void) ldap_abandon(lmap->ldap_ld, msgid);
- if (vp != NULL)
- sm_free(vp); /* XXX */
- errno = save_errno;
- return NULL;
- }
- ldap_msgfree(lmap->ldap_res);
- lmap->ldap_res = NULL;
+ *statp = EX_TEMPFAIL;
+ ldapmap_close(map);
}
- if (ret == 0)
- save_errno = ETIMEDOUT;
- else
- save_errno = sm_ldap_geterrno(lmap->ldap_ld);
- if (save_errno != LDAP_SUCCESS)
+ errno = save_errno;
+ if (*statp != EX_OK && *statp != EX_NOTFOUND)
{
- if (ret != 0)
- save_errno += E_LDAPBASE;
-
if (!bitset(MF_OPTIONAL, map->map_mflags))
{
- errno = save_errno;
if (bitset(MF_NODEFER, map->map_mflags))
syserr("Error getting LDAP results in map %s",
map->map_mname);
@@ -3929,25 +3584,9 @@ ldapmap_lookup(map, name, av, statp)
syserr("451 4.3.5 Error getting LDAP results in map %s",
map->map_mname);
}
- *statp = EX_TEMPFAIL;
- if (vp != NULL)
- sm_free(vp); /* XXX */
-
- switch (save_errno - E_LDAPBASE)
- {
-# ifdef LDAP_SERVER_DOWN
- case LDAP_SERVER_DOWN:
-# endif /* LDAP_SERVER_DOWN */
- case LDAP_TIMEOUT:
- case LDAP_UNAVAILABLE:
- /* server disappeared, try reopen on next search */
- ldapmap_close(map);
- break;
- }
errno = save_errno;
return NULL;
}
-# endif /* _FFR_LDAP_RECURSION */
/* Did we match anything? */
if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags))
@@ -3994,23 +3633,24 @@ ldapmap_findconn(lmap)
{
char *format;
char *nbuf;
+ char *id;
STAB *SM_NONVOLATILE s = NULL;
-# if _FFR_LDAP_SETVERSION
+ if (lmap->ldap_host != NULL)
+ id = lmap->ldap_host;
+ else if (lmap->ldap_uri != NULL)
+ id = lmap->ldap_uri;
+ else
+ id = "localhost";
+
format = "%s%c%d%c%d%c%s%c%s%d";
-# else /* _FFR_LDAP_SETVERSION */
- format = "%s%c%d%c%s%c%s%d";
-# endif /* _FFR_LDAP_SETVERSION */
nbuf = sm_stringf_x(format,
- (lmap->ldap_target == NULL ? "localhost"
- : lmap->ldap_target),
+ id,
CONDELSE,
lmap->ldap_port,
CONDELSE,
-# if _FFR_LDAP_SETVERSION
lmap->ldap_version,
CONDELSE,
-# endif /* _FFR_LDAP_SETVERSION */
(lmap->ldap_binddn == NULL ? ""
: lmap->ldap_binddn),
CONDELSE,
@@ -4061,9 +3701,7 @@ ldapmap_parseargs(map, args)
char *args;
{
bool secretread = true;
-# if _FFR_LDAP_URI
- bool ldaphost = false;
-# endif /* _FFR_LDAP_URI */
+ bool attrssetup = false;
int i;
register char *p = args;
SM_LDAP_STRUCT *lmap;
@@ -4132,8 +3770,22 @@ ldapmap_parseargs(map, args)
/* default args for an alias LDAP entry */
lmap->ldap_filter = ldapfilt;
- lmap->ldap_attr[0] = "sendmailMTAAliasValue";
- lmap->ldap_attr[1] = NULL;
+ lmap->ldap_attr[0] = "objectClass";
+ lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS;
+ lmap->ldap_attr_needobjclass[0] = NULL;
+ lmap->ldap_attr[1] = "sendmailMTAAliasValue";
+ lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL;
+ lmap->ldap_attr_needobjclass[1] = NULL;
+ lmap->ldap_attr[2] = "sendmailMTAAliasSearch";
+ lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER;
+ lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject";
+ lmap->ldap_attr[3] = "sendmailMTAAliasURL";
+ lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL;
+ lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject";
+ lmap->ldap_attr[4] = NULL;
+ lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE;
+ lmap->ldap_attr_needobjclass[4] = NULL;
+ attrssetup = true;
}
}
else if (bitset(MF_FILECLASS, map->map_mflags))
@@ -4345,16 +3997,13 @@ ldapmap_parseargs(map, args)
case 'h': /* ldap host */
while (isascii(*++p) && isspace(*p))
continue;
-# if _FFR_LDAP_URI
- if (lmap->ldap_uri)
+ if (lmap->ldap_uri != NULL)
{
syserr("Can not specify both an LDAP host and an LDAP URI in map %s",
map->map_mname);
return false;
}
- ldaphost = true;
-# endif /* _FFR_LDAP_URI */
- lmap->ldap_target = p;
+ lmap->ldap_host = p;
break;
case 'b': /* search base */
@@ -4436,14 +4085,13 @@ ldapmap_parseargs(map, args)
secretread = false;
break;
-# if _FFR_LDAP_URI
case 'H': /* Use LDAP URI */
# if !USE_LDAP_INIT
syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s",
map->map_mname);
return false;
-# else /* !USE_LDAP_INIT */
- if (ldaphost)
+# else /* !USE_LDAP_INIT */
+ if (lmap->ldap_host != NULL)
{
syserr("Can not specify both an LDAP host and an LDAP URI in map %s",
map->map_mname);
@@ -4451,19 +4099,16 @@ ldapmap_parseargs(map, args)
}
while (isascii(*++p) && isspace(*p))
continue;
- lmap->ldap_target = p;
- lmap->ldap_uri = true;
+ lmap->ldap_uri = p;
break;
# endif /* !USE_LDAP_INIT */
-# endif /* _FFR_LDAP_URI */
-# if _FFR_LDAP_SETVERSION
case 'w':
/* -w should be for passwd, -P should be for version */
while (isascii(*++p) && isspace(*p))
continue;
lmap->ldap_version = atoi(p);
-# ifdef LDAP_VERSION_MAX
+# ifdef LDAP_VERSION_MAX
if (lmap->ldap_version > LDAP_VERSION_MAX)
{
syserr("LDAP version %d exceeds max of %d in map %s",
@@ -4471,8 +4116,8 @@ ldapmap_parseargs(map, args)
map->map_mname);
return false;
}
-# endif /* LDAP_VERSION_MAX */
-# ifdef LDAP_VERSION_MIN
+# endif /* LDAP_VERSION_MAX */
+# ifdef LDAP_VERSION_MIN
if (lmap->ldap_version < LDAP_VERSION_MIN)
{
syserr("LDAP version %d is lower than min of %d in map %s",
@@ -4480,9 +4125,8 @@ ldapmap_parseargs(map, args)
map->map_mname);
return false;
}
-# endif /* LDAP_VERSION_MIN */
+# endif /* LDAP_VERSION_MIN */
break;
-# endif /* _FFR_LDAP_SETVERSION */
default:
syserr("Illegal option %c map %s", *p, map->map_mname);
@@ -4517,12 +4161,19 @@ ldapmap_parseargs(map, args)
** and dump it into map->map_dbptr1
*/
- if (lmap->ldap_target != NULL &&
+ if (lmap->ldap_host != NULL &&
+ (LDAPDefaults == NULL ||
+ LDAPDefaults == lmap ||
+ LDAPDefaults->ldap_host != lmap->ldap_host))
+ lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host));
+ map->map_domain = lmap->ldap_host;
+
+ if (lmap->ldap_uri != NULL &&
(LDAPDefaults == NULL ||
LDAPDefaults == lmap ||
- LDAPDefaults->ldap_target != lmap->ldap_target))
- lmap->ldap_target = newstr(ldapmap_dequote(lmap->ldap_target));
- map->map_domain = lmap->ldap_target;
+ LDAPDefaults->ldap_uri != lmap->ldap_uri))
+ lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri));
+ map->map_domain = lmap->ldap_uri;
if (lmap->ldap_binddn != NULL &&
(LDAPDefaults == NULL ||
@@ -4649,24 +4300,20 @@ ldapmap_parseargs(map, args)
}
}
- if (lmap->ldap_attr[0] != NULL)
+ if (!attrssetup && lmap->ldap_attr[0] != NULL)
{
-# if _FFR_LDAP_RECURSION
bool recurse = false;
bool normalseen = false;
-# endif /* _FFR_LDAP_RECURSION */
i = 0;
p = ldapmap_dequote(lmap->ldap_attr[0]);
lmap->ldap_attr[0] = NULL;
-# if _FFR_LDAP_RECURSION
/* Prime the attr list with the objectClass attribute */
lmap->ldap_attr[i] = "objectClass";
lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS;
lmap->ldap_attr_needobjclass[i] = NULL;
i++;
-# endif /* _FFR_LDAP_RECURSION */
while (p != NULL)
{
@@ -4689,7 +4336,6 @@ ldapmap_parseargs(map, args)
}
if (*v != '\0')
{
-# if _FFR_LDAP_RECURSION
int j;
int use;
char *type;
@@ -4781,14 +4427,11 @@ ldapmap_parseargs(map, args)
lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL;
normalseen = true;
}
-# else /* _FFR_LDAP_RECURSION */
- lmap->ldap_attr[i] = newstr(v);
-# endif /* _FFR_LDAP_RECURSION */
i++;
}
}
lmap->ldap_attr[i] = NULL;
-# if _FFR_LDAP_RECURSION
+ attrssetup = true;
if (recurse && !normalseen)
{
syserr("LDAP recursion requested in %s but no returnable attribute given",
@@ -4801,7 +4444,6 @@ ldapmap_parseargs(map, args)
map->map_mname);
return false;
}
-# endif /* _FFR_LDAP_RECURSION */
}
map->map_db1 = (ARBPTR_T) lmap;
return true;
@@ -4889,9 +4531,9 @@ static char phmap_id[128];
/* sendmail version for phmap id string */
extern const char Version[];
-/* assume we're using nph-1.1.x if not specified */
+/* assume we're using nph-1.2.x if not specified */
# ifndef NPH_VERSION
-# define NPH_VERSION 10100
+# define NPH_VERSION 10200
# endif
/* compatibility for versions older than nph-1.2.0 */
@@ -5000,12 +4642,6 @@ ph_map_parseargs(map, args)
pmap->ph_servers = p;
break;
- case 'v':
- sm_syslog(LOG_WARNING, NULL,
- "ph_map_parseargs: WARNING: -v option will be removed in a future release - please use -k instead");
- /* intentional fallthrough for backward compatibility */
- /* FALLTHROUGH */
-
case 'k': /* fields to search for */
while (isascii(*++p) && isspace(*p))
continue;
@@ -7399,3 +7035,638 @@ arith_map_lookup(map, name, av, statp)
*statp = EX_CONFIG;
return NULL;
}
+
+#if SOCKETMAP
+
+# if NETINET || NETINET6
+# include <arpa/inet.h>
+# endif /* NETINET || NETINET6 */
+
+# define socket_map_next map_stack[0]
+
+/*
+** SOCKET_MAP_OPEN -- open socket table
+*/
+
+bool
+socket_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ STAB *s;
+ int sock = 0;
+ SOCKADDR_LEN_T addrlen = 0;
+ int addrno = 0;
+ int save_errno;
+ char *p;
+ char *colon;
+ char *at;
+ struct hostent *hp = NULL;
+ SOCKADDR addr;
+
+ if (tTd(38, 2))
+ sm_dprintf("socket_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+ mode &= O_ACCMODE;
+
+ /* sendmail doesn't have the ability to write to SOCKET (yet) */
+ if (mode != O_RDONLY)
+ {
+ /* issue a pseudo-error message */
+ errno = SM_EMAPCANTWRITE;
+ return false;
+ }
+
+ if (*map->map_file == '\0')
+ {
+ syserr("socket map \"%s\": empty or missing socket information",
+ map->map_mname);
+ return false;
+ }
+
+ s = socket_map_findconn(map->map_file);
+ if (s->s_socketmap != NULL)
+ {
+ /* Copy open connection */
+ map->map_db1 = s->s_socketmap->map_db1;
+
+ /* Add this map as head of linked list */
+ map->socket_map_next = s->s_socketmap;
+ s->s_socketmap = map;
+
+ if (tTd(38, 2))
+ sm_dprintf("using cached connection\n");
+ return true;
+ }
+
+ if (tTd(38, 2))
+ sm_dprintf("opening new connection\n");
+
+ /* following code is ripped from milter.c */
+ /* XXX It should be put in a library... */
+
+ /* protocol:filename or protocol:port@host */
+ memset(&addr, '\0', sizeof addr);
+ p = map->map_file;
+ colon = strchr(p, ':');
+ if (colon != NULL)
+ {
+ *colon = '\0';
+
+ if (*p == '\0')
+ {
+# if NETUNIX
+ /* default to AF_UNIX */
+ addr.sa.sa_family = AF_UNIX;
+# else /* NETUNIX */
+# if NETINET
+ /* default to AF_INET */
+ addr.sa.sa_family = AF_INET;
+# else /* NETINET */
+# if NETINET6
+ /* default to AF_INET6 */
+ addr.sa.sa_family = AF_INET6;
+# else /* NETINET6 */
+ /* no protocols available */
+ syserr("socket map \"%s\": no valid socket protocols available",
+ map->map_mname);
+ return false;
+# endif /* NETINET6 */
+# endif /* NETINET */
+# endif /* NETUNIX */
+ }
+# if NETUNIX
+ else if (sm_strcasecmp(p, "unix") == 0 ||
+ sm_strcasecmp(p, "local") == 0)
+ addr.sa.sa_family = AF_UNIX;
+# endif /* NETUNIX */
+# if NETINET
+ else if (sm_strcasecmp(p, "inet") == 0)
+ addr.sa.sa_family = AF_INET;
+# endif /* NETINET */
+# if NETINET6
+ else if (sm_strcasecmp(p, "inet6") == 0)
+ addr.sa.sa_family = AF_INET6;
+# endif /* NETINET6 */
+ else
+ {
+# ifdef EPROTONOSUPPORT
+ errno = EPROTONOSUPPORT;
+# else /* EPROTONOSUPPORT */
+ errno = EINVAL;
+# endif /* EPROTONOSUPPORT */
+ syserr("socket map \"%s\": unknown socket type %s",
+ map->map_mname, p);
+ return false;
+ }
+ *colon++ = ':';
+ }
+ else
+ {
+ colon = p;
+#if NETUNIX
+ /* default to AF_UNIX */
+ addr.sa.sa_family = AF_UNIX;
+#else /* NETUNIX */
+# if NETINET
+ /* default to AF_INET */
+ addr.sa.sa_family = AF_INET;
+# else /* NETINET */
+# if NETINET6
+ /* default to AF_INET6 */
+ addr.sa.sa_family = AF_INET6;
+# else /* NETINET6 */
+ syserr("socket map \"%s\": unknown socket type %s",
+ map->map_mname, p);
+ return false;
+# endif /* NETINET6 */
+# endif /* NETINET */
+#endif /* NETUNIX */
+ }
+
+# if NETUNIX
+ if (addr.sa.sa_family == AF_UNIX)
+ {
+ long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK;
+
+ at = colon;
+ if (strlen(colon) >= sizeof addr.sunix.sun_path)
+ {
+ syserr("socket map \"%s\": local socket name %s too long",
+ map->map_mname, colon);
+ return false;
+ }
+ errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff,
+ S_IRUSR|S_IWUSR, NULL);
+
+ if (errno != 0)
+ {
+ /* if not safe, don't create */
+ syserr("socket map \"%s\": local socket name %s unsafe",
+ map->map_mname, colon);
+ return false;
+ }
+
+ (void) sm_strlcpy(addr.sunix.sun_path, colon,
+ sizeof addr.sunix.sun_path);
+ addrlen = sizeof (struct sockaddr_un);
+ }
+ else
+# endif /* NETUNIX */
+# if NETINET || NETINET6
+ if (false
+# if NETINET
+ || addr.sa.sa_family == AF_INET
+# endif /* NETINET */
+# if NETINET6
+ || addr.sa.sa_family == AF_INET6
+# endif /* NETINET6 */
+ )
+ {
+ unsigned short port;
+
+ /* Parse port@host */
+ at = strchr(colon, '@');
+ if (at == NULL)
+ {
+ syserr("socket map \"%s\": bad address %s (expected port@host)",
+ map->map_mname, colon);
+ return false;
+ }
+ *at = '\0';
+ if (isascii(*colon) && isdigit(*colon))
+ port = htons((unsigned short) atoi(colon));
+ else
+ {
+# ifdef NO_GETSERVBYNAME
+ syserr("socket map \"%s\": invalid port number %s",
+ map->map_mname, colon);
+ return false;
+# else /* NO_GETSERVBYNAME */
+ register struct servent *sp;
+
+ sp = getservbyname(colon, "tcp");
+ if (sp == NULL)
+ {
+ syserr("socket map \"%s\": unknown port name %s",
+ map->map_mname, colon);
+ return false;
+ }
+ port = sp->s_port;
+# endif /* NO_GETSERVBYNAME */
+ }
+ *at++ = '@';
+ if (*at == '[')
+ {
+ char *end;
+
+ end = strchr(at, ']');
+ if (end != NULL)
+ {
+ bool found = false;
+# if NETINET
+ unsigned long hid = INADDR_NONE;
+# endif /* NETINET */
+# if NETINET6
+ struct sockaddr_in6 hid6;
+# endif /* NETINET6 */
+
+ *end = '\0';
+# if NETINET
+ if (addr.sa.sa_family == AF_INET &&
+ (hid = inet_addr(&at[1])) != INADDR_NONE)
+ {
+ addr.sin.sin_addr.s_addr = hid;
+ addr.sin.sin_port = port;
+ found = true;
+ }
+# endif /* NETINET */
+# if NETINET6
+ (void) memset(&hid6, '\0', sizeof hid6);
+ if (addr.sa.sa_family == AF_INET6 &&
+ anynet_pton(AF_INET6, &at[1],
+ &hid6.sin6_addr) == 1)
+ {
+ addr.sin6.sin6_addr = hid6.sin6_addr;
+ addr.sin6.sin6_port = port;
+ found = true;
+ }
+# endif /* NETINET6 */
+ *end = ']';
+ if (!found)
+ {
+ syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"",
+ map->map_mname, at);
+ return false;
+ }
+ }
+ else
+ {
+ syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"",
+ map->map_mname, at);
+ return false;
+ }
+ }
+ else
+ {
+ hp = sm_gethostbyname(at, addr.sa.sa_family);
+ if (hp == NULL)
+ {
+ syserr("socket map \"%s\": Unknown host name %s",
+ map->map_mname, at);
+ return false;
+ }
+ addr.sa.sa_family = hp->h_addrtype;
+ switch (hp->h_addrtype)
+ {
+# if NETINET
+ case AF_INET:
+ memmove(&addr.sin.sin_addr,
+ hp->h_addr, INADDRSZ);
+ addr.sin.sin_port = port;
+ addrlen = sizeof (struct sockaddr_in);
+ addrno = 1;
+ break;
+# endif /* NETINET */
+
+# if NETINET6
+ case AF_INET6:
+ memmove(&addr.sin6.sin6_addr,
+ hp->h_addr, IN6ADDRSZ);
+ addr.sin6.sin6_port = port;
+ addrlen = sizeof (struct sockaddr_in6);
+ addrno = 1;
+ break;
+# endif /* NETINET6 */
+
+ default:
+ syserr("socket map \"%s\": Unknown protocol for %s (%d)",
+ map->map_mname, at, hp->h_addrtype);
+# if NETINET6
+ freehostent(hp);
+# endif /* NETINET6 */
+ return false;
+ }
+ }
+ }
+ else
+# endif /* NETINET || NETINET6 */
+ {
+ syserr("socket map \"%s\": unknown socket protocol",
+ map->map_mname);
+ return false;
+ }
+
+ /* nope, actually connecting */
+ for (;;)
+ {
+ sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ save_errno = errno;
+ if (tTd(38, 5))
+ sm_dprintf("socket map \"%s\": error creating socket: %s\n",
+ map->map_mname,
+ sm_errstring(save_errno));
+# if NETINET6
+ if (hp != NULL)
+ freehostent(hp);
+# endif /* NETINET6 */
+ return false;
+ }
+
+ if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0)
+ break;
+
+ /* couldn't connect.... try next address */
+ save_errno = errno;
+ p = CurHostName;
+ CurHostName = at;
+ if (tTd(38, 5))
+ sm_dprintf("socket_open (%s): open %s failed: %s\n",
+ map->map_mname, at, sm_errstring(save_errno));
+ CurHostName = p;
+ (void) close(sock);
+
+ /* try next address */
+ if (hp != NULL && hp->h_addr_list[addrno] != NULL)
+ {
+ switch (addr.sa.sa_family)
+ {
+# if NETINET
+ case AF_INET:
+ memmove(&addr.sin.sin_addr,
+ hp->h_addr_list[addrno++],
+ INADDRSZ);
+ break;
+# endif /* NETINET */
+
+# if NETINET6
+ case AF_INET6:
+ memmove(&addr.sin6.sin6_addr,
+ hp->h_addr_list[addrno++],
+ IN6ADDRSZ);
+ break;
+# endif /* NETINET6 */
+
+ default:
+ if (tTd(38, 5))
+ sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n",
+ map->map_mname, at,
+ hp->h_addrtype);
+# if NETINET6
+ freehostent(hp);
+# endif /* NETINET6 */
+ return false;
+ }
+ continue;
+ }
+ p = CurHostName;
+ CurHostName = at;
+ if (tTd(38, 5))
+ sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n",
+ map->map_mname, sm_errstring(save_errno));
+ CurHostName = p;
+# if NETINET6
+ if (hp != NULL)
+ freehostent(hp);
+# endif /* NETINET6 */
+ return false;
+ }
+# if NETINET6
+ if (hp != NULL)
+ {
+ freehostent(hp);
+ hp = NULL;
+ }
+# endif /* NETINET6 */
+ if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd,
+ SM_TIME_DEFAULT,
+ (void *) &sock,
+ SM_IO_RDWR,
+ NULL)) == NULL)
+ {
+ close(sock);
+ if (tTd(38, 2))
+ sm_dprintf("socket_open (%s): failed to create stream: %s\n",
+ map->map_mname, sm_errstring(errno));
+ return false;
+ }
+
+ /* Save connection for reuse */
+ s->s_socketmap = map;
+ return true;
+}
+
+/*
+** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server
+**
+** Cache SOCKET connections based on the connection specifier
+** and PID so we don't have multiple connections open to
+** the same server for different maps. Need a separate connection
+** per PID since a parent process may close the map before the
+** child is done with it.
+**
+** Parameters:
+** conn -- SOCKET map connection specifier
+**
+** Returns:
+** Symbol table entry for the SOCKET connection.
+*/
+
+static STAB *
+socket_map_findconn(conn)
+ const char *conn;
+{
+ char *nbuf;
+ STAB *SM_NONVOLATILE s = NULL;
+
+ nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid);
+ SM_TRY
+ s = stab(nbuf, ST_SOCKETMAP, ST_ENTER);
+ SM_FINALLY
+ sm_free(nbuf);
+ SM_END_TRY
+ return s;
+}
+
+/*
+** SOCKET_MAP_CLOSE -- close the socket
+*/
+
+void
+socket_map_close(map)
+ MAP *map;
+{
+ STAB *s;
+ MAP *smap;
+
+ if (tTd(38, 20))
+ sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file,
+ (long) CurrentPid);
+
+ /* Check if already closed */
+ if (map->map_db1 == NULL)
+ {
+ if (tTd(38, 20))
+ sm_dprintf("socket_map_close(%s) already closed\n",
+ map->map_file);
+ return;
+ }
+ sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT);
+
+ /* Mark all the maps that share the connection as closed */
+ s = socket_map_findconn(map->map_file);
+ smap = s->s_socketmap;
+ while (smap != NULL)
+ {
+ MAP *next;
+
+ if (tTd(38, 2) && smap != map)
+ sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n",
+ map->map_mname, smap->map_mname);
+
+ smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
+ smap->map_db1 = NULL;
+ next = smap->socket_map_next;
+ smap->socket_map_next = NULL;
+ smap = next;
+ }
+ s->s_socketmap = NULL;
+}
+
+/*
+** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table
+*/
+
+char *
+socket_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ unsigned int nettolen, replylen, recvlen;
+ char *replybuf, *rval, *value, *status;
+ SM_FILE_T *f;
+
+ replybuf = NULL;
+ rval = NULL;
+ f = (SM_FILE_T *)map->map_db1;
+ if (tTd(38, 20))
+ sm_dprintf("socket_map_lookup(%s, %s) %s\n",
+ map->map_mname, name, map->map_file);
+
+ nettolen = strlen(map->map_mname) + 1 + strlen(name);
+ SM_ASSERT(nettolen > strlen(map->map_mname));
+ SM_ASSERT(nettolen > strlen(name));
+ if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,",
+ nettolen, map->map_mname, name) == SM_IO_EOF) ||
+ (sm_io_flush(f, SM_TIME_DEFAULT) != 0) ||
+ (sm_io_error(f)))
+ {
+ syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request",
+ map->map_mname);
+ *statp = EX_TEMPFAIL;
+ goto errcl;
+ }
+
+ if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1)
+ {
+ syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply",
+ map->map_mname);
+ *statp = EX_TEMPFAIL;
+ goto errcl;
+ }
+ if (replylen > SOCKETMAP_MAXL)
+ {
+ syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u",
+ map->map_mname, replylen);
+ *statp = EX_TEMPFAIL;
+ goto errcl;
+ }
+ if (sm_io_getc(f, SM_TIME_DEFAULT) != ':')
+ {
+ syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply",
+ map->map_mname);
+ *statp = EX_TEMPFAIL;
+ goto error;
+ }
+
+ replybuf = (char *) sm_malloc(replylen + 1);
+ if (replybuf == NULL)
+ {
+ syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes",
+ map->map_mname, replylen + 1);
+ *statp = EX_OSERR;
+ goto error;
+ }
+
+ recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen);
+ if (recvlen < replylen)
+ {
+ syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters",
+ map->map_mname, recvlen, replylen);
+ *statp = EX_TEMPFAIL;
+ goto errcl;
+ }
+ if (sm_io_getc(f, SM_TIME_DEFAULT) != ',')
+ {
+ syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply",
+ map->map_mname);
+ *statp = EX_TEMPFAIL;
+ goto errcl;
+ }
+ status = replybuf;
+ replybuf[recvlen] = '\0';
+ value = strchr(replybuf, ' ');
+ if (value != NULL)
+ {
+ *value = '\0';
+ value++;
+ }
+ if (strcmp(status, "OK") == 0)
+ {
+ *statp = EX_OK;
+
+ /* collect the return value */
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ rval = map_rewrite(map, name, strlen(name), NULL);
+ else
+ rval = map_rewrite(map, value, strlen(value), av);
+ }
+ else if (strcmp(status, "NOTFOUND") == 0)
+ {
+ *statp = EX_NOTFOUND;
+ if (tTd(38, 20))
+ sm_dprintf("socket_map_lookup(%s): %s not found\n",
+ map->map_mname, name);
+ }
+ else
+ {
+ if (tTd(38, 5))
+ sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n",
+ map->map_mname, name, status,
+ value ? value : "");
+ if ((strcmp(status, "TEMP") == 0) ||
+ (strcmp(status, "TIMEOUT") == 0))
+ *statp = EX_TEMPFAIL;
+ else if(strcmp(status, "PERM") == 0)
+ *statp = EX_UNAVAILABLE;
+ else
+ *statp = EX_PROTOCOL;
+ }
+
+ if (replybuf != NULL)
+ sm_free(replybuf);
+ return rval;
+
+ errcl:
+ socket_map_close(map);
+ error:
+ if (replybuf != NULL)
+ sm_free(replybuf);
+ return rval;
+}
+#endif /* SOCKETMAP */
diff --git a/contrib/sendmail/src/mci.c b/contrib/sendmail/src/mci.c
index b8c0de2..dd8d7c3 100644
--- a/contrib/sendmail/src/mci.c
+++ b/contrib/sendmail/src/mci.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: mci.c,v 8.205.2.4 2003/03/31 17:35:27 ca Exp $")
+SM_RCSID("@(#)$Id: mci.c,v 8.211 2003/03/31 17:35:50 ca Exp $")
#if NETINET || NETINET6
# include <arpa/inet.h>
@@ -487,6 +487,7 @@ mci_setstat(mci, xstat, dstat, rstat)
** MCI_DUMP -- dump the contents of an MCI structure.
**
** Parameters:
+** fp -- output file pointer
** mci -- the MCI structure to dump.
**
** Returns:
@@ -529,7 +530,8 @@ static struct mcifbits MciFlags[] =
};
void
-mci_dump(mci, logit)
+mci_dump(fp, mci, logit)
+ SM_FILE_T *fp;
register MCI *mci;
bool logit;
{
@@ -597,12 +599,13 @@ printit:
if (logit)
sm_syslog(LOG_DEBUG, CurEnv->e_id, "%.1000s", buf);
else
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s\n", buf);
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s\n", buf);
}
/*
** MCI_DUMP_ALL -- print the entire MCI cache
**
** Parameters:
+** fp -- output file pointer
** logit -- if set, log the result instead of printing
** to stdout.
**
@@ -611,7 +614,8 @@ printit:
*/
void
-mci_dump_all(logit)
+mci_dump_all(fp, logit)
+ SM_FILE_T *fp;
bool logit;
{
register int i;
@@ -620,7 +624,7 @@ mci_dump_all(logit)
return;
for (i = 0; i < MaxMciCache; i++)
- mci_dump(MciCache[i], logit);
+ mci_dump(fp, MciCache[i], logit);
}
/*
** MCI_LOCK_HOST -- Lock host while sending.
@@ -925,7 +929,7 @@ mci_read_persistent(fp, mci)
case '.': /* end of file */
if (tTd(56, 93))
- mci_dump(mci, false);
+ mci_dump(sm_debug_file(), mci, false);
return 0;
default:
diff --git a/contrib/sendmail/src/milter.c b/contrib/sendmail/src/milter.c
index c25101c..b89fac0 100644
--- a/contrib/sendmail/src/milter.c
+++ b/contrib/sendmail/src/milter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -10,7 +10,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: milter.c,v 8.197.2.10 2003/12/01 23:57:44 msk Exp $")
+SM_RCSID("@(#)$Id: milter.c,v 8.225 2004/07/08 21:52:20 ca Exp $")
#if MILTER
# include <libmilter/mfapi.h>
@@ -18,9 +18,13 @@ SM_RCSID("@(#)$Id: milter.c,v 8.197.2.10 2003/12/01 23:57:44 msk Exp $")
# include <errno.h>
# include <sys/time.h>
+# include <sys/uio.h>
# if NETINET || NETINET6
# include <arpa/inet.h>
+# if _FFR_MILTER_NAGLE
+# include <netinet/tcp.h>
+# endif /* _FFR_MILTER_NAGLE */
# endif /* NETINET || NETINET6 */
# include <sm/fdset.h>
@@ -34,9 +38,9 @@ static char *MilterConnectMacros[MAXFILTERMACROS + 1];
static char *MilterHeloMacros[MAXFILTERMACROS + 1];
static char *MilterEnvFromMacros[MAXFILTERMACROS + 1];
static char *MilterEnvRcptMacros[MAXFILTERMACROS + 1];
-#if _FFR_MILTER_MACROS_EOM
+static char *MilterDataMacros[MAXFILTERMACROS + 1];
static char *MilterEOMMacros[MAXFILTERMACROS + 1];
-#endif /* _FFR_MILTER_MACROS_EOM */
+static size_t MilterMaxDataSize = MILTER_MAX_DATA_SIZE;
# define MILTER_CHECK_DONE_MSG() \
if (*state == SMFIR_REPLYCODE || \
@@ -48,8 +52,7 @@ static char *MilterEOMMacros[MAXFILTERMACROS + 1];
milter_abort(e); \
}
-# if _FFR_QUARANTINE
-# define MILTER_CHECK_ERROR(initial, action) \
+# define MILTER_CHECK_ERROR(initial, action) \
if (!initial && tTd(71, 100)) \
{ \
if (e->e_quarmsg == NULL) \
@@ -76,15 +79,6 @@ static char *MilterEOMMacros[MAXFILTERMACROS + 1];
*state = SMFIR_REJECT; \
else \
action;
-# else /* _FFR_QUARANTINE */
-# define MILTER_CHECK_ERROR(initial, action) \
- if (bitnset(SMF_TEMPFAIL, m->mf_flags)) \
- *state = SMFIR_TEMPFAIL; \
- else if (bitnset(SMF_REJECT, m->mf_flags)) \
- *state = SMFIR_REJECT; \
- else \
- action;
-# endif /* _FFR_QUARANTINE */
# define MILTER_CHECK_REPLYCODE(default) \
if (response == NULL || \
@@ -346,6 +340,11 @@ milter_read(m, cmd, rlen, to, e)
time_t readstart = 0;
ssize_t expl;
mi_int32 i;
+# if _FFR_MILTER_NAGLE
+# ifdef TCP_CORK
+ int cork = 0;
+# endif
+# endif /* _FFR_MILTER_NAGLE */
char *buf;
char data[MILTER_LEN_BYTES + 1];
@@ -355,9 +354,24 @@ milter_read(m, cmd, rlen, to, e)
if (to > 0)
readstart = curtime();
+# if _FFR_MILTER_NAGLE
+# ifdef TCP_CORK
+ setsockopt(m->mf_sock, IPPROTO_TCP, TCP_CORK, (char *)&cork,
+ sizeof(cork));
+# endif
+# endif /* _FFR_MILTER_NAGLE */
+
if (milter_sysread(m, data, sizeof data, to, e) == NULL)
return NULL;
+# if _FFR_MILTER_NAGLE
+# ifdef TCP_CORK
+ cork = 1;
+ setsockopt(m->mf_sock, IPPROTO_TCP, TCP_CORK, (char *)&cork,
+ sizeof(cork));
+# endif
+# endif /* _FFR_MILTER_NAGLE */
+
/* reset timeout */
if (to > 0)
{
@@ -418,6 +432,7 @@ milter_read(m, cmd, rlen, to, e)
*rlen = expl;
return buf;
}
+
/*
** MILTER_WRITE -- write to a remote milter filter
**
@@ -446,11 +461,19 @@ milter_write(m, cmd, buf, len, to, e)
{
time_t writestart = (time_t) 0;
ssize_t sl, i;
+ int num_vectors;
mi_int32 nl;
char data[MILTER_LEN_BYTES + 1];
bool started = false;
+ struct iovec vector[2];
+
+ /*
+ ** At most two buffers will be written, though
+ ** only one may actually be used (see num_vectors).
+ ** The first is the size/command and the second is the command data.
+ */
- if (len < 0 || len > MILTER_CHUNK_SIZE)
+ if (len < 0 || len > MilterMaxDataSize)
{
if (tTd(64, 5))
sm_dprintf("milter_write(%s): length %ld out of range\n",
@@ -472,65 +495,48 @@ milter_write(m, cmd, buf, len, to, e)
data[MILTER_LEN_BYTES] = cmd;
sl = MILTER_LEN_BYTES + 1;
- if (to > 0)
- {
- writestart = curtime();
- MILTER_TIMEOUT("write", to, true, started);
- }
+ /* set up the vector for the size / command */
+ vector[0].iov_base = (void *) data;
+ vector[0].iov_len = sl;
- /* use writev() instead to send the whole stuff at once? */
- i = write(m->mf_sock, (void *) data, sl);
- if (i != sl)
- {
- int save_errno = errno;
+ /*
+ ** Determine if there is command data. If so, there will be two
+ ** vectors. If not, there will be only one. The vectors are set
+ ** up here and 'num_vectors' and 'sl' are set appropriately.
+ */
- if (tTd(64, 5))
- sm_dprintf("milter_write (%s): write(%c) returned %ld, expected %ld: %s\n",
- m->mf_name, cmd, (long) i, (long) sl,
- sm_errstring(save_errno));
- if (MilterLogLevel > 0)
- sm_syslog(LOG_ERR, e->e_id,
- "Milter (%s): write(%c) returned %ld, expected %ld: %s",
- m->mf_name, cmd, (long) i, (long) sl,
- sm_errstring(save_errno));
- milter_error(m, e);
- return buf;
+ /* NOTE: len<0 has already been checked for. Pedantic */
+ if (len <= 0 || buf == NULL)
+ {
+ /* There is no command data -- only a size / command data */
+ num_vectors = 1;
}
+ else
+ {
+ /*
+ ** There is both size / command and command data.
+ ** Set up the vector for the command data.
+ */
- if (len <= 0 || buf == NULL)
- return buf;
+ num_vectors = 2;
+ sl += len;
+ vector[1].iov_base = (void *) buf;
+ vector[1].iov_len = len;
- if (tTd(64, 50))
- sm_dprintf("milter_write(%s): Sending %*s\n",
- m->mf_name, (int) len, buf);
- started = true;
+ if (tTd(64, 50))
+ sm_dprintf("milter_write(%s): Sending %*s\n",
+ m->mf_name, (int) len, buf);
+ }
if (to > 0)
{
- time_t now;
-
- now = curtime();
- if (now - writestart >= to)
- {
- if (tTd(64, 5))
- sm_dprintf("milter_write(%s): timeout before data write\n",
- m->mf_name);
- if (MilterLogLevel > 0)
- sm_syslog(LOG_ERR, e->e_id,
- "Milter (%s): timeout before data write",
- m->mf_name);
- milter_error(m, e);
- return NULL;
- }
- else
- {
- to -= now - writestart;
- MILTER_TIMEOUT("write", to, true, started);
- }
+ writestart = curtime();
+ MILTER_TIMEOUT("write", to, true, started);
}
- i = write(m->mf_sock, (void *) buf, len);
- if (i != len)
+ /* write the vector(s) */
+ i = writev(m->mf_sock, vector, num_vectors);
+ if (i != sl)
{
int save_errno = errno;
@@ -541,7 +547,7 @@ milter_write(m, cmd, buf, len, to, e)
if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
"Milter (%s): write(%c) returned %ld, expected %ld: %s",
- m->mf_name, cmd, (long) i, (long) len,
+ m->mf_name, cmd, (long) i, (long) sl,
sm_errstring(save_errno));
milter_error(m, e);
return NULL;
@@ -1107,6 +1113,16 @@ milter_open(m, parseonly, e)
hp = NULL;
}
# endif /* NETINET6 */
+# if _FFR_MILTER_NAGLE
+# ifndef TCP_CORK
+ {
+ int nodelay = 1;
+
+ setsockopt(m->mf_sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&nodelay, sizeof(nodelay));
+ }
+# endif /* TCP_CORK */
+# endif /* _FFR_MILTER_NAGLE */
return sock;
}
@@ -1270,11 +1286,7 @@ milter_config(spec, list, max)
list[0] = NULL;
return;
}
-#if _FFR_MILTER_PERDAEMON
p = strpbrk(p, ";,");
-#else /* _FFR_MILTER_PERDAEMON */
- p = strpbrk(p, ",");
-#endif /* _FFR_MILTER_PERDAEMON */
if (p != NULL)
*p++ = '\0';
@@ -1312,6 +1324,7 @@ milter_parse_timeouts(spec, m)
struct milter *m;
{
char fcode;
+ int tcode;
register char *p;
p = spec;
@@ -1339,40 +1352,25 @@ milter_parse_timeouts(spec, m)
/* p now points to the field body */
p = munchstring(p, &delimptr, ';');
+ tcode = -1;
/* install the field into the filter struct */
switch (fcode)
{
case 'C':
- m->mf_timeout[SMFTO_CONNECT] = convtime(p, 's');
- if (tTd(64, 5))
- sm_dprintf("X%s: %c=%lu\n",
- m->mf_name, fcode,
- (unsigned long) m->mf_timeout[SMFTO_CONNECT]);
+ tcode = SMFTO_CONNECT;
break;
case 'S':
- m->mf_timeout[SMFTO_WRITE] = convtime(p, 's');
- if (tTd(64, 5))
- sm_dprintf("X%s: %c=%lu\n",
- m->mf_name, fcode,
- (unsigned long) m->mf_timeout[SMFTO_WRITE]);
+ tcode = SMFTO_WRITE;
break;
case 'R':
- m->mf_timeout[SMFTO_READ] = convtime(p, 's');
- if (tTd(64, 5))
- sm_dprintf("X%s: %c=%lu\n",
- m->mf_name, fcode,
- (unsigned long) m->mf_timeout[SMFTO_READ]);
+ tcode = SMFTO_READ;
break;
case 'E':
- m->mf_timeout[SMFTO_EOM] = convtime(p, 's');
- if (tTd(64, 5))
- sm_dprintf("X%s: %c=%lu\n",
- m->mf_name, fcode,
- (unsigned long) m->mf_timeout[SMFTO_EOM]);
+ tcode = SMFTO_EOM;
break;
default:
@@ -1383,6 +1381,14 @@ milter_parse_timeouts(spec, m)
m->mf_name, fcode);
break;
}
+ if (tcode >= 0)
+ {
+ m->mf_timeout[tcode] = convtime(p, 's');
+ if (tTd(64, 5))
+ sm_dprintf("X%s: %c=%ld\n",
+ m->mf_name, fcode,
+ (u_long) m->mf_timeout[tcode]);
+ }
p = delimptr;
}
}
@@ -1416,12 +1422,16 @@ static struct milteropt
{ "macros.envfrom", MO_MACROS_ENVFROM },
# define MO_MACROS_ENVRCPT 0x04
{ "macros.envrcpt", MO_MACROS_ENVRCPT },
-# define MO_LOGLEVEL 0x05
- { "loglevel", MO_LOGLEVEL },
-#if _FFR_MILTER_MACROS_EOM
+# define MO_MACROS_DATA 0x05
+ { "macros.data", MO_MACROS_DATA },
# define MO_MACROS_EOM 0x06
{ "macros.eom", MO_MACROS_EOM },
-#endif /* _FFR_MILTER_MACROS_EOM */
+# define MO_LOGLEVEL 0x07
+ { "loglevel", MO_LOGLEVEL },
+# if _FFR_MAXDATASIZE
+# define MO_MAXDATASIZE 0x08
+ { "maxdatasize", MO_MAXDATASIZE },
+# endif /* _FFR_MAXDATASIZE */
{ NULL, 0 },
};
@@ -1477,6 +1487,12 @@ milter_set_option(name, val, sticky)
MilterLogLevel = atoi(val);
break;
+#if _FFR_MAXDATASIZE
+ case MO_MAXDATASIZE:
+ MilterMaxDataSize = (size_t)atol(val);
+ break;
+#endif /* _FFR_MAXDATASIZE */
+
case MO_MACROS_CONNECT:
if (macros == NULL)
macros = MilterConnectMacros;
@@ -1495,13 +1511,16 @@ milter_set_option(name, val, sticky)
case MO_MACROS_ENVRCPT:
if (macros == NULL)
macros = MilterEnvRcptMacros;
-#if _FFR_MILTER_MACROS_EOM
/* FALLTHROUGH */
case MO_MACROS_EOM:
if (macros == NULL)
macros = MilterEOMMacros;
-#endif /* _FFR_MILTER_MACROS_EOM */
+ /* FALLTHROUGH */
+
+ case MO_MACROS_DATA:
+ if (macros == NULL)
+ macros = MilterDataMacros;
p = newstr(val);
while (*p != '\0')
@@ -1567,9 +1586,8 @@ milter_reopen_df(e)
** read only again).
**
** In SuperSafe != SAFE_REALLY mode, e->e_dfp still points at the
- ** buffered file I/O descriptor, still open for writing
- ** so there isn't as much work to do, just truncate it
- ** and go.
+ ** buffered file I/O descriptor, still open for writing so there
+ ** isn't any work to do here (except checking for consistency).
*/
if (SuperSafe == SAFE_REALLY)
@@ -1861,6 +1879,9 @@ milter_send_command(m, command, data, sz, e, state)
char rcmd;
ssize_t rlen;
unsigned long skipflag;
+#if _FFR_MILTER_NOHDR_RESP
+ unsigned long norespflag = 0;
+#endif /* _FFR_MILTER_NOHDR_RESP */
char *action;
char *defresponse;
char *response;
@@ -1898,6 +1919,9 @@ milter_send_command(m, command, data, sz, e, state)
case SMFIC_HEADER:
skipflag = SMFIP_NOHDRS;
+#if _FFR_MILTER_NOHDR_RESP
+ norespflag = SMFIP_NOHREPL;
+#endif /* _FFR_MILTER_NOHDR_RESP */
action = "header";
defresponse = "550 5.7.1 Command rejected";
break;
@@ -1914,6 +1938,13 @@ milter_send_command(m, command, data, sz, e, state)
defresponse = "550 5.7.1 Command rejected";
break;
+#if SMFI_VERSION > 2
+ case SMFIC_UNKNOWN:
+ action = "unknown";
+ defresponse = "550 5.7.1 Command rejected";
+ break;
+#endif /* SMFI_VERSION > 2 */
+
case SMFIC_BODYEOB:
case SMFIC_OPTNEG:
case SMFIC_MACRO:
@@ -1943,6 +1974,12 @@ milter_send_command(m, command, data, sz, e, state)
return NULL;
}
+#if _FFR_MILTER_NOHDR_RESP
+ /* check if filter sends response to this command */
+ if (norespflag != 0 && bitset(norespflag, m->mf_pflags))
+ return NULL;
+#endif /* _FFR_MILTER_NOHDR_RESP */
+
/* get the response from the filter */
response = milter_read(m, &rcmd, &rlen,
m->mf_timeout[SMFTO_READ], e);
@@ -2364,7 +2401,7 @@ milter_headers(m, e, state)
/* don't send over deleted headers */
if (h->h_value == NULL)
{
- /* strip H_USER so not counted in milter_chgheader() */
+ /* strip H_USER so not counted in milter_changeheader() */
h->h_flags &= ~H_USER;
continue;
}
@@ -2621,6 +2658,84 @@ milter_addheader(response, rlen, e)
}
}
/*
+** MILTER_INSHEADER -- Insert the supplied header
+**
+** Parameters:
+** response -- encoded form of header/value.
+** rlen -- length of response.
+** e -- current envelope.
+**
+** Returns:
+** none
+**
+** Notes:
+** Unlike milter_addheader(), this does not attempt to determine
+** if the header already exists in the envelope, even a
+** deleted version. It just blindly inserts.
+*/
+
+static void
+milter_insheader(response, rlen, e)
+ char *response;
+ ssize_t rlen;
+ ENVELOPE *e;
+{
+ mi_int32 idx, i;
+ char *field;
+ char *val;
+
+ if (tTd(64, 10))
+ sm_dprintf("milter_insheader: ");
+
+ /* sanity checks */
+ if (response == NULL)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("NULL response\n");
+ return;
+ }
+
+ if (rlen < 2 || strlen(response) + 1 >= (size_t) rlen)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("didn't follow protocol (total len)\n");
+ return;
+ }
+
+ /* decode */
+ (void) memcpy((char *) &i, response, MILTER_LEN_BYTES);
+ idx = ntohl(i);
+ field = response + MILTER_LEN_BYTES;
+ val = field + strlen(field) + 1;
+
+ /* another sanity check */
+ if (MILTER_LEN_BYTES + strlen(field) + 1 +
+ strlen(val) + 1 != (size_t) rlen)
+ {
+ if (tTd(64, 10))
+ sm_dprintf("didn't follow protocol (part len)\n");
+ return;
+ }
+
+ if (*field == '\0')
+ {
+ if (tTd(64, 10))
+ sm_dprintf("empty field name\n");
+ return;
+ }
+
+ /* add to e_msgsize */
+ e->e_msgsize += strlen(response) + 2 + strlen(val);
+
+ if (tTd(64, 10))
+ sm_dprintf("Insert (%d) %s: %s\n", idx, response, val);
+ if (MilterLogLevel > 8)
+ sm_syslog(LOG_INFO, e->e_id,
+ "Milter insert (%d): header: %s: %s",
+ idx, field, val);
+ insheader(idx, newstr(field), val, H_USER, e);
+}
+/*
** MILTER_CHANGEHEADER -- Change the supplied header in the message
**
** Parameters:
@@ -2753,7 +2868,7 @@ milter_changeheader(response, rlen, e)
if (*val == '\0')
{
sm_syslog(LOG_INFO, e->e_id,
- "Milter delete: header %s %s: %s",
+ "Milter delete: header%s %s: %s",
h == sysheader ? " (default header)" : "",
field,
h->h_value == NULL ? "<NULL>" : h->h_value);
@@ -2761,7 +2876,7 @@ milter_changeheader(response, rlen, e)
else
{
sm_syslog(LOG_INFO, e->e_id,
- "Milter change: header %s %s: from %s to %s",
+ "Milter change: header%s %s: from %s to %s",
h == sysheader ? " (default header)" : "",
field,
h->h_value == NULL ? "<NULL>" : h->h_value,
@@ -2848,8 +2963,8 @@ milter_addrcpt(response, rlen, e)
if (MilterLogLevel > 8)
sm_syslog(LOG_INFO, e->e_id, "Milter add: rcpt: %s", response);
olderrors = Errors;
- (void) sendtolist(response, NULLADDR, &e->e_sendqueue, 0, e);
- Errors = olderrors;
+ (void) sendtolist(response, NULLADDR, &e->e_sendqueue, 0, e);
+ Errors = olderrors;
return;
}
/*
@@ -3113,6 +3228,7 @@ milter_init(e, state)
/* if negotation failure, close socket */
milter_error(m, e);
MILTER_CHECK_ERROR(true, continue);
+ continue;
}
if (MilterLogLevel > 9)
sm_syslog(LOG_INFO, e->e_id,
@@ -3256,11 +3372,9 @@ milter_connect(hostname, addr, e, state)
if (response != NULL &&
*response == '4')
{
-#if _FFR_MILTER_421
if (strncmp(response, "421 ", 4) == 0)
*state = SMFIR_SHUTDOWN;
else
-#endif /* _FFR_MILTER_421 */
*state = SMFIR_TEMPFAIL;
}
else
@@ -3419,6 +3533,7 @@ milter_envfrom(args, e, state)
sm_syslog(LOG_INFO, e->e_id, "Milter: reject, senders");
return response;
}
+
/*
** MILTER_ENVRCPT -- send SMTP RCPT command info to milter filters
**
@@ -3487,6 +3602,32 @@ milter_envrcpt(args, e, state)
sm_free(buf); /* XXX */
return response;
}
+
+#if SMFI_VERSION > 3
+/*
+** MILTER_DATA_CMD -- send SMTP DATA command info to milter filters
+**
+** Parameters:
+** e -- current envelope.
+** state -- return state from response.
+**
+** Returns:
+** response string (may be NULL)
+*/
+
+char *
+milter_data_cmd(e, state)
+ ENVELOPE *e;
+ char *state;
+{
+ if (tTd(64, 10))
+ sm_dprintf("milter_data_cmd\n");
+
+ /* send it over */
+ return milter_command(SMFIC_DATA, NULL, 0, MilterDataMacros, e, state);
+}
+#endif /* SMFI_VERSION > 3 */
+
/*
** MILTER_DATA -- send message headers/body and gather final message results
**
@@ -3608,10 +3749,9 @@ milter_data(e, state)
MILTER_CHECK_RESULTS();
}
-#if _FFR_MILTER_MACROS_EOM
if (MilterEOMMacros[0] != NULL)
- milter_send_macros(m, MilterEOMMacros, SMFIC_BODYEOB, e);
-#endif /* _FFR_MILTER_MACROS_EOM */
+ milter_send_macros(m, MilterEOMMacros,
+ SMFIC_BODYEOB, e);
/* send the final body chunk */
(void) milter_write(m, SMFIC_BODYEOB, NULL, 0,
@@ -3696,7 +3836,6 @@ milter_data(e, state)
case SMFIR_PROGRESS:
break;
-# if _FFR_QUARANTINE
case SMFIR_QUARANTINE:
if (!bitset(SMFIF_QUARANTINE, m->mf_fflags))
{
@@ -3716,7 +3855,6 @@ milter_data(e, state)
macdefine(&e->e_macro, A_PERM,
macid("{quarantine}"), e->e_quarmsg);
break;
-# endif /* _FFR_QUARANTINE */
case SMFIR_ADDHEADER:
if (!bitset(SMFIF_ADDHDRS, m->mf_fflags))
@@ -3729,6 +3867,17 @@ milter_data(e, state)
milter_addheader(response, rlen, e);
break;
+ case SMFIR_INSHEADER:
+ if (!bitset(SMFIF_ADDHDRS, m->mf_fflags))
+ {
+ if (MilterLogLevel > 9)
+ sm_syslog(LOG_WARNING, e->e_id,
+ "milter_data(%s): lied about adding headers, honoring request anyway",
+ m->mf_name);
+ }
+ milter_insheader(response, rlen, e);
+ break;
+
case SMFIR_CHGHEADER:
if (!bitset(SMFIF_CHGHDRS, m->mf_fflags))
{
@@ -3765,7 +3914,7 @@ milter_data(e, state)
case SMFIR_REPLBODY:
if (!bitset(SMFIF_MODBODY, m->mf_fflags))
{
- if (MilterLogLevel > 9)
+ if (MilterLogLevel > 0)
sm_syslog(LOG_ERR, e->e_id,
"milter_data(%s): lied about replacing body, rejecting request and tempfailing message",
m->mf_name);
@@ -3878,6 +4027,36 @@ finishup:
sm_syslog(LOG_INFO, e->e_id, "Milter: reject, data");
return response;
}
+
+#if SMFI_VERSION > 2
+/*
+** MILTER_UNKNOWN -- send any unrecognized or unimplemented command
+** string to milter filters
+**
+** Parameters:
+** cmd -- the string itself.
+** e -- current envelope.
+** state -- return state from response.
+**
+**
+** Returns:
+** response string (may be NULL)
+*/
+
+char *
+milter_unknown(cmd, e, state)
+ char *cmd;
+ ENVELOPE *e;
+ char *state;
+{
+ if (tTd(64, 10))
+ sm_dprintf("milter_unknown(%s)\n", cmd);
+
+ return milter_command(SMFIC_UNKNOWN, cmd, strlen(cmd) + 1,
+ NULL, e, state);
+}
+#endif /* SMFI_VERSION > 2 */
+
/*
** MILTER_QUIT -- informs the filter(s) we are done and closes connection(s)
**
diff --git a/contrib/sendmail/src/mime.c b/contrib/sendmail/src/mime.c
index a9a26c4..6f4e782 100644
--- a/contrib/sendmail/src/mime.c
+++ b/contrib/sendmail/src/mime.c
@@ -14,7 +14,7 @@
#include <sendmail.h>
#include <string.h>
-SM_RCSID("@(#)$Id: mime.c,v 8.130.2.3 2004/01/08 21:42:56 ca Exp $")
+SM_RCSID("@(#)$Id: mime.c,v 8.136 2004/03/22 18:21:34 ca Exp $")
/*
** MIME support.
@@ -137,7 +137,7 @@ mime8to7(mci, header, e, boundaries, flags)
p = hvalue("Content-Transfer-Encoding", header);
if (p == NULL ||
(pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
- MimeTokenTab)) == NULL ||
+ MimeTokenTab, false)) == NULL ||
pvp[0] == NULL)
{
cte = NULL;
@@ -159,7 +159,7 @@ mime8to7(mci, header, e, boundaries, flags)
}
if (p != NULL &&
(pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
- MimeTokenTab)) != NULL &&
+ MimeTokenTab, false)) != NULL &&
pvp[0] != NULL)
{
if (tTd(43, 40))
@@ -768,11 +768,11 @@ mime_getchar(fp, boundaries, btp)
return SM_IO_EOF;
}
- atbol = c == '\n';
- if (c != SM_IO_EOF)
+ if (bp < &buf[sizeof buf - 2] && c != SM_IO_EOF)
*bp++ = c;
}
+ atbol = c == '\n';
buflen = bp - buf - 1;
if (buflen < 0)
{
@@ -990,7 +990,7 @@ mime7to8(mci, header, e)
p = hvalue("Content-Transfer-Encoding", header);
if (p == NULL ||
(pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
- MimeTokenTab)) == NULL ||
+ MimeTokenTab, false)) == NULL ||
pvp[0] == NULL)
{
/* "can't happen" -- upper level should have caught this */
diff --git a/contrib/sendmail/src/parseaddr.c b/contrib/sendmail/src/parseaddr.c
index 48ed142..e1c60c8 100644
--- a/contrib/sendmail/src/parseaddr.c
+++ b/contrib/sendmail/src/parseaddr.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: parseaddr.c,v 8.359.2.9 2003/09/16 18:07:50 ca Exp $")
+SM_RCSID("@(#)$Id: parseaddr.c,v 8.378 2004/05/18 20:01:54 ca Exp $")
static void allocaddr __P((ADDRESS *, int, char *, ENVELOPE *));
static int callsubr __P((char**, int, ENVELOPE *));
@@ -90,7 +90,7 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
if (delimptr == NULL)
delimptr = &delimptrbuf;
- pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL);
+ pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL, false);
if (pvp == NULL)
{
if (tTd(20, 1))
@@ -228,7 +228,7 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
if (tTd(20, 1))
{
sm_dprintf("parseaddr-->");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
return a;
@@ -460,6 +460,7 @@ allocaddr(a, flags, paddr, e)
** terminating delimiter.
** toktab -- if set, a token table to use for parsing.
** If NULL, use the default table.
+** ignore -- if true, ignore unbalanced addresses
**
** Returns:
** A pointer to a vector of tokens.
@@ -611,13 +612,14 @@ unsigned char TokTypeNoC[256] =
#define NOCHAR (-1) /* signal nothing in lookahead token */
char **
-prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
+prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab, ignore)
char *addr;
int delim;
char pvpbuf[];
int pvpbsize;
char **delimptr;
unsigned char *toktab;
+ bool ignore;
{
register char *p;
register char *q;
@@ -633,7 +635,6 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
char *saveto = CurEnv->e_to;
static char *av[MAXATOM + 1];
static bool firsttime = true;
- extern int errno;
if (firsttime)
{
@@ -678,7 +679,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
if (tTd(22, 11))
{
sm_dprintf("prescan: ");
- xputs(p);
+ xputs(sm_debug_file(), p);
sm_dprintf("\n");
}
@@ -722,7 +723,9 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
if (c == '\0')
{
/* diagnose and patch up bad syntax */
- if (state == QST)
+ if (ignore)
+ break;
+ else if (state == QST)
{
usrerr("553 Unbalanced '\"'");
c = '"';
@@ -748,7 +751,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
break;
/* special case for better error management */
- if (delim == ',' && !route_syntax)
+ if (delim == ',' && !route_syntax && !ignore)
{
usrerr("553 Unbalanced '<'");
c = '>';
@@ -799,8 +802,11 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
{
if (cmntcnt <= 0)
{
- usrerr("553 Unbalanced ')'");
- c = NOCHAR;
+ if (!ignore)
+ {
+ usrerr("553 Unbalanced ')'");
+ c = NOCHAR;
+ }
}
else
cmntcnt--;
@@ -823,8 +829,11 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
{
if (anglecnt <= 0)
{
- usrerr("553 Unbalanced '>'");
- c = NOCHAR;
+ if (!ignore)
+ {
+ usrerr("553 Unbalanced '>'");
+ c = NOCHAR;
+ }
}
else
anglecnt--;
@@ -868,7 +877,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
if (tTd(22, 36))
{
sm_dprintf("tok=");
- xputs(tok);
+ xputs(sm_debug_file(), tok);
sm_dprintf("\n");
}
if (avp >= &av[MAXATOM])
@@ -894,7 +903,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
if (tTd(22, 12))
{
sm_dprintf("prescan==>");
- printav(av);
+ printav(sm_debug_file(), av);
}
CurEnv->e_to = saveto;
if (av[0] == NULL)
@@ -997,12 +1006,12 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"%s%-16.16s input:", prefix, rulename);
- printav(pvp);
+ printav(smioout, pvp);
}
else if (tTd(21, 1))
{
sm_dprintf("%s%-16.16s input:", prefix, rulename);
- printav(pvp);
+ printav(sm_debug_file(), pvp);
}
if (reclevel++ > MaxRuleRecursion)
{
@@ -1037,7 +1046,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
rwr->r_line);
else
sm_dprintf("-----trying rule:");
- printav(rwr->r_lhs);
+ printav(sm_debug_file(), rwr->r_lhs);
}
/* try to match on this rule */
@@ -1051,7 +1060,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (tTd(21, 1))
{
sm_dprintf("workspace: ");
- printav(pvp);
+ printav(sm_debug_file(), pvp);
}
break;
}
@@ -1062,9 +1071,9 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (tTd(21, 35))
{
sm_dprintf("ADVANCE rp=");
- xputs(rp);
+ xputs(sm_debug_file(), rp);
sm_dprintf(", ap=");
- xputs(ap);
+ xputs(sm_debug_file(), ap);
sm_dprintf("\n");
}
if (rp == NULL)
@@ -1097,9 +1106,9 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (tTd(21, 36))
{
sm_dprintf("EXTEND rp=");
- xputs(rp);
+ xputs(sm_debug_file(), rp);
sm_dprintf(", ap=");
- xputs(ap);
+ xputs(sm_debug_file(), ap);
sm_dprintf("\n");
}
goto extendclass;
@@ -1195,9 +1204,9 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (tTd(21, 36))
{
sm_dprintf("BACKUP rp=");
- xputs(rp);
+ xputs(sm_debug_file(), rp);
sm_dprintf(", ap=");
- xputs(ap);
+ xputs(sm_debug_file(), ap);
sm_dprintf("\n");
}
@@ -1248,7 +1257,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (tTd(21, 12))
{
sm_dprintf("-----rule matches:");
- printav(rvp);
+ printav(sm_debug_file(), rvp);
}
rp = *rvp;
@@ -1359,7 +1368,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
/* scan the new replacement */
xpvp = prescan(mval, '\0', pvpbuf,
sizeof pvpbuf, NULL,
- NULL);
+ NULL, false);
if (xpvp == NULL)
{
/* prescan pre-printed error */
@@ -1531,7 +1540,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
{
/* scan the new replacement */
xpvp = prescan(replac, '\0', pvpbuf,
- sizeof pvpbuf, NULL, NULL);
+ sizeof pvpbuf, NULL, NULL, false);
if (xpvp == NULL)
{
/* prescan already printed error */
@@ -1571,7 +1580,7 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
if (tTd(21, 4))
{
sm_dprintf("rewritten as:");
- printav(pvp);
+ printav(sm_debug_file(), pvp);
}
}
@@ -1579,12 +1588,12 @@ rewrite(pvp, ruleset, reclevel, e, maxatom)
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"%s%-16.16s returns:", prefix, rulename);
- printav(pvp);
+ printav(smioout, pvp);
}
else if (tTd(21, 1))
{
sm_dprintf("%s%-16.16s returns:", prefix, rulename);
- printav(pvp);
+ printav(sm_debug_file(), pvp);
}
return rstat;
}
@@ -1896,7 +1905,7 @@ buildaddr(tv, a, flags, e)
if (tTd(24, 5))
{
sm_dprintf("buildaddr, flags=%x, tv=", flags);
- printav(tv);
+ printav(sm_debug_file(), tv);
}
maxatom = MAXATOM;
@@ -1913,7 +1922,6 @@ buildaddr(tv, a, flags, e)
{
syserr("554 5.3.5 buildaddr: no mailer in parsed address");
badaddr:
-#if _FFR_ALLOW_S0_ERROR_4XX
/*
** ExitStat may have been set by an earlier map open
** failure (to a permanent error (EX_OSERR) in syserr())
@@ -1923,11 +1931,7 @@ badaddr:
** XXX the real fix is probably to set ExitStat correctly,
** i.e., to EX_TEMPFAIL if the map open is just a temporary
** error.
- **
- ** tempfail is tested here even if _FFR_ALLOW_S0_ERROR_4XX
- ** is not set; that's ok because it is initialized to false.
*/
-#endif /* _FFR_ALLOW_S0_ERROR_4XX */
if (ExitStat == EX_TEMPFAIL || tempfail)
a->q_state = QS_QUEUEUP;
@@ -2027,10 +2031,8 @@ badaddr:
else
usrerr(fmt, ubuf + off);
/* XXX ubuf[off - 1] = ' '; */
-#if _FFR_ALLOW_S0_ERROR_4XX
if (ubuf[0] == '4')
tempfail = true;
-#endif /* _FFR_ALLOW_S0_ERROR_4XX */
}
else
{
@@ -2123,7 +2125,7 @@ badaddr:
if (tTd(24, 6))
{
sm_dprintf("buildaddr => ");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
return a;
}
@@ -2182,19 +2184,19 @@ cataddr(pvp, evp, buf, sz, spacesub)
if (--sz <= 0)
break;
}
- if ((i = sm_strlcpy(p, *pvp, sz)) >= sz)
+ i = sm_strlcpy(p, *pvp, sz);
+ sz -= i;
+ if (sz <= 0)
break;
oatomtok = natomtok;
p += i;
- sz -= i;
if (pvp++ == evp)
break;
}
-#if _FFR_CATCH_LONG_STRINGS
- /* Don't silently truncate long strings; broken for evp != NULL */
- if (*pvp != NULL)
+
+ /* Don't silently truncate long strings */
+ if (sz <= 0)
syserr("cataddr: string too long");
-#endif /* _FFR_CATCH_LONG_STRINGS */
*p = '\0';
}
/*
@@ -2298,7 +2300,8 @@ static struct qflags AddressFlags[] =
};
void
-printaddr(a, follow)
+printaddr(fp, a, follow)
+ SM_FILE_T *fp;
register ADDRESS *a;
bool follow;
{
@@ -2309,14 +2312,14 @@ printaddr(a, follow)
if (a == NULL)
{
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "[NULL]\n");
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "[NULL]\n");
return;
}
while (a != NULL)
{
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%p=", a);
- (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%p=", a);
+ (void) sm_io_flush(fp, SM_TIME_DEFAULT);
/* find the mailer -- carefully */
m = a->q_mailer;
@@ -2327,100 +2330,100 @@ printaddr(a, follow)
m->m_name = "NULL";
}
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"%s:\n\tmailer %d (%s), host `%s'\n",
a->q_paddr == NULL ? "<null>" : a->q_paddr,
m->m_mno, m->m_name,
a->q_host == NULL ? "<null>" : a->q_host);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"\tuser `%s', ruser `%s'\n",
a->q_user,
a->q_ruser == NULL ? "<null>" : a->q_ruser);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\tstate=");
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "\tstate=");
switch (a->q_state)
{
case QS_OK:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "OK");
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "OK");
break;
case QS_DONTSEND:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"DONTSEND");
break;
case QS_BADADDR:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"BADADDR");
break;
case QS_QUEUEUP:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"QUEUEUP");
break;
case QS_RETRY:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "RETRY");
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "RETRY");
break;
case QS_SENT:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "SENT");
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "SENT");
break;
case QS_VERIFIED:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"VERIFIED");
break;
case QS_EXPANDED:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"EXPANDED");
break;
case QS_SENDER:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"SENDER");
break;
case QS_CLONED:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"CLONED");
break;
case QS_DISCARDED:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"DISCARDED");
break;
case QS_REPLACED:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"REPLACED");
break;
case QS_REMOVED:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"REMOVED");
break;
case QS_DUPLICATE:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"DUPLICATE");
break;
case QS_INCLUDED:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"INCLUDED");
break;
default:
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"%d", a->q_state);
break;
}
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
", next=%p, alias %p, uid %d, gid %d\n",
a->q_next, a->q_alias,
(int) a->q_uid, (int) a->q_gid);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\tflags=%lx<",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "\tflags=%lx<",
a->q_flags);
firstone = true;
for (qfp = AddressFlags; qfp->qf_name != NULL; qfp++)
@@ -2428,30 +2431,30 @@ printaddr(a, follow)
if (!bitset(qfp->qf_bit, a->q_flags))
continue;
if (!firstone)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
",");
firstone = false;
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s",
qfp->qf_name);
}
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ">\n");
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, ">\n");
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"\towner=%s, home=\"%s\", fullname=\"%s\"\n",
a->q_owner == NULL ? "(none)" : a->q_owner,
a->q_home == NULL ? "(none)" : a->q_home,
a->q_fullname == NULL ? "(none)" : a->q_fullname);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"\torcpt=\"%s\", statmta=%s, status=%s\n",
a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
a->q_statmta == NULL ? "(none)" : a->q_statmta,
a->q_status == NULL ? "(none)" : a->q_status);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"\tfinalrcpt=\"%s\"\n",
a->q_finalrcpt == NULL ? "(none)" : a->q_finalrcpt);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"\trstatus=\"%s\"\n",
a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"\tstatdate=%s\n",
a->q_statdate == 0 ? "(none)" : ctime(&a->q_statdate));
@@ -2559,7 +2562,7 @@ remotename(name, m, flags, pstat, e)
** domain will be appended.
*/
- pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
+ pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL, false);
if (pvp == NULL)
return name;
if (REWRITE(pvp, 3, e) == EX_TEMPFAIL)
@@ -2684,9 +2687,9 @@ maplocaluser(a, sendq, aliaslevel, e)
if (tTd(29, 1))
{
sm_dprintf("maplocaluser: ");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
- pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
+ pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL, false);
if (pvp == NULL)
{
if (tTd(29, 9))
@@ -2748,7 +2751,7 @@ maplocaluser(a, sendq, aliaslevel, e)
if (tTd(29, 5))
{
sm_dprintf("maplocaluser: QS_REPLACED ");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
a1->q_alias = a;
allocaddr(a1, RF_COPYALL, sm_rpool_strdup_x(e->e_rpool, a->q_paddr), e);
@@ -2942,10 +2945,8 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
auto ADDRESS a1;
bool saveQuickAbort = QuickAbort;
bool saveSuprErrs = SuprErrs;
-#if _FFR_QUARANTINE
bool quarantine = false;
char ubuf[BUFSIZ * 2];
-#endif /* _FFR_QUARANTINE */
char buf0[MAXLINE];
char pvpbuf[PSBUFSIZE];
extern char MsgBuf[];
@@ -2987,7 +2988,8 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
SuprErrs = true;
QuickAbort = false;
pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL,
- bitset(RSF_RMCOMM, flags) ? NULL : TokTypeNoC);
+ bitset(RSF_RMCOMM, flags) ? NULL : TokTypeNoC,
+ bitset(RSF_RMCOMM, flags) ? false : true);
SuprErrs = saveSuprErrs;
if (pvp == NULL)
{
@@ -3019,7 +3021,6 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
e->e_flags |= EF_DISCARD;
discard = true;
}
-#if _FFR_QUARANTINE
else if (strcmp(pvp[1], "error") == 0 &&
pvp[2] != NULL && (pvp[2][0] & 0377) == CANONHOST &&
pvp[3] != NULL && strcmp(pvp[3], "quarantine") == 0)
@@ -3040,7 +3041,6 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
macid("{quarantine}"), e->e_quarmsg);
quarantine = true;
}
-#endif /* _FFR_QUARANTINE */
else
{
int savelogusrerrs = LogUsrErrs;
@@ -3091,12 +3091,10 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid)
sm_syslog(LOG_NOTICE, logid,
"ruleset=%s, arg1=%s%s, discard",
rwset, p1, lbuf);
-#if _FFR_QUARANTINE
else if (quarantine)
sm_syslog(LOG_NOTICE, logid,
"ruleset=%s, arg1=%s%s, quarantine=%s",
rwset, p1, lbuf, ubuf);
-#endif /* _FFR_QUARANTINE */
else
sm_syslog(LOG_NOTICE, logid,
"ruleset=%s, arg1=%s%s, reject=%s",
@@ -3198,7 +3196,7 @@ rscap(rwset, p1, p2, e, pvp, pvpbuf, size)
{
SuprErrs = true;
QuickAbort = false;
- *pvp = prescan(buf, '\0', pvpbuf, size, NULL, NULL);
+ *pvp = prescan(buf, '\0', pvpbuf, size, NULL, NULL, false);
if (*pvp != NULL)
rstat = rewrite(*pvp, rsno, 0, e, size);
else
diff --git a/contrib/sendmail/src/queue.c b/contrib/sendmail/src/queue.c
index e71b8f2..f37a293 100644
--- a/contrib/sendmail/src/queue.c
+++ b/contrib/sendmail/src/queue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: queue.c,v 8.863.2.67 2003/12/02 23:56:01 ca Exp $")
+SM_RCSID("@(#)$Id: queue.c,v 8.938 2004/06/03 19:02:10 ca Exp $")
#include <dirent.h>
@@ -37,23 +37,15 @@ SM_RCSID("@(#)$Id: queue.c,v 8.863.2.67 2003/12/02 23:56:01 ca Exp $")
** Historical notes:
** QF_VERSION == 4 was sendmail 8.10/8.11 without _FFR_QUEUEDELAY
** QF_VERSION == 5 was sendmail 8.10/8.11 with _FFR_QUEUEDELAY
-** QF_VERSION == 6 is sendmail 8.12 without _FFR_QUEUEDELAY
-** QF_VERSION == 7 is sendmail 8.12 with _FFR_QUEUEDELAY
+** QF_VERSION == 6 was sendmail 8.12 without _FFR_QUEUEDELAY
+** QF_VERSION == 7 was sendmail 8.12 with _FFR_QUEUEDELAY
+** QF_VERSION == 8 is sendmail 8.13
*/
-#if _FFR_QUEUEDELAY
-# define QF_VERSION 7 /* version number of this queue format */
-static time_t queuedelay __P((ENVELOPE *));
-# define queuedelay_qfver_unsupported(qfver) false
-#else /* _FFR_QUEUEDELAY */
-# define QF_VERSION 6 /* version number of this queue format */
-# define queuedelay(e) MinQueueAge
-# define queuedelay_qfver_unsupported(qfver) ((qfver) == 5 || (qfver) == 7)
-#endif /* _FFR_QUEUEDELAY */
-#if _FFR_QUARANTINE
+#define QF_VERSION 8 /* version number of this queue format */
+
static char queue_letter __P((ENVELOPE *, int));
static bool quarantine_queue_item __P((int, int, ENVELOPE *, char *));
-#endif /* _FFR_QUARANTINE */
/* Naming convention: qgrp: index of queue group, qg: QUEUEGROUP */
@@ -304,7 +296,7 @@ hash_q(p, h)
** d data file directory name (added in 8.12)
** E error recipient
** F flag bits
-** G queue delay algorithm (_FFR_QUEUEDELAY)
+** G free (was: queue delay algorithm if _FFR_QUEUEDELAY)
** H header
** I data file's inode number
** K time of last delivery attempt
@@ -312,7 +304,7 @@ hash_q(p, h)
** M message
** N number of delivery attempts
** P message priority
-** q quarantine reason (_FFR_QUARANTINE)
+** q quarantine reason
** Q original recipient (ORCPT=)
** r final recipient (Final-Recipient: DSN field)
** R recipient
@@ -320,7 +312,7 @@ hash_q(p, h)
** T init time
** V queue file version
** X free (was: character set if _FFR_SAVE_CHARSET)
-** Y current delay (_FFR_QUEUEDELAY)
+** Y free (was: current delay if _FFR_QUEUEDELAY)
** Z original envelope id from ESMTP
** ! deliver by (added in 8.12)
** $ define macro
@@ -397,15 +389,15 @@ queueup(e, announce, msync)
!lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB) ||
#endif /* !SM_OPEN_EXLOCK */
(tfp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
- (void *) &tfd, SM_IO_WRONLY_B,
+ (void *) &tfd, SM_IO_WRONLY,
NULL)) == NULL)
{
int save_errno = errno;
printopenfds(true);
errno = save_errno;
- syserr("!queueup: cannot create queue file %s, euid=%d",
- tf, (int) geteuid());
+ syserr("!queueup: cannot create queue file %s, euid=%d, fd=%d, fp=%p",
+ tf, (int) geteuid(), tfd, tfp);
/* NOTREACHED */
}
e->e_lockfp = tfp;
@@ -490,7 +482,7 @@ queueup(e, announce, msync)
if (tTd(40, 32))
{
sm_dprintf(" sendq=");
- printaddr(e->e_sendqueue, true);
+ printaddr(sm_debug_file(), e->e_sendqueue, true);
}
if (tTd(40, 9))
{
@@ -513,6 +505,7 @@ queueup(e, announce, msync)
{
if (e->e_dfp != NULL &&
SuperSafe != SAFE_REALLY &&
+ SuperSafe != SAFE_REALLY_POSTMILTER &&
sm_io_setinfo(e->e_dfp, SM_BF_COMMIT, NULL) < 0 &&
errno != EINVAL)
{
@@ -574,6 +567,7 @@ queueup(e, announce, msync)
(*e->e_putbody)(&mcibuf, e, NULL);
if (SuperSafe == SAFE_REALLY ||
+ SuperSafe == SAFE_REALLY_POSTMILTER ||
(SuperSafe == SAFE_INTERACTIVE && msync))
{
if (tTd(40,32))
@@ -610,17 +604,7 @@ queueup(e, announce, msync)
(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "T%ld\n", (long) e->e_ctime);
/* output last delivery time */
-#if _FFR_QUEUEDELAY
- (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "K%ld\n", (long) e->e_dtime);
- (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "G%d\n", e->e_queuealg);
- (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "Y%ld\n", (long) e->e_queuedelay);
- if (tTd(40, 64))
- sm_syslog(LOG_INFO, e->e_id,
- "queue alg: %d delay %ld next: %ld (now: %ld)\n",
- e->e_queuealg, e->e_queuedelay, e->e_dtime, curtime());
-#else /* _FFR_QUEUEDELAY */
(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "K%ld\n", (long) e->e_dtime);
-#endif /* _FFR_QUEUEDELAY */
/* output number of delivery attempts */
(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "N%d\n", e->e_ntries);
@@ -654,12 +638,10 @@ queueup(e, announce, msync)
(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "B%s\n",
denlstring(e->e_bodytype, true, false));
-#if _FFR_QUARANTINE
/* quarantine reason */
if (e->e_quarmsg != NULL)
(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "q%s\n",
denlstring(e->e_quarmsg, true, false));
-#endif /* _FFR_QUARANTINE */
/* message from envelope, if it exists */
if (e->e_message != NULL)
@@ -753,10 +735,8 @@ queueup(e, announce, msync)
{
char *tag = "queued";
-#if _FFR_QUARANTINE
if (e->e_quarmsg != NULL)
tag = "quarantined";
-#endif /* _FFR_QUARANTINE */
e->e_to = q->q_paddr;
message(tag);
@@ -768,7 +748,7 @@ queueup(e, announce, msync)
if (tTd(40, 1))
{
sm_dprintf("queueing ");
- printaddr(q, false);
+ printaddr(sm_debug_file(), q, false);
}
}
@@ -879,6 +859,7 @@ queueup(e, announce, msync)
if (sm_io_flush(tfp, SM_TIME_DEFAULT) != 0 ||
((SuperSafe == SAFE_REALLY ||
+ SuperSafe == SAFE_REALLY_POSTMILTER ||
(SuperSafe == SAFE_INTERACTIVE && msync)) &&
fsync(sm_io_getinfo(tfp, SM_IO_WHAT_FD, NULL)) < 0) ||
sm_io_error(tfp))
@@ -891,9 +872,7 @@ queueup(e, announce, msync)
if (!newid)
{
-#if _FFR_QUARANTINE
char new = queue_letter(e, ANYQFL_LETTER);
-#endif /* _FFR_QUARANTINE */
/* rename (locked) tf to be (locked) [qh]f */
(void) sm_strlcpy(qf, queuename(e, ANYQFL_LETTER),
@@ -901,7 +880,6 @@ queueup(e, announce, msync)
if (rename(tf, qf) < 0)
syserr("cannot rename(%s, %s), uid=%d",
tf, qf, (int) geteuid());
-# if _FFR_QUARANTINE
else
{
/*
@@ -931,7 +909,6 @@ queueup(e, announce, msync)
}
}
e->e_qfletter = new;
-# endif /* _FFR_QUARANTINE */
/*
** fsync() after renaming to make sure metadata is
@@ -965,9 +942,7 @@ queueup(e, announce, msync)
if (LogLevel > 79)
sm_syslog(LOG_DEBUG, e->e_id, "queueup %s", tf);
-#if _FFR_QUARANTINE
e->e_qfletter = queue_letter(e, ANYQFL_LETTER);
-#endif /* _FFR_QUARANTINE */
}
errno = 0;
@@ -1538,9 +1513,6 @@ runqueue(forkflag, verbose, persistent, runall)
** Increment CurRunners before calling run_work_group()
** to avoid a "race condition" with proc_list_drop() which
** decrements CurRunners if the queue runners terminate.
- ** This actually doesn't cause any harm, but CurRunners
- ** might become negative which is at least confusing.
- **
** Notice: CurRunners is an upper limit, in some cases
** (too few jobs in the queue) this value is larger than
** the actual number of queue runners. The discrepancy can
@@ -1595,6 +1567,57 @@ runqueue(forkflag, verbose, persistent, runall)
#endif /* SM_HEAP_CHECK */
return ret;
}
+
+#if _FFR_SKIP_DOMAINS
+/*
+** SKIP_DOMAINS -- Skip 'skip' number of domains in the WorkQ.
+**
+** Added by Stephen Frost <sfrost@snowman.net> to support
+** having each runner process every N'th domain instead of
+** every N'th message.
+**
+** Parameters:
+** skip -- number of domains in WorkQ to skip.
+**
+** Returns:
+** total number of messages skipped.
+**
+** Side Effects:
+** may change WorkQ
+*/
+
+static int
+skip_domains(skip)
+ int skip;
+{
+ int n, seqjump;
+
+ for (n = 0, seqjump = 0; n < skip && WorkQ != NULL; seqjump++)
+ {
+ if (WorkQ->w_next != NULL)
+ {
+ if (WorkQ->w_host != NULL &&
+ WorkQ->w_next->w_host != NULL)
+ {
+ if (sm_strcasecmp(WorkQ->w_host,
+ WorkQ->w_next->w_host) != 0)
+ n++;
+ }
+ else
+ {
+ if ((WorkQ->w_host != NULL &&
+ WorkQ->w_next->w_host == NULL) ||
+ (WorkQ->w_host == NULL &&
+ WorkQ->w_next->w_host != NULL))
+ n++;
+ }
+ }
+ WorkQ = WorkQ->w_next;
+ }
+ return seqjump;
+}
+#endif /* _FFR_SKIP_DOMAINS */
+
/*
** RUNNER_WORK -- have a queue runner do its work
**
@@ -1627,7 +1650,7 @@ runner_work(e, sequenceno, didfork, skip, njobs)
int skip;
int njobs;
{
- int n;
+ int n, seqjump;
WORK *w;
time_t now;
@@ -1641,6 +1664,7 @@ runner_work(e, sequenceno, didfork, skip, njobs)
*/
BlockOldsh = true;
+ seqjump = skip;
/* process them once at a time */
while (WorkQ != NULL)
@@ -1675,10 +1699,49 @@ runner_work(e, sequenceno, didfork, skip, njobs)
** It is set 'skip' ahead (the number of parallel queue
** runners working on WorkQ together) since each runner
** works on every 'skip'th (N-th) item.
+#if _FFR_SKIP_DOMAINS
+ ** In the case of the BYHOST Queue Sort Order, the 'item'
+ ** is a domain, so we work on every 'skip'th (N-th) domain.
+#endif * _FFR_SKIP_DOMAINS *
*/
- for (n = 0; n < skip && WorkQ != NULL; n++)
- WorkQ = WorkQ->w_next;
+#if _FFR_SKIP_DOMAINS
+ if (QueueSortOrder == QSO_BYHOST)
+ {
+ seqjump = 1;
+ if (WorkQ->w_next != NULL)
+ {
+ if (WorkQ->w_host != NULL &&
+ WorkQ->w_next->w_host != NULL)
+ {
+ if (sm_strcasecmp(WorkQ->w_host,
+ WorkQ->w_next->w_host)
+ != 0)
+ seqjump = skip_domains(skip);
+ else
+ WorkQ = WorkQ->w_next;
+ }
+ else
+ {
+ if ((WorkQ->w_host != NULL &&
+ WorkQ->w_next->w_host == NULL) ||
+ (WorkQ->w_host == NULL &&
+ WorkQ->w_next->w_host != NULL))
+ seqjump = skip_domains(skip);
+ else
+ WorkQ = WorkQ->w_next;
+ }
+ }
+ else
+ WorkQ = WorkQ->w_next;
+ }
+ else
+#endif /* _FFR_SKIP_DOMAINS */
+ {
+ for (n = 0; n < skip && WorkQ != NULL; n++)
+ WorkQ = WorkQ->w_next;
+ }
+
e->e_to = NULL;
/*
@@ -1753,7 +1816,7 @@ runner_work(e, sequenceno, didfork, skip, njobs)
if (w->w_host != NULL)
sm_free(w->w_host); /* XXX */
sm_free((char *) w); /* XXX */
- sequenceno += skip; /* next sequence number */
+ sequenceno += seqjump; /* next sequence number */
#if SM_HEAP_CHECK
if (sm_debug_active(&DebugLeakQ, 1))
sm_heap_setgroup(oldgroup);
@@ -1883,7 +1946,8 @@ run_work_group(wgrp, flags)
/* wgrp only used when queue runners are persistent */
proc_list_add(pid, "Queue runner", PROC_QUEUE,
WorkGrp[wgrp].wg_maxact,
- bitset(RWG_PERSISTENT, flags) ? wgrp : -1);
+ bitset(RWG_PERSISTENT, flags) ? wgrp : -1,
+ NULL);
(void) sm_releasesignal(SIGALRM);
(void) sm_releasesignal(SIGCHLD);
return true;
@@ -1897,6 +1961,7 @@ run_work_group(wgrp, flags)
ShutdownRequest = NULL;
PendingSignal = 0;
CurrentPid = getpid();
+ close_sendmail_pid();
/*
** Initialize exception stack and default exception
@@ -1909,7 +1974,7 @@ run_work_group(wgrp, flags)
/* Add parent process as first child item */
proc_list_add(CurrentPid, "Queue runner child process",
- PROC_QUEUE_CHILD, 0, -1);
+ PROC_QUEUE_CHILD, 0, -1, NULL);
(void) sm_releasesignal(SIGCHLD);
(void) sm_signal(SIGCHLD, SIG_DFL);
(void) sm_signal(SIGHUP, SIG_DFL);
@@ -1952,9 +2017,7 @@ run_work_group(wgrp, flags)
*/
if (QueueLimitId != NULL || QueueLimitSender != NULL ||
-#if _FFR_QUARANTINE
QueueLimitQuarantine != NULL ||
-#endif /* _FFR_QUARANTINE */
QueueLimitRecipient != NULL)
{
IgnoreHostStatus = true;
@@ -2099,10 +2162,20 @@ run_work_group(wgrp, flags)
{
/* parent -- clean out connection cache */
mci_flush(false, NULL);
- WorkQ = WorkQ->w_next; /* for the skip */
- sequenceno++;
+#if _FFR_SKIP_DOMAINS
+ if (QueueSortOrder == QSO_BYHOST)
+ {
+ sequenceno += skip_domains(1);
+ }
+ else
+#endif /* _FFR_SKIP_DOMAINS */
+ {
+ /* for the skip */
+ WorkQ = WorkQ->w_next;
+ sequenceno++;
+ }
proc_list_add(pid, "Queue child runner process",
- PROC_QUEUE_CHILD, 0, -1);
+ PROC_QUEUE_CHILD, 0, -1, NULL);
/* No additional work, no additional runners */
if (WorkQ == NULL)
@@ -2116,6 +2189,7 @@ run_work_group(wgrp, flags)
ShutdownRequest = NULL;
PendingSignal = 0;
CurrentPid = getpid();
+ close_sendmail_pid();
/*
** Initialize exception stack and default
@@ -2227,9 +2301,9 @@ run_work_group(wgrp, flags)
rmexpstab();
#if NAMED_BIND
- /* Update MX records for FallBackMX. */
- if (FallBackMX != NULL)
- (void) getfallbackmxrr(FallBackMX);
+ /* Update MX records for FallbackMX. */
+ if (FallbackMX != NULL)
+ (void) getfallbackmxrr(FallbackMX);
#endif /* NAMED_BIND */
#if USERDB
@@ -2371,10 +2445,8 @@ runqueueevent()
#define NEED_R 0004 /* 'R': recipient */
#define NEED_S 0010 /* 'S': sender */
#define NEED_H 0020 /* host */
-#if _FFR_QUARANTINE
-# define HAS_QUARANTINE 0040 /* has an unexpected 'q' line */
-# define NEED_QUARANTINE 0100 /* 'q': reason */
-#endif /* _FFR_QUARANTINE */
+#define HAS_QUARANTINE 0040 /* has an unexpected 'q' line */
+#define NEED_QUARANTINE 0100 /* 'q': reason */
static WORK *WorkList = NULL; /* list of unsort work */
static int WorkListSize = 0; /* current max size of WorkList */
@@ -2440,7 +2512,6 @@ gatherq(qgrp, qdir, doall, full, more)
check = check->queue_next;
}
-#if _FFR_QUARANTINE
if (QueueMode == QM_QUARANTINE)
{
check = QueueLimitQuarantine;
@@ -2452,7 +2523,6 @@ gatherq(qgrp, qdir, doall, full, more)
check = check->queue_next;
}
}
-#endif /* _FFR_QUARANTINE */
}
/* open the queue directory */
@@ -2483,7 +2553,6 @@ gatherq(qgrp, qdir, doall, full, more)
sm_dprintf("gatherq: checking %s..", d->d_name);
/* is this an interesting entry? */
-#if _FFR_QUARANTINE
if (!(((QueueMode == QM_NORMAL &&
d->d_name[0] == NORMQF_LETTER) ||
(QueueMode == QM_QUARANTINE &&
@@ -2491,9 +2560,6 @@ gatherq(qgrp, qdir, doall, full, more)
(QueueMode == QM_LOST &&
d->d_name[0] == LOSEQF_LETTER)) &&
d->d_name[1] == 'f'))
-#else /* _FFR_QUARANTINE */
- if (d->d_name[0] != NORMQF_LETTER || d->d_name[1] != 'f')
-#endif /* _FFR_QUARANTINE */
{
if (tTd(41, 50))
sm_dprintf(" skipping\n");
@@ -2564,10 +2630,8 @@ gatherq(qgrp, qdir, doall, full, more)
/* Yikes! Skip it or we will hang on open! */
if (!((d->d_name[0] == DATAFL_LETTER ||
d->d_name[0] == NORMQF_LETTER ||
-#if _FFR_QUARANTINE
d->d_name[0] == QUARQF_LETTER ||
d->d_name[0] == LOSEQF_LETTER ||
-#endif /* _FFR_QUARANTINE */
d->d_name[0] == XSCRPT_LETTER) &&
d->d_name[1] == 'f' && d->d_name[2] == '\0'))
syserr("gatherq: %s/%s is not a regular file",
@@ -2580,9 +2644,7 @@ gatherq(qgrp, qdir, doall, full, more)
if ((QueueSortOrder == QSO_BYFILENAME ||
QueueSortOrder == QSO_BYMODTIME ||
QueueSortOrder == QSO_RANDOM) &&
-#if _FFR_QUARANTINE
QueueLimitQuarantine == NULL &&
-#endif /* _FFR_QUARANTINE */
QueueLimitSender == NULL &&
QueueLimitRecipient == NULL)
{
@@ -2644,10 +2706,8 @@ gatherq(qgrp, qdir, doall, full, more)
i |= NEED_S;
if (QueueLimitRecipient != NULL)
i |= NEED_R;
-#if _FFR_QUARANTINE
if (QueueLimitQuarantine != NULL)
i |= NEED_QUARANTINE;
-#endif /* _FFR_QUARANTINE */
while (cf != NULL && i != 0 &&
sm_io_fgets(cf, SM_TIME_DEFAULT, lbuf,
sizeof lbuf) != NULL)
@@ -2682,7 +2742,6 @@ gatherq(qgrp, qdir, doall, full, more)
i &= ~NEED_T;
break;
-#if _FFR_QUARANTINE
case 'q':
if (QueueMode != QM_QUARANTINE &&
QueueMode != QM_LOST)
@@ -2715,7 +2774,6 @@ gatherq(qgrp, qdir, doall, full, more)
i &= ~NEED_QUARANTINE;
}
break;
-#endif /* _FFR_QUARANTINE */
case 'R':
if (w->w_host == NULL &&
@@ -2787,27 +2845,14 @@ gatherq(qgrp, qdir, doall, full, more)
if (atol(&lbuf[1]) == 0)
w->w_tooyoung = false;
break;
-
-#if _FFR_QUEUEDELAY
-/*
- case 'G':
- queuealg = atoi(lbuf[1]);
- break;
- case 'Y':
- queuedelay = (time_t) atol(&lbuf[1]);
- break;
-*/
-#endif /* _FFR_QUEUEDELAY */
}
}
if (cf != NULL)
(void) sm_io_close(cf, SM_TIME_DEFAULT);
if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) ||
-#if _FFR_QUARANTINE
bitset(HAS_QUARANTINE, i) ||
bitset(NEED_QUARANTINE, i) ||
-#endif /* _FFR_QUARANTINE */
bitset(NEED_R|NEED_S, i))
{
/* don't even bother sorting this job in */
@@ -2866,19 +2911,17 @@ sortq(max)
if (WorkQ != NULL)
{
+ WORK *nw;
+
/* Clear out old WorkQ. */
- for (w = WorkQ; w != NULL; )
+ for (w = WorkQ; w != NULL; w = nw)
{
- register WORK *nw = w->w_next;
-
- WorkQ = nw;
+ nw = w->w_next;
sm_free(w->w_name); /* XXX */
if (w->w_host != NULL)
sm_free(w->w_host); /* XXX */
sm_free((char *) w); /* XXX */
- w = nw;
}
- sm_free((char *) WorkQ);
WorkQ = NULL;
}
@@ -2990,7 +3033,7 @@ sortq(max)
qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf7);
}
#endif /* _FFR_RHS */
- else
+ else if (QueueSortOrder == QSO_BYPRIORITY)
{
/*
** Simple sort based on queue priority only.
@@ -2998,6 +3041,7 @@ sortq(max)
qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0);
}
+ /* else don't sort at all */
/*
** Convert the work list into canonical form.
@@ -3021,6 +3065,15 @@ sortq(max)
w->w_next = WorkQ;
WorkQ = w;
}
+
+ /* free the rest of the list */
+ for (i = WorkListCount; --i >= wc; )
+ {
+ sm_free(WorkList[i].w_name);
+ if (WorkList[i].w_host != NULL)
+ sm_free(WorkList[i].w_host);
+ }
+
if (WorkList != NULL)
sm_free(WorkList); /* XXX */
WorkList = NULL;
@@ -3755,11 +3808,9 @@ doworklist(el, forkflag, requeueflag)
if (WILL_BE_QUEUED(ei->e_sendmode))
continue;
-#if _FFR_QUARANTINE
else if (QueueMode != QM_QUARANTINE &&
ei->e_quarmsg != NULL)
continue;
-#endif /* _FFR_QUARANTINE */
rpool = sm_rpool_new_x(NULL);
clearenvelope(&e, true, rpool);
@@ -4051,9 +4102,7 @@ readqf(e, openonly)
e->e_flags |= EF_GLOBALERRS;
set_op_mode(MD_QUEUERUN);
ctladdr = NULL;
-#if _FFR_QUARANTINE
e->e_qfletter = queue_letter(e, ANYQFL_LETTER);
-#endif /* _FFR_QUARANTINE */
e->e_dfqgrp = e->e_qgrp;
e->e_dfqdir = e->e_qdir;
#if _FFR_QUEUE_MACRO
@@ -4062,10 +4111,6 @@ readqf(e, openonly)
#endif /* _FFR_QUEUE_MACRO */
e->e_dfino = -1;
e->e_msgsize = -1;
-#if _FFR_QUEUEDELAY
- e->e_queuealg = QD_LINEAR;
- e->e_queuedelay = (time_t) 0;
-#endif /* _FFR_QUEUEDELAY */
while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL)
{
unsigned long qflags;
@@ -4188,19 +4233,11 @@ readqf(e, openonly)
}
break;
-#if _FFR_QUEUEDELAY
- case 'G': /* queue delay algorithm */
- e->e_queuealg = atoi(&buf[1]);
- break;
-#endif /* _FFR_QUEUEDELAY */
-
-#if _FFR_QUARANTINE
case 'q': /* quarantine reason */
e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
macdefine(&e->e_macro, A_PERM,
macid("{quarantine}"), e->e_quarmsg);
break;
-#endif /* _FFR_QUARANTINE */
case 'H': /* header */
@@ -4233,7 +4270,7 @@ readqf(e, openonly)
/* if this has been tried recently, let it be */
now = curtime();
if (e->e_ntries > 0 && e->e_dtime <= now &&
- now < e->e_dtime + queuedelay(e))
+ now < e->e_dtime + MinQueueAge)
{
char *howlong;
@@ -4363,10 +4400,6 @@ readqf(e, openonly)
case 'V': /* queue file version number */
qfver = atoi(&bp[1]);
- if (queuedelay_qfver_unsupported(qfver))
- syserr("queue file version %d not supported: %s",
- qfver,
- "sendmail not compiled with _FFR_QUEUEDELAY");
if (qfver <= QF_VERSION)
break;
syserr("Version number in queue file (%d) greater than max (%d)",
@@ -4376,12 +4409,6 @@ readqf(e, openonly)
/* NOTREACHED */
break;
-#if _FFR_QUEUEDELAY
- case 'Y': /* current delay */
- e->e_queuedelay = (time_t) atol(&buf[1]);
- break;
-#endif /* _FFR_QUEUEDELAY */
-
case 'Z': /* original envelope id from ESMTP */
e->e_envid = sm_rpool_strdup_x(e->e_rpool, &bp[1]);
macdefine(&e->e_macro, A_PERM,
@@ -4411,6 +4438,24 @@ readqf(e, openonly)
nomore = true;
break;
+#if _FFR_QUEUEDELAY
+ case 'G':
+ case 'Y':
+
+ /*
+ ** Maintain backward compatibility for
+ ** users who defined _FFR_QUEUEDELAY in
+ ** previous releases. Remove this
+ ** code in 8.14 or 8.15.
+ */
+
+ if (qfver == 5 || qfver == 7)
+ break;
+
+ /* If not qfver 5 or 7, then 'G' or 'Y' is invalid */
+ /* FALLTHROUGH */
+#endif /* _FFR_QUEUEDELAY */
+
default:
syserr("readqf: %s: line %d: bad line \"%s\"",
qf, LineNumber, shortenstring(bp, MAXSHORTSTR));
@@ -4782,9 +4827,7 @@ print_single_queue(qgrp, qdir)
long dfsize;
int flags = 0;
int qfver;
-#if _FFR_QUARANTINE
char quarmsg[MAXLINE];
-#endif /* _FFR_QUARANTINE */
char statmsg[MAXLINE];
char bodytype[MAXNAME + 1];
char qf[MAXPATHLEN];
@@ -4847,10 +4890,8 @@ print_single_queue(qgrp, qdir)
}
if (w->w_lock)
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "*");
-#if _FFR_QUARANTINE
else if (QueueMode == QM_LOST)
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "?");
-#endif /* _FFR_QUARANTINE */
else if (w->w_tooyoung)
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "-");
else if (shouldqueue(w->w_pri, w->w_ctime))
@@ -4860,9 +4901,7 @@ print_single_queue(qgrp, qdir)
errno = 0;
-#if _FFR_QUARANTINE
quarmsg[0] = '\0';
-#endif /* _FFR_QUARANTINE */
statmsg[0] = bodytype[0] = '\0';
qfver = 0;
while (sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
@@ -4887,14 +4926,12 @@ print_single_queue(qgrp, qdir)
statmsg[i] = '\0';
break;
-#if _FFR_QUARANTINE
case 'q': /* quarantine reason */
if ((i = strlen(&buf[1])) >= sizeof quarmsg)
i = sizeof quarmsg - 1;
memmove(quarmsg, &buf[1], i);
quarmsg[i] = '\0';
break;
-#endif /* _FFR_QUARANTINE */
case 'B': /* body type */
if ((i = strlen(&buf[1])) >= sizeof bodytype)
@@ -4925,7 +4962,7 @@ print_single_queue(qgrp, qdir)
ctime(&submittime));
prtstr(&buf[1], 39);
}
-#if _FFR_QUARANTINE
+
if (quarmsg[0] != '\0')
{
(void) sm_io_fprintf(smioout,
@@ -4935,7 +4972,7 @@ print_single_queue(qgrp, qdir)
quarmsg);
quarmsg[0] = '\0';
}
-#endif /* _FFR_QUARANTINE */
+
if (statmsg[0] != '\0' || bodytype[0] != '\0')
{
(void) sm_io_fprintf(smioout,
@@ -5018,7 +5055,6 @@ print_single_queue(qgrp, qdir)
return nrequests;
}
-#if _FFR_QUARANTINE
/*
** QUEUE_LETTER -- get the proper queue letter for the current QueueMode.
**
@@ -5066,7 +5102,6 @@ queue_letter(e, type)
}
return type;
}
-#endif /* _FFR_QUARANTINE */
/*
** QUEUENAME -- build a file name in the queue directory for this envelope.
@@ -5098,10 +5133,7 @@ queuename(e, type)
/* Assign an ID if needed */
if (e->e_id == NULL)
assign_queueid(e);
-
-#if _FFR_QUARANTINE
type = queue_letter(e, type);
-#endif /* _FFR_QUARANTINE */
/* begin of filename */
pref[0] = (char) type;
@@ -5169,9 +5201,7 @@ queuename(e, type)
sub = "/df/";
break;
-#if _FFR_QUARANTINE
case QUARQF_LETTER:
-#endif /* _FFR_QUARANTINE */
case TEMPQF_LETTER:
case NEWQFL_LETTER:
case LOSEQF_LETTER:
@@ -5252,8 +5282,8 @@ static const char QueueIdChars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh
** Note: the length is "officially" 60 because minutes and seconds are
** usually only 0-59. However (Linux):
** tm_sec The number of seconds after the minute, normally in
-** the range 0 to 59, but can be up to 61 to allow for
-** leap seconds.
+** the range 0 to 59, but can be up to 61 to allow for
+** leap seconds.
** Hence the real length of the string is 62 to take this into account.
** Alternatively % QIC_LEN can (should) be used for access everywhere.
*/
@@ -5326,10 +5356,10 @@ assign_queueid(e)
e->e_qdir = NOQDIR;
e->e_xfqgrp = NOQGRP;
#endif /* 0 */
-#if _FFR_QUARANTINE
+
/* New ID means it's not on disk yet */
e->e_qfletter = '\0';
-#endif /* _FFR_QUARANTINE */
+
if (tTd(7, 1))
sm_dprintf("assign_queueid: assigned id %s, e=%p\n",
e->e_id, e);
@@ -5517,10 +5547,8 @@ loseqfile(e, why)
return;
if (!bitset(EF_INQUEUE, e->e_flags))
queueup(e, false, true);
-#if _FFR_QUARANTINE
else if (QueueMode == QM_LOST)
loseit = false;
-#endif /* _FFR_QUARANTINE */
/* if already lost, no need to re-lose */
if (loseit)
@@ -7210,6 +7238,11 @@ makequeue(line, qdef)
break;
# endif /* _FFR_RHS */
+ case 'n': /* none */
+ case 'N':
+ qg->qg_sortorder = QSO_NONE;
+ break;
+
default:
syserr("Invalid queue sort order \"%s\"", p);
}
@@ -7335,44 +7368,6 @@ hashfqn(fqn, buckets)
}
#endif /* 0 */
-#if _FFR_QUEUEDELAY
-/*
-** QUEUEDELAY -- compute queue delay time
-**
-** Parameters:
-** e -- the envelope to queue up.
-**
-** Returns:
-** queue delay time
-**
-** Side Effects:
-** may change e_queuedelay
-*/
-
-static time_t
-queuedelay(e)
- ENVELOPE *e;
-{
- time_t qd;
-
- if (e->e_queuealg == QD_EXP)
- {
- if (e->e_queuedelay == 0)
- e->e_queuedelay = QueueInitDelay;
- else
- {
- e->e_queuedelay *= 2;
- if (e->e_queuedelay > QueueMaxDelay)
- e->e_queuedelay = QueueMaxDelay;
- }
- qd = e->e_queuedelay;
- }
- else
- qd = MinQueueAge;
- return qd;
-}
-#endif /* _FFR_QUEUEDELAY */
-
/*
** A structure for sorting Queue according to maxqrun without
** screwing up Queue itself.
@@ -7720,11 +7715,9 @@ split_env(e, sendqueue, qgrp, qdir)
ee->e_qdir = ee->e_dfqdir = qdir;
ee->e_errormode = EM_MAIL;
ee->e_statmsg = NULL;
-#if _FFR_QUARANTINE
if (e->e_quarmsg != NULL)
ee->e_quarmsg = sm_rpool_strdup_x(ee->e_rpool,
e->e_quarmsg);
-#endif /* _FFR_QUARANTINE */
/*
** XXX Not sure if this copying is necessary.
@@ -8255,7 +8248,6 @@ split_by_recipient(e)
return split;
}
-#if _FFR_QUARANTINE
/*
** QUARANTINE_QUEUE_ITEM -- {un,}quarantine a single envelope
**
@@ -8483,7 +8475,9 @@ quarantine_queue_item(qgrp, qdir, e, reason)
/* Make sure we wrote things out safely */
if (!failing &&
(sm_io_flush(tempqfp, SM_TIME_DEFAULT) != 0 ||
- ((SuperSafe == SAFE_REALLY || SuperSafe == SAFE_INTERACTIVE) &&
+ ((SuperSafe == SAFE_REALLY ||
+ SuperSafe == SAFE_REALLY_POSTMILTER ||
+ SuperSafe == SAFE_INTERACTIVE) &&
fsync(sm_io_getinfo(tempqfp, SM_IO_WHAT_FD, NULL)) < 0) ||
((errno = sm_io_error(tempqfp)) != 0)))
{
@@ -8728,4 +8722,3 @@ quarantine_queue(reason, qgrplimit)
changed == 1 ? "" : "s");
}
}
-#endif /* _FFR_QUARANTINE */
diff --git a/contrib/sendmail/src/ratectrl.c b/contrib/sendmail/src/ratectrl.c
new file mode 100644
index 0000000..d141125
--- /dev/null
+++ b/contrib/sendmail/src/ratectrl.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2003 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ * Contributed by Jose Marcio Martins da Cruz - Ecole des Mines de Paris
+ * Jose-Marcio.Martins@ensmp.fr
+ */
+
+/* a part of this code is based on inetd.c for which this copyright applies: */
+/*
+ * Copyright (c) 1983, 1991, 1993, 1994
+ * 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.
+ */
+
+#include <sendmail.h>
+SM_RCSID("@(#)$Id: ratectrl.c,v 8.9 2004/07/07 21:23:57 ca Exp $")
+
+/*
+** stuff included - given some warnings (inet_ntoa)
+** - surely not everything is needed
+*/
+
+#if NETINET || NETINET6
+# include <arpa/inet.h>
+#endif /* NETINET || NETINET6 */
+
+#include <sys/time.h>
+
+#ifndef HASH_ALG
+# define HASH_ALG 2
+#endif /* HASH_ALG */
+
+#ifndef RATECTL_DEBUG
+# define RATECTL_DEBUG 0
+#endif /* RATECTL_DEBUG */
+
+/* forward declarations */
+static int client_rate __P((time_t, SOCKADDR *, bool));
+static int total_rate __P((time_t, bool));
+#if 0
+static int sockaddrcmp __P((SOCKADDR *, SOCKADDR *));
+#endif /* 0 */
+
+/*
+** CONNECTION_RATE_CHECK - updates connection history data
+** and computes connection rate for the given host
+**
+** Parameters:
+** hostaddr -- ip address of smtp client
+** e -- envelope
+**
+** Returns:
+** true (always)
+**
+** Side Effects:
+** updates connection history
+**
+** Warnings:
+** For each connection, this call shall be
+** done only once with the value true for the
+** update parameter.
+** Typically, this call is done with the value
+** true by the father, and once again with
+** the value false by the children.
+**
+*/
+
+bool
+connection_rate_check(hostaddr, e)
+ SOCKADDR *hostaddr;
+ ENVELOPE *e;
+{
+ time_t now;
+ int totalrate, clientrate;
+ static int clientconn = 0;
+
+ now = time(NULL);
+#if RATECTL_DEBUG
+ sm_syslog(LOG_INFO, NOQID, "connection_rate_check entering...");
+#endif /* RATECTL_DEBUG */
+
+ /* update server connection rate */
+ totalrate = total_rate(now, e == NULL);
+#if RATECTL_DEBUG
+ sm_syslog(LOG_INFO, NOQID, "global connection rate: %d", globalRate);
+#endif /* RATECTL_DEBUG */
+
+ /* update client connection rate */
+ clientrate = client_rate(now, hostaddr, e == NULL);
+
+ if (e == NULL)
+ clientconn = count_open_connections(hostaddr);
+
+ if (e != NULL)
+ {
+ char s[16];
+
+ sm_snprintf(s, sizeof(s), "%d", clientrate);
+ macdefine(&e->e_macro, A_TEMP, macid("{client_rate}"), s);
+ sm_snprintf(s, sizeof(s), "%d", totalrate);
+ macdefine(&e->e_macro, A_TEMP, macid("{total_rate}"), s);
+ sm_snprintf(s, sizeof(s), "%d", clientconn);
+ macdefine(&e->e_macro, A_TEMP, macid("{client_connections}"),
+ s);
+ }
+ return true;
+}
+
+/*
+** Data declarations needed to evaluate connection rate
+*/
+
+static int CollTime = 60;
+
+/* this should be a power of 2, otherwise CPMHMASK doesn't work well */
+#ifndef CPMHSIZE
+# define CPMHSIZE 1024
+#endif /* CPMHSIZE */
+
+#define CPMHMASK (CPMHSIZE-1)
+
+#ifndef MAX_CT_STEPS
+# define MAX_CT_STEPS 10
+#endif /* MAX_CT_STEPS */
+
+/*
+** time granularity: 10s (that's one "tick")
+** will be initialised to ConnectionRateWindowSize/CHTSIZE
+** before being used the first time
+*/
+
+static int ChtGran = -1;
+
+#define CHTSIZE 6
+
+/* Number of connections for a certain "tick" */
+typedef struct CTime
+{
+ unsigned long ct_Ticks;
+ int ct_Count;
+}
+CTime_T;
+
+typedef struct CHash
+{
+#if NETINET6 && NETINET
+ union
+ {
+ struct in_addr c4_Addr;
+ struct in6_addr c6_Addr;
+ } cu_Addr;
+# define ch_Addr4 cu_Addr.c4_Addr
+# define ch_Addr6 cu_Addr.c6_Addr
+#else /* NETINET6 && NETINET */
+# if NETINET6
+ struct in6_addr ch_Addr;
+# define ch_Addr6 ch_Addr
+# else /* NETINET6 */
+ struct in_addr ch_Addr;
+# define ch_Addr4 ch_Addr
+# endif /* NETINET6 */
+#endif /* NETINET6 && NETINET */
+
+ int ch_Family;
+ time_t ch_LTime;
+ unsigned long ch_colls;
+
+ /* 6 buckets for ticks: 60s */
+ CTime_T ch_Times[CHTSIZE];
+}
+CHash_T;
+
+static CHash_T CHashAry[CPMHSIZE];
+static bool CHashAryOK = false;
+
+/*
+** CLIENT_RATE - Evaluate connection rate per smtp client
+**
+** Parameters:
+** now - current time in secs
+** saddr - client address
+** update - update data / check only
+**
+** Returns:
+** connection rate (connections / ConnectionRateWindowSize)
+**
+** Side effects:
+** update static global data
+**
+*/
+
+static int
+client_rate(now, saddr, update)
+ time_t now;
+ SOCKADDR *saddr;
+ bool update;
+{
+ unsigned int hv;
+ int i;
+ int cnt;
+ bool coll;
+ CHash_T *chBest = NULL;
+ unsigned int ticks;
+
+ cnt = 0;
+ hv = 0xABC3D20F;
+ if (ChtGran < 0)
+ ChtGran = ConnectionRateWindowSize / CHTSIZE;
+ if (ChtGran <= 0)
+ ChtGran = 10;
+
+ ticks = now / ChtGran;
+
+ if (!CHashAryOK)
+ {
+ memset(CHashAry, 0, sizeof (CHashAry));
+ CHashAryOK = true;
+ }
+
+ {
+ char *p;
+ int addrlen;
+#if HASH_ALG != 1
+ int c, d;
+#endif /* HASH_ALG != 1 */
+
+ switch (saddr->sa.sa_family)
+ {
+#if NETINET
+ case AF_INET:
+ p = (char *)&saddr->sin.sin_addr;
+ addrlen = sizeof(struct in_addr);
+ break;
+#endif /* NETINET */
+#if NETINET6
+ case AF_INET6:
+ p = (char *)&saddr->sin6.sin6_addr;
+ addrlen = sizeof(struct in6_addr);
+ break;
+#endif /* NETINET6 */
+ default:
+ /* should not happen */
+ return -1;
+ }
+
+ /* compute hash value */
+ for (i = 0; i < addrlen; ++i, ++p)
+#if HASH_ALG == 1
+ hv = (hv << 5) ^ (hv >> 23) ^ *p;
+ hv = (hv ^ (hv >> 16));
+#elif HASH_ALG == 2
+ {
+ d = *p;
+ c = d;
+ c ^= c<<6;
+ hv += (c<<11) ^ (c>>1);
+ hv ^= (d<<14) + (d<<7) + (d<<4) + d;
+ }
+#elif HASH_ALG == 3
+ {
+ hv = (hv << 4) + *p;
+ d = hv & 0xf0000000;
+ if (d != 0)
+ {
+ hv ^= (d >> 24);
+ hv ^= d;
+ }
+ }
+#else /* HASH_ALG == 1 */
+ hv = ((hv << 1) ^ (*p & 0377)) % cctx->cc_size;
+#endif /* HASH_ALG == 1 */
+ }
+
+ coll = true;
+ for (i = 0; i < MAX_CT_STEPS; ++i)
+ {
+ CHash_T *ch = &CHashAry[(hv + i) & CPMHMASK];
+
+#if NETINET
+ if (saddr->sa.sa_family == AF_INET &&
+ ch->ch_Family == AF_INET &&
+ (saddr->sin.sin_addr.s_addr == ch->ch_Addr4.s_addr ||
+ ch->ch_Addr4.s_addr == 0))
+ {
+ chBest = ch;
+ coll = false;
+ break;
+ }
+#endif /* NETINET */
+#if NETINET6
+ if (saddr->sa.sa_family == AF_INET6 &&
+ ch->ch_Family == AF_INET6 &&
+ (IN6_ARE_ADDR_EQUAL(&saddr->sin6.sin6_addr,
+ &ch->ch_Addr6) != 0 ||
+ IN6_IS_ADDR_UNSPECIFIED(&ch->ch_Addr6)))
+ {
+ chBest = ch;
+ coll = false;
+ break;
+ }
+#endif /* NETINET6 */
+ if (chBest == NULL || ch->ch_LTime == 0 ||
+ ch->ch_LTime < chBest->ch_LTime)
+ chBest = ch;
+ }
+
+ /* Let's update data... */
+ if (update)
+ {
+ if (coll && (now - chBest->ch_LTime < CollTime))
+ {
+ /*
+ ** increment the number of collisions last
+ ** CollTime for this client
+ */
+
+ chBest->ch_colls++;
+
+ /*
+ ** Maybe shall log if collision rate is too high...
+ ** and take measures to resize tables
+ ** if this is the case
+ */
+ }
+
+ /*
+ ** If it's not a match, then replace the data.
+ ** Note: this purges the history of a colliding entry,
+ ** which may cause "overruns", i.e., if two entries are
+ ** "cancelling" each other out, then they may exceed
+ ** the limits that are set. This might be mitigated a bit
+ ** by the above "best of 5" function however.
+ **
+ ** Alternative approach: just use the old data, which may
+ ** cause false positives however.
+ ** To activate this, change deactivate following memset call.
+ */
+
+ if (coll)
+ {
+#if NETINET
+ if (saddr->sa.sa_family == AF_INET)
+ {
+ chBest->ch_Family = AF_INET;
+ chBest->ch_Addr4 = saddr->sin.sin_addr;
+ }
+#endif /* NETINET */
+#if NETINET6
+ if (saddr->sa.sa_family == AF_INET6)
+ {
+ chBest->ch_Family = AF_INET6;
+ chBest->ch_Addr6 = saddr->sin6.sin6_addr;
+ }
+#endif /* NETINET6 */
+#if 1
+ memset(chBest->ch_Times, '\0',
+ sizeof (chBest->ch_Times));
+#endif /* 1 */
+ }
+
+ chBest->ch_LTime = now;
+ {
+ CTime_T *ct = &chBest->ch_Times[ticks % CHTSIZE];
+
+ if (ct->ct_Ticks != ticks)
+ {
+ ct->ct_Ticks = ticks;
+ ct->ct_Count = 0;
+ }
+ ++ct->ct_Count;
+ }
+ }
+
+ /* Now let's count connections on the window */
+ for (i = 0; i < CHTSIZE; ++i)
+ {
+ CTime_T *ct = &chBest->ch_Times[i];
+
+ if (ct->ct_Ticks <= ticks && ct->ct_Ticks >= ticks - CHTSIZE)
+ cnt += ct->ct_Count;
+ }
+
+#if RATECTL_DEBUG
+ sm_syslog(LOG_WARNING, NOQID,
+ "cln: cnt=(%d), CHTSIZE=(%d), ChtGran=(%d)",
+ cnt, CHTSIZE, ChtGran);
+#endif /* RATECTL_DEBUG */
+ return cnt;
+}
+
+/*
+** TOTAL_RATE - Evaluate global connection rate
+**
+** Parameters:
+** now - current time in secs
+** update - update data / check only
+**
+** Returns:
+** connection rate (connections / ConnectionRateWindowSize)
+*/
+
+static CTime_T srv_Times[CHTSIZE];
+static bool srv_Times_OK = false;
+
+static int
+total_rate(now, update)
+ time_t now;
+ bool update;
+{
+ int i;
+ int cnt = 0;
+ CTime_T *ct;
+ unsigned int ticks;
+
+ if (ChtGran < 0)
+ ChtGran = ConnectionRateWindowSize / CHTSIZE;
+ if (ChtGran == 0)
+ ChtGran = 10;
+ ticks = now / ChtGran;
+ if (!srv_Times_OK)
+ {
+ memset(srv_Times, 0, sizeof(srv_Times));
+ srv_Times_OK = true;
+ }
+
+ /* Let's update data */
+ if (update)
+ {
+ ct = &srv_Times[ticks % CHTSIZE];
+
+ if (ct->ct_Ticks != ticks)
+ {
+ ct->ct_Ticks = ticks;
+ ct->ct_Count = 0;
+ }
+ ++ct->ct_Count;
+ }
+
+ /* Let's count connections on the window */
+ for (i = 0; i < CHTSIZE; ++i)
+ {
+ ct = &srv_Times[i];
+
+ if (ct->ct_Ticks <= ticks && ct->ct_Ticks >= ticks - CHTSIZE)
+ cnt += ct->ct_Count;
+ }
+
+#if RATECTL_DEBUG
+ sm_syslog(LOG_WARNING, NOQID,
+ "srv: cnt=(%d), CHTSIZE=(%d), ChtGran=(%d)",
+ cnt, CHTSIZE, ChtGran);
+#endif /* RATECTL_DEBUG */
+
+ return cnt;
+}
+
+#if 0
+/*
+** SOCKADDRCMP - compare two SOCKADDR structures
+** this function may be used to compare SOCKADDR
+** structures when using bsearch and qsort functions
+** in the same way we do with strcmp
+**
+** Parameters:
+** a, b - addresses
+**
+** Returns:
+** 1 if a > b
+** -1 if a < b
+** 0 if a = b
+**
+** OBS: This call isn't used at the moment, it will
+** be used when code will be extended to work with IPV6
+*/
+
+static int
+sockaddrcmp(a, b)
+ SOCKADDR *a;
+ SOCKADDR *b;
+{
+ if (a->sa.sa_family > b->sa.sa_family)
+ return 1;
+ if (a->sa.sa_family < b->sa.sa_family)
+ return -1;
+
+ switch (a->sa.sa_family)
+ {
+ case AF_INET:
+ if (a->sin.sin_addr.s_addr > b->sin.sin_addr.s_addr)
+ return 1;
+ if (a->sin.sin_addr.s_addr < b->sin.sin_addr.s_addr)
+ return -1;
+ return 0;
+ break;
+
+ case AF_INET6:
+ /* TO BE DONE */
+ break;
+ }
+ return 0;
+}
+#endif /* 0 */
diff --git a/contrib/sendmail/src/readcf.c b/contrib/sendmail/src/readcf.c
index 161e7d5..49eb120 100644
--- a/contrib/sendmail/src/readcf.c
+++ b/contrib/sendmail/src/readcf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: readcf.c,v 8.607.2.12 2003/10/07 17:45:28 ca Exp $")
+SM_RCSID("@(#)$Id: readcf.c,v 8.641 2004/07/23 20:45:02 gshapiro Exp $")
#if NETINET || NETINET6
# include <arpa/inet.h>
@@ -200,7 +200,8 @@ readcf(cfname, safe, e)
expand(&bp[1], exbuf, sizeof exbuf, e);
rwp->r_lhs = prescan(exbuf, '\t', pvpbuf,
sizeof pvpbuf, NULL,
- ConfigLevel >= 9 ? TokTypeNoC : NULL);
+ ConfigLevel >= 9 ? TokTypeNoC : NULL,
+ true);
nfuzzy = 0;
if (rwp->r_lhs != NULL)
{
@@ -287,7 +288,8 @@ readcf(cfname, safe, e)
expand(q, exbuf, sizeof exbuf, e);
rwp->r_rhs = prescan(exbuf, '\t', pvpbuf,
sizeof pvpbuf, NULL,
- ConfigLevel >= 9 ? TokTypeNoC : NULL);
+ ConfigLevel >= 9 ? TokTypeNoC : NULL,
+ true);
if (rwp->r_rhs != NULL)
{
register char **ap;
@@ -960,7 +962,7 @@ fileclass(class, filename, fmt, ismap, safe, optional)
cl = "ldap";
n = sm_snprintf(buf, sizeof buf,
- "-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName=%s)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))) -v sendmailMTAClassValue",
+ "-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName=%s)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))) -v sendmailMTAClassValue,sendmailMTAClassSearch:FILTER:sendmailMTAClass,sendmailMTAClassURL:URL:sendmailMTAClass",
mn, lc, jbuf);
if (n >= sizeof buf)
{
@@ -1185,6 +1187,8 @@ makemailer(line)
}
m->m_name = newstr(line);
m->m_qgrp = NOQGRP;
+ m->m_uid = NO_UID;
+ m->m_gid = NO_GID;
/* now scan through and assign info from the fields */
while (*p != '\0')
@@ -1793,17 +1797,14 @@ printrules()
{
if (RewriteRules[ruleset] == NULL)
continue;
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
- "\n----Rule Set %d:", ruleset);
+ sm_dprintf("\n----Rule Set %d:", ruleset);
for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next)
{
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
- "\nLHS:");
- printav(rwp->r_lhs);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
- "RHS:");
- printav(rwp->r_rhs);
+ sm_dprintf("\nLHS:");
+ printav(sm_debug_file(), rwp->r_lhs);
+ sm_dprintf("RHS:");
+ printav(sm_debug_file(), rwp->r_rhs);
}
}
}
@@ -1811,6 +1812,7 @@ printrules()
** PRINTMAILER -- print mailer structure (for debugging)
**
** Parameters:
+** fp -- output file
** m -- the mailer to print
**
** Returns:
@@ -1818,71 +1820,72 @@ printrules()
*/
void
-printmailer(m)
+printmailer(fp, m)
+ SM_FILE_T *fp;
register MAILER *m;
{
int j;
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"mailer %d (%s): P=%s S=", m->m_mno, m->m_name,
m->m_mailer);
if (RuleSetNames[m->m_se_rwset] == NULL)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%d/",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d/",
m->m_se_rwset);
else
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s/",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s/",
RuleSetNames[m->m_se_rwset]);
if (RuleSetNames[m->m_sh_rwset] == NULL)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%d R=",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d R=",
m->m_sh_rwset);
else
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s R=",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s R=",
RuleSetNames[m->m_sh_rwset]);
if (RuleSetNames[m->m_re_rwset] == NULL)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%d/",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d/",
m->m_re_rwset);
else
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s/",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s/",
RuleSetNames[m->m_re_rwset]);
if (RuleSetNames[m->m_rh_rwset] == NULL)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%d ",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%d ",
m->m_rh_rwset);
else
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s ",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s ",
RuleSetNames[m->m_rh_rwset]);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "M=%ld U=%d:%d F=",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "M=%ld U=%d:%d F=",
m->m_maxsize, (int) m->m_uid, (int) m->m_gid);
for (j = '\0'; j <= '\177'; j++)
if (bitnset(j, m->m_flags))
- (void) sm_io_putc(smioout, SM_TIME_DEFAULT, j);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " L=%d E=",
+ (void) sm_io_putc(fp, SM_TIME_DEFAULT, j);
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " L=%d E=",
m->m_linelimit);
- xputs(m->m_eol);
+ xputs(fp, m->m_eol);
if (m->m_defcharset != NULL)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " C=%s",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " C=%s",
m->m_defcharset);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " T=%s/%s/%s",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " T=%s/%s/%s",
m->m_mtatype == NULL
? "<undefined>" : m->m_mtatype,
m->m_addrtype == NULL
? "<undefined>" : m->m_addrtype,
m->m_diagtype == NULL
? "<undefined>" : m->m_diagtype);
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " r=%d", m->m_maxrcpt);
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " r=%d", m->m_maxrcpt);
if (m->m_argv != NULL)
{
char **a = m->m_argv;
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " A=");
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " A=");
while (*a != NULL)
{
if (a != m->m_argv)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
" ");
- xputs(*a++);
+ xputs(fp, *a++);
}
}
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\n");
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "\n");
}
/*
** SETOPTION -- set global processing option
@@ -2103,10 +2106,6 @@ static struct optioninfo
{ "XscriptFileBufferSize", O_XF_BUFSIZE, OI_NONE },
#define O_LDAPDEFAULTSPEC 0xb2
{ "LDAPDefaultSpec", O_LDAPDEFAULTSPEC, OI_NONE },
-#if _FFR_QUEUEDELAY
-# define O_QUEUEDELAY 0xb3
- { "QueueDelay", O_QUEUEDELAY, OI_NONE },
-#endif /* _FFR_QUEUEDELAY */
#define O_SRVCERTFILE 0xb4
{ "ServerCertFile", O_SRVCERTFILE, OI_NONE },
#define O_SRVKEYFILE 0xb5
@@ -2171,14 +2170,27 @@ static struct optioninfo
# define O_SHMKEYFILE 0xd0
{ "SharedMemoryKeyFile", O_SHMKEYFILE, OI_NONE },
#endif /* _FFR_SELECT_SHM */
-#if _FFR_REJECT_LOG
-# define O_REJECTLOGINTERVAL 0xd1
+#define O_REJECTLOGINTERVAL 0xd1
{ "RejectLogInterval", O_REJECTLOGINTERVAL, OI_NONE },
-#endif /* _FFR_REJECT_LOG */
-#if _FFR_REQ_DIR_FSYNC_OPT
-# define O_REQUIRES_DIR_FSYNC 0xd2
+#define O_REQUIRES_DIR_FSYNC 0xd2
{ "RequiresDirfsync", O_REQUIRES_DIR_FSYNC, OI_NONE },
-#endif /* _FFR_REQ_DIR_FSYNC_OPT */
+#define O_CONNECTION_RATE_WINDOW_SIZE 0xd3
+ { "ConnectionRateWindowSize", O_CONNECTION_RATE_WINDOW_SIZE, OI_NONE },
+#define O_CRLFILE 0xd4
+ { "CRLFile", O_CRLFILE, OI_NONE },
+#define O_FALLBACKSMARTHOST 0xd5
+ { "FallbackSmartHost", O_FALLBACKSMARTHOST, OI_NONE },
+#define O_SASLREALM 0xd6
+ { "AuthRealm", O_SASLREALM, OI_NONE },
+#if _FFR_CRLPATH
+# define O_CRLPATH 0xd7
+ { "CRLPath", O_CRLPATH, OI_NONE },
+#endif /* _FFR_CRLPATH */
+#if _FFR_HELONAME
+# define O_HELONAME 0xd8
+ { "HeloName", O_HELONAME, OI_NONE },
+#endif /* _FFR_HELONAME */
+
{ NULL, '\0', OI_NONE }
};
@@ -2318,7 +2330,7 @@ setoption(opt, val, safe, sticky, e)
"setoption %s (0x%x)%s%s=",
OPTNAME, opt, subopt == NULL ? "" : ".",
subopt == NULL ? "" : subopt);
- xputs(val);
+ xputs(sm_debug_file(), val);
}
/*
@@ -2444,7 +2456,8 @@ setoption(opt, val, safe, sticky, e)
break;
case 'C': /* checkpoint every N addresses */
- CheckpointInterval = atoi(val);
+ if (safe || CheckpointInterval > atoi(val))
+ CheckpointInterval = atoi(val);
break;
case 'd': /* delivery mode */
@@ -2726,6 +2739,13 @@ setoption(opt, val, safe, sticky, e)
case 's': /* be super safe, even if expensive */
if (tolower(*val) == 'i')
SuperSafe = SAFE_INTERACTIVE;
+ else if (tolower(*val) == 'p')
+#if MILTER
+ SuperSafe = SAFE_REALLY_POSTMILTER;
+#else /* MILTER */
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n");
+#endif /* MILTER */
else
SuperSafe = atobool(val) ? SAFE_REALLY : SAFE_NO;
break;
@@ -2802,7 +2822,7 @@ setoption(opt, val, safe, sticky, e)
case 'V': /* fallback MX host */
if (val[0] != '\0')
- FallBackMX = newstr(val);
+ FallbackMX = newstr(val);
break;
case 'v': /* run in verbose mode */
@@ -2887,47 +2907,15 @@ setoption(opt, val, safe, sticky, e)
break;
#endif /* _FFR_RHS */
- default:
- syserr("Invalid queue sort order \"%s\"", val);
- }
- break;
-
-#if _FFR_QUEUEDELAY
- case O_QUEUEDELAY: /* queue delay algorithm */
- switch (*val)
- {
- case 'e': /* exponential */
- case 'E':
- QueueAlg = QD_EXP;
- QueueInitDelay = 10 MINUTES;
- QueueMaxDelay = 2 HOURS;
- p = strchr(val, '/');
- if (p != NULL)
- {
- char *q;
-
- *p++ = '\0';
- q = strchr(p, '/');
- if (q != NULL)
- *q++ = '\0';
- QueueInitDelay = convtime(p, 's');
- if (q != NULL)
- {
- QueueMaxDelay = convtime(q, 's');
- }
- }
- break;
-
- case 'l': /* linear */
- case 'L':
- QueueAlg = QD_LINEAR;
+ case 'n': /* none */
+ case 'N':
+ QueueSortOrder = QSO_NONE;
break;
default:
- syserr("Invalid queue delay algorithm \"%s\"", val);
+ syserr("Invalid queue sort order \"%s\"", val);
}
break;
-#endif /* _FFR_QUEUEDELAY */
case O_HOSTSFILE: /* pathname of /etc/hosts file */
CANONIFY(val);
@@ -3408,6 +3396,15 @@ setoption(opt, val, safe, sticky, e)
AuthMechanisms = NULL;
break;
+ case O_SASLREALM:
+ if (AuthRealm != NULL)
+ sm_free(AuthRealm);
+ if (*val != '\0')
+ AuthRealm = newstr(val);
+ else
+ AuthRealm = NULL;
+ break;
+
case O_SASLOPTS:
while (val != NULL && *val != '\0')
{
@@ -3433,14 +3430,11 @@ setoption(opt, val, safe, sticky, e)
SASLOpts |= SASL_SEC_FORWARD_SECRECY;
break;
-# if _FFR_SASL_OPT_M
-/* to be activated in 8.13 */
# if SASL >= 20101
case 'm':
SASLOpts |= SASL_SEC_MUTUAL_AUTH;
break;
# endif /* SASL >= 20101 */
-# endif /* _FFR_SASL_OPT_M */
case 'p':
SASLOpts |= SASL_SEC_NOPLAINTEXT;
@@ -3478,6 +3472,7 @@ setoption(opt, val, safe, sticky, e)
#else /* SASL */
case O_SASLINFO:
case O_SASLMECH:
+ case O_SASLREALM:
case O_SASLOPTS:
case O_SASLBITS:
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
@@ -3507,6 +3502,27 @@ setoption(opt, val, safe, sticky, e)
case O_CIPHERLIST:
SET_STRING_EXP(CipherList);
# endif /* _FFR_TLS_1 */
+ case O_CRLFILE:
+# if OPENSSL_VERSION_NUMBER > 0x00907000L
+ SET_STRING_EXP(CRLFile);
+# else /* OPENSSL_VERSION_NUMBER > 0x00907000L */
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "Warning: Option: %s requires at least OpenSSL 0.9.7\n",
+ OPTNAME);
+ break;
+# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
+
+# if _FFR_CRLPATH
+ case O_CRLPATH:
+# if OPENSSL_VERSION_NUMBER > 0x00907000L
+ SET_STRING_EXP(CRLPath);
+# else /* OPENSSL_VERSION_NUMBER > 0x00907000L */
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "Warning: Option: %s requires at least OpenSSL 0.9.7\n",
+ OPTNAME);
+ break;
+# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
+# endif /* _FFR_CRLPATH */
/*
** XXX How about options per daemon/client instead of globally?
@@ -3575,6 +3591,10 @@ setoption(opt, val, safe, sticky, e)
case O_DHPARAMS5:
case O_CIPHERLIST:
# endif /* _FFR_TLS_1 */
+ case O_CRLFILE:
+# if _FFR_CRLPATH
+ case O_CRLPATH:
+# endif /* _FFR_CRLPATH */
case O_RANDFILE:
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Warning: Option: %s requires TLS support\n",
@@ -3663,21 +3683,32 @@ setoption(opt, val, safe, sticky, e)
break;
#endif /* _FFR_SOFT_BOUNCE */
-#if _FFR_REJECT_LOG
case O_REJECTLOGINTERVAL: /* time btwn log msgs while refusing */
RejectLogInterval = convtime(val, 'h');
break;
-#endif /* _FFR_REJECT_LOG */
-#if _FFR_REQ_DIR_FSYNC_OPT
case O_REQUIRES_DIR_FSYNC:
-# if REQUIRES_DIR_FSYNC
+#if REQUIRES_DIR_FSYNC
RequiresDirfsync = atobool(val);
-# else /* REQUIRES_DIR_FSYNC */
+#else /* REQUIRES_DIR_FSYNC */
/* silently ignored... required for cf file option */
-# endif /* REQUIRES_DIR_FSYNC */
+#endif /* REQUIRES_DIR_FSYNC */
break;
-#endif /* _FFR_REQ_DIR_FSYNC_OPT */
+
+ case O_CONNECTION_RATE_WINDOW_SIZE:
+ ConnectionRateWindowSize = convtime(val, 's');
+ break;
+
+ case O_FALLBACKSMARTHOST: /* fallback smart host */
+ if (val[0] != '\0')
+ FallbackSmartHost = newstr(val);
+ break;
+
+#if _FFR_HELONAME
+ case O_HELONAME:
+ HeloName = newstr(val);
+ break;
+#endif /* _FFR_HELONAME */
default:
if (tTd(37, 1))
@@ -4047,12 +4078,10 @@ static struct timeoutinfo
{ "starttls", TO_STARTTLS },
#define TO_ACONNECT 0x23
{ "aconnect", TO_ACONNECT },
-#if _FFR_QUEUERETURN_DSN
-# define TO_QUEUEWARN_DSN 0x24
+#define TO_QUEUEWARN_DSN 0x24
{ "queuewarn.dsn", TO_QUEUEWARN_DSN },
-# define TO_QUEUERETURN_DSN 0x25
+#define TO_QUEUERETURN_DSN 0x25
{ "queuereturn.dsn", TO_QUEUERETURN_DSN },
-#endif /* _FFR_QUEUERETURN_DSN */
{ NULL, 0 },
};
@@ -4171,9 +4200,7 @@ settimeout(name, val, sticky)
TimeOuts.to_q_warning[TOC_NORMAL] = toval;
TimeOuts.to_q_warning[TOC_URGENT] = toval;
TimeOuts.to_q_warning[TOC_NONURGENT] = toval;
-#if _FFR_QUEUERETURN_DSN
TimeOuts.to_q_warning[TOC_DSN] = toval;
-#endif /* _FFR_QUEUERETURN_DSN */
addopts = 2;
break;
@@ -4192,21 +4219,17 @@ settimeout(name, val, sticky)
TimeOuts.to_q_warning[TOC_NONURGENT] = toval;
break;
-#if _FFR_QUEUERETURN_DSN
case TO_QUEUEWARN_DSN:
toval = convtime(val, 'h');
TimeOuts.to_q_warning[TOC_DSN] = toval;
break;
-#endif /* _FFR_QUEUERETURN_DSN */
case TO_QUEUERETURN:
toval = convtime(val, 'd');
TimeOuts.to_q_return[TOC_NORMAL] = toval;
TimeOuts.to_q_return[TOC_URGENT] = toval;
TimeOuts.to_q_return[TOC_NONURGENT] = toval;
-#if _FFR_QUEUERETURN_DSN
TimeOuts.to_q_return[TOC_DSN] = toval;
-#endif /* _FFR_QUEUERETURN_DSN */
addopts = 2;
break;
@@ -4225,12 +4248,10 @@ settimeout(name, val, sticky)
TimeOuts.to_q_return[TOC_NONURGENT] = toval;
break;
-#if _FFR_QUEUERETURN_DSN
case TO_QUEUERETURN_DSN:
toval = convtime(val, 'd');
TimeOuts.to_q_return[TOC_DSN] = toval;
break;
-#endif /* _FFR_QUEUERETURN_DSN */
case TO_HOSTSTATUS:
MciInfoTimeout = toval;
diff --git a/contrib/sendmail/src/recipient.c b/contrib/sendmail/src/recipient.c
index b7b6660..02ef8d7 100644
--- a/contrib/sendmail/src/recipient.c
+++ b/contrib/sendmail/src/recipient.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: recipient.c,v 8.330.2.4 2003/10/06 20:43:29 ca Exp $")
+SM_RCSID("@(#)$Id: recipient.c,v 8.336 2004/07/23 20:45:02 gshapiro Exp $")
static void includetimeout __P((void));
static ADDRESS *self_reference __P((ADDRESS *));
@@ -183,7 +183,7 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
if (tTd(25, 1))
{
sm_dprintf("sendto: %s\n ctladdr=", list);
- printaddr(ctladdr, false);
+ printaddr(sm_debug_file(), ctladdr, false);
}
/* heuristic to determine old versus new style addresses */
@@ -245,7 +245,7 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
if (tTd(27, 5))
{
sm_dprintf("sendtolist: QSELFREF ");
- printaddr(ctladdr, false);
+ printaddr(sm_debug_file(), ctladdr, false);
}
ctladdr->q_flags |= QSELFREF;
}
@@ -258,14 +258,14 @@ sendtolist(list, ctladdr, sendq, aliaslevel, e)
if (tTd(27, 5))
{
sm_dprintf("sendtolist: QSELFREF ");
- printaddr(b, false);
+ printaddr(sm_debug_file(), b, false);
}
if (a != b)
{
if (tTd(27, 5))
{
sm_dprintf("sendtolist: QS_DONTSEND ");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
a->q_state = QS_DONTSEND;
b->q_flags |= a->q_flags & QNOTREMOTE;
@@ -403,7 +403,7 @@ removefromlist(list, sendq, e)
if (tTd(25, 5))
{
sm_dprintf("removefromlist: QS_REMOVED ");
- printaddr(&a, false);
+ printaddr(sm_debug_file(), &a, false);
}
q->q_state = QS_REMOVED;
naddrs++;
@@ -476,7 +476,7 @@ recipient(new, sendq, aliaslevel, e)
if (tTd(26, 1))
{
sm_dprintf("\nrecipient (%d): ", aliaslevel);
- printaddr(new, false);
+ printaddr(sm_debug_file(), new, false);
}
/* if this is primary, use it as original recipient */
@@ -727,7 +727,7 @@ recipient(new, sendq, aliaslevel, e)
{
sm_dprintf("%s in sendq: ",
new->q_paddr);
- printaddr(q, false);
+ printaddr(sm_debug_file(), q, false);
}
if (!bitset(QPRIMARY, q->q_flags))
{
@@ -800,7 +800,7 @@ recipient(new, sendq, aliaslevel, e)
if (tTd(29, 7))
{
sm_dprintf("at trylocaluser: ");
- printaddr(new, false);
+ printaddr(sm_debug_file(), new, false);
}
if (!QS_IS_OK(new->q_state))
@@ -930,7 +930,7 @@ recipient(new, sendq, aliaslevel, e)
{
sm_dprintf("recipient: testing local? cl=%d, rr5=%p\n\t",
ConfigLevel, RewriteRules[5]);
- printaddr(new, false);
+ printaddr(sm_debug_file(), new, false);
}
if (ConfigLevel >= 2 && RewriteRules[5] != NULL &&
bitnset(M_TRYRULESET5, m->m_flags) &&
@@ -1028,11 +1028,11 @@ recipient(new, sendq, aliaslevel, e)
if (tTd(26, 8))
{
sm_dprintf("testselfdestruct: ");
- printaddr(new, false);
+ printaddr(sm_debug_file(), new, false);
if (tTd(26, 10))
{
sm_dprintf("SENDQ:\n");
- printaddr(*sendq, true);
+ printaddr(sm_debug_file(), *sendq, true);
sm_dprintf("----\n");
}
}
@@ -1309,9 +1309,20 @@ writable(filename, ctladdr, flags)
}
else if (FileMailer != NULL && !bitset(SFF_ROOTOK, flags))
{
- euid = FileMailer->m_uid;
- egid = FileMailer->m_gid;
- user = NULL;
+ if (FileMailer->m_uid == NO_UID)
+ {
+ euid = DefUid;
+ user = DefUser;
+ }
+ else
+ {
+ euid = FileMailer->m_uid;
+ user = NULL;
+ }
+ if (FileMailer->m_gid == NO_GID)
+ egid = DefGid;
+ else
+ egid = FileMailer->m_gid;
}
else
{
@@ -1417,7 +1428,7 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
if (tTd(27, 14))
{
sm_dprintf("ctladdr ");
- printaddr(ctladdr, false);
+ printaddr(sm_debug_file(), ctladdr, false);
}
if (tTd(27, 9))
@@ -1850,7 +1861,7 @@ resetuid:
if (tTd(27, 5))
{
sm_dprintf("include: QS_DONTSEND ");
- printaddr(ctladdr, false);
+ printaddr(sm_debug_file(), ctladdr, false);
}
ctladdr->q_state = QS_DONTSEND;
}
diff --git a/contrib/sendmail/src/sasl.c b/contrib/sendmail/src/sasl.c
index 4b30f47..e2bf415 100644
--- a/contrib/sendmail/src/sasl.c
+++ b/contrib/sendmail/src/sasl.c
@@ -9,7 +9,7 @@
*/
#include <sm/gen.h>
-SM_RCSID("@(#)$Id: sasl.c,v 8.19.2.2 2002/09/26 23:03:40 gshapiro Exp $")
+SM_RCSID("@(#)$Id: sasl.c,v 8.20 2004/06/02 22:48:06 ca Exp $")
#if SASL
# include <stdlib.h>
@@ -208,7 +208,7 @@ intersect(s1, s2, rpool)
# if SASL >= 20000
/*
** IPTOSTRING -- create string for SASL_IP*PORT property
-** (borrowed from lib/iptostring.c in Cyrus-IMAP)
+** (borrowed from lib/iptostring.c in Cyrus-IMAP)
**
** Parameters:
** addr -- (pointer to) socket address
diff --git a/contrib/sendmail/src/savemail.c b/contrib/sendmail/src/savemail.c
index 073c31f..231382a 100644
--- a/contrib/sendmail/src/savemail.c
+++ b/contrib/sendmail/src/savemail.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: savemail.c,v 8.299.2.1 2002/10/23 15:08:47 ca Exp $")
+SM_RCSID("@(#)$Id: savemail.c,v 8.303 2004/01/14 02:56:51 ca Exp $")
static void errbody __P((MCI *, ENVELOPE *, char *));
static bool pruneroute __P((char *));
@@ -74,7 +74,7 @@ savemail(e, sendbody)
sm_dprintf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n e_from=",
e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id,
ExitStat);
- printaddr(&e->e_from, false);
+ printaddr(sm_debug_file(), &e->e_from, false);
}
if (e->e_id == NULL)
@@ -178,7 +178,12 @@ savemail(e, sendbody)
** then write the error messages back to hir (sic).
*/
+#if USE_TTYPATH
p = ttypath();
+#else /* USE_TTYPATH */
+ p = NULL;
+#endif /* USE_TTYPATH */
+
if (p == NULL || sm_io_reopen(SmFtStdio,
SM_TIME_DEFAULT,
p, SM_IO_WRONLY, NULL,
@@ -518,11 +523,11 @@ returntosender(msg, returnq, flags, e)
{
sm_dprintf("\n*** Return To Sender: msg=\"%s\", depth=%d, e=%p, returnq=",
msg, returndepth, e);
- printaddr(returnq, true);
+ printaddr(sm_debug_file(), returnq, true);
if (tTd(6, 20))
{
sm_dprintf("Sendq=");
- printaddr(e->e_sendqueue, true);
+ printaddr(sm_debug_file(), e->e_sendqueue, true);
}
}
diff --git a/contrib/sendmail/src/sendmail.8 b/contrib/sendmail/src/sendmail.8
index eacfbd0..2d0284a 100644
--- a/contrib/sendmail/src/sendmail.8
+++ b/contrib/sendmail/src/sendmail.8
@@ -1,4 +1,4 @@
-.\" Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
+.\" Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
.\" All rights reserved.
.\" Copyright (c) 1983, 1997 Eric P. Allman. All rights reserved.
.\" Copyright (c) 1988, 1991, 1993
@@ -9,9 +9,9 @@
.\" the sendmail distribution.
.\"
.\"
-.\" $Id: sendmail.8,v 8.51.2.3 2003/12/01 17:02:00 ca Exp $
+.\" $Id: sendmail.8,v 8.57 2003/12/01 17:02:41 ca Exp $
.\"
-.TH SENDMAIL 8 "$Date: 2003/12/01 17:02:00 $"
+.TH SENDMAIL 8 "$Date: 2003/12/01 17:02:41 $"
.SH NAME
sendmail
\- an electronic mail transport agent
@@ -153,6 +153,9 @@ Use alternate configuration file.
gives up any enhanced (set-user-ID or set-group-ID) privileges
if an alternate configuration file is specified.
.TP
+.BI "\-D " logfile
+Send debugging output to the indicated log file instead of stdout.
+.TP
.BI \-d category . level...
Set the debugging flag for
.I category
@@ -323,6 +326,13 @@ as a substring of the queue id or not when
.I !
is specified.
.TP
+\fB\-q\fR[\fI!\fR]Q\fIsubstr\fR
+Limit processed jobs to quarantined jobs containing
+.I substr
+as a substring of the quarantine reason or not when
+.I !
+is specified.
+.TP
\fB\-q\fR[\fI!\fR]R\fIsubstr\fR
Limit processed jobs to those containing
.I substr
@@ -337,6 +347,12 @@ as a substring of the sender or not when
.I !
is specified.
.TP
+\fB\-Q\fR[reason]
+Quarantine a normal queue items with the given reason or
+unquarantine quarantined queue items if no reason is given.
+This should only be used with some sort of item matching using
+as described above.
+.TP
.BI "\-R " return
Set the amount of the message to be returned
if the message bounces.
diff --git a/contrib/sendmail/src/sendmail.h b/contrib/sendmail/src/sendmail.h
index 2e1b732..306605e 100644
--- a/contrib/sendmail/src/sendmail.h
+++ b/contrib/sendmail/src/sendmail.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -17,6 +17,10 @@
#ifndef _SENDMAIL_H
# define _SENDMAIL_H 1
+#ifndef MILTER
+# define MILTER 1 /* turn on MILTER by default */
+#endif /* MILTER */
+
#ifdef _DEFINE
# define EXTERN
#else /* _DEFINE */
@@ -48,7 +52,7 @@
#ifdef _DEFINE
# ifndef lint
-SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.919.2.29 2003/11/07 00:08:02 ca Exp $";
+SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.984 2004/07/14 21:54:22 ca Exp $";
# endif /* ! lint */
#endif /* _DEFINE */
@@ -336,8 +340,8 @@ extern int include __P((char *, bool, ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern bool invalidaddr __P((char *, char *, bool));
extern ADDRESS *parseaddr __P((char *, ADDRESS *, int, int, char **,
ENVELOPE *, bool));
-extern char **prescan __P((char *, int, char[], int, char **, unsigned char *));
-extern void printaddr __P((ADDRESS *, bool));
+extern char **prescan __P((char *, int, char[], int, char **, unsigned char *, bool));
+extern void printaddr __P((SM_FILE_T *, ADDRESS *, bool));
extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern char *remotename __P((char *, MAILER *, int, int *, ENVELOPE *));
extern int rewrite __P((char **, int, int, ENVELOPE *, int));
@@ -396,9 +400,7 @@ struct mailer
#define M_ESMTP 'a' /* run Extended SMTP */
#define M_ALIASABLE 'A' /* user can be LHS of an alias */
#define M_BLANKEND 'b' /* ensure blank line at end of message */
-#if _FFR_STRIPBACKSL
-# define M_STRIPBACKSL 'B' /* strip leading backslash from user */
-#endif /* _FFR_STRIPBACKSL */
+#define M_STRIPBACKSL 'B' /* strip leading backslash from user */
#define M_NOCOMMENT 'c' /* don't include comment part of address */
#define M_CANONICAL 'C' /* make addresses canonical "u@dom" */
#define M_NOBRACKET 'd' /* never angle bracket envelope route-addrs */
@@ -434,6 +436,7 @@ struct mailer
#define M_CONTENT_LEN 'v' /* add Content-Length: header (SVr4) */
/* 'V' UIUC: !-relativize all addresses */
#define M_HASPWENT 'w' /* check for /etc/passwd entry */
+#define M_NOHOSTSTAT 'W' /* ignore long term host status information */
/* 'x' CF: include Full-Name: */
#define M_XDOT 'X' /* use hidden-dot algorithm */
#define M_LMTP 'z' /* run Local Mail Transport Protocol */
@@ -610,6 +613,7 @@ extern void stop_sasl_client __P((void));
typedef char *SASL_AI_T[SASL_ENTRIES];
EXTERN char *AuthMechanisms; /* AUTH mechanisms */
+EXTERN char *AuthRealm; /* AUTH realm */
EXTERN char *SASLInfo; /* file with AUTH info */
EXTERN int SASLOpts; /* options for SASL */
EXTERN int MaxSLBits; /* max. encryption bits for SASL */
@@ -724,8 +728,8 @@ MCI
/* functions */
extern void mci_cache __P((MCI *));
-extern void mci_dump __P((MCI *, bool));
-extern void mci_dump_all __P((bool));
+extern void mci_dump __P((SM_FILE_T *, MCI *, bool));
+extern void mci_dump_all __P((SM_FILE_T *, bool));
extern void mci_flush __P((bool, MCI *));
extern MCI *mci_get __P((char *, MAILER *));
extern int mci_lock_host __P((MCI *));
@@ -808,6 +812,7 @@ extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
extern HDR *copyheader __P((HDR *, SM_RPOOL_T *));
extern void eatheader __P((ENVELOPE *, bool, bool));
extern char *hvalue __P((char *, HDR *));
+extern void insheader __P((int, char *, char *, int, ENVELOPE *));
extern bool isheader __P((char *));
extern void putfromline __P((MCI *, ENVELOPE *));
extern void setupheaders __P((void));
@@ -887,10 +892,8 @@ struct envelope
char *e_statmsg; /* stat msg (changes per delivery).
* readonly. NULL or allocated from
* e_rpool. */
-#if _FFR_QUARANTINE
char *e_quarmsg; /* why envelope is quarantined */
char e_qfletter; /* queue file letter on disk */
-#endif /* _FFR_QUARANTINE */
char *e_msgboundary; /* MIME-style message part boundary */
char *e_origrcpt; /* original recipient (one only) */
char *e_envid; /* envelope id from MAIL FROM: line */
@@ -904,10 +907,6 @@ struct envelope
char *e_auth_param; /* readonly; NULL or static storage or
* allocated from e_rpool */
TIMERS e_timers; /* per job timers */
-#if _FFR_QUEUEDELAY
- int e_queuealg; /* algorithm for queue delay */
- time_t e_queuedelay; /* current delay */
-#endif /* _FFR_QUEUEDELAY */
long e_deliver_by; /* deliver by */
int e_dlvr_flag; /* deliver by flag */
SM_RPOOL_T *e_rpool; /* resource pool for this envelope */
@@ -1333,6 +1332,52 @@ struct ph_map_struct
typedef struct ph_map_struct PH_MAP_STRUCT;
#endif /* PH_MAP */
+
+/*
+** Regular UNIX sockaddrs are too small to handle ISO addresses, so
+** we are forced to declare a supertype here.
+*/
+
+#if NETINET || NETINET6 || NETUNIX || NETISO || NETNS || NETX25
+union bigsockaddr
+{
+ struct sockaddr sa; /* general version */
+# if NETUNIX
+ struct sockaddr_un sunix; /* UNIX family */
+# endif /* NETUNIX */
+# if NETINET
+ struct sockaddr_in sin; /* INET family */
+# endif /* NETINET */
+# if NETINET6
+ struct sockaddr_in6 sin6; /* INET/IPv6 */
+# endif /* NETINET6 */
+# if NETISO
+ struct sockaddr_iso siso; /* ISO family */
+# endif /* NETISO */
+# if NETNS
+ struct sockaddr_ns sns; /* XNS family */
+# endif /* NETNS */
+# if NETX25
+ struct sockaddr_x25 sx25; /* X.25 family */
+# endif /* NETX25 */
+};
+
+# define SOCKADDR union bigsockaddr
+
+/* functions */
+extern char *anynet_ntoa __P((SOCKADDR *));
+# if NETINET6
+extern char *anynet_ntop __P((struct in6_addr *, char *, size_t));
+extern int anynet_pton __P((int, const char *, void *));
+# endif /* NETINET6 */
+extern char *hostnamebyanyaddr __P((SOCKADDR *));
+extern char *validate_connection __P((SOCKADDR *, char *, ENVELOPE *));
+# if SASL >= 20000
+extern bool iptostring __P((SOCKADDR *, SOCKADDR_LEN_T, char *, unsigned));
+# endif /* SASL >= 20000 */
+
+#endif /* NETINET || NETINET6 || NETUNIX || NETISO || NETNS || NETX25 */
+
/*
** Process List (proclist)
*/
@@ -1352,7 +1397,7 @@ typedef struct ph_map_struct PH_MAP_STRUCT;
#define PROC_CONTROL_CHILD 5
/* functions */
-extern void proc_list_add __P((pid_t, char *, int, int, int));
+extern void proc_list_add __P((pid_t, char *, int, int, int, SOCKADDR *));
extern void proc_list_clear __P((void));
extern void proc_list_display __P((SM_FILE_T *, char *));
extern void proc_list_drop __P((pid_t, int, int *));
@@ -1387,6 +1432,9 @@ struct symtab
#if LDAPMAP
MAP *sv_lmap; /* Maps for LDAP connection */
#endif /* LDAPMAP */
+#if SOCKETMAP
+ MAP *sv_socketmap; /* Maps for SOCKET connection */
+#endif /* SOCKETMAP */
#if MILTER
struct milter *sv_milter; /* milter filter name */
#endif /* MILTER */
@@ -1418,8 +1466,12 @@ typedef struct symtab STAB;
#endif /* MILTER */
#define ST_QUEUE 15 /* a queue entry */
+#if SOCKETMAP
+# define ST_SOCKETMAP 16 /* List head of maps for SOCKET connection */
+#endif /* SOCKETMAP */
+
/* This entry must be last */
-#define ST_MCI 16 /* mailer connection info (offset) */
+#define ST_MCI 17 /* mailer connection info (offset) */
#define s_class s_value.sv_class
#define s_address s_value.sv_addr
@@ -1437,6 +1489,9 @@ typedef struct symtab STAB;
#if LDAPMAP
# define s_lmap s_value.sv_lmap
#endif /* LDAPMAP */
+#if SOCKETMAP
+# define s_socketmap s_value.sv_socketmap
+#endif /* SOCKETMAP */
#if MILTER
# define s_milter s_value.sv_milter
#endif /* MILTER */
@@ -1606,51 +1661,6 @@ extern int mime8to7 __P((MCI *, HDR *, ENVELOPE *, char **, int));
extern int returntosender __P((char *, ADDRESS *, int, ENVELOPE *));
/*
-** Regular UNIX sockaddrs are too small to handle ISO addresses, so
-** we are forced to declare a supertype here.
-*/
-
-#if NETINET || NETINET6 || NETUNIX || NETISO || NETNS || NETX25
-union bigsockaddr
-{
- struct sockaddr sa; /* general version */
-# if NETUNIX
- struct sockaddr_un sunix; /* UNIX family */
-# endif /* NETUNIX */
-# if NETINET
- struct sockaddr_in sin; /* INET family */
-# endif /* NETINET */
-# if NETINET6
- struct sockaddr_in6 sin6; /* INET/IPv6 */
-# endif /* NETINET6 */
-# if NETISO
- struct sockaddr_iso siso; /* ISO family */
-# endif /* NETISO */
-# if NETNS
- struct sockaddr_ns sns; /* XNS family */
-# endif /* NETNS */
-# if NETX25
- struct sockaddr_x25 sx25; /* X.25 family */
-# endif /* NETX25 */
-};
-
-# define SOCKADDR union bigsockaddr
-
-/* functions */
-extern char *anynet_ntoa __P((SOCKADDR *));
-# if NETINET6
-extern char *anynet_ntop __P((struct in6_addr *, char *, size_t));
-extern int anynet_pton __P((int, const char *, void *));
-# endif /* NETINET6 */
-extern char *hostnamebyanyaddr __P((SOCKADDR *));
-extern char *validate_connection __P((SOCKADDR *, char *, ENVELOPE *));
-# if SASL >= 20000
-extern bool iptostring __P((SOCKADDR *, SOCKADDR_LEN_T, char *, unsigned));
-# endif /* SASL >= 20000 */
-
-#endif /* NETINET || NETINET6 || NETUNIX || NETISO || NETNS || NETX25 */
-
-/*
** Mail Filters (milter)
*/
@@ -1699,10 +1709,8 @@ EXTERN struct milter *InputFilters[MAXFILTERS];
EXTERN char *InputFilterList;
EXTERN int MilterLogLevel;
-# if _FFR_MILTER_PERDAEMON
/* functions */
extern void setup_daemon_milters __P((void));
-# endif /* _FFR_MILTER_PERDAEMON */
#endif /* MILTER */
/*
@@ -1759,9 +1767,7 @@ struct termescape
#define D_IFNHELO 'h' /* use if name for HELO */
#define D_FQMAIL 'f' /* fq sender address required (cf) */
#define D_FQRCPT 'r' /* fq recipient address required (cf) */
-#if _FFR_SMTP_SSL
-# define D_SMTPS 's' /* SMTP over SSL (smtps) */
-#endif /* _FFR_SMTP_SSL */
+#define D_SMTPS 's' /* SMTP over SSL (smtps) */
#define D_UNQUALOK 'u' /* unqualified address is ok (cf) */
#define D_NOAUTH 'A' /* no AUTH */
#define D_NOCANON 'C' /* no canonification (cf) */
@@ -1802,6 +1808,8 @@ struct termescape
#define TLS_I_DH2048 0x00100000 /* generate 2048bit DH param */
#define TLS_I_NO_VRFY 0x00200000 /* do not require authentication */
#define TLS_I_KEY_OUNR 0x00400000 /* Key must be other unreadable */
+#define TLS_I_CRLF_EX 0x00800000 /* CRL file must exist */
+#define TLS_I_CRLF_UNR 0x01000000 /* CRL file must be g/o unreadable */
/* require server cert */
#define TLS_I_SRV_CERT (TLS_I_CERT_EX | TLS_I_KEY_EX | \
@@ -1843,6 +1851,10 @@ EXTERN char *DHParams; /* file with DH parameters */
EXTERN char *RandFile; /* source of random data */
EXTERN char *SrvCertFile; /* file with server certificate */
EXTERN char *SrvKeyFile; /* file with server private key */
+EXTERN char *CRLFile; /* file CRLs */
+#if _FFR_CRLPATH
+EXTERN char *CRLPath; /* path to CRLs (dir. with hashes) */
+#endif /* _FFR_CRLPATH */
EXTERN unsigned long TLS_Srv_Opts; /* TLS server options */
#endif /* STARTTLS */
@@ -1851,13 +1863,8 @@ EXTERN unsigned long TLS_Srv_Opts; /* TLS server options */
*/
/* queue file names */
-#if _FFR_QUARANTINE
-# define ANYQFL_LETTER '?'
-# define QUARQF_LETTER 'h'
-#else /* _FFR_QUARANTINE */
-/* Before quarantining, ANYQF == NORMQF */
-# define ANYQFL_LETTER 'q'
-#endif /* _FFR_QUARANTINE */
+#define ANYQFL_LETTER '?'
+#define QUARQF_LETTER 'h'
#define DATAFL_LETTER 'd'
#define XSCRPT_LETTER 'x'
#define NORMQF_LETTER 'q'
@@ -1873,15 +1880,11 @@ EXTERN unsigned long TLS_Srv_Opts; /* TLS server options */
#define QSO_BYFILENAME 3 /* sort by file name only */
#define QSO_RANDOM 4 /* sort in random order */
#define QSO_BYMODTIME 5 /* sort by modification time */
+#define QSO_NONE 6 /* do not sort */
#if _FFR_RHS
-# define QSO_BYSHUFFLE 6 /* sort by shuffled host name */
+# define QSO_BYSHUFFLE 7 /* sort by shuffled host name */
#endif /* _FFR_RHS */
-#if _FFR_QUEUEDELAY
-# define QD_LINEAR 0 /* linear (old) delay alg */
-# define QD_EXP 1 /* exponential delay alg */
-#endif /* _FFR_QUEUEDELAY */
-
#define NOQGRP (-1) /* no queue group (yet) */
#define ENVQGRP (-2) /* use queue group of envelope */
#define NOAQGRP (-3) /* no queue group in addr (yet) */
@@ -1898,13 +1901,12 @@ EXTERN unsigned long TLS_Srv_Opts; /* TLS server options */
#define SAFE_NO 0 /* no fsync(): don't use... */
#define SAFE_INTERACTIVE 1 /* limit fsync() in -odi */
#define SAFE_REALLY 2 /* always fsync() */
+#define SAFE_REALLY_POSTMILTER 3 /* fsync() if milter says OK */
-#if _FFR_QUARANTINE
/* QueueMode bits */
-# define QM_NORMAL ' '
-# define QM_QUARANTINE 'Q'
-# define QM_LOST 'L'
-#endif /* _FFR_QUARANTINE */
+#define QM_NORMAL ' '
+#define QM_QUARANTINE 'Q'
+#define QM_LOST 'L'
/* Queue Run Limitations */
struct queue_char
@@ -1931,22 +1933,13 @@ EXTERN int MaxRunnersPerQueue; /* max # proc's active in queue group */
EXTERN int NiceQueueRun; /* nice queue runs to this value */
EXTERN int NumQueue; /* number of queue groups */
EXTERN int QueueFileMode; /* mode on files in mail queue */
-#if _FFR_QUARANTINE
EXTERN int QueueMode; /* which queue items to act upon */
-#endif /* _FFR_QUARANTINE */
EXTERN int QueueSortOrder; /* queue sorting order algorithm */
EXTERN time_t MinQueueAge; /* min delivery interval */
EXTERN time_t QueueIntvl; /* intervals between running the queue */
EXTERN char *QueueDir; /* location of queue directory */
-#if _FFR_QUEUEDELAY
-EXTERN int QueueAlg; /* algorithm for queue delays */
-EXTERN time_t QueueInitDelay; /* initial queue delay */
-EXTERN time_t QueueMaxDelay; /* maximum queue delay */
-#endif /* _FFR_QUEUEDELAY */
EXTERN QUEUE_CHAR *QueueLimitId; /* limit queue run to id */
-#if _FFR_QUARANTINE
EXTERN QUEUE_CHAR *QueueLimitQuarantine; /* limit queue run to quarantine reason */
-#endif /* _FFR_QUARANTINE */
EXTERN QUEUE_CHAR *QueueLimitRecipient; /* limit queue run to rcpt */
EXTERN QUEUE_CHAR *QueueLimitSender; /* limit queue run to sender */
EXTERN QUEUEGRP *Queue[MAXQUEUEGROUPS + 1]; /* queue groups */
@@ -1961,9 +1954,7 @@ extern void loseqfile __P((ENVELOPE *, char *));
extern int name2qid __P((char *));
extern char *qid_printname __P((ENVELOPE *));
extern char *qid_printqueue __P((int, int));
-#if _FFR_QUARANTINE
extern void quarantine_queue __P((char *, int));
-#endif /* _FFR_QUARANTINE */
extern char *queuename __P((ENVELOPE *, int));
extern void queueup __P((ENVELOPE *, bool, bool));
extern bool runqueue __P((bool, bool, bool, bool));
@@ -2027,9 +2018,7 @@ EXTERN struct
#define TOC_NORMAL 0 /* normal delivery */
#define TOC_URGENT 1 /* urgent delivery */
#define TOC_NONURGENT 2 /* non-urgent delivery */
-#if _FFR_QUEUERETURN_DSN
-# define TOC_DSN 3 /* DSN delivery */
-#endif /* _FFR_QUEUERETURN_DSN */
+#define TOC_DSN 3 /* DSN delivery */
/* resolver timeout specifiers */
#define RES_TO_FIRST 0 /* first attempt */
@@ -2083,8 +2072,6 @@ extern unsigned char tTdvect[100]; /* trace vector */
ExitStat = s; \
}
-/* make a copy of a string */
-#define newstr(s) strcpy(xalloc(strlen(s) + 1), s)
#define STRUCTCOPY(s, d) d = s
@@ -2138,6 +2125,11 @@ extern unsigned char tTdvect[100]; /* trace vector */
# define CHECK_RESTART _CHECK_RESTART
+/* reply types (text in SmtpMsgBuffer) */
+#define XS_DEFAULT 0
+#define XS_STARTTLS 1
+#define XS_AUTH 2
+
/*
** Global variables.
*/
@@ -2169,10 +2161,9 @@ EXTERN bool NoAlias; /* suppress aliasing */
EXTERN bool NoConnect; /* don't connect to non-local mailers */
EXTERN bool OnlyOneError; /* .... or only want to give one SMTP reply */
EXTERN bool QuickAbort; /* .... but only if we want a quick abort */
-#if _FFR_REQ_DIR_FSYNC_OPT
+#if REQUIRES_DIR_FSYNC
EXTERN bool RequiresDirfsync; /* requires fsync() for directory */
-#endif /* _FFR_REQ_DIR_FSYNC_OPT */
-EXTERN bool ResNoAliases; /* don't use $HOSTALIASES */
+#endif /* REQUIRES_DIR_FSYNC */
EXTERN bool volatile RestartWorkGroup; /* daemon needs to restart some work groups */
EXTERN bool RrtImpliesDsn; /* turn Return-Receipt-To: into DSN */
EXTERN bool SaveFrom; /* save leading "From" lines */
@@ -2232,9 +2223,7 @@ EXTERN int NumFileSys; /* number of queue file systems */
EXTERN int QueueLA; /* load average starting forced queueing */
EXTERN int RefuseLA; /* load average refusing connections */
-#if _FFR_REJECT_LOG
EXTERN time_t RejectLogInterval; /* time btwn log msgs while refusing */
-#endif /* _FFR_REJECT_LOG */
EXTERN int SuperSafe; /* be extra careful, even if expensive */
EXTERN int VendorCode; /* vendor-specific operation enhancements */
EXTERN int Verbose; /* set if blow-by-blow desired */
@@ -2250,6 +2239,7 @@ EXTERN char *ShmKeyFile; /* shared memory key file */
#endif /* SM_CONF_SHM */
EXTERN pid_t CurrentPid; /* current process id */
EXTERN pid_t DaemonPid; /* process id of daemon */
+EXTERN pid_t PidFilePid; /* daemon/queue runner who wrote pid file */
EXTERN uid_t DefUid; /* default uid to run as */
EXTERN uid_t RealUid; /* real uid of caller */
EXTERN uid_t RunAsUid; /* UID to become for bulk of run */
@@ -2274,9 +2264,13 @@ EXTERN char *DefUser; /* default user to run as (from DefUid) */
EXTERN char *DefaultCharSet; /* default character set for MIME */
EXTERN char *DoubleBounceAddr; /* where to send double bounces */
EXTERN char *ErrMsgFile; /* file to prepend to all error messages */
-EXTERN char *FallBackMX; /* fall back MX host */
+EXTERN char *FallbackMX; /* fall back MX host */
+EXTERN char *FallbackSmartHost; /* fall back smart host */
EXTERN char *FileName; /* name to print on error messages */
EXTERN char *ForwardPath; /* path to search for .forward files */
+#if _FFR_HELONAME
+EXTERN char *HeloName; /* hostname to announce in HELO */
+#endif /* _FFR_HELONAME */
EXTERN char *HelpFile; /* location of SMTP help file */
EXTERN char *HostStatDir; /* location of host status information */
EXTERN char *HostsFile; /* path to /etc/hosts file */
@@ -2320,6 +2314,7 @@ EXTERN SOCKADDR RealHostAddr; /* address of host we are talking to */
extern const SM_EXC_TYPE_T EtypeQuickAbort; /* type of a QuickAbort exception */
+EXTERN int ConnectionRateWindowSize;
/*
** Declarations of useful functions
@@ -2355,7 +2350,7 @@ extern void PRINTFLIKE(3, 4) sm_syslog __P((int, const char *, const char *, ...
/* SMTP */
extern void giveresponse __P((int, char *, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *, ADDRESS *));
-extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)(), char **));
+extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)(), char **, int));
extern void smtp __P((char *volatile, BITMAP256, ENVELOPE *volatile));
#if SASL
extern int smtpauth __P((MAILER *, MCI *, ENVELOPE *));
@@ -2386,9 +2381,7 @@ extern void sendall __P((ENVELOPE *, int));
/* stats */
#define STATS_NORMAL 'n'
-#if _FFR_QUARANTINE
-# define STATS_QUARANTINE 'q'
-#endif /* _FFR_QUARANTINE */
+#define STATS_QUARANTINE 'q'
#define STATS_REJECT 'r'
#define STATS_CONNECT 'c'
@@ -2414,8 +2407,10 @@ extern void milter_abort __P((ENVELOPE *));
extern char *milter_connect __P((char *, SOCKADDR, ENVELOPE *, char *));
extern char *milter_helo __P((char *, ENVELOPE *, char *));
extern char *milter_envfrom __P((char **, ENVELOPE *, char *));
+extern char *milter_data_cmd __P((ENVELOPE *, char *));
extern char *milter_envrcpt __P((char **, ENVELOPE *, char *));
extern char *milter_data __P((ENVELOPE *, char *));
+extern char *milter_unknown __P((char *, ENVELOPE *, char *));
#endif /* MILTER */
extern char *addquotes __P((char *, SM_RPOOL_T *));
@@ -2441,14 +2436,18 @@ extern void cleanstrcpy __P((char *, char *, int));
#if SM_CONF_SHM
extern void cleanup_shm __P((bool));
#endif /* SM_CONF_SHM */
+extern void close_sendmail_pid __P((void));
extern void clrdaemon __P((void));
extern void collect __P((SM_FILE_T *, bool, HDR **, ENVELOPE *, bool));
+extern bool connection_rate_check __P((SOCKADDR *, ENVELOPE *));
extern time_t convtime __P((char *, int));
extern char **copyplist __P((char **, bool, SM_RPOOL_T *));
extern void copy_class __P((int, int));
+extern int count_open_connections __P((SOCKADDR *));
extern time_t curtime __P((void));
extern char *defcharset __P((ENVELOPE *));
extern char *denlstring __P((char *, bool, bool));
+extern void dferror __P((SM_FILE_T *volatile, char *, ENVELOPE *));
extern void disconnect __P((int, ENVELOPE *));
#if _FFR_CONTROL_MSTAT
extern void disk_status __P((SM_FILE_T *, char *));
@@ -2500,14 +2499,15 @@ extern void makeworkgroups __P((void));
extern void mark_work_group_restart __P((int, int));
extern char * munchstring __P((char *, char **, int));
extern struct hostent *myhostname __P((char *, int));
+extern char *newstr __P((const char *));
#if NISPLUS
extern char *nisplus_default_domain __P((void)); /* extern for Sun */
#endif /* NISPLUS */
extern bool path_is_dir __P((char *, bool));
extern int pickqdir __P((QUEUEGRP *qg, long fsize, ENVELOPE *e));
extern char *pintvl __P((time_t, bool));
-extern void printav __P((char **));
-extern void printmailer __P((MAILER *));
+extern void printav __P((SM_FILE_T *, char **));
+extern void printmailer __P((SM_FILE_T *, MAILER *));
extern void printnqe __P((SM_FILE_T *, char *));
extern void printopenfds __P((bool));
extern void printqueue __P((void));
@@ -2541,6 +2541,8 @@ extern char *shortenstring __P((const char *, size_t));
extern char *shorten_hostname __P((char []));
extern bool shorten_rfc822_string __P((char *, size_t));
extern void shutdown_daemon __P((void));
+extern void sm_closefrom __P((int lowest, int highest));
+extern void sm_close_on_exec __P((int lowest, int highest));
extern struct hostent *sm_gethostbyname __P((char *, int));
extern struct hostent *sm_gethostbyaddr __P((char *, int, int));
extern void sm_getla __P((void));
@@ -2551,9 +2553,7 @@ extern pid_t sm_wait __P((int *));
extern bool split_by_recipient __P((ENVELOPE *e));
extern void stop_sendmail __P((void));
extern char *str2prt __P((char *));
-#if _FFR_STRIPBACKSL
extern void stripbackslash __P((char *));
-#endif /* _FFR_STRIPBACKSL */
extern bool strreplnonprt __P((char *, int));
extern bool strcontainedin __P((bool, char *, char *));
extern int switch_map_find __P((char *, char *[], short []));
@@ -2590,7 +2590,7 @@ extern char *xalloc_tagged __P((int, char*, int));
#else /* SM_HEAP_CHECK */
extern char *xalloc __P((int));
#endif /* SM_HEAP_CHECK */
-extern void xputs __P((const char *));
+extern void xputs __P((SM_FILE_T *, const char *));
extern char *xtextify __P((char *, char *));
extern bool xtextok __P((char *));
extern int xunlink __P((char *));
diff --git a/contrib/sendmail/src/sfsasl.c b/contrib/sendmail/src/sfsasl.c
index 48afb9a..ab8aca3 100644
--- a/contrib/sendmail/src/sfsasl.c
+++ b/contrib/sendmail/src/sfsasl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -9,7 +9,7 @@
*/
#include <sm/gen.h>
-SM_RCSID("@(#)$Id: sfsasl.c,v 8.91.2.5 2003/08/08 17:30:11 ca Exp $")
+SM_RCSID("@(#)$Id: sfsasl.c,v 8.98 2004/03/03 19:20:31 ca Exp $")
#include <stdlib.h>
#include <sendmail.h>
#include <errno.h>
@@ -349,16 +349,16 @@ sfdcsasl(fin, fout, conn)
SM_TIME_FOREVER);
info.fp = *fin;
info.conn = conn;
- newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY,
- NULL);
+ newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
+ SM_IO_RDONLY_B, NULL);
if (newin == NULL)
return -1;
info.fp = *fout;
info.conn = conn;
- newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY,
- NULL);
+ newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
+ SM_IO_WRONLY_B, NULL);
if (newout == NULL)
{
@@ -750,13 +750,13 @@ sfdctls(fin, fout, con)
SM_TIME_FOREVER);
info.fp = *fin;
info.con = con;
- tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY,
+ tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
NULL);
if (tlsin == NULL)
return -1;
info.fp = *fout;
- tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY,
+ tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
NULL);
if (tlsout == NULL)
{
diff --git a/contrib/sendmail/src/sm_resolve.c b/contrib/sendmail/src/sm_resolve.c
index 8828fd1..d788d00 100644
--- a/contrib/sendmail/src/sm_resolve.c
+++ b/contrib/sendmail/src/sm_resolve.c
@@ -46,7 +46,7 @@
# if NAMED_BIND
# include "sm_resolve.h"
-SM_RCSID("$Id: sm_resolve.c,v 8.24.4.7 2003/03/22 22:55:37 ca Exp $")
+SM_RCSID("$Id: sm_resolve.c,v 8.32 2003/03/22 22:57:26 ca Exp $")
static struct stot
{
diff --git a/contrib/sendmail/src/srvrsmtp.c b/contrib/sendmail/src/srvrsmtp.c
index e752aa0..cb0366e 100644
--- a/contrib/sendmail/src/srvrsmtp.c
+++ b/contrib/sendmail/src/srvrsmtp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,13 +13,16 @@
#include <sendmail.h>
#if MILTER
+# include <libmilter/mfapi.h>
# include <libmilter/mfdef.h>
#endif /* MILTER */
-SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.829.2.34 2004/01/14 19:13:46 ca Exp $")
+SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.900 2004/07/08 23:29:33 ca Exp $")
+
+#include <sys/time.h>
+#include <sm/fdset.h>
#if SASL || STARTTLS
-# include <sys/time.h>
# include "sfsasl.h"
#endif /* SASL || STARTTLS */
#if SASL
@@ -56,12 +59,14 @@ extern void tls_set_verify __P((SSL_CTX *, SSL *, bool));
# endif /* _FFR_NO_PIPE */
#endif /* PIPELINING */
#define SRV_REQ_AUTH 0x0400 /* require AUTH */
+#define SRV_REQ_SEC 0x0800 /* require security - equiv to AuthOptions=p */
#define SRV_TMP_FAIL 0x1000 /* ruleset caused a temporary failure */
static unsigned int srvfeatures __P((ENVELOPE *, char *, unsigned int));
-static time_t checksmtpattack __P((volatile unsigned int *, int, bool,
- char *, ENVELOPE *));
+#define STOP_ATTACK ((time_t) -1)
+static time_t checksmtpattack __P((volatile unsigned int *, unsigned int,
+ bool, char *, ENVELOPE *));
static void mail_esmtp_args __P((char *, char *, ENVELOPE *));
static void printvrfyaddr __P((ADDRESS *, bool, bool));
static void rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *));
@@ -75,7 +80,7 @@ static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
char *_auth_id, sasl_ssf_t *_ext_ssf));
# define RESET_SASLCONN \
- result = reset_saslconn(&conn, hostname, remoteip, localip, auth_id, \
+ result = reset_saslconn(&conn, AuthRealm, remoteip, localip, auth_id, \
&ext_ssf); \
if (result != SASL_OK) \
{ \
@@ -89,7 +94,7 @@ static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
struct sockaddr_in *_saddr_l,
sasl_external_properties_t *_ext_ssf));
# define RESET_SASLCONN \
- result = reset_saslconn(&conn, hostname, &saddr_r, &saddr_l, &ext_ssf); \
+ result = reset_saslconn(&conn, AuthRealm, &saddr_r, &saddr_l, &ext_ssf); \
if (result != SASL_OK) \
{ \
/* This is pretty fatal */ \
@@ -101,6 +106,16 @@ static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
extern ENVELOPE BlankEnvelope;
+#define NBADRCPTS \
+ do \
+ { \
+ char buf[16]; \
+ (void) sm_snprintf(buf, sizeof buf, "%d", \
+ BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
+ ? n_badrcpts - 1 : n_badrcpts); \
+ macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
+ } while (0)
+
#define SKIP_SPACE(s) while (isascii(*s) && isspace(*s)) \
(s)++
@@ -221,6 +236,31 @@ static char *CurSmtpClient; /* who's at the other end of channel */
# define MAXTIMEOUT (4 * 60) /* max timeout for bad commands */
#endif /* ! MAXTIMEOUT */
+/*
+** Maximum shift value to compute timeout for bad commands.
+** This introduces an upper limit of 2^MAXSHIFT for the timeout.
+*/
+
+#ifndef MAXSHIFT
+# define MAXSHIFT 8
+#endif /* ! MAXSHIFT */
+#if MAXSHIFT > 31
+ ERROR _MAXSHIFT > 31 is invalid
+#endif /* MAXSHIFT */
+
+
+#if MAXBADCOMMANDS > 0
+# define STOP_IF_ATTACK(r) do \
+ { \
+ if ((r) == STOP_ATTACK) \
+ goto stopattack; \
+ } while (0)
+
+#else /* MAXBADCOMMANDS > 0 */
+# define STOP_IF_ATTACK(r) r
+#endif /* MAXBADCOMMANDS > 0 */
+
+
#if SM_HEAP_CHECK
static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp",
"@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $");
@@ -230,38 +270,21 @@ typedef struct
{
bool sm_gotmail; /* mail command received */
unsigned int sm_nrcpts; /* number of successful RCPT commands */
-#if _FFR_ADAPTIVE_EOL
-WARNING: do NOT use this FFR, it is most likely broken
- bool sm_crlf; /* input in CRLF form? */
-#endif /* _FFR_ADAPTIVE_EOL */
bool sm_discard;
#if MILTER
bool sm_milterize;
bool sm_milterlist; /* any filters in the list? */
#endif /* MILTER */
-#if _FFR_QUARANTINE
char *sm_quarmsg; /* carry quarantining across messages */
-#endif /* _FFR_QUARANTINE */
} SMTP_T;
-static void smtp_data __P((SMTP_T *, ENVELOPE *));
+static bool smtp_data __P((SMTP_T *, ENVELOPE *));
-#define MSG_TEMPFAIL "451 4.7.1 Please try again later"
+#define MSG_TEMPFAIL "451 4.3.2 Please try again later"
#if MILTER
# define MILTER_ABORT(e) milter_abort((e))
-#if _FFR_MILTER_421
-# define MILTER_SHUTDOWN \
- if (strncmp(response, "421 ", 4) == 0) \
- { \
- e->e_sendqueue = NULL; \
- goto doquit; \
- }
-#else /* _FFR_MILTER_421 */
-# define MILTER_SHUTDOWN
-#endif /* _FFR_MILTER_421 */
-
# define MILTER_REPLY(str) \
{ \
int savelogusrerrs = LogUsrErrs; \
@@ -276,8 +299,18 @@ static void smtp_data __P((SMTP_T *, ENVELOPE *));
str, addr, response); \
LogUsrErrs = false; \
} \
- usrerr(response); \
- MILTER_SHUTDOWN \
+ if (strncmp(response, "421 ", 4) == 0) \
+ { \
+ bool tsave = QuickAbort; \
+ \
+ QuickAbort = false; \
+ usrerr(response); \
+ QuickAbort = tsave; \
+ e->e_sendqueue = NULL; \
+ goto doquit; \
+ } \
+ else \
+ usrerr(response); \
break; \
\
case SMFIR_REJECT: \
@@ -321,6 +354,7 @@ static void smtp_data __P((SMTP_T *, ENVELOPE *));
/* clear all SMTP state (for HELO/EHLO/RSET) */
#define CLEAR_STATE(cmd) \
+do \
{ \
/* abort milter filters */ \
MILTER_ABORT(e); \
@@ -347,7 +381,26 @@ static void smtp_data __P((SMTP_T *, ENVELOPE *));
sm_rpool_free(e->e_rpool); \
e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL)); \
CurEnv = e; \
-}
+ \
+ /* put back discard bit */ \
+ if (smtp.sm_discard) \
+ e->e_flags |= EF_DISCARD; \
+ \
+ /* restore connection quarantining */ \
+ if (smtp.sm_quarmsg == NULL) \
+ { \
+ e->e_quarmsg = NULL; \
+ macdefine(&e->e_macro, A_PERM, \
+ macid("{quarantine}"), ""); \
+ } \
+ else \
+ { \
+ e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, \
+ smtp.sm_quarmsg); \
+ macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), \
+ e->e_quarmsg); \
+ } \
+} while (0)
/* sleep to flatten out connection load */
#define MIN_DELAY_LOG 15 /* wait before logging this again */
@@ -401,9 +454,9 @@ smtp(nullserver, d_flags, e)
volatile unsigned int n_helo = 0; /* count of HELO/EHLO */
volatile int save_sevenbitinput;
bool ok;
-#if _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL
+#if _FFR_BLOCK_PROXIES
volatile bool first;
-#endif /* _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL */
+#endif /* _FFR_BLOCK_PROXIES */
volatile bool tempfail = false;
volatile time_t wt; /* timeout after too many commands */
volatile time_t previous; /* time after checksmtpattack() */
@@ -448,13 +501,12 @@ smtp(nullserver, d_flags, e)
volatile unsigned int n_mechs;
unsigned int len;
#endif /* SASL */
-#if STARTTLS
int r;
+#if STARTTLS
+ int fdfl;
int rfd, wfd;
volatile bool tls_active = false;
-# if _FFR_SMTP_SSL
- volatile bool smtps = false;
-# endif /* _FFR_SMTP_SSL */
+ volatile bool smtps = bitnset(D_SMTPS, d_flags);
bool saveQuickAbort;
bool saveSuprErrs;
time_t tlsstart;
@@ -521,6 +573,8 @@ smtp(nullserver, d_flags, e)
: SRV_OFFER_DSN)
#if SASL
| (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH)
+ | (bitset(SASL_SEC_NOPLAINTEXT, SASLOpts) ? SRV_REQ_SEC
+ : SRV_NONE)
#endif /* SASL */
#if PIPELINING
| SRV_OFFER_PIPE
@@ -542,19 +596,35 @@ smtp(nullserver, d_flags, e)
CurSmtpClient);
nullserver = "450 4.3.0 Please try again later.";
}
+ else
+ {
#if PIPELINING
# if _FFR_NO_PIPE
- else if (bitset(SRV_NO_PIPE, features))
- {
- /* for consistency */
- features &= ~SRV_OFFER_PIPE;
- }
+ if (bitset(SRV_NO_PIPE, features))
+ {
+ /* for consistency */
+ features &= ~SRV_OFFER_PIPE;
+ }
# endif /* _FFR_NO_PIPE */
#endif /* PIPELINING */
+#if SASL
+ if (bitset(SRV_REQ_SEC, features))
+ SASLOpts |= SASL_SEC_NOPLAINTEXT;
+ else
+ SASLOpts &= ~SASL_SEC_NOPLAINTEXT;
+#endif /* SASL */
+ }
+ }
+ else if (strncmp(nullserver, "421 ", 4) == 0)
+ {
+ message(nullserver);
+ goto doquit;
}
hostname = macvalue('j', e);
#if SASL
+ if (AuthRealm == NULL)
+ AuthRealm = hostname;
sasl_ok = bitset(SRV_OFFER_AUTH, features);
n_mechs = 0;
authenticating = SASL_NOT_AUTH;
@@ -563,14 +633,14 @@ smtp(nullserver, d_flags, e)
if (sasl_ok)
{
# if SASL >= 20000
- result = sasl_server_new("smtp", hostname, NULL, NULL, NULL,
+ result = sasl_server_new("smtp", AuthRealm, NULL, NULL, NULL,
NULL, 0, &conn);
# elif SASL > 10505
/* use empty realm: only works in SASL > 1.5.5 */
- result = sasl_server_new("smtp", hostname, "", NULL, 0, &conn);
+ result = sasl_server_new("smtp", AuthRealm, "", NULL, 0, &conn);
# else /* SASL >= 20000 */
/* use no realm -> realm is set to hostname by SASL lib */
- result = sasl_server_new("smtp", hostname, NULL, NULL, 0,
+ result = sasl_server_new("smtp", AuthRealm, NULL, NULL, 0,
&conn);
# endif /* SASL >= 20000 */
sasl_ok = result == SASL_OK;
@@ -775,7 +845,6 @@ smtp(nullserver, d_flags, e)
smtp.sm_milterize = false;
break;
-#if _FFR_MILTER_421
case SMFIR_SHUTDOWN:
if (MilterLogLevel > 3)
sm_syslog(LOG_INFO, e->e_id,
@@ -790,18 +859,75 @@ smtp(nullserver, d_flags, e)
/* arrange to ignore send list */
e->e_sendqueue = NULL;
goto doquit;
-#endif /* _FFR_MILTER_421 */
}
if (response != NULL)
-
sm_free(response); /* XXX */
}
#endif /* MILTER */
+ /*
+ ** Broken proxies and SMTP slammers
+ ** push data without waiting, catch them
+ */
+
+ if (
+#if STARTTLS
+ !smtps &&
+#endif /* STARTTLS */
+ *greetcode == '2')
+ {
+ time_t msecs = 0;
+ char **pvp;
+ char pvpbuf[PSBUFSIZE];
+
+ /* Ask the rulesets how long to pause */
+ pvp = NULL;
+ r = rscap("greet_pause", peerhostname,
+ anynet_ntoa(&RealHostAddr), e,
+ &pvp, pvpbuf, sizeof(pvpbuf));
+ if (r == EX_OK && pvp != NULL && pvp[0] != NULL &&
+ (pvp[0][0] & 0377) == CANONNET && pvp[1] != NULL)
+ {
+ msecs = strtol(pvp[1], NULL, 10);
+ }
+
+ if (msecs > 0)
+ {
+ int fd;
+ fd_set readfds;
+ struct timeval timeout;
+
+ /* pause for a moment */
+ timeout.tv_sec = msecs / 1000;
+ timeout.tv_usec = (msecs % 1000) * 1000;
+
+ /* Obey RFC 2821: 4.3.5.2: 220 timeout of 5 minutes */
+ if (timeout.tv_sec >= 300)
+ {
+ timeout.tv_sec = 300;
+ timeout.tv_usec = 0;
+ }
+
+ /* check if data is on the socket during the pause */
+ fd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
+ FD_ZERO(&readfds);
+ SM_FD_SET(fd, &readfds);
+ if (select(fd + 1, FDSET_CAST &readfds,
+ NULL, NULL, &timeout) > 0 &&
+ FD_ISSET(fd, &readfds))
+ {
+ greetcode = "554";
+ nullserver = "Command rejected";
+ sm_syslog(LOG_INFO, e->e_id,
+ "rejecting commands from %s [%s] due to pre-greeting traffic",
+ peerhostname,
+ anynet_ntoa(&RealHostAddr));
+ }
+ }
+ }
+
#if STARTTLS
-# if _FFR_SMTP_SSL
/* If this an smtps connection, start TLS now */
- smtps = bitnset(D_SMTPS, d_flags);
if (smtps)
{
Errors = 0;
@@ -810,7 +936,6 @@ smtp(nullserver, d_flags, e)
greeting:
-# endif /* _FFR_SMTP_SSL */
#endif /* STARTTLS */
/* output the first line, inserting "ESMTP" as second word */
@@ -854,20 +979,18 @@ smtp(nullserver, d_flags, e)
protocol = NULL;
sendinghost = macvalue('s', e);
-#if _FFR_QUARANTINE
/* If quarantining by a connect/ehlo action, save between messages */
if (e->e_quarmsg == NULL)
smtp.sm_quarmsg = NULL;
else
smtp.sm_quarmsg = newstr(e->e_quarmsg);
-#endif /* _FFR_QUARANTINE */
/* sendinghost's storage must outlive the current envelope */
if (sendinghost != NULL)
sendinghost = sm_strdup_x(sendinghost);
-#if _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL
+#if _FFR_BLOCK_PROXIES
first = true;
-#endif /* _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL */
+#endif /* _FFR_BLOCK_PROXIES */
gothello = false;
smtp.sm_gotmail = false;
for (;;)
@@ -932,10 +1055,9 @@ smtp(nullserver, d_flags, e)
goto doquit;
}
-#if _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL
+#if _FFR_BLOCK_PROXIES
if (first)
{
-#if _FFR_BLOCK_PROXIES
size_t inplen, cmdlen;
int idx;
char *http_cmd;
@@ -960,27 +1082,9 @@ smtp(nullserver, d_flags, e)
goto doquit;
}
}
-#endif /* _FFR_BLOCK_PROXIES */
-#if _FFR_ADAPTIVE_EOL
- char *p;
-
- smtp.sm_crlf = true;
- p = strchr(inp, '\n');
- if (p == NULL || p <= inp || p[-1] != '\r')
- {
- smtp.sm_crlf = false;
- if (tTd(66, 1) && LogLevel > 8)
- {
- /* how many bad guys are there? */
- sm_syslog(LOG_INFO, NOQID,
- "%s did not use CRLF",
- CurSmtpClient);
- }
- }
-#endif /* _FFR_ADAPTIVE_EOL */
first = false;
}
-#endif /* _FFR_BLOCK_PROXIES || _FFR_ADAPTIVE_EOL */
+#endif /* _FFR_BLOCK_PROXIES */
/* clean up end of line */
fixcrlf(inp, true);
@@ -1090,7 +1194,8 @@ smtp(nullserver, d_flags, e)
{
macdefine(&BlankEnvelope.e_macro,
A_TEMP,
- macid("{auth_authen}"), user);
+ macid("{auth_authen}"),
+ xtextify(user, "<>\")"));
}
# if 0
@@ -1353,15 +1458,15 @@ smtp(nullserver, d_flags, e)
sm_syslog(LOG_INFO, e->e_id,
"SMTP AUTH command (%.100s) from %s tempfailed (due to previous checks)",
p, CurSmtpClient);
- usrerr("454 4.7.1 Please try again later");
+ usrerr("454 4.3.0 Please try again later");
break;
}
ismore = false;
/* crude way to avoid crack attempts */
- (void) checksmtpattack(&n_auth, n_mechs + 1, true,
- "AUTH", e);
+ STOP_IF_ATTACK(checksmtpattack(&n_auth, n_mechs + 1,
+ true, "AUTH", e));
/* make sure mechanism (p) is a valid string */
for (q = p; *q != '\0' && isascii(*q); q++)
@@ -1524,12 +1629,10 @@ smtp(nullserver, d_flags, e)
sm_syslog(LOG_INFO, e->e_id,
"SMTP STARTTLS command (%.100s) from %s tempfailed (due to previous checks)",
p, CurSmtpClient);
- usrerr("454 4.7.1 Please try again later");
+ usrerr("454 4.7.0 Please try again later");
break;
}
-# if _FFR_SMTP_SSL
starttls:
-# endif /* _FFR_SMTP_SSL */
# if TLS_NO_RSA
/*
** XXX do we need a temp key ?
@@ -1554,11 +1657,7 @@ smtp(nullserver, d_flags, e)
message("454 4.3.3 TLS not available: error generating SSL handle");
if (LogLevel > 8)
tlslogerr("server");
-# if _FFR_SMTP_SSL
goto tls_done;
-# else /* _FFR_SMTP_SSL */
- break;
-# endif /* _FFR_SMTP_SSL */
}
# if !TLS_VRFY_PER_CTX
@@ -1581,15 +1680,9 @@ smtp(nullserver, d_flags, e)
message("454 4.3.3 TLS not available: error set fd");
SSL_free(srv_ssl);
srv_ssl = NULL;
-# if _FFR_SMTP_SSL
goto tls_done;
-# else /* _FFR_SMTP_SSL */
- break;
-# endif /* _FFR_SMTP_SSL */
}
-# if _FFR_SMTP_SSL
if (!smtps)
-# endif /* _FFR_SMTP_SSL */
message("220 2.0.0 Ready to start TLS");
# if PIPELINING
(void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
@@ -1600,6 +1693,9 @@ smtp(nullserver, d_flags, e)
# define SSL_ACC(s) SSL_accept(s)
tlsstart = curtime();
+ fdfl = fcntl(rfd, F_GETFL);
+ if (fdfl != -1)
+ fcntl(rfd, F_SETFL, fdfl|O_NONBLOCK);
ssl_retry:
if ((r = SSL_ACC(srv_ssl)) <= 0)
{
@@ -1702,6 +1798,9 @@ tlsfail:
goto doquit;
}
+ if (fdfl != -1)
+ fcntl(rfd, F_SETFL, fdfl);
+
/* ignore return code for now, it's in {verify} */
(void) tls_get_info(srv_ssl, true,
CurSmtpClient,
@@ -1739,25 +1838,31 @@ tlsfail:
# if SASL
if (sasl_ok)
{
- char *s;
+ int cipher_bits;
+ bool verified;
+ char *s, *v, *c;
s = macvalue(macid("{cipher_bits}"), e);
-# if SASL >= 20000
- if (s != NULL && (ext_ssf = atoi(s)) > 0)
+ v = macvalue(macid("{verify}"), e);
+ c = macvalue(macid("{cert_subject}"), e);
+ verified = (v != NULL && strcmp(v, "OK") == 0);
+ if (s != NULL && (cipher_bits = atoi(s)) > 0)
{
- auth_id = macvalue(macid("{cert_subject}"),
- e);
- sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL,
- &ext_ssf) == SASL_OK) &&
- (sasl_setprop(conn, SASL_AUTH_EXTERNAL,
- auth_id) == SASL_OK));
+# if SASL >= 20000
+ ext_ssf = cipher_bits;
+ auth_id = verified ? c : NULL;
+ sasl_ok = ((sasl_setprop(conn,
+ SASL_SSF_EXTERNAL,
+ &ext_ssf) == SASL_OK) &&
+ (sasl_setprop(conn,
+ SASL_AUTH_EXTERNAL,
+ auth_id) == SASL_OK));
# else /* SASL >= 20000 */
- if (s != NULL && (ext_ssf.ssf = atoi(s)) > 0)
- {
- ext_ssf.auth_id = macvalue(macid("{cert_subject}"),
- e);
- sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL,
- &ext_ssf) == SASL_OK;
+ ext_ssf.ssf = cipher_bits;
+ ext_ssf.auth_id = verified ? c : NULL;
+ sasl_ok = sasl_setprop(conn,
+ SASL_SSF_EXTERNAL,
+ &ext_ssf) == SASL_OK;
# endif /* SASL >= 20000 */
mechlist = NULL;
if (sasl_ok)
@@ -1789,7 +1894,6 @@ tlsfail:
nullserver = "454 4.3.3 TLS not available: can't switch to encrypted layer";
syserr("STARTTLS: can't switch to encrypted layer");
}
-# if _FFR_SMTP_SSL
tls_done:
if (smtps)
{
@@ -1798,7 +1902,6 @@ tlsfail:
else
goto doquit;
}
-# endif /* _FFR_SMTP_SSL */
break;
#endif /* STARTTLS */
@@ -1817,8 +1920,8 @@ tlsfail:
}
/* avoid denial-of-service */
- (void) checksmtpattack(&n_helo, MAXHELOCOMMANDS, true,
- "HELO/EHLO", e);
+ STOP_IF_ATTACK(checksmtpattack(&n_helo, MAXHELOCOMMANDS,
+ true, "HELO/EHLO", e));
#if 0
/* RFC2821 4.1.4 allows duplicate HELO/EHLO */
@@ -1891,24 +1994,6 @@ tlsfail:
if (gothello)
{
CLEAR_STATE(cmdbuf);
-
-#if _FFR_QUARANTINE
- /* restore connection quarantining */
- if (smtp.sm_quarmsg == NULL)
- {
- e->e_quarmsg = NULL;
- macdefine(&e->e_macro, A_PERM,
- macid("{quarantine}"), "");
- }
- else
- {
- e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
- smtp.sm_quarmsg);
- macdefine(&e->e_macro, A_PERM,
- macid("{quarantine}"),
- e->e_quarmsg);
- }
-#endif /* _FFR_QUARANTINE */
}
#if MILTER
@@ -1951,7 +2036,6 @@ tlsfail:
if (response != NULL)
sm_free(response);
-# if _FFR_QUARANTINE
/*
** If quarantining by a connect/ehlo action,
** save between messages
@@ -1960,7 +2044,6 @@ tlsfail:
if (smtp.sm_quarmsg == NULL &&
e->e_quarmsg != NULL)
smtp.sm_quarmsg = newstr(e->e_quarmsg);
-# endif /* _FFR_QUARANTINE */
}
#endif /* MILTER */
gothello = true;
@@ -2113,6 +2196,8 @@ tlsfail:
n_badrcpts = 0;
macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0");
macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0");
+ macdefine(&e->e_macro, A_PERM, macid("{nbadrcpts}"),
+ "0");
e->e_flags |= EF_CLRQUEUE;
sm_setproctitle(true, e, "%s %s: %.80s",
qid_printname(e),
@@ -2352,6 +2437,7 @@ tlsfail:
/* To avoid duplicated message */
n_badrcpts++;
}
+ NBADRCPTS;
/*
** Don't use exponential backoff for now.
@@ -2556,20 +2642,25 @@ tlsfail:
}
rcpt_done:
if (Errors > 0)
+ {
++n_badrcpts;
+ NBADRCPTS;
+ }
}
SM_EXCEPT(exc, "[!F]*")
{
/* An exception occurred while processing RCPT */
e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
++n_badrcpts;
+ NBADRCPTS;
}
SM_END_TRY
break;
case CMDDATA: /* data -- text of mail */
DELAY_CONN("DATA");
- smtp_data(&smtp, e);
+ if (!smtp_data(&smtp, e))
+ goto doquit;
break;
case CMDRSET: /* rset -- reset state */
@@ -2578,22 +2669,6 @@ tlsfail:
else
message("250 2.0.0 Reset state");
CLEAR_STATE(cmdbuf);
-#if _FFR_QUARANTINE
- /* restore connection quarantining */
- if (smtp.sm_quarmsg == NULL)
- {
- e->e_quarmsg = NULL;
- macdefine(&e->e_macro, A_PERM,
- macid("{quarantine}"), "");
- }
- else
- {
- e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
- smtp.sm_quarmsg);
- macdefine(&e->e_macro, A_PERM,
- macid("{quarantine}"), e->e_quarmsg);
- }
-#endif /* _FFR_QUARANTINE */
break;
case CMDVRFY: /* vrfy -- verify address */
@@ -2614,6 +2689,7 @@ tlsfail:
}
wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS,
false, vrfy ? "VRFY" : "EXPN", e);
+ STOP_IF_ATTACK(wt);
previous = curtime();
if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) ||
(!vrfy && !bitset(SRV_OFFER_EXPN, features)))
@@ -2741,8 +2817,8 @@ tlsfail:
}
/* crude way to avoid denial-of-service attacks */
- (void) checksmtpattack(&n_etrn, MAXETRNCOMMANDS, true,
- "ETRN", e);
+ STOP_IF_ATTACK(checksmtpattack(&n_etrn, MAXETRNCOMMANDS,
+ true, "ETRN", e));
/*
** Do config file checking of the parameter.
@@ -2817,8 +2893,8 @@ tlsfail:
case CMDNOOP: /* noop -- do nothing */
DELAY_CONN("NOOP");
- (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, true,
- "NOOP", e);
+ STOP_IF_ATTACK(checksmtpattack(&n_noop, MAXNOOPCOMMANDS,
+ true, "NOOP", e));
message("250 2.0.0 OK");
break;
@@ -2900,8 +2976,8 @@ doquit:
message("502 5.7.0 Verbose unavailable");
break;
}
- (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, true,
- "VERB", e);
+ STOP_IF_ATTACK(checksmtpattack(&n_noop, MAXNOOPCOMMANDS,
+ true, "VERB", e));
Verbose = 1;
set_delivery_mode(SM_DELIVER, e);
message("250 2.0.0 Verbose mode");
@@ -2911,7 +2987,7 @@ doquit:
case CMDDBGQSHOW: /* show queues */
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Send Queue=");
- printaddr(e->e_sendqueue, true);
+ printaddr(smioout, e->e_sendqueue, true);
break;
case CMDDBGDEBUG: /* set debug mode */
@@ -2937,6 +3013,7 @@ doquit:
#if MAXBADCOMMANDS > 0
if (++n_badcmds > MAXBADCOMMANDS)
{
+ stopattack:
message("421 4.7.0 %s Too many bad commands; closing connection",
MyHostName);
@@ -2946,6 +3023,28 @@ doquit:
}
#endif /* MAXBADCOMMANDS > 0 */
+#if MILTER && SMFI_VERSION > 2
+ if (smtp.sm_milterlist && smtp.sm_milterize &&
+ !bitset(EF_DISCARD, e->e_flags))
+ {
+ char state;
+ char *response;
+
+ if (MilterLogLevel > 9)
+ sm_syslog(LOG_INFO, e->e_id,
+ "Sending \"%s\" to Milter", inp);
+ response = milter_unknown(inp, e, &state);
+ MILTER_REPLY("unknown");
+ if (state == SMFIR_REPLYCODE ||
+ state == SMFIR_REJECT ||
+ state == SMFIR_TEMPFAIL)
+ {
+ /* MILTER_REPLY already gave an error */
+ break;
+ }
+ }
+#endif /* MILTER && SMFI_VERSION > 2 */
+
usrerr("500 5.5.1 Command unrecognized: \"%s\"",
shortenstring(inp, MAXSHORTSTR));
break;
@@ -2984,13 +3083,13 @@ doquit:
** e -- envelope.
**
** Returns:
-** none.
+** true iff SMTP session can continue.
**
** Side Effects:
** possibly sends message.
*/
-static void
+static bool
smtp_data(smtp, e)
SMTP_T *smtp;
ENVELOPE *e;
@@ -3010,18 +3109,79 @@ smtp_data(smtp, e)
if (!smtp->sm_gotmail)
{
usrerr("503 5.0.0 Need MAIL command");
- return;
+ return true;
}
else if (smtp->sm_nrcpts <= 0)
{
usrerr("503 5.0.0 Need RCPT (recipient)");
- return;
+ return true;
}
(void) sm_snprintf(buf, sizeof buf, "%u", smtp->sm_nrcpts);
if (rscheck("check_data", buf, NULL, e,
RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL,
e->e_id) != EX_OK)
- return;
+ return true;
+
+#if MILTER && SMFI_VERSION > 3
+ if (smtp->sm_milterlist && smtp->sm_milterize &&
+ !bitset(EF_DISCARD, e->e_flags))
+ {
+ char state;
+ char *response;
+ int savelogusrerrs = LogUsrErrs;
+
+ response = milter_data_cmd(e, &state);
+ switch (state)
+ {
+ case SMFIR_REPLYCODE:
+ if (MilterLogLevel > 3)
+ {
+ sm_syslog(LOG_INFO, e->e_id,
+ "Milter: cmd=data, reject=%s",
+ response);
+ LogUsrErrs = false;
+ }
+ usrerr(response);
+ if (strncmp(response, "421 ", 4) == 0)
+ {
+ e->e_sendqueue = NULL;
+ return false;
+ }
+ return true;
+
+ case SMFIR_REJECT:
+ if (MilterLogLevel > 3)
+ {
+ sm_syslog(LOG_INFO, e->e_id,
+ "Milter: cmd=data, reject=550 5.7.1 Command rejected");
+ LogUsrErrs = false;
+ }
+ usrerr("550 5.7.1 Command rejected");
+ return true;
+
+ case SMFIR_DISCARD:
+ if (MilterLogLevel > 3)
+ sm_syslog(LOG_INFO, e->e_id,
+ "Milter: cmd=data, discard");
+ e->e_flags |= EF_DISCARD;
+ break;
+
+ case SMFIR_TEMPFAIL:
+ if (MilterLogLevel > 3)
+ {
+ sm_syslog(LOG_INFO, e->e_id,
+ "Milter: cmd=data, reject=%s",
+ MSG_TEMPFAIL);
+ LogUsrErrs = false;
+ }
+ usrerr(MSG_TEMPFAIL);
+ return true;
+ }
+ LogUsrErrs = savelogusrerrs;
+ if (response != NULL)
+ sm_free(response); /* XXX */
+ }
+#endif /* MILTER && SMFI_VERSION > 3 */
/* put back discard bit */
if (smtp->sm_discard)
@@ -3049,12 +3209,6 @@ smtp_data(smtp, e)
SmtpPhase = "collect";
buffer_errors();
-#if _FFR_ADAPTIVE_EOL
- /* triggers error in collect, disabled for now */
- if (smtp->sm_crlf)
- e->e_flags |= EF_NL_NOT_EOL;
-#endif /* _FFR_ADAPTIVE_EOL */
-
collect(InChannel, true, NULL, e, true);
/* redefine message size */
@@ -3128,13 +3282,86 @@ smtp_data(smtp, e)
if (milteraccept && MilterLogLevel > 9)
sm_syslog(LOG_INFO, e->e_id, "Milter accept: message");
}
+
+ /*
+ ** If SuperSafe is SAFE_REALLY_POSTMILTER, and we don't have milter or
+ ** milter accepted message, sync it now
+ **
+ ** XXX This is almost a copy of the code in collect(): put it into
+ ** a function that is called from both places?
+ */
+
+ if (milteraccept && SuperSafe == SAFE_REALLY_POSTMILTER)
+ {
+ int afd;
+ SM_FILE_T *volatile df;
+ char *dfname;
+
+ df = e->e_dfp;
+ dfname = queuename(e, DATAFL_LETTER);
+ if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0
+ && errno != EINVAL)
+ {
+ int save_errno;
+
+ save_errno = errno;
+ if (save_errno == EEXIST)
+ {
+ struct stat st;
+ int dfd;
+
+ if (stat(dfname, &st) < 0)
+ st.st_size = -1;
+ errno = EEXIST;
+ syserr("@collect: bfcommit(%s): already on disk, size=%ld",
+ dfname, (long) st.st_size);
+ dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
+ if (dfd >= 0)
+ dumpfd(dfd, true, true);
+ }
+ errno = save_errno;
+ dferror(df, "bfcommit", e);
+ flush_errors(true);
+ finis(save_errno != EEXIST, true, ExitStat);
+ }
+ else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
+ {
+ dferror(df, "sm_io_getinfo", e);
+ flush_errors(true);
+ finis(true, true, ExitStat);
+ /* NOTREACHED */
+ }
+ else if (fsync(afd) < 0)
+ {
+ dferror(df, "fsync", e);
+ flush_errors(true);
+ finis(true, true, ExitStat);
+ /* NOTREACHED */
+ }
+ else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
+ {
+ dferror(df, "sm_io_close", e);
+ flush_errors(true);
+ finis(true, true, ExitStat);
+ /* NOTREACHED */
+ }
+
+ /* Now reopen the df file */
+ e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
+ SM_IO_RDONLY, NULL);
+ if (e->e_dfp == NULL)
+ {
+ /* we haven't acked receipt yet, so just chuck this */
+ syserr("@Cannot reopen %s", dfname);
+ finis(true, true, ExitStat);
+ /* NOTREACHED */
+ }
+ }
#endif /* MILTER */
-#if _FFR_QUARANTINE
/* Check if quarantining stats should be updated */
if (e->e_quarmsg != NULL)
markstats(e, NULL, STATS_QUARANTINE);
-#endif /* _FFR_QUARANTINE */
/*
** If a header/body check (header checks or milter)
@@ -3148,9 +3375,7 @@ smtp_data(smtp, e)
aborting = Errors > 0;
if (!(aborting || bitset(EF_DISCARD, e->e_flags)) &&
-#if _FFR_QUARANTINE
(QueueMode == QM_QUARANTINE || e->e_quarmsg == NULL) &&
-#endif /* _FFR_QUARANTINE */
!split_by_recipient(e))
aborting = bitset(EF_FATALERRS, e->e_flags);
@@ -3248,14 +3473,12 @@ smtp_data(smtp, e)
ee->e_sendmode = SM_QUEUE;
continue;
}
-#if _FFR_QUARANTINE
else if (QueueMode != QM_QUARANTINE &&
ee->e_quarmsg != NULL)
{
ee->e_sendmode = SM_QUEUE;
continue;
}
-#endif /* _FFR_QUARANTINE */
anything_to_send = true;
/* close all the queue files */
@@ -3300,7 +3523,6 @@ smtp_data(smtp, e)
{
for (ee = e; ee != NULL; ee = ee->e_sibling)
{
-#if _FFR_QUARANTINE
if (!doublequeue &&
QueueMode != QM_QUARANTINE &&
ee->e_quarmsg != NULL)
@@ -3308,7 +3530,6 @@ smtp_data(smtp, e)
dropenvelope(ee, true, false);
continue;
}
-#endif /* _FFR_QUARANTINE */
if (WILL_BE_QUEUED(ee->e_sendmode))
dropenvelope(ee, true, false);
}
@@ -3326,7 +3547,6 @@ smtp_data(smtp, e)
newenvelope(e, e, sm_rpool_new_x(NULL));
e->e_flags = BlankEnvelope.e_flags;
-#if _FFR_QUARANTINE
/* restore connection quarantining */
if (smtp->sm_quarmsg == NULL)
{
@@ -3339,7 +3559,7 @@ smtp_data(smtp, e)
macdefine(&e->e_macro, A_PERM,
macid("{quarantine}"), e->e_quarmsg);
}
-#endif /* _FFR_QUARANTINE */
+ return true;
}
/*
** LOGUNDELRCPTS -- log undelivered (or all) recipients.
@@ -3395,7 +3615,9 @@ logundelrcpts(e, msg, level, all)
** e -- the current envelope.
**
** Returns:
-** time to wait.
+** time to wait,
+** STOP_ATTACK if twice as many commands as allowed and
+** MaxChildren > 0.
**
** Side Effects:
** Slows down if we seem to be under attack.
@@ -3404,7 +3626,7 @@ logundelrcpts(e, msg, level, all)
static time_t
checksmtpattack(pcounter, maxcount, waitnow, cname, e)
volatile unsigned int *pcounter;
- int maxcount;
+ unsigned int maxcount;
bool waitnow;
char *cname;
ENVELOPE *e;
@@ -3414,6 +3636,7 @@ checksmtpattack(pcounter, maxcount, waitnow, cname, e)
if (++(*pcounter) >= maxcount)
{
+ unsigned int shift;
time_t s;
if (*pcounter == maxcount && LogLevel > 5)
@@ -3422,19 +3645,25 @@ checksmtpattack(pcounter, maxcount, waitnow, cname, e)
"%s: possible SMTP attack: command=%.40s, count=%u",
CurSmtpClient, cname, *pcounter);
}
- s = 1 << (*pcounter - maxcount);
- if (s >= MAXTIMEOUT || s <= 0)
+ shift = *pcounter - maxcount;
+ s = 1 << shift;
+ if (shift > MAXSHIFT || s >= MAXTIMEOUT || s <= 0)
s = MAXTIMEOUT;
+#define IS_ATTACK(s) ((MaxChildren > 0 && *pcounter >= maxcount * 2) \
+ ? STOP_ATTACK : (time_t) s)
+
/* sleep at least 1 second before returning */
(void) sleep(*pcounter / maxcount);
s -= *pcounter / maxcount;
- if (waitnow)
+ if (s >= MAXTIMEOUT || s < 0)
+ s = MAXTIMEOUT;
+ if (waitnow && s > 0)
{
(void) sleep(s);
- return 0;
+ return IS_ATTACK(0);
}
- return s;
+ return IS_ATTACK(s);
}
return (time_t) 0;
}
@@ -3688,7 +3917,6 @@ mail_esmtp_args(kp, vp, e)
bool saveQuickAbort = QuickAbort;
bool saveSuprErrs = SuprErrs;
bool saveExitStat = ExitStat;
- char pbuf[256];
if (vp == NULL)
{
@@ -3713,12 +3941,9 @@ mail_esmtp_args(kp, vp, e)
/* NOTREACHED */
}
- /* XXX this might be cut off */
- (void) sm_strlcpy(pbuf, xuntextify(auth_param), sizeof pbuf);
- /* xalloc() the buffer instead? */
-
/* XXX define this always or only if trusted? */
- macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"), pbuf);
+ macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"),
+ auth_param);
/*
** call Strust_auth to find out whether
@@ -3730,14 +3955,14 @@ mail_esmtp_args(kp, vp, e)
SuprErrs = true;
QuickAbort = false;
if (strcmp(auth_param, "<>") != 0 &&
- (rscheck("trust_auth", pbuf, NULL, e, RSF_RMCOMM,
+ (rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM,
9, NULL, NOQID) != EX_OK || Errors > 0))
{
if (tTd(95, 8))
{
q = e->e_auth_param;
sm_dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n",
- pbuf, (q == NULL) ? "" : q);
+ auth_param, (q == NULL) ? "" : q);
}
/* not trusted */
@@ -3750,7 +3975,7 @@ mail_esmtp_args(kp, vp, e)
else
{
if (tTd(95, 8))
- sm_dprintf("auth=\"%.100s\" trusted\n", pbuf);
+ sm_dprintf("auth=\"%.100s\" trusted\n", auth_param);
e->e_auth_param = sm_rpool_strdup_x(e->e_rpool,
auth_param);
}
@@ -4169,21 +4394,22 @@ static struct
} srv_feat_table[] =
{
{ 'A', SRV_OFFER_AUTH },
- { 'B', SRV_OFFER_VERB }, /* FFR; not documented in 8.12 */
- { 'D', SRV_OFFER_DSN }, /* FFR; not documented in 8.12 */
- { 'E', SRV_OFFER_ETRN }, /* FFR; not documented in 8.12 */
- { 'L', SRV_REQ_AUTH }, /* FFR; not documented in 8.12 */
+ { 'B', SRV_OFFER_VERB },
+ { 'C', SRV_REQ_SEC },
+ { 'D', SRV_OFFER_DSN },
+ { 'E', SRV_OFFER_ETRN },
+ { 'L', SRV_REQ_AUTH },
#if PIPELINING
# if _FFR_NO_PIPE
{ 'N', SRV_NO_PIPE },
# endif /* _FFR_NO_PIPE */
{ 'P', SRV_OFFER_PIPE },
#endif /* PIPELINING */
- { 'R', SRV_VRFY_CLT }, /* FFR; not documented in 8.12 */
+ { 'R', SRV_VRFY_CLT }, /* same as V; not documented */
{ 'S', SRV_OFFER_TLS },
/* { 'T', SRV_TMP_FAIL }, */
{ 'V', SRV_VRFY_CLT },
- { 'X', SRV_OFFER_EXPN }, /* FFR; not documented in 8.12 */
+ { 'X', SRV_OFFER_EXPN },
/* { 'Y', SRV_OFFER_VRFY }, */
{ '\0', SRV_NONE }
};
diff --git a/contrib/sendmail/src/stab.c b/contrib/sendmail/src/stab.c
index 4d1d2dd..2a71514 100644
--- a/contrib/sendmail/src/stab.c
+++ b/contrib/sendmail/src/stab.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: stab.c,v 8.86.4.1 2003/03/31 17:44:24 ca Exp $")
+SM_RCSID("@(#)$Id: stab.c,v 8.88 2003/05/21 15:36:30 ca Exp $")
/*
** STAB -- manage the symbol table
@@ -173,6 +173,12 @@ stab(name, type, op)
len = sizeof s->s_quegrp;
break;
+#if SOCKETMAP
+ case ST_SOCKETMAP:
+ len = sizeof s->s_socketmap;
+ break;
+#endif /* SOCKETMAP */
+
default:
/*
** Each mailer has its own MCI stab entry:
diff --git a/contrib/sendmail/src/stats.c b/contrib/sendmail/src/stats.c
index bf9d33a..5725219 100644
--- a/contrib/sendmail/src/stats.c
+++ b/contrib/sendmail/src/stats.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: stats.c,v 8.55 2002/05/21 22:28:52 gshapiro Exp $")
+SM_RCSID("@(#)$Id: stats.c,v 8.56 2002/06/27 22:47:37 gshapiro Exp $")
#include <sendmail/mailstats.h>
@@ -47,12 +47,10 @@ markstats(e, to, type)
{
switch (type)
{
-#if _FFR_QUARANTINE
case STATS_QUARANTINE:
if (e->e_from.q_mailer != NULL)
Stat.stat_nq[e->e_from.q_mailer->m_mno]++;
break;
-#endif /* _FFR_QUARANTINE */
case STATS_REJECT:
if (e->e_from.q_mailer != NULL)
@@ -180,9 +178,7 @@ poststats(sfile)
stats.stat_bt[i] += Stat.stat_bt[i];
stats.stat_nr[i] += Stat.stat_nr[i];
stats.stat_nd[i] += Stat.stat_nd[i];
-#if _FFR_QUARANTINE
stats.stat_nq[i] += Stat.stat_nq[i];
-#endif /* _FFR_QUARANTINE */
}
stats.stat_cr += Stat.stat_cr;
stats.stat_ct += Stat.stat_ct;
diff --git a/contrib/sendmail/src/sysexits.c b/contrib/sendmail/src/sysexits.c
index 2781b07..990ffe3 100644
--- a/contrib/sendmail/src/sysexits.c
+++ b/contrib/sendmail/src/sysexits.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: sysexits.c,v 8.33.4.1 2002/09/09 02:42:37 gshapiro Exp $")
+SM_RCSID("@(#)$Id: sysexits.c,v 8.34 2002/09/09 02:43:00 gshapiro Exp $")
/*
** DSNTOEXITSTAT -- convert DSN-style error code to EX_ style.
diff --git a/contrib/sendmail/src/tls.c b/contrib/sendmail/src/tls.c
index 598c187..6a8e8a1 100644
--- a/contrib/sendmail/src/tls.c
+++ b/contrib/sendmail/src/tls.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2000-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -10,7 +10,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: tls.c,v 8.79.4.5 2003/12/28 04:23:28 gshapiro Exp $")
+SM_RCSID("@(#)$Id: tls.c,v 8.95 2004/07/13 21:37:33 ca Exp $")
#if STARTTLS
# include <openssl/err.h>
@@ -29,6 +29,10 @@ static int tls_verify_cb __P((X509_STORE_CTX *));
static int tls_verify_cb __P((X509_STORE_CTX *, void *));
# endif /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */
+# if OPENSSL_VERSION_NUMBER > 0x00907000L
+static int x509_verify_cb __P((int, X509_STORE_CTX *));
+# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
+
# if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x00907000L
# define CONST097
# else /* !defined() || OPENSSL_VERSION_NUMBER < 0x00907000L */
@@ -332,6 +336,8 @@ tls_set_verify(ctx, ssl, vrfy)
# define TLS_S_CERTP_OK 0x00000020 /* CA cert path is ok */
# define TLS_S_CERTF_EX 0x00000040 /* CA cert file exists */
# define TLS_S_CERTF_OK 0x00000080 /* CA cert file is ok */
+# define TLS_S_CRLF_EX 0x00000100 /* CRL file exists */
+# define TLS_S_CRLF_OK 0x00000200 /* CRL file is ok */
# if _FFR_TLS_1
# define TLS_S_CERT2_EX 0x00001000 /* 2nd cert file exists */
@@ -373,7 +379,7 @@ tls_ok_f(var, fn, type)
if (LogLevel > 12)
sm_syslog(LOG_WARNING, NOQID, "STARTTLS: %s%s missing",
type == TLS_T_SRV ? "Server" :
- (type == TLS_T_CLT ? "Client" : ""), var);
+ (type == TLS_T_CLT ? "Client" : ""), fn);
return false;
}
/*
@@ -508,6 +514,11 @@ inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam)
# if SM_CONF_SHM
extern int ShmId;
# endif /* SM_CONF_SHM */
+# if OPENSSL_VERSION_NUMBER > 0x00907000L
+ BIO *crl_file;
+ X509_CRL *crl;
+ X509_STORE *store;
+# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
status = TLS_S_NONE;
who = srv ? "server" : "client";
@@ -553,6 +564,11 @@ inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam)
TLS_OK_F(cacertfile, "CACertFile", bitset(TLS_I_CERTF_EX, req),
TLS_S_CERTF_EX, TLS_T_OTHER);
+# if OPENSSL_VERSION_NUMBER > 0x00907000L
+ TLS_OK_F(CRLFile, "CRLFile", bitset(TLS_I_CRLF_EX, req),
+ TLS_S_CRLF_EX, TLS_T_OTHER);
+# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
+
# if _FFR_TLS_1
/*
** if the second file is specified it must exist
@@ -630,6 +646,11 @@ inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam)
TLS_SAFE_F(dhparam, sff | TLS_UNR(TLS_I_DHPAR_UNR, req),
bitset(TLS_I_DHPAR_EX, req),
bitset(TLS_S_DHPAR_EX, status), TLS_S_DHPAR_OK, srv);
+# if OPENSSL_VERSION_NUMBER > 0x00907000L
+ TLS_SAFE_F(CRLFile, sff | TLS_UNR(TLS_I_CRLF_UNR, req),
+ bitset(TLS_I_CRLF_EX, req),
+ bitset(TLS_S_CRLF_EX, status), TLS_S_CRLF_OK, srv);
+# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
if (!ok)
return ok;
# if _FFR_TLS_1
@@ -660,6 +681,68 @@ inittls(ctx, req, srv, certfile, keyfile, cacertpath, cacertfile, dhparam)
return false;
}
+# if OPENSSL_VERSION_NUMBER > 0x00907000L
+ if (CRLFile != NULL)
+ {
+ /* get a pointer to the current certificate validation store */
+ store = SSL_CTX_get_cert_store(*ctx); /* does not fail */
+ crl_file = BIO_new(BIO_s_file_internal());
+ if (crl_file != NULL)
+ {
+ if (BIO_read_filename(crl_file, CRLFile) >= 0)
+ {
+ crl = PEM_read_bio_X509_CRL(crl_file, NULL,
+ NULL, NULL);
+ BIO_free(crl_file);
+ X509_STORE_add_crl(store, crl);
+ X509_CRL_free(crl);
+ X509_STORE_set_flags(store,
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+ X509_STORE_set_verify_cb_func(store,
+ x509_verify_cb);
+ }
+ else
+ {
+ if (LogLevel > 9)
+ {
+ sm_syslog(LOG_WARNING, NOQID,
+ "STARTTLS=%s, error: PEM_read_bio_X509_CRL(%s)=failed",
+ who, CRLFile);
+ }
+
+ /* avoid memory leaks */
+ BIO_free(crl_file);
+ return false;
+ }
+
+ }
+ else if (LogLevel > 9)
+ sm_syslog(LOG_WARNING, NOQID,
+ "STARTTLS=%s, error: BIO_new=failed", who);
+ }
+# if _FFR_CRLPATH
+ if (CRLPath != NULL)
+ {
+ X509_LOOKUP *lookup;
+
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
+ if (lookup == NULL)
+ {
+ if (LogLevel > 9)
+ {
+ sm_syslog(LOG_WARNING, NOQID,
+ "STARTTLS=%s, error: X509_STORE_add_lookup(hash)=failed",
+ who, CRLFile);
+ }
+ return false;
+ }
+ X509_LOOKUP_add_dir(lookup, CRLPath, X509_FILETYPE_PEM);
+ X509_STORE_set_flags(store,
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+ }
+# endif /* _FFR_CRLPATH */
+# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
+
# if TLS_NO_RSA
/* turn off backward compatibility, required for no-rsa */
SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2);
@@ -1020,6 +1103,7 @@ tls_get_info(ssl, srv, host, mac, certreq)
{
SSL_CIPHER *c;
int b, r;
+ long verifyok;
char *s, *who;
char bitstr[16];
X509 *cert;
@@ -1041,11 +1125,11 @@ tls_get_info(ssl, srv, host, mac, certreq)
who = srv ? "server" : "client";
cert = SSL_get_peer_certificate(ssl);
+ verifyok = SSL_get_verify_result(ssl);
if (LogLevel > 14)
sm_syslog(LOG_INFO, NOQID,
"STARTTLS=%s, get_verify: %ld get_peer: 0x%lx",
- who, SSL_get_verify_result(ssl),
- (unsigned long) cert);
+ who, verifyok, (unsigned long) cert);
if (cert != NULL)
{
unsigned int n;
@@ -1094,7 +1178,7 @@ tls_get_info(ssl, srv, host, mac, certreq)
macdefine(mac, A_PERM, macid("{cn_issuer}"), "");
macdefine(mac, A_TEMP, macid("{cert_md5}"), "");
}
- switch (SSL_get_verify_result(ssl))
+ switch (verifyok)
{
case X509_V_OK:
if (cert != NULL)
@@ -1148,8 +1232,9 @@ tls_get_info(ssl, srv, host, mac, certreq)
s1 = macget(mac, macid("{cert_subject}"));
s2 = macget(mac, macid("{cert_issuer}"));
sm_syslog(LOG_INFO, NOQID,
- "STARTTLS=%s, cert-subject=%.128s, cert-issuer=%.128s",
- who, s1, s2);
+ "STARTTLS=%s, cert-subject=%.256s, cert-issuer=%.256s, verifymsg=%s",
+ who, s1, s2,
+ X509_verify_cert_error_string(verifyok));
}
}
return r;
@@ -1393,9 +1478,10 @@ apps_ssl_info_cb(s, where, ret)
*/
static int
-tls_verify_log(ok, ctx)
+tls_verify_log(ok, ctx, name)
int ok;
X509_STORE_CTX *ctx;
+ char *name;
{
SSL *ssl;
X509 *cert;
@@ -1418,10 +1504,11 @@ tls_verify_log(ok, ctx)
X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof buf);
sm_syslog(LOG_INFO, NOQID,
- "STARTTLS: cert verify: depth=%d %s, state=%d, reason=%s",
- depth, buf, ok, X509_verify_cert_error_string(reason));
+ "STARTTLS: %s cert verify: depth=%d %s, state=%d, reason=%s",
+ name, depth, buf, ok, X509_verify_cert_error_string(reason));
return 1;
}
+
/*
** TLS_VERIFY_CB -- verify callback for TLS certificates
**
@@ -1449,7 +1536,7 @@ tls_verify_cb(ctx, unused)
if (ok == 0)
{
if (LogLevel > 13)
- return tls_verify_log(ok, ctx);
+ return tls_verify_log(ok, ctx, "TLS");
return 1; /* override it */
}
return ok;
@@ -1486,4 +1573,35 @@ tlslogerr(who)
bitset(ERR_TXT_STRING, flags) ? data : "");
}
}
+
+# if OPENSSL_VERSION_NUMBER > 0x00907000L
+/*
+** X509_VERIFY_CB -- verify callback
+**
+** Parameters:
+** ctx -- x509 context
+**
+** Returns:
+** accept connection?
+** currently: always yes.
+*/
+
+static int
+x509_verify_cb(ok, ctx)
+ int ok;
+ X509_STORE_CTX *ctx;
+{
+ if (ok == 0)
+ {
+ if (LogLevel > 13)
+ tls_verify_log(ok, ctx, "x509");
+ if (ctx->error == X509_V_ERR_UNABLE_TO_GET_CRL)
+ {
+ ctx->error = 0;
+ return 1; /* override it */
+ }
+ }
+ return ok;
+}
+# endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
#endif /* STARTTLS */
diff --git a/contrib/sendmail/src/trace.c b/contrib/sendmail/src/trace.c
index a10b9f1..4a9051e 100644
--- a/contrib/sendmail/src/trace.c
+++ b/contrib/sendmail/src/trace.c
@@ -15,7 +15,7 @@
#include <sm/debug.h>
#include <sm/string.h>
-SM_RCSID("@(#)$Id: trace.c,v 8.37.4.1 2002/12/05 17:28:05 ca Exp $")
+SM_RCSID("@(#)$Id: trace.c,v 8.38 2002/12/05 17:28:35 ca Exp $")
static char *tTnewflag __P((char *));
static char *tToldflag __P((char *));
diff --git a/contrib/sendmail/src/udb.c b/contrib/sendmail/src/udb.c
index 3f218cc..aaf8569 100644
--- a/contrib/sendmail/src/udb.c
+++ b/contrib/sendmail/src/udb.c
@@ -14,9 +14,9 @@
#include <sendmail.h>
#if USERDB
-SM_RCSID("@(#)$Id: udb.c,v 8.153.4.5 2003/04/03 16:31:00 ca Exp $ (with USERDB)")
+SM_RCSID("@(#)$Id: udb.c,v 8.160 2003/04/03 16:32:46 ca Exp $ (with USERDB)")
#else /* USERDB */
-SM_RCSID("@(#)$Id: udb.c,v 8.153.4.5 2003/04/03 16:31:00 ca Exp $ (without USERDB)")
+SM_RCSID("@(#)$Id: udb.c,v 8.160 2003/04/03 16:32:46 ca Exp $ (without USERDB)")
#endif /* USERDB */
#if USERDB
@@ -334,7 +334,7 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 5))
{
sm_dprintf("udbexpand: QS_EXPANDED ");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
a->q_state = QS_EXPANDED;
}
@@ -474,7 +474,7 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 5))
{
sm_dprintf("udbexpand: QS_EXPANDED ");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
a->q_state = QS_EXPANDED;
}
@@ -525,7 +525,7 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 5))
{
sm_dprintf("udbexpand: QS_EXPANDED ");
- printaddr(a, false);
+ printaddr(sm_debug_file(), a, false);
}
a->q_state = QS_EXPANDED;
}
diff --git a/contrib/sendmail/src/usersmtp.c b/contrib/sendmail/src/usersmtp.c
index e760361..5c2b8f8 100644
--- a/contrib/sendmail/src/usersmtp.c
+++ b/contrib/sendmail/src/usersmtp.c
@@ -13,7 +13,7 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: usersmtp.c,v 8.437.2.10 2003/05/05 23:51:47 ca Exp $")
+SM_RCSID("@(#)$Id: usersmtp.c,v 8.451 2004/03/01 21:50:36 ca Exp $")
#include <sysexits.h>
@@ -82,7 +82,7 @@ smtpinit(m, mci, e, onlyhelo)
if (tTd(18, 1))
{
sm_dprintf("smtpinit ");
- mci_dump(mci, false);
+ mci_dump(sm_debug_file(), mci, false);
}
/*
@@ -138,7 +138,8 @@ smtpinit(m, mci, e, onlyhelo)
SmtpPhase = mci->mci_phase = "client greeting";
sm_setproctitle(true, e, "%s %s: %s",
qid_printname(e), CurHostName, mci->mci_phase);
- r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check, NULL);
+ r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check, NULL,
+ XS_DEFAULT);
if (r < 0)
goto tempfail1;
if (REPLYTYPE(r) == 4)
@@ -184,7 +185,7 @@ tryhelo:
r = reply(m, mci, e,
bitnset(M_LMTP, m->m_flags) ? TimeOuts.to_lhlo
: TimeOuts.to_helo,
- helo_options, NULL);
+ helo_options, NULL, XS_DEFAULT);
if (r < 0)
goto tempfail1;
else if (REPLYTYPE(r) == 5)
@@ -226,21 +227,19 @@ tryhelo:
/*
** If this is expected to be another sendmail, send some internal
** commands.
+ ** If we're running as MSP, "propagate" -v flag if possible.
*/
- if (false
+ if ((UseMSP && Verbose && bitset(MCIF_VERB, mci->mci_flags))
# if !_FFR_DEPRECATE_MAILER_FLAG_I
|| bitnset(M_INTERNAL, m->m_flags)
# endif /* !_FFR_DEPRECATE_MAILER_FLAG_I */
-# if _FFR_MSP_VERBOSE
- /* If we're running as MSP, "propagate" -v flag if possible. */
- || (UseMSP && Verbose && bitset(MCIF_VERB, mci->mci_flags))
-# endif /* _FFR_MSP_VERBOSE */
)
{
/* tell it to be verbose */
smtpmessage("VERB", m, mci);
- r = reply(m, mci, e, TimeOuts.to_miscshort, NULL, &enhsc);
+ r = reply(m, mci, e, TimeOuts.to_miscshort, NULL, &enhsc,
+ XS_DEFAULT);
if (r < 0)
goto tempfail1;
}
@@ -1744,12 +1743,10 @@ attemptauth(m, mci, e, sai)
/* send the info across the wire */
if (out == NULL
-#if _FFR_SASL_INITIAL_WORKAROUND
/* login and digest-md5 up to 1.5.28 set out="" */
|| (outlen == 0 &&
(sm_strcasecmp(mechusing, "LOGIN") == 0 ||
sm_strcasecmp(mechusing, "DIGEST-MD5") == 0))
-#endif /* _FFR_SASL_INITIAL_WORKAROUND */
)
{
/* no initial response */
@@ -1782,7 +1779,8 @@ attemptauth(m, mci, e, sai)
# endif /* SASL < 20000 */
/* get the reply */
- smtpresult = reply(m, mci, e, TimeOuts.to_auth, getsasldata, NULL);
+ smtpresult = reply(m, mci, e, TimeOuts.to_auth, getsasldata, NULL,
+ XS_AUTH);
for (;;)
{
@@ -1826,7 +1824,7 @@ attemptauth(m, mci, e, sai)
*/
smtpresult = reply(m, mci, e, TimeOuts.to_auth,
- getsasldata, NULL);
+ getsasldata, NULL, XS_AUTH);
return EX_NOPERM;
}
@@ -1848,7 +1846,7 @@ attemptauth(m, mci, e, sai)
# endif /* SASL < 20000 */
smtpmessage("%s", m, mci, in64);
smtpresult = reply(m, mci, e, TimeOuts.to_auth,
- getsasldata, NULL);
+ getsasldata, NULL, XS_AUTH);
}
/* NOTREACHED */
}
@@ -2168,7 +2166,7 @@ smtpmailfrom(m, mci, e)
SmtpPhase = mci->mci_phase = "client MAIL";
sm_setproctitle(true, e, "%s %s: %s", qid_printname(e),
CurHostName, mci->mci_phase);
- r = reply(m, mci, e, TimeOuts.to_mail, NULL, &enhsc);
+ r = reply(m, mci, e, TimeOuts.to_mail, NULL, &enhsc, XS_DEFAULT);
if (r < 0)
{
/* communications failure */
@@ -2420,7 +2418,7 @@ smtprcptstat(to, m, mci, e)
}
enhsc = NULL;
- r = reply(m, mci, e, TimeOuts.to_rcpt, NULL, &enhsc);
+ r = reply(m, mci, e, TimeOuts.to_rcpt, NULL, &enhsc, XS_DEFAULT);
save_errno = errno;
to->q_rstatus = sm_rpool_strdup_x(e->e_rpool, SmtpReplyBuffer);
to->q_status = ENHSCN_RPOOL(enhsc, smtptodsn(r), e->e_rpool);
@@ -2570,7 +2568,7 @@ smtpdata(m, mci, e, ctladdr, xstart)
mci->mci_state = MCIS_DATA;
sm_setproctitle(true, e, "%s %s: %s",
qid_printname(e), CurHostName, mci->mci_phase);
- r = reply(m, mci, e, TimeOuts.to_datainit, NULL, &enhsc);
+ r = reply(m, mci, e, TimeOuts.to_datainit, NULL, &enhsc, XS_DEFAULT);
if (r < 0 || REPLYTYPE(r) == 4)
{
if (r >= 0)
@@ -2723,7 +2721,7 @@ smtpdata(m, mci, e, ctladdr, xstart)
CurHostName, mci->mci_phase);
if (bitnset(M_LMTP, m->m_flags))
return EX_OK;
- r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc);
+ r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DEFAULT);
if (r < 0)
return EX_TEMPFAIL;
mci->mci_state = MCIS_OPEN;
@@ -2830,7 +2828,7 @@ smtpgetstat(m, mci, e)
enhsc = NULL;
/* check for the results of the transaction */
- r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc);
+ r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DEFAULT);
if (r < 0)
return EX_TEMPFAIL;
xstat = EX_NOTSTICKY;
@@ -2913,7 +2911,8 @@ smtpquit(m, mci, e)
SmtpPhase = "client QUIT";
mci->mci_state = MCIS_QUITING;
smtpmessage("QUIT", m, mci);
- (void) reply(m, mci, e, TimeOuts.to_quit, NULL, NULL);
+ (void) reply(m, mci, e, TimeOuts.to_quit, NULL, NULL,
+ XS_DEFAULT);
SuprErrs = oldSuprErrs;
if (mci->mci_state == MCIS_CLOSED)
goto end;
@@ -2988,7 +2987,7 @@ smtprset(m, mci, e)
SmtpPhase = "client RSET";
smtpmessage("RSET", m, mci);
- r = reply(m, mci, e, TimeOuts.to_rset, NULL, NULL);
+ r = reply(m, mci, e, TimeOuts.to_rset, NULL, NULL, XS_DEFAULT);
if (r < 0)
return;
@@ -3033,7 +3032,7 @@ smtpprobe(mci)
e = &BlankEnvelope;
SmtpPhase = "client probe";
smtpmessage("RSET", m, mci);
- r = reply(m, mci, e, TimeOuts.to_miscshort, NULL, NULL);
+ r = reply(m, mci, e, TimeOuts.to_miscshort, NULL, NULL, XS_DEFAULT);
if (REPLYTYPE(r) != 2)
smtpquit(m, mci, e);
return r;
@@ -3049,6 +3048,7 @@ smtpprobe(mci)
** pfunc -- processing function called on each line of response.
** If null, no special processing is done.
** enhstat -- optional, returns enhanced error code string (if set)
+** rtype -- type of SmtpMsgBuffer: does it contains secret data?
**
** Returns:
** reply code it reads.
@@ -3058,13 +3058,14 @@ smtpprobe(mci)
*/
int
-reply(m, mci, e, timeout, pfunc, enhstat)
+reply(m, mci, e, timeout, pfunc, enhstat, rtype)
MAILER *m;
MCI *mci;
ENVELOPE *e;
time_t timeout;
void (*pfunc)();
char **enhstat;
+ int rtype;
{
register char *bufp;
register int r;
@@ -3207,9 +3208,17 @@ reply(m, mci, e, timeout, pfunc, enhstat)
SmtpNeedIntro = false;
}
if (SmtpMsgBuffer[0] != '\0')
- (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
- ">>> %s\n", SmtpMsgBuffer);
- SmtpMsgBuffer[0] = '\0';
+ {
+ (void) sm_io_fprintf(e->e_xfp,
+ SM_TIME_DEFAULT,
+ ">>> %s\n",
+ (rtype == XS_STARTTLS)
+ ? "STARTTLS dialogue"
+ : ((rtype == XS_AUTH)
+ ? "AUTH dialogue"
+ : SmtpMsgBuffer));
+ SmtpMsgBuffer[0] = '\0';
+ }
/* now log the message as from the other side */
(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
diff --git a/contrib/sendmail/src/util.c b/contrib/sendmail/src/util.c
index 911f692..6945e64 100644
--- a/contrib/sendmail/src/util.c
+++ b/contrib/sendmail/src/util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,12 +13,36 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: util.c,v 8.363.2.10 2003/10/15 17:19:14 ca Exp $")
+SM_RCSID("@(#)$Id: util.c,v 8.382 2004/03/26 19:01:10 ca Exp $")
#include <sysexits.h>
#include <sm/xtrap.h>
/*
+** NEWSTR -- Create a copy of a C string
+**
+** Parameters:
+** s -- the string to copy.
+**
+** Returns:
+** pointer to newly allocated string.
+*/
+
+char *
+newstr(s)
+ const char *s;
+{
+ size_t l;
+ char *n;
+
+ l = strlen(s);
+ SM_ASSERT(l + 1 > l);
+ n = xalloc(l + 1);
+ sm_strlcpy(n, s, l + 1);
+ return n;
+}
+
+/*
** ADDQUOTES -- Adds quotes & quote bits to a string.
**
** Runs through a string and adds backslashes and quote bits.
@@ -68,7 +92,6 @@ addquotes(s, rpool)
return r;
}
-#if _FFR_STRIPBACKSL
/*
** STRIPBACKSLASH -- Strip leading backslash from a string.
**
@@ -97,7 +120,6 @@ stripbackslash(s)
c = *q++ = *p++;
} while (c != '\0');
}
-#endif /* _FFR_STRIPBACKSL */
/*
** RFC822_STRING -- Checks string for proper RFC822 string quoting.
@@ -540,48 +562,81 @@ copyqueue(addr, rpool)
**
** Side Effects:
** writes pidfile, logs command line.
+** keeps file open and locked to prevent overwrite of active file
*/
+static SM_FILE_T *Pidf = NULL;
+
void
log_sendmail_pid(e)
ENVELOPE *e;
{
long sff;
- SM_FILE_T *pidf;
char pidpath[MAXPATHLEN];
extern char *CommandLineArgs;
/* write the pid to the log file for posterity */
- sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT;
+ sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT|SFF_NBLOCK;
if (TrustedUid != 0 && RealUid == TrustedUid)
sff |= SFF_OPENASROOT;
expand(PidFile, pidpath, sizeof pidpath, e);
- pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, FileMode, sff);
- if (pidf == NULL)
+ Pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, FileMode, sff);
+ if (Pidf == NULL)
{
- sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s",
- pidpath, sm_errstring(errno));
+ if (errno == EWOULDBLOCK)
+ sm_syslog(LOG_ERR, NOQID,
+ "unable to write pid to %s: file in use by another process",
+ pidpath);
+ else
+ sm_syslog(LOG_ERR, NOQID,
+ "unable to write pid to %s: %s",
+ pidpath, sm_errstring(errno));
}
else
{
- pid_t pid;
-
- pid = getpid();
+ PidFilePid = getpid();
/* write the process id on line 1 */
- (void) sm_io_fprintf(pidf, SM_TIME_DEFAULT, "%ld\n",
- (long) pid);
+ (void) sm_io_fprintf(Pidf, SM_TIME_DEFAULT, "%ld\n",
+ (long) PidFilePid);
/* line 2 contains all command line flags */
- (void) sm_io_fprintf(pidf, SM_TIME_DEFAULT, "%s\n",
+ (void) sm_io_fprintf(Pidf, SM_TIME_DEFAULT, "%s\n",
CommandLineArgs);
- /* flush and close */
- (void) sm_io_close(pidf, SM_TIME_DEFAULT);
+ /* flush */
+ (void) sm_io_flush(Pidf, SM_TIME_DEFAULT);
+
+ /*
+ ** Leave pid file open until process ends
+ ** so it's not overwritten by another
+ ** process.
+ */
}
if (LogLevel > 9)
sm_syslog(LOG_INFO, NOQID, "started as: %s", CommandLineArgs);
}
+
+/*
+** CLOSE_SENDMAIL_PID -- close sendmail pid file
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+*/
+
+void
+close_sendmail_pid()
+{
+ if (Pidf == NULL)
+ return;
+
+ (void) sm_io_close(Pidf, SM_TIME_DEFAULT);
+ Pidf = NULL;
+}
+
/*
** SET_DELIVERY_MODE -- set and record the delivery mode
**
@@ -638,6 +693,7 @@ set_op_mode(mode)
** PRINTAV -- print argument vector.
**
** Parameters:
+** fp -- output file pointer.
** av -- argument vector.
**
** Returns:
@@ -648,7 +704,8 @@ set_op_mode(mode)
*/
void
-printav(av)
+printav(fp, av)
+ SM_FILE_T *fp;
register char **av;
{
while (*av != NULL)
@@ -656,15 +713,16 @@ printav(av)
if (tTd(0, 44))
sm_dprintf("\n\t%08lx=", (unsigned long) *av);
else
- (void) sm_io_putc(smioout, SM_TIME_DEFAULT, ' ');
- xputs(*av++);
+ (void) sm_io_putc(fp, SM_TIME_DEFAULT, ' ');
+ xputs(fp, *av++);
}
- (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '\n');
+ (void) sm_io_putc(fp, SM_TIME_DEFAULT, '\n');
}
/*
** XPUTS -- put string doing control escapes.
**
** Parameters:
+** fp -- output file pointer.
** s -- string to put.
**
** Returns:
@@ -675,7 +733,8 @@ printav(av)
*/
void
-xputs(s)
+xputs(fp, s)
+ SM_FILE_T *fp;
register const char *s;
{
register int c;
@@ -707,7 +766,7 @@ xputs(s)
if (s == NULL)
{
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s<null>%s",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s<null>%s",
TermEscape.te_rv_on, TermEscape.te_rv_off);
return;
}
@@ -715,7 +774,7 @@ xputs(s)
{
if (shiftout)
{
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s",
TermEscape.te_rv_off);
shiftout = false;
}
@@ -723,7 +782,7 @@ xputs(s)
{
if (c == MATCHREPL)
{
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"%s$",
TermEscape.te_rv_on);
shiftout = true;
@@ -734,26 +793,26 @@ xputs(s)
}
if (c == MACROEXPAND || c == MACRODEXPAND)
{
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT,
"%s$",
TermEscape.te_rv_on);
if (c == MACRODEXPAND)
- (void) sm_io_putc(smioout,
+ (void) sm_io_putc(fp,
SM_TIME_DEFAULT, '&');
shiftout = true;
if (*s == '\0')
continue;
if (strchr("=~&?", *s) != NULL)
- (void) sm_io_putc(smioout,
+ (void) sm_io_putc(fp,
SM_TIME_DEFAULT,
*s++);
if (bitset(0200, *s))
- (void) sm_io_fprintf(smioout,
+ (void) sm_io_fprintf(fp,
SM_TIME_DEFAULT,
"{%s}",
macname(bitidx(*s++)));
else
- (void) sm_io_fprintf(smioout,
+ (void) sm_io_fprintf(fp,
SM_TIME_DEFAULT,
"%c",
*s++);
@@ -763,7 +822,7 @@ xputs(s)
{
if (bitidx(mp->metaval) == c)
{
- (void) sm_io_fprintf(smioout,
+ (void) sm_io_fprintf(fp,
SM_TIME_DEFAULT,
"%s$%c",
TermEscape.te_rv_on,
@@ -775,12 +834,12 @@ xputs(s)
if (c == MATCHCLASS || c == MATCHNCLASS)
{
if (bitset(0200, *s))
- (void) sm_io_fprintf(smioout,
+ (void) sm_io_fprintf(fp,
SM_TIME_DEFAULT,
"{%s}",
macname(bitidx(*s++)));
else if (*s != '\0')
- (void) sm_io_fprintf(smioout,
+ (void) sm_io_fprintf(fp,
SM_TIME_DEFAULT,
"%c",
*s++);
@@ -789,7 +848,7 @@ xputs(s)
continue;
/* unrecognized meta character */
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%sM-",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%sM-",
TermEscape.te_rv_on);
shiftout = true;
c &= 0177;
@@ -797,7 +856,7 @@ xputs(s)
printchar:
if (isprint(c))
{
- (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c);
+ (void) sm_io_putc(fp, SM_TIME_DEFAULT, c);
continue;
}
@@ -818,25 +877,25 @@ xputs(s)
}
if (!shiftout)
{
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s",
TermEscape.te_rv_on);
shiftout = true;
}
if (isprint(c))
{
- (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '\\');
- (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c);
+ (void) sm_io_putc(fp, SM_TIME_DEFAULT, '\\');
+ (void) sm_io_putc(fp, SM_TIME_DEFAULT, c);
}
else
{
- (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '^');
- (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c ^ 0100);
+ (void) sm_io_putc(fp, SM_TIME_DEFAULT, '^');
+ (void) sm_io_putc(fp, SM_TIME_DEFAULT, c ^ 0100);
}
}
if (shiftout)
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s",
+ (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s",
TermEscape.te_rv_off);
- (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
+ (void) sm_io_flush(fp, SM_TIME_DEFAULT);
}
/*
** MAKELOWER -- Translate a line into lower case
@@ -1697,7 +1756,7 @@ printopenfds(logit)
** fd -- the file descriptor to dump.
** printclosed -- if set, print a notification even if
** it is closed; otherwise print nothing.
-** logit -- if set, send output to syslog instead of stdout.
+** logit -- if set, use sm_syslog instead of sm_dprintf()
**
** Returns:
** none.
@@ -1877,7 +1936,7 @@ printit:
sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL,
"%.800s", buf);
else
- (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s\n", buf);
+ sm_dprintf("%s\n", buf);
}
/*
** SHORTEN_HOSTNAME -- strip local domain information off of hostname.
@@ -1945,7 +2004,6 @@ prog_open(argv, pfd, e)
ENVELOPE *e;
{
pid_t pid;
- int i;
int save_errno;
int sff;
int ret;
@@ -2086,13 +2144,7 @@ prog_open(argv, pfd, e)
argv[0], sm_errstring(ret));
/* arrange for all the files to be closed */
- for (i = 3; i < DtableSize; i++)
- {
- register int j;
-
- if ((j = fcntl(i, F_GETFD, 0)) != -1)
- (void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
- }
+ sm_close_on_exec(STDERR_FILENO + 1, DtableSize);
/* now exec the process */
(void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron);
@@ -2469,23 +2521,25 @@ typedef struct procs PROCS_T;
struct procs
{
- pid_t proc_pid;
- char *proc_task;
- int proc_type;
- int proc_count;
- int proc_other;
+ pid_t proc_pid;
+ char *proc_task;
+ int proc_type;
+ int proc_count;
+ int proc_other;
+ SOCKADDR proc_hostaddr;
};
static PROCS_T *volatile ProcListVec = NULL;
static int ProcListSize = 0;
void
-proc_list_add(pid, task, type, count, other)
+proc_list_add(pid, task, type, count, other, hostaddr)
pid_t pid;
char *task;
int type;
int count;
int other;
+ SOCKADDR *hostaddr;
{
int i;
@@ -2537,6 +2591,11 @@ proc_list_add(pid, task, type, count, other)
ProcListVec[i].proc_type = type;
ProcListVec[i].proc_count = count;
ProcListVec[i].proc_other = other;
+ if (hostaddr != NULL)
+ ProcListVec[i].proc_hostaddr = *hostaddr;
+ else
+ memset(&ProcListVec[i].proc_hostaddr, 0,
+ sizeof(ProcListVec[i].proc_hostaddr));
/* if process adding itself, it's not a child */
if (pid != CurrentPid)
@@ -2774,3 +2833,47 @@ proc_list_signal(type, signal)
if (chldwasblocked == 0)
(void) sm_releasesignal(SIGCHLD);
}
+
+/*
+** COUNT_OPEN_CONNECTIONS
+**
+** Parameters:
+** hostaddr - ClientAddress
+**
+** Returns:
+** the number of open connections for this client
+**
+*/
+
+int
+count_open_connections(hostaddr)
+ SOCKADDR *hostaddr;
+{
+ int i, n;
+
+ if (hostaddr == NULL)
+ return 0;
+ n = 0;
+ for (i = 0; i < ProcListSize; i++)
+ {
+ if (ProcListVec[i].proc_pid == NO_PID)
+ continue;
+
+ if (hostaddr->sa.sa_family !=
+ ProcListVec[i].proc_hostaddr.sa.sa_family)
+ continue;
+#if NETINET
+ if (hostaddr->sa.sa_family == AF_INET &&
+ (hostaddr->sin.sin_addr.s_addr ==
+ ProcListVec[i].proc_hostaddr.sin.sin_addr.s_addr))
+ n++;
+#endif /* NETINET */
+#if NETINET6
+ if (hostaddr->sa.sa_family == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(&(hostaddr->sin6.sin6_addr),
+ &(ProcListVec[i].proc_hostaddr.sin6.sin6_addr)))
+ n++;
+#endif /* NETINET6 */
+ }
+ return n;
+}
diff --git a/contrib/sendmail/src/version.c b/contrib/sendmail/src/version.c
index ec91cfe..6ea57aa 100644
--- a/contrib/sendmail/src/version.c
+++ b/contrib/sendmail/src/version.c
@@ -13,6 +13,6 @@
#include <sm/gen.h>
-SM_RCSID("@(#)$Id: version.c,v 8.104.2.26 2004/01/13 00:29:26 ca Exp $")
+SM_RCSID("@(#)$Id: version.c,v 8.130 2004/07/30 18:03:07 ca Exp $")
-char Version[] = "8.12.11";
+char Version[] = "8.13.1";
OpenPOWER on IntegriCloud