summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src/usersmtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/usersmtp.c')
-rw-r--r--usr.sbin/sendmail/src/usersmtp.c168
1 files changed, 138 insertions, 30 deletions
diff --git a/usr.sbin/sendmail/src/usersmtp.c b/usr.sbin/sendmail/src/usersmtp.c
index 1b684fb970f2..1be0d840a5c0 100644
--- a/usr.sbin/sendmail/src/usersmtp.c
+++ b/usr.sbin/sendmail/src/usersmtp.c
@@ -36,9 +36,9 @@
#ifndef lint
#ifdef SMTP
-static char sccsid[] = "@(#)usersmtp.c 8.72 (Berkeley) 9/15/96 (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.75 (Berkeley) 11/6/96 (with SMTP)";
#else
-static char sccsid[] = "@(#)usersmtp.c 8.72 (Berkeley) 9/15/96 (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.75 (Berkeley) 11/6/96 (without SMTP)";
#endif
#endif /* not lint */
@@ -143,8 +143,10 @@ smtpinit(m, mci, e)
SmtpPhase = mci->mci_phase = "client greeting";
setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
- if (r < 0 || REPLYTYPE(r) == 4)
+ if (r < 0)
goto tempfail1;
+ if (REPLYTYPE(r) == 4)
+ goto tempfail2;
if (REPLYTYPE(r) != 2)
goto unavailable;
@@ -153,11 +155,24 @@ smtpinit(m, mci, e)
** My mother taught me to always introduce myself.
*/
+#if FFR_LMTP
+ if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags))
+#else
if (bitnset(M_ESMTP, m->m_flags))
+#endif
mci->mci_flags |= MCIF_ESMTP;
tryhelo:
+#if FFR_LMTP
+ if (bitnset(M_LMTP, m->m_flags))
+ {
+ smtpmessage("LHLO %s", m, mci, MyHostName);
+ SmtpPhase = mci->mci_phase = "client LHLO";
+ }
+ else if (bitset(MCIF_ESMTP, mci->mci_flags))
+#else
if (bitset(MCIF_ESMTP, mci->mci_flags))
+#endif
{
smtpmessage("EHLO %s", m, mci, MyHostName);
SmtpPhase = mci->mci_phase = "client EHLO";
@@ -173,7 +188,12 @@ tryhelo:
goto tempfail1;
else if (REPLYTYPE(r) == 5)
{
+#if FFR_LMTP
+ if (bitset(MCIF_ESMTP, mci->mci_flags) &&
+ !bitnset(M_LMTP, m->m_flags))
+#else
if (bitset(MCIF_ESMTP, mci->mci_flags))
+#endif
{
/* try old SMTP instead */
mci->mci_flags &= ~MCIF_ESMTP;
@@ -182,7 +202,7 @@ tryhelo:
goto unavailable;
}
else if (REPLYTYPE(r) != 2)
- goto tempfail1;
+ goto tempfail2;
/*
** Check to see if we actually ended up talking to ourself.
@@ -194,11 +214,14 @@ tryhelo:
if (p != NULL)
*p = '\0';
if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
+#if FFR_LMTP
+ !bitnset(M_LMTP, m->m_flags) &&
+#endif
strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
{
syserr("553 %s config error: mail loops back to me (MX problem?)",
mci->mci_host);
- mci->mci_exitstat = EX_CONFIG;
+ mci_setstat(mci, EX_CONFIG, NULL, NULL);
mci->mci_errno = 0;
smtpquit(m, mci, e);
return;
@@ -215,7 +238,7 @@ tryhelo:
smtpmessage("VERB", m, mci);
r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
if (r < 0)
- goto tempfail2;
+ goto tempfail1;
}
if (mci->mci_state != MCIS_CLOSED)
@@ -227,17 +250,25 @@ tryhelo:
/* got a 421 error code during startup */
tempfail1:
+ if (mci->mci_errno == 0)
+ mci->mci_errno = errno;
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
+ if (mci->mci_state != MCIS_CLOSED)
+ smtpquit(m, mci, e);
+ return;
+
tempfail2:
- mci->mci_exitstat = EX_TEMPFAIL;
if (mci->mci_errno == 0)
mci->mci_errno = errno;
+ /* XXX should use code from other end iff ENHANCEDSTATUSCODES */
+ mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
if (mci->mci_state != MCIS_CLOSED)
smtpquit(m, mci, e);
return;
unavailable:
- mci->mci_exitstat = EX_UNAVAILABLE;
mci->mci_errno = errno;
+ mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer);
smtpquit(m, mci, e);
return;
}
@@ -387,7 +418,7 @@ smtpmailfrom(m, mci, e)
extern char MsgBuf[];
usrerr("%s does not support 8BITMIME", mci->mci_host);
- mci_setstat(mci, "5.6.3", MsgBuf);
+ mci_setstat(mci, EX_DATAERR, "5.6.3", MsgBuf);
return EX_DATAERR;
}
@@ -447,17 +478,24 @@ smtpmailfrom(m, mci, e)
SmtpPhase = mci->mci_phase = "client MAIL";
setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
r = reply(m, mci, e, TimeOuts.to_mail, NULL);
- if (r < 0 || r == 421)
+ if (r < 0)
{
- /* communications failure/service shutting down */
- mci->mci_exitstat = EX_TEMPFAIL;
+ /* communications failure */
mci->mci_errno = errno;
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
+ smtpquit(m, mci, e);
+ return EX_TEMPFAIL;
+ }
+ else if (r == 421)
+ {
+ /* service shutting down */
+ mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
smtpquit(m, mci, e);
return EX_TEMPFAIL;
}
else if (REPLYTYPE(r) == 4)
{
- mci_setstat(mci, smtptodsn(r), SmtpReplyBuffer);
+ mci_setstat(mci, EX_TEMPFAIL, smtptodsn(r), SmtpReplyBuffer);
return EX_TEMPFAIL;
}
else if (REPLYTYPE(r) == 2)
@@ -467,25 +505,25 @@ smtpmailfrom(m, mci, e)
else if (r == 501)
{
/* syntax error in arguments */
- mci_setstat(mci, "5.5.2", SmtpReplyBuffer);
+ mci_setstat(mci, EX_DATAERR, "5.5.2", SmtpReplyBuffer);
return EX_DATAERR;
}
else if (r == 553)
{
/* mailbox name not allowed */
- mci_setstat(mci, "5.1.3", SmtpReplyBuffer);
+ mci_setstat(mci, EX_DATAERR, "5.1.3", SmtpReplyBuffer);
return EX_DATAERR;
}
else if (r == 552)
{
/* exceeded storage allocation */
- mci_setstat(mci, "5.2.2", SmtpReplyBuffer);
+ mci_setstat(mci, EX_UNAVAILABLE, "5.2.2", SmtpReplyBuffer);
return EX_UNAVAILABLE;
}
else if (REPLYTYPE(r) == 5)
{
/* unknown error */
- mci_setstat(mci, "5.0.0", SmtpReplyBuffer);
+ mci_setstat(mci, EX_UNAVAILABLE, "5.0.0", SmtpReplyBuffer);
return EX_UNAVAILABLE;
}
@@ -499,7 +537,7 @@ smtpmailfrom(m, mci, e)
#endif
/* protocol error -- close up */
- mci_setstat(mci, "5.5.1", SmtpReplyBuffer);
+ mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
smtpquit(m, mci, e);
return EX_PROTOCOL;
}
@@ -536,7 +574,8 @@ smtprcpt(to, m, mci, e)
{
/* NOTIFY= parameter */
if (bitset(QHASNOTIFY, to->q_flags) &&
- bitset(QPRIMARY, to->q_flags))
+ bitset(QPRIMARY, to->q_flags) &&
+ !bitnset(M_LOCALMAILER, m->m_flags))
{
bool firstone = TRUE;
@@ -622,6 +661,7 @@ smtprcpt(to, m, mci, e)
**
** Parameters:
** m -- mailer being sent to.
+** mci -- the mailer connection information.
** e -- the envelope for this message.
**
** Returns:
@@ -642,6 +682,7 @@ smtpdata(m, mci, e)
{
register int r;
register EVENT *ev;
+ int rstat;
time_t timeout;
/*
@@ -690,8 +731,8 @@ smtpdata(m, mci, e)
if (setjmp(CtxDataTimeout) != 0)
{
mci->mci_errno = errno;
- mci->mci_exitstat = EX_TEMPFAIL;
mci->mci_state = MCIS_ERROR;
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
syserr("451 timeout writing message to %s", mci->mci_host);
smtpquit(m, mci, e);
return EX_TEMPFAIL;
@@ -720,8 +761,8 @@ smtpdata(m, mci, e)
{
/* error during processing -- don't send the dot */
mci->mci_errno = EIO;
- mci->mci_exitstat = EX_IOERR;
mci->mci_state = MCIS_ERROR;
+ mci_setstat(mci, EX_IOERR, "4.4.2", NULL);
smtpquit(m, mci, e);
return EX_IOERR;
}
@@ -734,8 +775,12 @@ smtpdata(m, mci, e)
nmessage(">>> .");
/* check for the results of the transaction */
- SmtpPhase = mci->mci_phase = "client DATA 250";
+ SmtpPhase = mci->mci_phase = "client DATA status";
setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+#if FFR_LMTP
+ if (bitnset(M_LMTP, m->m_flags))
+ return EX_OK;
+#endif
r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
if (r < 0)
{
@@ -743,16 +788,22 @@ smtpdata(m, mci, e)
return EX_TEMPFAIL;
}
mci->mci_state = MCIS_OPEN;
- mci_setstat(mci, smtptodsn(r), SmtpReplyBuffer);
- e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
if (REPLYTYPE(r) == 4)
- return EX_TEMPFAIL;
+ rstat = EX_TEMPFAIL;
else if (REPLYCLASS(r) != 5)
- /* fall through */ ;
+ rstat = EX_PROTOCOL;
else if (REPLYTYPE(r) == 2)
- return EX_OK;
+ rstat = EX_OK;
else if (REPLYTYPE(r) == 5)
- return EX_UNAVAILABLE;
+ rstat = EX_UNAVAILABLE;
+ else
+ rstat = EX_PROTOCOL;
+ mci_setstat(mci, rstat, smtptodsn(r), SmtpReplyBuffer);
+ if (e->e_statmsg != NULL)
+ free(e->e_statmsg);
+ e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
+ if (rstat != EX_PROTOCOL)
+ return rstat;
#ifdef LOG
if (LogLevel > 1)
{
@@ -761,7 +812,7 @@ smtpdata(m, mci, e)
shortenstring(SmtpReplyBuffer, 403));
}
#endif
- return EX_PROTOCOL;
+ return rstat;
}
@@ -771,10 +822,66 @@ datatimeout()
longjmp(CtxDataTimeout, 1);
}
/*
+** SMTPGETSTAT -- get status code from DATA in LMTP
+**
+** Parameters:
+** m -- the mailer to which we are sending the message.
+** mci -- the mailer connection structure.
+** e -- the current envelope.
+**
+** Returns:
+** The exit status corresponding to the reply code.
+*/
+
+#if FFR_LMTP
+
+int
+smtpgetstat(m, mci, e)
+ MAILER *m;
+ MCI *mci;
+ ENVELOPE *e;
+{
+ int r;
+ int stat;
+
+ /* check for the results of the transaction */
+ r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
+ if (r < 0)
+ {
+ smtpquit(m, mci, e);
+ return EX_TEMPFAIL;
+ }
+ if (e->e_statmsg != NULL)
+ free(e->e_statmsg);
+ e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
+ if (REPLYTYPE(r) == 4)
+ stat = EX_TEMPFAIL;
+ else if (REPLYCLASS(r) != 5)
+ stat = EX_PROTOCOL;
+ else if (REPLYTYPE(r) == 2)
+ stat = EX_OK;
+ else if (REPLYTYPE(r) == 5)
+ stat = EX_UNAVAILABLE;
+ mci_setstat(mci, stat, smtptodsn(r), SmtpReplyBuffer);
+#ifdef LOG
+ if (LogLevel > 1 && stat == EX_PROTOCOL)
+ {
+ syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-3 protocol error: %s",
+ e->e_id, mci->mci_host,
+ shortenstring(SmtpReplyBuffer, 403));
+ }
+#endif
+ return stat;
+}
+
+#endif
+ /*
** SMTPQUIT -- close the SMTP connection.
**
** Parameters:
** m -- a pointer to the mailer.
+** mci -- the mailer connection information.
+** e -- the current envelope.
**
** Returns:
** none.
@@ -927,6 +1034,7 @@ reply(m, mci, e, timeout, pfunc)
if (p == NULL)
{
bool oldholderrs;
+ extern char MsgBuf[];
/* if the remote end closed early, fake an error */
if (errno == 0)
@@ -937,10 +1045,10 @@ reply(m, mci, e, timeout, pfunc)
# endif /* ECONNRESET */
mci->mci_errno = errno;
- mci->mci_exitstat = EX_TEMPFAIL;
oldholderrs = HoldErrs;
HoldErrs = TRUE;
usrerr("451 reply: read error from %s", mci->mci_host);
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf);
/* if debugging, pause so we can see state */
if (tTd(18, 100))