From: Wietse Venema Date: Thu, 8 Dec 2005 05:00:00 +0000 (-0500) Subject: postfix-2.2.7 X-Git-Tag: v2.2.7^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e26f0fda655b8c2f64c5740bb07e538077884050;p=thirdparty%2Fpostfix.git postfix-2.2.7 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index d17c89855..d325405a4 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -10730,3 +10730,25 @@ Apologies for any names omitted. be fixed; it must be specified before the message content is received. Files: smtpd/smtpd.c, smtpd/smtpd_check.c, cleanup/cleanup_extracted.c, pickup/pickup.c. + +20051201 + + Bugfix: the LMTP client would reuse a session after negative + reply to the RSET command (which may happen when client and + server somehow get out of sync). Problem found by Christian + Theune. Files: lmtp/lmtp.c, lmtp/lmtp_proto.c. + +20051207 + + Bugfix: race condition in the connection caching protocol, + causing the SMTP delivery agent to hang after delivering + mail, while trying to save a connection. Introduced with + Postfix 2.2.5. Files: scache/scache.c. + +20051208 + + Bugfix: the best_mx_transport, mailbox_transport and + fallback_transport features did not write a per-recipient + defer logfile record when the target delivery agent was + broken. This the analog of queue manager bugfix 20051119. + Files: global/deliver_pass.c. diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c index e9a2b0807..0e6081be5 100644 --- a/postfix/src/global/deliver_pass.c +++ b/postfix/src/global/deliver_pass.c @@ -72,6 +72,9 @@ #include #include +#define DELIVER_PASS_DEFER 1 +#define DELIVER_PASS_UNKNOWN 2 + /* deliver_pass_initial_reply - retrieve initial delivery process response */ static int deliver_pass_initial_reply(VSTREAM *stream) @@ -141,9 +144,10 @@ static int deliver_pass_final_reply(VSTREAM *stream, VSTRING *reason) ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat, ATTR_TYPE_END) != 2) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); - stat = -1; + return (DELIVER_PASS_UNKNOWN); + } else { + return (stat ? DELIVER_PASS_DEFER : 0); } - return (stat); } /* deliver_pass - deliver one per-site queue entry */ @@ -185,10 +189,20 @@ int deliver_pass(const char *class, const char *service, * XXX Can't pass back hop status info because the problem is with a * different transport. */ - if ((status = deliver_pass_initial_reply(stream)) == 0 - && (status = deliver_pass_send_request(stream, request, nexthop, - orig_addr, addr, offs)) == 0) - status = deliver_pass_final_reply(stream, reason); + if (deliver_pass_initial_reply(stream) != 0 + || deliver_pass_send_request(stream, request, nexthop, + orig_addr, addr, offs) != 0) { + status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags), + request->queue_id, orig_addr, addr, + offs, "none", request->arrival_time, + "mail transport unavailable"); + } else if ((status = deliver_pass_final_reply(stream, reason)) + == DELIVER_PASS_UNKNOWN) { + status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags), + request->queue_id, orig_addr, addr, + offs, "none", request->arrival_time, + "unknown mail transport error"); + } /* * Clean up. diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f402600a1..e3ced8a03 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,8 +20,8 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only. */ -#define MAIL_RELEASE_DATE "20051130" -#define MAIL_VERSION_NUMBER "2.2.6" +#define MAIL_RELEASE_DATE "20051208" +#define MAIL_VERSION_NUMBER "2.2.7" #define VAR_MAIL_VERSION "mail_version" #ifdef SNAPSHOT diff --git a/postfix/src/lmtp/lmtp.c b/postfix/src/lmtp/lmtp.c index e9078e551..763c05229 100644 --- a/postfix/src/lmtp/lmtp.c +++ b/postfix/src/lmtp/lmtp.c @@ -365,7 +365,8 @@ static int deliver_message(DELIVER_REQUEST *request, char **unused_argv) * Disconnect if RSET can't be sent over an existing connection. * Discard transcript and status information for sending RSET. */ - else if (lmtp_rset(state) != 0) { + else if (lmtp_rset(state) != 0 + || (state->features & LMTP_FEATURE_RSET_REJECTED) != 0) { lmtp_chat_reset(state); state->session = lmtp_session_free(state->session); #ifdef USE_SASL_AUTH diff --git a/postfix/src/lmtp/lmtp.h b/postfix/src/lmtp/lmtp.h index 2c30226c4..31a3b9066 100644 --- a/postfix/src/lmtp/lmtp.h +++ b/postfix/src/lmtp/lmtp.h @@ -66,6 +66,7 @@ typedef struct LMTP_STATE { #define LMTP_FEATURE_XFORWARD_PROTO (1<<8) #define LMTP_FEATURE_XFORWARD_HELO (1<<9) #define LMTP_FEATURE_XFORWARD_DOMAIN (1<<10) +#define LMTP_FEATURE_RSET_REJECTED (1<<11) /* * lmtp.c diff --git a/postfix/src/lmtp/lmtp_proto.c b/postfix/src/lmtp/lmtp_proto.c index ebfa6323d..cdc318952 100644 --- a/postfix/src/lmtp/lmtp_proto.c +++ b/postfix/src/lmtp/lmtp_proto.c @@ -31,6 +31,7 @@ /* accordingly. /* /* lmtp_rset() sends a lone RSET command and waits for the response. +/* In case of a negative reply it sets the CANT_RSET_THIS_SESSION flag. /* /* lmtp_quit() sends a lone QUIT command and waits for the response /* only if waiting for QUIT replies is enabled. @@ -354,6 +355,9 @@ static int lmtp_loop(LMTP_STATE *state, NOCLOBBER int send_state, #define SENDING_MAIL \ (recv_state <= LMTP_STATE_DOT) +#define CANT_RSET_THIS_SESSION \ + (state->features |= LMTP_FEATURE_RSET_REJECTED) + /* * Pipelining support requires two loops: one loop for sending and one * for receiving. Each loop has its own independent state. Most of the @@ -734,6 +738,8 @@ static int lmtp_loop(LMTP_STATE *state, NOCLOBBER int send_state, * Ignore the RSET response. */ case LMTP_STATE_RSET: + if (resp->code / 100 != 2) + CANT_RSET_THIS_SESSION; recv_state = LMTP_STATE_LAST; break; diff --git a/postfix/src/scache/scache.c b/postfix/src/scache/scache.c index deb6f0dad..4046b6424 100644 --- a/postfix/src/scache/scache.c +++ b/postfix/src/scache/scache.c @@ -422,6 +422,7 @@ static void scache_service(VSTREAM *client_stream, char *unused_service, * dedicated to the scache service. All connection-management stuff is * handled by the common code in multi_server.c. */ +do { if (attr_scan(client_stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_REQ, scache_request, @@ -442,6 +443,7 @@ static void scache_service(VSTREAM *client_stream, char *unused_service, ATTR_TYPE_END); } } +} while (vstream_peek(client_stream) > 0); vstream_fflush(client_stream); }