diff options
Diffstat (limited to 'usr.sbin/sendmail/src/usersmtp.c')
-rw-r--r-- | usr.sbin/sendmail/src/usersmtp.c | 195 |
1 files changed, 162 insertions, 33 deletions
diff --git a/usr.sbin/sendmail/src/usersmtp.c b/usr.sbin/sendmail/src/usersmtp.c index edfe7beb8d53b..97248595532f0 100644 --- a/usr.sbin/sendmail/src/usersmtp.c +++ b/usr.sbin/sendmail/src/usersmtp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983, 1995 Eric P. Allman + * Copyright (c) 1983, 1995, 1996 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -36,9 +36,9 @@ #ifndef lint #ifdef SMTP -static char sccsid[] = "@(#)usersmtp.c 8.65.1.2 (Berkeley) 9/16/96 (with SMTP)"; +static char sccsid[] = "@(#)usersmtp.c 8.75 (Berkeley) 11/6/96 (with SMTP)"; #else -static char sccsid[] = "@(#)usersmtp.c 8.65.1.2 (Berkeley) 9/16/96 (without SMTP)"; +static char sccsid[] = "@(#)usersmtp.c 8.75 (Berkeley) 11/6/96 (without SMTP)"; #endif #endif /* not lint */ @@ -64,6 +64,7 @@ int SmtpPid; /* pid of mailer */ bool SmtpNeedIntro; /* need "while talking" in transcript */ extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...)); +extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)())); /* ** SMTPINIT -- initialize SMTP. ** @@ -83,7 +84,7 @@ extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...)); void smtpinit(m, mci, e) - struct mailer *m; + MAILER *m; register MCI *mci; ENVELOPE *e; { @@ -142,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; @@ -152,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"; @@ -172,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; @@ -181,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. @@ -193,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; @@ -214,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) @@ -226,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; } @@ -327,7 +359,7 @@ helo_options(line, firstline, m, mci, e) int smtpmailfrom(m, mci, e) - struct mailer *m; + MAILER *m; MCI *mci; ENVELOPE *e; { @@ -383,14 +415,16 @@ smtpmailfrom(m, mci, e) else if (!bitset(MM_PASS8BIT, MimeMode)) { /* cannot just send a 8-bit version */ + extern char MsgBuf[]; + usrerr("%s does not support 8BITMIME", mci->mci_host); - mci->mci_status = "5.6.3"; + mci_setstat(mci, EX_DATAERR, "5.6.3", MsgBuf); return EX_DATAERR; } if (bitset(MCIF_DSN, mci->mci_flags)) { - if (e->e_envid != NULL && strlen(e->e_envid) < (SIZE_T) l) + if (e->e_envid != NULL && strlen(e->e_envid) < (SIZE_T) (l - 7)) { strcat(optbuf, " ENVID="); strcat(optbuf, e->e_envid); @@ -444,16 +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, EX_TEMPFAIL, smtptodsn(r), SmtpReplyBuffer); return EX_TEMPFAIL; } else if (REPLYTYPE(r) == 2) @@ -463,24 +505,25 @@ smtpmailfrom(m, mci, e) else if (r == 501) { /* syntax error in arguments */ - mci->mci_status = "5.5.2"; + mci_setstat(mci, EX_DATAERR, "5.5.2", SmtpReplyBuffer); return EX_DATAERR; } else if (r == 553) { /* mailbox name not allowed */ - mci->mci_status = "5.1.3"; + mci_setstat(mci, EX_DATAERR, "5.1.3", SmtpReplyBuffer); return EX_DATAERR; } else if (r == 552) { /* exceeded storage allocation */ - mci->mci_status = "5.2.2"; + mci_setstat(mci, EX_UNAVAILABLE, "5.2.2", SmtpReplyBuffer); return EX_UNAVAILABLE; } else if (REPLYTYPE(r) == 5) { /* unknown error */ + mci_setstat(mci, EX_UNAVAILABLE, "5.0.0", SmtpReplyBuffer); return EX_UNAVAILABLE; } @@ -494,6 +537,7 @@ smtpmailfrom(m, mci, e) #endif /* protocol error -- close up */ + mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer); smtpquit(m, mci, e); return EX_PROTOCOL; } @@ -523,7 +567,6 @@ smtprcpt(to, m, mci, e) register int r; int l; char optbuf[MAXLINE]; - extern char *smtptodsn(); strcpy(optbuf, ""); l = sizeof optbuf - 1; @@ -531,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; @@ -581,10 +625,25 @@ smtprcpt(to, m, mci, e) return EX_TEMPFAIL; else if (REPLYTYPE(r) == 2) return EX_OK; - else if (r == 550 || r == 551 || r == 553) + else if (r == 550) + { + to->q_status = "5.1.1"; + return EX_NOUSER; + } + else if (r == 551) + { + to->q_status = "5.1.6"; + return EX_NOUSER; + } + else if (r == 553) + { + to->q_status = "5.1.3"; return EX_NOUSER; + } else if (REPLYTYPE(r) == 5) + { return EX_UNAVAILABLE; + } #ifdef LOG if (LogLevel > 1) @@ -602,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: @@ -616,12 +676,13 @@ static void datatimeout(); int smtpdata(m, mci, e) - struct mailer *m; + MAILER *m; register MCI *mci; register ENVELOPE *e; { register int r; register EVENT *ev; + int rstat; time_t timeout; /* @@ -670,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; @@ -700,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; } @@ -714,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) { @@ -723,15 +788,22 @@ smtpdata(m, mci, e) return EX_TEMPFAIL; } mci->mci_state = MCIS_OPEN; - 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) { @@ -740,7 +812,7 @@ smtpdata(m, mci, e) shortenstring(SmtpReplyBuffer, 403)); } #endif - return EX_PROTOCOL; + return rstat; } @@ -750,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. @@ -906,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) @@ -916,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)) |