From fd0940608c8db7fd470593f4b53a39d603630269 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Tue, 5 Dec 2006 00:00:00 -0500 Subject: [PATCH] postfix-2.3.5-RC1 --- postfix/AAAREADME | 4 +- postfix/HISTORY | 58 +++++++++++++++++++ postfix/README_FILES/ADDRESS_REWRITING_README | 18 +++--- postfix/conf/post-install | 10 ++-- postfix/html/ADDRESS_REWRITING_README.html | 18 +++--- postfix/proto/ADDRESS_REWRITING_README.html | 18 +++--- postfix/src/cleanup/cleanup_message.c | 29 ++++++++++ postfix/src/cleanup/cleanup_milter.c | 12 ++++ postfix/src/cleanup/cleanup_out.c | 13 +++++ postfix/src/global/dict_proxy.c | 4 +- postfix/src/global/mail_version.h | 4 +- postfix/src/global/resolve_clnt.c | 4 +- postfix/src/global/rewrite_clnt.c | 4 +- postfix/src/global/scache_clnt.c | 6 +- postfix/src/global/verify_clnt.c | 4 +- postfix/src/milter/milter8.c | 47 +++++++++++---- postfix/src/oqmgr/qmgr_entry.c | 2 +- postfix/src/qmgr/qmgr_job.c | 10 ++++ postfix/src/qmgr/qmgr_message.c | 3 + postfix/src/smtp/smtp_chat.c | 3 +- postfix/src/smtp/smtp_connect.c | 8 ++- postfix/src/smtp/smtp_proto.c | 2 + 22 files changed, 226 insertions(+), 55 deletions(-) diff --git a/postfix/AAAREADME b/postfix/AAAREADME index d68a0f16d..e78b4d8e1 100644 --- a/postfix/AAAREADME +++ b/postfix/AAAREADME @@ -135,7 +135,6 @@ Postfix daemons: src/cleanup/ Canonicalize and enqueue mail src/discard/ Trivial discard mailer src/error/ Trivial error mailer - src/lmtp/ LMTP client src/local/ Local delivery src/master/ Postfix resident superserver src/oqmgr/ Old queue manager @@ -144,9 +143,10 @@ Postfix daemons: src/qmgr/ Queue manager src/qmqpd/ QMQPD server src/showq/ List Postfix queue status - src/smtp/ SMTP client + src/smtp/ SMTP and LMTP client src/smtpd/ SMTP server src/spawn/ Run non-Postfix server + src/tlsmgr/ TLS session keys and random pool src/trivial-rewrite/ Address rewriting and resolving src/verify/ address verification service src/virtual/ virtual mailbox-only delivery agent diff --git a/postfix/HISTORY b/postfix/HISTORY index b26603692..ba6c0b991 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -12769,3 +12769,61 @@ Apologies for any names omitted. Bugfix: null pointer bug when receiving a non-protocol response on a cached SMTP/LMTP connection. Report by Brian Kantor. Fix by Victor Duchovni. File: smtp/smtp_reuse.c. + +20061113 + + Bugfix: the Postfix install/upgrade procedure broke with + non-default config_directory. File: conf/post-install. + +20061115 + + Bugfix: null pointer bug in end-of-header Milter action + when the last header line is too large. Reported by Mark + Martinec. The root of the problem is that the MIME state + engine may execute up to three call-back functions when it + reaches the end of the headers, before it returns to the + caller; as long as call-backs return no result, each call-back + has to check for itself if a previous call-back ran into a + problem. File: milter/milter8.c. + + Workaround: reduce effective header_size_limit to 60000 + when Milter inspection is enabled, to avoid breaking the + Milter protocol request length limit. File: + cleanup/cleanup_message.c. + +20061123 + + Workaround: more agressive early refill of in-memory + recipients to prevent a worst-case scenario where the queue + manager became starved until after the last batch of slow + in-memory recipients of jumbo multi-recipient mail. Files: + qmgr/qmgr_job.c. + + Safety: don't read more than 5000 recipients at a time, to + avoid spending too much time away from interrupts. File: + qmgr/qmgr_message.c. + +20061201 + + Workaround: don't complain with "Error 0" in the trivial-rewrite, + verify, proxymap or connection cache client when the server + exits after the client sends its request. We still complain, + however, when the problem persists. Files: global/rewrite_clnt.c, + global/resolve_clnt.c, global/verify_clnt.c, global/scache_clnt.c, + global/dict_proxy.c. + + + Safety: the header_size_limit is now enforced more strictly, + to avoid inter-operability problems with the Milter protocol. + Long headers are truncated at a line boundary if possible, + otherwise they are cut between line boundaries. File: + cleanup/cleanup_out.c. + +20061203 + + Bugfix (introduced with Postfix 2.2): with SMTP server + tarpit delays of smtp_rset_timeout or larger, the SMTP + client could get out of sync with the server while reusing + a connection. The symptoms were "recipient rejected .. in + reply to DATA". Fix by Victor Duchovni and Wietse. File: + smtp/smtp_proto.c. diff --git a/postfix/README_FILES/ADDRESS_REWRITING_README b/postfix/README_FILES/ADDRESS_REWRITING_README index 5a701344a..b7e75ad5a 100644 --- a/postfix/README_FILES/ADDRESS_REWRITING_README +++ b/postfix/README_FILES/ADDRESS_REWRITING_README @@ -787,14 +787,14 @@ mailbox, or delivery to non-Postfix command. Content-Description: Notification Content-Type: text/plain - This is the Postfix program at host spike.porcupine.org. + This is the mail system at host spike.porcupine.org. Enclosed is the mail delivery report that you requested. - The Postfix program + The mail system : delivery via mail.cloud9.net[168.100.1.4]: 250 - Ok + 2.1.5 Ok The second part of the report is in machine-readable form, and includes the following information: @@ -814,13 +814,13 @@ version 2.3 and later. Reporting-MTA: dns; spike.porcupine.org X-Postfix-Queue-ID: 84863BC0E5 X-Postfix-Sender: rfc822; wietse@porcupine.org - Arrival-Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT) + Arrival-Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) Final-Recipient: rfc822; postfix-users@postfix.org Action: deliverable - Status: 2.0.0 + Status: 2.1.5 Remote-MTA: dns; mail.cloud9.net - Diagnostic-Code: smtp; 250 Ok + Diagnostic-Code: smtp; 250 2.1.5 Ok The third part of the report contains the message that Postfix would have delivered, including From: and To: message headers, so that you can see any @@ -831,10 +831,10 @@ no body content so none is shown in the example below. Content-Type: message/rfc822 Received: by spike.porcupine.org (Postfix, from userid 1001) - id 84863BC0E5; Tue, 13 Apr 2004 19:27:43 -0400 (EDT) + id 84863BC0E5; Sun, 26 Nov 2006 17:01:01 -0500 (EST) Subject: probe To: postfix-users@postfix.org - Message-Id: <20040413232743.84863BC0E5@spike.porcupine.org> - Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT) + Message-Id: <20061126220101.84863BC0E5@spike.porcupine.org> + Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) From: wietse@porcupine.org (Wietse Venema) diff --git a/postfix/conf/post-install b/postfix/conf/post-install index c64ff19f6..54b3b93bc 100644 --- a/postfix/conf/post-install +++ b/postfix/conf/post-install @@ -589,14 +589,14 @@ EOF # This safety net is also documented in LOCAL_RECIPIENT_README. unknown_local=unknown_local_recipient_reject_code - has_lrm=`$POSTCONF -n local_recipient_maps` - has_lrjc=`$POSTCONF -n $unknown_local` + has_lrm=`$POSTCONF -c $config_directory -n local_recipient_maps` + has_lrjc=`$POSTCONF -c $config_directory -n $unknown_local` if [ -z "$has_lrm" -a -z "$has_lrjc" ] then echo SAFETY: editing main.cf, setting $unknown_local=450. echo See the LOCAL_RECIPIENT_README file for details. - $POSTCONF -e "$unknown_local = 450" || exit 1 + $POSTCONF -c $config_directory -e "$unknown_local = 450" || exit 1 fi # Add missing proxymap service to master.cf. @@ -678,8 +678,8 @@ EOF test -n "$first_install_reminder" && { - ALIASES=`$POSTCONF -h alias_database | sed 's/^[^:]*://'` - NEWALIASES_PATH=`$POSTCONF -h newaliases_path` + ALIASES=`$POSTCONF -c $config_directory -h alias_database | sed 's/^[^:]*://'` + NEWALIASES_PATH=`$POSTCONF -c $config_directory -h newaliases_path` cat < Content-Description: Notification Content-Type: text/plain -This is the Postfix program at host spike.porcupine.org. +This is the mail system at host spike.porcupine.org. Enclosed is the mail delivery report that you requested. - The Postfix program + The mail system -<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 Ok +<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 2.1.5 Ok @@ -1210,13 +1210,13 @@ Content-Type: message/delivery-status Reporting-MTA: dns; spike.porcupine.org X-Postfix-Queue-ID: 84863BC0E5 X-Postfix-Sender: rfc822; wietse@porcupine.org -Arrival-Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT) +Arrival-Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) Final-Recipient: rfc822; postfix-users@postfix.org Action: deliverable -Status: 2.0.0 +Status: 2.1.5 Remote-MTA: dns; mail.cloud9.net -Diagnostic-Code: smtp; 250 Ok +Diagnostic-Code: smtp; 250 2.1.5 Ok @@ -1232,11 +1232,11 @@ Content-Description: Message Content-Type: message/rfc822 Received: by spike.porcupine.org (Postfix, from userid 1001) - id 84863BC0E5; Tue, 13 Apr 2004 19:27:43 -0400 (EDT) + id 84863BC0E5; Sun, 26 Nov 2006 17:01:01 -0500 (EST) Subject: probe To: postfix-users@postfix.org -Message-Id: <20040413232743.84863BC0E5@spike.porcupine.org> -Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT) +Message-Id: <20061126220101.84863BC0E5@spike.porcupine.org> +Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) From: wietse@porcupine.org (Wietse Venema) diff --git a/postfix/proto/ADDRESS_REWRITING_README.html b/postfix/proto/ADDRESS_REWRITING_README.html index 76c78e0cb..3fef90643 100644 --- a/postfix/proto/ADDRESS_REWRITING_README.html +++ b/postfix/proto/ADDRESS_REWRITING_README.html @@ -1174,13 +1174,13 @@ to mailbox, or delivery to non-Postfix command.

Content-Description: Notification Content-Type: text/plain -This is the Postfix program at host spike.porcupine.org. +This is the mail system at host spike.porcupine.org. Enclosed is the mail delivery report that you requested. - The Postfix program + The mail system -<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 Ok +<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 2.1.5 Ok @@ -1210,13 +1210,13 @@ Content-Type: message/delivery-status Reporting-MTA: dns; spike.porcupine.org X-Postfix-Queue-ID: 84863BC0E5 X-Postfix-Sender: rfc822; wietse@porcupine.org -Arrival-Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT) +Arrival-Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) Final-Recipient: rfc822; postfix-users@postfix.org Action: deliverable -Status: 2.0.0 +Status: 2.1.5 Remote-MTA: dns; mail.cloud9.net -Diagnostic-Code: smtp; 250 Ok +Diagnostic-Code: smtp; 250 2.1.5 Ok @@ -1232,11 +1232,11 @@ Content-Description: Message Content-Type: message/rfc822 Received: by spike.porcupine.org (Postfix, from userid 1001) - id 84863BC0E5; Tue, 13 Apr 2004 19:27:43 -0400 (EDT) + id 84863BC0E5; Sun, 26 Nov 2006 17:01:01 -0500 (EST) Subject: probe To: postfix-users@postfix.org -Message-Id: <20040413232743.84863BC0E5@spike.porcupine.org> -Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT) +Message-Id: <20061126220101.84863BC0E5@spike.porcupine.org> +Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) From: wietse@porcupine.org (Wietse Venema) diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 5af24c59c..5e71c8b89 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -596,6 +596,16 @@ static void cleanup_header_done_callback(void *context) TOK822 *token; time_t tv; + /* + * XXX Workaround: when we reach the end of headers, mime_state_update() + * may execute up to three call-backs before returning to the caller: + * head_out(), head_end(), and body_out() or body_end(). As long as + * call-backs don't return a result, each call-back has to check for + * itself if the previous call-back experienced a problem. + */ + if (CLEANUP_OUT_OK(state) == 0) + return; + /* * Add a missing (Resent-)Message-Id: header. The message ID gives the * time in GMT units, plus the local queue ID. @@ -706,6 +716,16 @@ static void cleanup_body_callback(void *context, int type, { CLEANUP_STATE *state = (CLEANUP_STATE *) context; + /* + * XXX Workaround: when we reach the end of headers, mime_state_update() + * may execute up to three call-backs before returning to the caller: + * head_out(), head_end(), and body_out() or body_end(). As long as + * call-backs don't return a result, each call-back has to check for + * itself if the previous call-back experienced a problem. + */ + if (CLEANUP_OUT_OK(state) == 0) + return; + /* * Crude message body content filter for emergencies. This code has * several problems: it sees one line at a time; it looks at long lines @@ -892,6 +912,15 @@ void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t cleanup_mime_error_callback, (void *) state); + /* + * XXX Workaround: truncate a long message header so that we don't exceed + * the Milter request size limit of 65535. + */ +#define KLUDGE_HEADER_LIMIT 60000 + if ((cleanup_milters || state->milters) + && var_header_limit > KLUDGE_HEADER_LIMIT) + var_header_limit = KLUDGE_HEADER_LIMIT; + /* * Pass control to the header processing routine. */ diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index 6e40e1680..5836159c4 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -1697,6 +1697,8 @@ static void usage(void) msg_warn(" del_rcpt addr"); } +/* flatten_args - unparse partial command line */ + static void flatten_args(VSTRING *buf, char **argv) { char **cpp; @@ -1710,6 +1712,8 @@ static void flatten_args(VSTRING *buf, char **argv) VSTRING_TERMINATE(buf); } +/* open_queue_file - open an unedited queue file (all-zero dummy PTRs) */ + static void open_queue_file(CLEANUP_STATE *state, const char *path) { VSTRING *buf = vstring_alloc(100); @@ -1720,6 +1724,13 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path) long rcpt_count; long qmgr_opts; + if (state->dst != 0) { + msg_warn("closing %s", cleanup_path); + vstream_fclose(state->dst); + state->dst = 0; + myfree(cleanup_path); + cleanup_path = 0; + } if ((state->dst = vstream_fopen(path, O_RDWR, 0)) == 0) { msg_warn("open %s: %m", path); } else { @@ -1794,6 +1805,7 @@ int main(int unused_argc, char **argv) msg_vstream_init(argv[0], VSTREAM_ERR); var_line_limit = DEF_LINE_LIMIT; + var_header_limit = DEF_HEADER_LIMIT; for (;;) { ARGV *argv; diff --git a/postfix/src/cleanup/cleanup_out.c b/postfix/src/cleanup/cleanup_out.c index c81637372..52d3211fb 100644 --- a/postfix/src/cleanup/cleanup_out.c +++ b/postfix/src/cleanup/cleanup_out.c @@ -175,9 +175,22 @@ void cleanup_out_header(CLEANUP_STATE *state, VSTRING *header_buf) * of such header lines. NB: This code destroys the header. We could try * to avoid clobbering it, but we're not going to use the data any * further. + * + * XXX We prefer to truncate a header at the last line boundary before the + * header size limit. If this would undershoot the limit by more than + * 10%, we truncate between line boundaries to avoid losing too much + * text. This "unkind cut" may result in syntax errors and may trigger + * warnings from down-stream MTAs. */ for (line = start; line; line = next_line) { next_line = split_at(line, '\n'); + if ((next_line ? next_line - 1 : line + strlen(line)) + > start + var_header_limit) { + if (line - start > 0.9 * var_header_limit) /* nice cut */ + break; + start[var_header_limit] = 0; /* unkind cut */ + next_line = 0; + } if (line == start || IS_SPACE_TAB(*line)) { cleanup_out_string(state, REC_TYPE_NORM, line); } else { diff --git a/postfix/src/global/dict_proxy.c b/postfix/src/global/dict_proxy.c index 5ce496af7..b8da5abce 100644 --- a/postfix/src/global/dict_proxy.c +++ b/postfix/src/global/dict_proxy.c @@ -90,6 +90,7 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key) DICT_PROXY *dict_proxy = (DICT_PROXY *) dict; VSTREAM *stream; int status; + int count = 0; /* * The client and server live in separate processes that may start and @@ -103,6 +104,7 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key) for (;;) { stream = clnt_stream_access(proxy_stream); errno = 0; + count += 1; if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_LOOKUP, ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict->name, @@ -114,7 +116,7 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key) ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_VALUE, dict_proxy->result, ATTR_TYPE_END) != 2) { - if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream)); } else { if (msg_verbose) diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 7e9562ced..22caf42e5 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,8 +20,8 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20061101" -#define MAIL_VERSION_NUMBER "2.3.4" +#define MAIL_RELEASE_DATE "20061205" +#define MAIL_VERSION_NUMBER "2.3.5-RC1" #ifdef SNAPSHOT # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff --git a/postfix/src/global/resolve_clnt.c b/postfix/src/global/resolve_clnt.c index 1b9ae4e8d..b96f0a736 100644 --- a/postfix/src/global/resolve_clnt.c +++ b/postfix/src/global/resolve_clnt.c @@ -164,6 +164,7 @@ void resolve_clnt(const char *class, const char *sender, const char *myname = "resolve_clnt"; VSTREAM *stream; int server_flags; + int count = 0; /* * One-entry cache. @@ -226,6 +227,7 @@ void resolve_clnt(const char *class, const char *sender, for (;;) { stream = clnt_stream_access(rewrite_clnt_stream); errno = 0; + count += 1; if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, class, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, @@ -239,7 +241,7 @@ void resolve_clnt(const char *class, const char *sender, ATTR_TYPE_STR, MAIL_ATTR_RECIP, reply->recipient, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &reply->flags, ATTR_TYPE_END) != 5) { - if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", var_rewrite_service); } else { diff --git a/postfix/src/global/rewrite_clnt.c b/postfix/src/global/rewrite_clnt.c index 601f7ca00..8bb3f0a52 100644 --- a/postfix/src/global/rewrite_clnt.c +++ b/postfix/src/global/rewrite_clnt.c @@ -82,6 +82,7 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) { VSTREAM *stream; int server_flags; + int count = 0; /* * One-entry cache. @@ -129,6 +130,7 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) for (;;) { stream = clnt_stream_access(rewrite_clnt_stream); errno = 0; + count += 1; if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, REWRITE_ADDR, ATTR_TYPE_STR, MAIL_ATTR_RULE, rule, @@ -139,7 +141,7 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &server_flags, ATTR_TYPE_STR, MAIL_ATTR_ADDR, result, ATTR_TYPE_END) != 2) { - if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", var_rewrite_service); } else { diff --git a/postfix/src/global/scache_clnt.c b/postfix/src/global/scache_clnt.c index 10573e7df..658e88f75 100644 --- a/postfix/src/global/scache_clnt.c +++ b/postfix/src/global/scache_clnt.c @@ -91,6 +91,7 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, VSTREAM *stream; int status; int tries; + int count = 0; if (msg_verbose) msg_info("%s: endp=%s prop=%s fd=%d", @@ -110,6 +111,7 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, for (tries = 0; sp->auto_clnt != 0; tries++) { if ((stream = auto_clnt_access(sp->auto_clnt)) != 0) { errno = 0; + count += 1; if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, SCACHE_REQ_SAVE_ENDP, ATTR_TYPE_INT, MAIL_ATTR_TTL, endp_ttl, @@ -126,7 +128,7 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, || attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) { - if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", VSTREAM_PATH(stream)); /* Give up or recover. */ @@ -281,7 +283,7 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl, myname, status); break; } - } + } /* Give up or recover. */ if (tries >= SCACHE_MAX_TRIES - 1) { msg_warn("disabling connection caching"); diff --git a/postfix/src/global/verify_clnt.c b/postfix/src/global/verify_clnt.c index 916cce3fc..7468c1f0c 100644 --- a/postfix/src/global/verify_clnt.c +++ b/postfix/src/global/verify_clnt.c @@ -96,6 +96,7 @@ int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why) { VSTREAM *stream; int request_status; + int count = 0; /* * Do client-server plumbing. @@ -109,6 +110,7 @@ int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why) for (;;) { stream = clnt_stream_access(vrfy_clnt); errno = 0; + count += 1; if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, VRFY_REQ_QUERY, ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr, @@ -119,7 +121,7 @@ int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why) ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, addr_status, ATTR_TYPE_STR, MAIL_ATTR_WHY, why, ATTR_TYPE_END) != 3) { - if (msg_verbose || (errno != EPIPE && errno != ENOENT)) + if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", var_verify_service); } else { diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index b4105c0cb..4ded90673 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -858,6 +858,7 @@ static const char *milter8_event(MILTER8 *milter, int event, int skip_reply, ARGV *macros,...) { + const char *myname = "milter8_event"; va_list ap; ssize_t data_len; int err; @@ -871,6 +872,17 @@ static const char *milter8_event(MILTER8 *milter, int event, #define DONT_SKIP_REPLY 0 + /* + * Sanity check. + */ + if (milter->fp == 0 || milter->def_reply != 0) { + msg_warn("%s: attempt to send event %s to milter %s after error", + myname, + (smfic_name = str_name_code(smfic_table, event)) != 0 ? + smfic_name : "(unknown MTA event)", milter->m.name); + return (milter->def_reply); + } + /* * Skip this event if it doesn't exist in the protocol that I announced. */ @@ -1185,7 +1197,7 @@ static const char *milter8_event(MILTER8 *milter, int event, (ssize_t) index, STR(milter->buf)); if (edit_resp) - return (milter8_def_reply(milter, edit_resp)); + return (edit_resp); continue; #endif @@ -1203,7 +1215,7 @@ static const char *milter8_event(MILTER8 *milter, int event, STR(milter->buf), STR(milter->body)); if (edit_resp) - return (milter8_def_reply(milter, edit_resp)); + return (edit_resp); continue; /* @@ -1232,7 +1244,7 @@ static const char *milter8_event(MILTER8 *milter, int event, STR(milter->buf), STR(milter->body)); if (edit_resp) - return (milter8_def_reply(milter, edit_resp)); + return (edit_resp); continue; #endif @@ -1248,7 +1260,7 @@ static const char *milter8_event(MILTER8 *milter, int event, edit_resp = parent->add_rcpt(parent->chg_context, STR(milter->buf)); if (edit_resp) - return (milter8_def_reply(milter, edit_resp)); + return (edit_resp); continue; /* @@ -1263,7 +1275,7 @@ static const char *milter8_event(MILTER8 *milter, int event, edit_resp = parent->del_rcpt(parent->chg_context, STR(milter->buf)); if (edit_resp) - return (milter8_def_reply(milter, edit_resp)); + return (edit_resp); continue; /* @@ -1280,7 +1292,7 @@ static const char *milter8_event(MILTER8 *milter, int event, edit_resp = parent->repl_body(parent->chg_context, milter->body); if (edit_resp) - return (milter8_def_reply(milter, edit_resp)); + return (edit_resp); continue; #endif } @@ -1927,6 +1939,16 @@ static void milter8_header(void *ptr, int unused_header_class, char *cp; int skip_reply; + /* + * XXX Workaround: mime_state_update() may invoke multiple call-backs + * before returning to the caller. + */ +#define MILTER8_MESSAGE_DONE(milter, msg_ctx) \ + ((milter)->state != MILTER8_STAT_MESSAGE || (msg_ctx)->resp != 0) + + if (MILTER8_MESSAGE_DONE(milter, msg_ctx)) + return; + /* * XXX Sendmail compatibility. Don't expose our first (received) header * to mail filter applications. See also cleanup_milter.c for code to @@ -1990,6 +2012,8 @@ static void milter8_eoh(void *ptr) MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr; MILTER8 *milter = msg_ctx->milter; + if (MILTER8_MESSAGE_DONE(milter, msg_ctx)) + return; if (msg_verbose) msg_info("%s: eoh milter %s", myname, milter->m.name); msg_ctx->resp = @@ -2012,6 +2036,9 @@ static void milter8_body(void *ptr, int rec_type, ssize_t space; ssize_t count; + if (MILTER8_MESSAGE_DONE(milter, msg_ctx)) + return; + /* * XXX Sendmail compatibility: don't expose our first body line. */ @@ -2079,6 +2106,8 @@ static void milter8_eob(void *ptr) MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr; MILTER8 *milter = msg_ctx->milter; + if (MILTER8_MESSAGE_DONE(milter, msg_ctx)) + return; if (msg_verbose) msg_info("%s: eob milter %s", myname, milter->m.name); msg_ctx->resp = @@ -2144,7 +2173,7 @@ static const char *milter8_message(MILTER *m, VSTREAM *qfile, /* * XXX When the message (not MIME body part) does not end in CRLF - * (i.e. the last record was REC_TYPE_CONT), do we send CRLF + * (i.e. the last record was REC_TYPE_CONT), do we send a CRLF * terminator before triggering the end-of-body condition? */ for (;;) { @@ -2164,9 +2193,7 @@ static const char *milter8_message(MILTER *m, VSTREAM *qfile, msg_ctx.resp = "450 4.3.0 Queue file write error"; break; } - if (msg_ctx.resp != 0) - break; - if (milter->state != MILTER8_STAT_MESSAGE) + if (MILTER8_MESSAGE_DONE(milter, &msg_ctx)) break; if (rec_type != REC_TYPE_NORM && rec_type != REC_TYPE_CONT) break; diff --git a/postfix/src/oqmgr/qmgr_entry.c b/postfix/src/oqmgr/qmgr_entry.c index 3783a61f1..ccffdb0b0 100644 --- a/postfix/src/oqmgr/qmgr_entry.c +++ b/postfix/src/oqmgr/qmgr_entry.c @@ -237,7 +237,7 @@ void qmgr_entry_done(QMGR_ENTRY *entry, int which) #define FUDGE(x) ((x) * (var_qmgr_fudge / 100.0)) message->refcount--; if (message->rcpt_offset > 0 - && qmgr_recipient_count < FUDGE(var_qmgr_rcpt_limit)) + && qmgr_recipient_count < FUDGE(var_qmgr_rcpt_limit) - 100) qmgr_message_realloc(message); if (message->refcount == 0) qmgr_active_done(message); diff --git a/postfix/src/qmgr/qmgr_job.c b/postfix/src/qmgr/qmgr_job.c index 30365f6a8..6318893f4 100644 --- a/postfix/src/qmgr/qmgr_job.c +++ b/postfix/src/qmgr/qmgr_job.c @@ -763,6 +763,16 @@ static QMGR_PEER *qmgr_job_peer_select(QMGR_JOB *job) QMGR_PEER *peer; QMGR_MESSAGE *message = job->message; + /* + * Workaround to prevent queue manager starvation until the last slow + * batch of multi-recipient mail is finished. Postfix 2.4 has a final + * solution, but that involves major changes. + */ + if (message->rcpt_offset != 0 + && message->rcpt_limit > message->rcpt_count + 100 + && message->refcount > 0) { + qmgr_message_realloc(message); + } if (HAS_ENTRIES(job) && (peer = qmgr_peer_select(job)) != 0) return (peer); diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index aa71e1907..dcb796df0 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -361,6 +361,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message) if (recipient_limit < message->rcpt_limit) recipient_limit = message->rcpt_limit; } + /* Keep interrupt latency in check. */ + if (recipient_limit > 5000) + recipient_limit = 5000; if (recipient_limit <= 0) msg_panic("%s: no recipient slots available", message->queue_id); diff --git a/postfix/src/smtp/smtp_chat.c b/postfix/src/smtp/smtp_chat.c index 82ea27564..252924f92 100644 --- a/postfix/src/smtp/smtp_chat.c +++ b/postfix/src/smtp/smtp_chat.c @@ -305,7 +305,8 @@ SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session) */ session->error_mask |= MAIL_ERROR_PROTOCOL; if (session->features & SMTP_FEATURE_PIPELINING) { - msg_warn("non-%s response from %s: %.100s", + msg_warn("%s: non-%s response from %s: %.100s", + session->state->request->queue_id, (session->state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "ESMTP", session->namaddrport, STR(session->buffer)); diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c index 3f87e7dc3..19b5267f4 100644 --- a/postfix/src/smtp/smtp_connect.c +++ b/postfix/src/smtp/smtp_connect.c @@ -379,7 +379,11 @@ static void smtp_cleanup_session(SMTP_STATE *state) bad_session = THIS_SESSION_IS_BAD; /* smtp_quit() may fail */ if (THIS_SESSION_IS_EXPIRED) smtp_quit(state); /* also disables caching */ - if (THIS_SESSION_IS_CACHED) { + if (THIS_SESSION_IS_CACHED + /* Redundant tests for safety... */ + && vstream_ferror(session->stream) == 0 + && vstream_ftimeout(session->stream) == 0 + && vstream_feof(session->stream) == 0) { smtp_save_session(state); } else { smtp_session_free(session); @@ -493,6 +497,7 @@ static void smtp_connect_local(SMTP_STATE *state, const char *path) && smtp_helo(state) != 0) { if (!THIS_SESSION_IS_DEAD && vstream_ferror(session->stream) == 0 + && vstream_ftimeout(session->stream) == 0 && vstream_feof(session->stream) == 0) smtp_quit(state); } else { @@ -871,6 +876,7 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop, */ if (!THIS_SESSION_IS_DEAD && vstream_ferror(session->stream) == 0 + && vstream_ftimeout(session->stream) == 0 && vstream_feof(session->stream) == 0) smtp_quit(state); } else { diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 276db41ce..23ed31648 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -1014,6 +1014,8 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, } while (0) #define RETURN(x) do { \ + if (recv_state != SMTP_STATE_LAST) \ + DONT_CACHE_THIS_SESSION; \ vstring_free(next_command); \ if (survivors) \ myfree((char *) survivors); \