summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/deliver.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/deliver.c')
-rw-r--r--contrib/sendmail/src/deliver.c209
1 files changed, 125 insertions, 84 deletions
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)
OpenPOWER on IntegriCloud