diff options
Diffstat (limited to 'contrib/sendmail/src/deliver.c')
-rw-r--r-- | contrib/sendmail/src/deliver.c | 156 |
1 files changed, 87 insertions, 69 deletions
diff --git a/contrib/sendmail/src/deliver.c b/contrib/sendmail/src/deliver.c index 6454da7..01d5258 100644 --- a/contrib/sendmail/src/deliver.c +++ b/contrib/sendmail/src/deliver.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2007 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 <sm/time.h> -SM_RCSID("@(#)$Id: deliver.c,v 8.1003.2.1 2006/05/23 01:32:08 ca Exp $") +SM_RCSID("@(#)$Id: deliver.c,v 8.1012 2007/03/29 21:20:15 ca Exp $") #if HASSETUSERCONTEXT # include <login_cap.h> @@ -34,7 +34,6 @@ static void mailfiletimeout __P((int)); static void endwaittimeout __P((int)); static int parse_hostsignature __P((char *, char **, MAILER *)); static void sendenvelope __P((ENVELOPE *, int)); -extern MCI *mci_new __P((SM_RPOOL_T *)); static int coloncmp __P((const char *, const char *)); #if STARTTLS @@ -383,7 +382,7 @@ sendall(e, mode) */ ee = (ENVELOPE *) sm_rpool_malloc_x(e->e_rpool, - sizeof *ee); + sizeof(*ee)); STRUCTCOPY(*e, *ee); ee->e_message = NULL; ee->e_id = NULL; @@ -884,7 +883,7 @@ sendenvelope(e, mode) #if XDEBUG char wbuf[MAXNAME + 20]; - (void) sm_snprintf(wbuf, sizeof wbuf, "sendall(%.*s)", + (void) sm_snprintf(wbuf, sizeof(wbuf), "sendall(%.*s)", MAXNAME, q->q_paddr); checkfd012(wbuf); #endif /* XDEBUG */ @@ -959,7 +958,7 @@ sync_dir(filename, panic) dirp = strrchr(filename, '/'); if (dirp != NULL) { - if (sm_strlcpy(dir, filename, sizeof dir) >= sizeof dir) + if (sm_strlcpy(dir, filename, sizeof(dir)) >= sizeof(dir)) return; dir[dirp - filename] = '\0'; dirp = dir; @@ -1012,8 +1011,8 @@ dup_queue_file(e, ee, type) ** Make sure both are in the same directory. */ - (void) sm_strlcpy(f1buf, queuename(e, type), sizeof f1buf); - (void) sm_strlcpy(f2buf, queuename(ee, type), sizeof f2buf); + (void) sm_strlcpy(f1buf, queuename(e, type), sizeof(f1buf)); + (void) sm_strlcpy(f2buf, queuename(ee, type), sizeof(f2buf)); /* Force the df to disk if it's not there yet */ if (type == DATAFL_LETTER && e->e_dfp != NULL && @@ -1192,6 +1191,8 @@ coloncmp(a, b) ** true iff FallbackSmartHost should be tried. */ +static bool should_try_fbsh __P((ENVELOPE *, bool *, char *, size_t, int)); + static bool should_try_fbsh(e, tried_fallbacksmarthost, hostbuf, hbsz, status) ENVELOPE *e; @@ -1333,11 +1334,13 @@ deliver(e, firstto) char cbuf[MAXPATHLEN]; errno = 0; + SM_REQUIRE(firstto != NULL); /* same as to */ if (!QS_IS_OK(to->q_state)) return 0; suidwarn = geteuid() == 0; + SM_REQUIRE(e != NULL); m = to->q_mailer; host = to->q_host; CurEnv = e; /* just in case */ @@ -1382,6 +1385,7 @@ deliver(e, firstto) /* rewrite from address, using rewriting rules */ rcode = EX_OK; + SM_ASSERT(e->e_from.q_mailer != NULL); if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags)) p = e->e_sender; else @@ -1441,7 +1445,7 @@ deliver(e, firstto) break; /* this entry is safe -- go ahead and process it */ - expand(*mvp, buf, sizeof buf, e); + expand(*mvp, buf, sizeof(buf), e); *pvp++ = sm_rpool_strdup_x(e->e_rpool, buf); if (pvp >= &pv[MAXPV - 3]) { @@ -1595,7 +1599,7 @@ deliver(e, firstto) quarantine = (e->e_quarmsg != NULL); rcode = rscheck("check_compat", e->e_from.q_paddr, to->q_paddr, e, RSF_RMCOMM|RSF_COUNT, 3, NULL, - e->e_id); + e->e_id, NULL); if (rcode == EX_OK) { /* do in-code checking if not discarding */ @@ -1698,7 +1702,7 @@ deliver(e, firstto) if (p == NULL && ctladdr != NULL) p = ctladdr->q_home; macdefine(&e->e_macro, A_PERM, 'z', p); - expand(m->m_argv[1], buf, sizeof buf, e); + expand(m->m_argv[1], buf, sizeof(buf), e); if (strlen(buf) > 0) rcode = mailfile(buf, m, ctladdr, SFF_CREAT, e); else @@ -1754,18 +1758,18 @@ deliver(e, firstto) notify[0] = '\0'; if (bitset(QPINGONSUCCESS, to->q_flags)) (void) sm_strlcat(notify, "SUCCESS,", - sizeof notify); + sizeof(notify)); if (bitset(QPINGONFAILURE, to->q_flags)) (void) sm_strlcat(notify, "FAILURE,", - sizeof notify); + sizeof(notify)); if (bitset(QPINGONDELAY, to->q_flags)) (void) sm_strlcat(notify, "DELAY,", - sizeof notify); + sizeof(notify)); /* Set to NEVER or drop trailing comma */ if (notify[0] == '\0') (void) sm_strlcat(notify, "NEVER", - sizeof notify); + sizeof(notify)); else notify[strlen(notify) - 1] = '\0'; @@ -1782,7 +1786,7 @@ deliver(e, firstto) if (!clever) { - expand(*mvp, buf, sizeof buf, e); + expand(*mvp, buf, sizeof(buf), e); *pvp++ = sm_rpool_strdup_x(e->e_rpool, buf); if (pvp >= &pv[MAXPV - 2]) { @@ -1829,7 +1833,7 @@ deliver(e, firstto) { while (*++mvp != NULL) { - expand(*mvp, buf, sizeof buf, e); + expand(*mvp, buf, sizeof(buf), e); *pvp++ = sm_rpool_strdup_x(e->e_rpool, buf); if (pvp >= &pv[MAXPV]) syserr("554 5.3.0 deliver: pv overflow after $u for %s", @@ -1883,7 +1887,7 @@ deliver(e, firstto) char wbuf[MAXLINE]; /* make absolutely certain 0, 1, and 2 are in use */ - (void) sm_snprintf(wbuf, sizeof wbuf, "%s... openmailer(%s)", + (void) sm_snprintf(wbuf, sizeof(wbuf), "%s... openmailer(%s)", shortenstring(e->e_to, MAXSHORTSTR), m->m_name); checkfd012(wbuf); @@ -2060,7 +2064,7 @@ tryhost: continue; } (void) sm_strlcpy(hostbuf, mxhosts[hostnum], - sizeof hostbuf); + sizeof(hostbuf)); hostnum++; if (endp != NULL) *endp = sep; @@ -2098,7 +2102,7 @@ tryhost: /* Try FallbackSmartHost? */ if (should_try_fbsh(e, &tried_fallbacksmarthost, - hostbuf, sizeof hostbuf, + hostbuf, sizeof(hostbuf), mci->mci_exitstat)) goto one_last_try; @@ -2190,7 +2194,7 @@ tryhost: { /* Try FallbackSmartHost? */ if (should_try_fbsh(e, &tried_fallbacksmarthost, - hostbuf, sizeof hostbuf, i)) + hostbuf, sizeof(hostbuf), i)) goto one_last_try; if (tTd(11, 1)) @@ -2527,7 +2531,7 @@ tryhost: /* change root to some "safe" directory */ if (m->m_rootdir != NULL) { - expand(m->m_rootdir, cbuf, sizeof cbuf, e); + expand(m->m_rootdir, cbuf, sizeof(cbuf), e); if (tTd(11, 20)) sm_dprintf("openmailer: chroot %s\n", cbuf); @@ -2664,7 +2668,7 @@ tryhost: q = strchr(p, ':'); if (q != NULL) *q = '\0'; - expand(p, cbuf, sizeof cbuf, e); + expand(p, cbuf, sizeof(cbuf), e); if (q != NULL) *q++ = ':'; if (tTd(11, 20)) @@ -2945,16 +2949,19 @@ reconnect: /* after switching to an encrypted connection */ if (usetls) usetls = !iscltflgset(e, D_NOTLS); + host = macvalue(macid("{server_name}"), e); if (usetls) { - host = macvalue(macid("{server_name}"), e); olderrors = Errors; QuickAbort = false; SuprErrs = true; if (rscheck("try_tls", host, NULL, e, - RSF_RMCOMM, 7, host, NOQID) != EX_OK + RSF_RMCOMM, 7, host, NOQID, NULL) + != EX_OK || Errors > olderrors) + { usetls = false; + } SuprErrs = saveSuprErrs; QuickAbort = saveQuickAbort; } @@ -3024,7 +3031,7 @@ reconnect: /* after switching to an encrypted connection */ if (rscheck("tls_server", macvalue(macid("{verify}"), e), NULL, e, RSF_RMCOMM|RSF_COUNT, 5, - host, NOQID) != EX_OK || + host, NOQID, NULL) != EX_OK || Errors > olderrors || rcode == EX_SOFTWARE) { @@ -3041,7 +3048,7 @@ reconnect: /* after switching to an encrypted connection */ { p = "403 4.7.0 server not authenticated."; (void) sm_strlcpy(enhsc, "4.7.0", - sizeof enhsc); + sizeof(enhsc)); } SuprErrs = saveSuprErrs; QuickAbort = saveQuickAbort; @@ -3079,8 +3086,18 @@ reconnect: /* after switching to an encrypted connection */ */ (void) sm_strlcpy(SmtpError, p, - sizeof SmtpError); + sizeof(SmtpError)); + } + else if (mci->mci_state == MCIS_CLOSED) + { + /* connection close caused by 421 */ + mci->mci_errno = 0; + rcode = EX_TEMPFAIL; + mci_setstat(mci, rcode, NULL, "421"); } + else + rcode = 0; + QuickAbort = saveQuickAbort; SuprErrs = saveSuprErrs; if (DONE_STARTTLS(mci->mci_flags) && @@ -3171,7 +3188,7 @@ reconnect: /* after switching to an encrypted connection */ (void) sm_strlcpy(SmtpError, "Temporary AUTH failure", - sizeof SmtpError); + sizeof(SmtpError)); } } # endif /* SASL */ @@ -3233,7 +3250,7 @@ do_transfer: rcode = EX_DATAERR; /* Need an e_message for error */ - (void) sm_snprintf(SmtpError, sizeof SmtpError, + (void) sm_snprintf(SmtpError, sizeof(SmtpError), "Message is too large; %ld bytes max", mci->mci_maxsize); goto give_up; @@ -3297,7 +3314,7 @@ do_transfer: ** We set SmtpError as */ - (void) sm_snprintf(SmtpError, sizeof SmtpError, + (void) sm_snprintf(SmtpError, sizeof(SmtpError), "%s mailer (%s) exited with EX_TEMPFAIL", m->m_name, m->m_mailer); } @@ -3337,7 +3354,7 @@ do_transfer: # if STARTTLS i = rscheck("tls_rcpt", to->q_user, NULL, e, RSF_RMCOMM|RSF_COUNT, 3, - mci->mci_host, e->e_id); + mci->mci_host, e->e_id, NULL); if (i != EX_OK) { markfailure(e, to, mci, i, false); @@ -3612,7 +3629,7 @@ cleanup: ; char wbuf[MAXLINE]; /* make absolutely certain 0, 1, and 2 are in use */ - (void) sm_snprintf(wbuf, sizeof wbuf, + (void) sm_snprintf(wbuf, sizeof(wbuf), "%s... end of deliver(%s)", e->e_to == NULL ? "NO-TO-LIST" : shortenstring(e->e_to, @@ -3756,7 +3773,7 @@ markfailure(e, q, mci, rcode, ovr) { char buf[16]; - (void) sm_snprintf(buf, sizeof buf, "%d", rcode); + (void) sm_snprintf(buf, sizeof(buf), "%d", rcode); q->q_rstatus = sm_rpool_strdup_x(e->e_rpool, buf); } @@ -3830,7 +3847,7 @@ endmailer(mci, e, pv) if (mci->mci_in != NULL && mci->mci_state != MCIS_ERROR && e->e_xfp != NULL) { - while (sfgets(buf, sizeof buf, mci->mci_in, + while (sfgets(buf, sizeof(buf), mci->mci_in, TimeOuts.to_quit, "Draining Input") != NULL) (void) sm_io_fputs(e->e_xfp, SM_TIME_DEFAULT, buf); } @@ -3980,7 +3997,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) statmsg = "250 2.0.0 Sent"; if (e->e_statmsg != NULL) { - (void) sm_snprintf(buf, sizeof buf, "%s (%s)", + (void) sm_snprintf(buf, sizeof(buf), "%s (%s)", statmsg, shortenstring(e->e_statmsg, 403)); statmsg = buf; @@ -3988,7 +4005,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) } else if (exmsg == NULL) { - (void) sm_snprintf(buf, sizeof buf, + (void) sm_snprintf(buf, sizeof(buf), "554 5.3.0 unknown mailer error %d", status); status = EX_UNAVAILABLE; @@ -4054,7 +4071,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) else if (status == EX_NOHOST && h_errno != 0) { statmsg = sm_errstring(h_errno + E_DNSBASE); - (void) sm_snprintf(buf, sizeof buf, "%s (%s)", exmsg + 1, + (void) sm_snprintf(buf, sizeof(buf), "%s (%s)", exmsg + 1, statmsg); statmsg = buf; usestat = true; @@ -4065,14 +4082,14 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) statmsg = exmsg; if (*statmsg++ == ':' && errnum != 0) { - (void) sm_snprintf(buf, sizeof buf, "%s: %s", statmsg, + (void) sm_snprintf(buf, sizeof(buf), "%s: %s", statmsg, sm_errstring(errnum)); statmsg = buf; usestat = true; } else if (bitnset(M_LMTP, m->m_flags) && e->e_statmsg != NULL) { - (void) sm_snprintf(buf, sizeof buf, "%s (%s)", statmsg, + (void) sm_snprintf(buf, sizeof(buf), "%s (%s)", statmsg, shortenstring(e->e_statmsg, 403)); statmsg = buf; usestat = true; @@ -4091,7 +4108,7 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) { if (dsn == NULL) { - (void) sm_snprintf(dsnbuf, sizeof dsnbuf, + (void) sm_snprintf(dsnbuf, sizeof(dsnbuf), "%.*s", off, statmsg + 4); dsn = dsnbuf; } @@ -4112,11 +4129,11 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) Errors++; if ((off = isenhsc(statmsg + 4, ' ')) > 0 && - off < sizeof mbuf - 4) + off < sizeof(mbuf) - 4) { if (dsn == NULL) { - (void) sm_snprintf(dsnbuf, sizeof dsnbuf, + (void) sm_snprintf(dsnbuf, sizeof(dsnbuf), "%.*s", off, statmsg + 4); dsn = dsnbuf; } @@ -4124,12 +4141,12 @@ giveresponse(status, dsn, m, mci, ctladdr, xstart, e, to) /* copy only part of statmsg to mbuf */ (void) sm_strlcpy(mbuf, statmsg, off); - (void) sm_strlcat(mbuf, " %s", sizeof mbuf); + (void) sm_strlcat(mbuf, " %s", sizeof(mbuf)); } else { dsnbuf[0] = '\0'; - (void) sm_snprintf(mbuf, sizeof mbuf, "%.3s %%s", + (void) sm_snprintf(mbuf, sizeof(mbuf), "%.3s %%s", statmsg); off = 4; } @@ -4315,10 +4332,10 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e) # endif /* (STATLEN) > 203 */ /* stat: max 210 bytes */ - if ((bp - buf) > (sizeof buf - ((STATLEN) + 20))) + if ((bp - buf) > (sizeof(buf) - ((STATLEN) + 20))) { /* desperation move -- truncate data */ - bp = buf + sizeof buf - ((STATLEN) + 17); + bp = buf + sizeof(buf) - ((STATLEN) + 17); (void) sm_strlcpy(bp, "...", SPACELEFT(buf, bp)); bp += 3; } @@ -4434,7 +4451,7 @@ logdelivery(m, mci, dsn, status, ctladdr, xstart, e) { p = macvalue('h', e); if (p != NULL && p[0] != '\0') - (void) sm_snprintf(buf, sizeof buf, "relay=%.100s", p); + (void) sm_snprintf(buf, sizeof(buf), "relay=%.100s", p); } if (buf[0] != '\0') sm_syslog(LOG_INFO, e->e_id, "%.1000s", buf); @@ -4481,7 +4498,7 @@ putfromline(mci, e) { char *bang; - expand("\201g", buf, sizeof buf, e); + expand("\201g", buf, sizeof(buf), e); bang = strchr(buf, '!'); if (bang == NULL) { @@ -4495,25 +4512,25 @@ putfromline(mci, e) at = strrchr(buf, '@'); if (at == NULL) { - expand("\201k", hname, sizeof hname, e); + expand("\201k", hname, sizeof(hname), e); at = hname; } else *at++ = '\0'; - (void) sm_snprintf(xbuf, sizeof xbuf, + (void) sm_snprintf(xbuf, sizeof(xbuf), "From %.800s \201d remote from %.100s\n", buf, at); } else { *bang++ = '\0'; - (void) sm_snprintf(xbuf, sizeof xbuf, + (void) sm_snprintf(xbuf, sizeof(xbuf), "From %.800s \201d remote from %.100s\n", bang, buf); template = xbuf; } } - expand(template, buf, sizeof buf, e); + expand(template, buf, sizeof(buf), e); return putxline(buf, strlen(buf), mci, PXLF_HEADER); } @@ -4620,7 +4637,7 @@ putbody(mci, e, separator) if (hvalue("Content-Type", e->e_header) == NULL) { - (void) sm_snprintf(buf, sizeof buf, + (void) sm_snprintf(buf, sizeof(buf), "Content-Type: text/plain; charset=%s", defcharset(e)); if (!putline(buf, mci)) @@ -4688,9 +4705,9 @@ putbody(mci, e, separator) } /* determine end of buffer; allow for short mailer lines */ - buflim = &buf[sizeof buf - 1]; + buflim = &buf[sizeof(buf) - 1]; if (mci->mci_mailer->m_linelimit > 0 && - mci->mci_mailer->m_linelimit < sizeof buf - 1) + mci->mci_mailer->m_linelimit < sizeof(buf) - 1) buflim = &buf[mci->mci_mailer->m_linelimit - 1]; /* copy temp file to output with mapping */ @@ -4836,6 +4853,7 @@ putbody(mci, e, separator) SM_TIME_DEFAULT, mci->mci_mailer->m_eol); } + pos = 0; ostate = OSTATE_HEAD; continue; } @@ -5135,13 +5153,13 @@ mailfile(filename, mailer, ctladdr, sfflags, e) if (strncmp(SafeFileEnv, filename, len) == 0) filename += len; - if (len + strlen(filename) + 1 >= sizeof targetfile) + if (len + strlen(filename) + 1 >= sizeof(targetfile)) { syserr("mailfile: filename too long (%s/%s)", SafeFileEnv, filename); return EX_CANTCREAT; } - (void) sm_strlcpy(targetfile, SafeFileEnv, sizeof targetfile); + (void) sm_strlcpy(targetfile, SafeFileEnv, sizeof(targetfile)); realfile = targetfile + len; if (*filename == '/') filename++; @@ -5150,20 +5168,20 @@ mailfile(filename, mailer, ctladdr, sfflags, e) /* paranoia: trailing / should be removed in readcf */ if (targetfile[len - 1] != '/') (void) sm_strlcat(targetfile, - "/", sizeof targetfile); + "/", sizeof(targetfile)); (void) sm_strlcat(targetfile, filename, - sizeof targetfile); + sizeof(targetfile)); } } else if (mailer->m_rootdir != NULL) { - expand(mailer->m_rootdir, targetfile, sizeof targetfile, e); + expand(mailer->m_rootdir, targetfile, sizeof(targetfile), e); len = strlen(targetfile); if (strncmp(targetfile, filename, len) == 0) filename += len; - if (len + strlen(filename) + 1 >= sizeof targetfile) + if (len + strlen(filename) + 1 >= sizeof(targetfile)) { syserr("mailfile: filename too long (%s/%s)", targetfile, filename); @@ -5171,18 +5189,18 @@ mailfile(filename, mailer, ctladdr, sfflags, e) } realfile = targetfile + len; if (targetfile[len - 1] != '/') - (void) sm_strlcat(targetfile, "/", sizeof targetfile); + (void) sm_strlcat(targetfile, "/", sizeof(targetfile)); if (*filename == '/') (void) sm_strlcat(targetfile, filename + 1, - sizeof targetfile); + sizeof(targetfile)); else (void) sm_strlcat(targetfile, filename, - sizeof targetfile); + sizeof(targetfile)); } else { - if (sm_strlcpy(targetfile, filename, sizeof targetfile) >= - sizeof targetfile) + if (sm_strlcpy(targetfile, filename, sizeof(targetfile)) >= + sizeof(targetfile)) { syserr("mailfile: filename too long (%s)", filename); return EX_CANTCREAT; @@ -5460,7 +5478,7 @@ mailfile(filename, mailer, ctladdr, sfflags, e) q = strchr(p, ':'); if (q != NULL) *q = '\0'; - expand(p, buf, sizeof buf, e); + expand(p, buf, sizeof(buf), e); if (q != NULL) *q++ = ':'; if (tTd(11, 20)) @@ -5544,7 +5562,7 @@ mailfile(filename, mailer, ctladdr, sfflags, e) if (ev != NULL) sm_clrevent(ev); - memset(&mcibuf, '\0', sizeof mcibuf); + memset(&mcibuf, '\0', sizeof(mcibuf)); mcibuf.mci_mailer = mailer; mcibuf.mci_out = f; if (bitnset(M_7BITS, mailer->m_flags)) |