From: Wietse Venema Date: Fri, 20 Jul 2007 05:00:00 +0000 (-0500) Subject: postfix-2.4.4-RC4 X-Git-Tag: v2.4.4-RC4^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=940147e72cd8ac3dc507edd6d3df2818588faf09;p=thirdparty%2Fpostfix.git postfix-2.4.4-RC4 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 5cd65d01b..38de68661 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -13509,3 +13509,11 @@ Apologies for any names omitted. Portability: /dev/poll support for Solaris chroot jail setup scripts. Files: examples/chroot-setup/Solaris8, examples/chroot-setup/Solaris10. + +20070719 + + Cleanup: streamlined Milter client error handling, so that + the (Postfix SMTP server's Milter client) does not get out + of sync with Milter applications after the (cleanup server's + Milter client) encounters some non-recoverable problem. + Files: milter/milter8.c, smtpd/smtpd.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index ecbe12960..cf371e567 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -14,12 +14,13 @@ specifies the release date of a stable release or snapshot release. Incompatibility with Postfix 2.4.4 ================================== -By default, the Cyrus SASL client no longer sends an authoriZation -ID (authzid); it sends only the authentiCation ID (authcid) plus -the authcid's password. Specify "send_cyrus_sasl_authzid = yes" to -get the old behavior, which is to send the (authzid, authcid, -password), with the authzid equal to the authcid. This workaround -for non-Cyrus SASL servers is back-ported from Postfix 2.5. +By default, the Postfix Cyrus SASL client no longer sends a SASL +authoriZation ID (authzid); it sends only the SASL authentiCation +ID (authcid) plus the authcid's password. Specify "send_cyrus_sasl_authzid += yes" to get the old behavior, which is to send the (authzid, +authcid, password), with the authzid equal to the authcid. This +workaround for non-Cyrus SASL servers is back-ported from Postfix +2.5. Release notes for Postfix 2.4.0 =============================== diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html index c00a1ea8d..d9a7767de 100644 --- a/postfix/html/lmtp.8.html +++ b/postfix/html/lmtp.8.html @@ -256,10 +256,10 @@ SMTP(8) SMTP(8) Available in Postfix version 2.4.4 and later: send_cyrus_sasl_authzid (no) - When authenticating to a SASL server with the - default setting "no", send no authoriZation ID - (authzid); send only the authentiCation ID (auth- - cid) plus the authcid's password. + When authenticating to a remote SMTP or LMTP server + with the default setting "no", send no SASL autho- + riZation ID (authzid); send only the SASL authenti- + Cation ID (authcid) plus the authcid's password. MIME PROCESSING CONTROLS Available in Postfix version 2.0 and later: diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index c799d1f4a..a19b6b341 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -6691,14 +6691,15 @@ The name of the directory with example Postfix configuration files.
send_cyrus_sasl_authzid (default: no)
-

When authenticating to a SASL server with the default setting -"no", send no authoriZation ID (authzid); send only the authentiCation -ID (authcid) plus the authcid's password.

+

When authenticating to a remote SMTP or LMTP server with the +default setting "no", send no SASL authoriZation ID (authzid); send +only the SASL authentiCation ID (authcid) plus the authcid's password. +

The non-default setting "yes" enables the behavior of older -Postfix versions. These always send an authzid that is equal to -the authcid, but this causes inter-operability problems with some -SMTP servers.

+Postfix versions. These always send a SASL authzid that is equal +to the SASL authcid, but this causes inter-operability problems +with some SMTP servers.

This feature is available in Postfix 2.4.4 and later.

diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html index c00a1ea8d..d9a7767de 100644 --- a/postfix/html/smtp.8.html +++ b/postfix/html/smtp.8.html @@ -256,10 +256,10 @@ SMTP(8) SMTP(8) Available in Postfix version 2.4.4 and later: send_cyrus_sasl_authzid (no) - When authenticating to a SASL server with the - default setting "no", send no authoriZation ID - (authzid); send only the authentiCation ID (auth- - cid) plus the authcid's password. + When authenticating to a remote SMTP or LMTP server + with the default setting "no", send no SASL autho- + riZation ID (authzid); send only the SASL authenti- + Cation ID (authcid) plus the authcid's password. MIME PROCESSING CONTROLS Available in Postfix version 2.0 and later: diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 3603d302e..7af763b32 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -3712,14 +3712,14 @@ This feature is available in Postfix 2.0 and later. .SH sample_directory (default: /etc/postfix) The name of the directory with example Postfix configuration files. .SH send_cyrus_sasl_authzid (default: no) -When authenticating to a SASL server with the default setting -"no", send no authoriZation ID (authzid); send only the authentiCation -ID (authcid) plus the authcid's password. +When authenticating to a remote SMTP or LMTP server with the +default setting "no", send no SASL authoriZation ID (authzid); send +only the SASL authentiCation ID (authcid) plus the authcid's password. .PP The non-default setting "yes" enables the behavior of older -Postfix versions. These always send an authzid that is equal to -the authcid, but this causes inter-operability problems with some -SMTP servers. +Postfix versions. These always send a SASL authzid that is equal +to the SASL authcid, but this causes inter-operability problems +with some SMTP servers. .PP This feature is available in Postfix 2.4.4 and later. .SH sender_based_routing (default: no) diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8 index c882a0930..61e91dc7d 100644 --- a/postfix/man/man8/smtp.8 +++ b/postfix/man/man8/smtp.8 @@ -229,9 +229,9 @@ from a remote LMTP server. .PP Available in Postfix version 2.4.4 and later: .IP "\fBsend_cyrus_sasl_authzid (no)\fR" -When authenticating to a SASL server with the default setting -"no", send no authoriZation ID (authzid); send only the authentiCation -ID (authcid) plus the authcid's password. +When authenticating to a remote SMTP or LMTP server with the +default setting "no", send no SASL authoriZation ID (authzid); send +only the SASL authentiCation ID (authcid) plus the authcid's password. .SH "MIME PROCESSING CONTROLS" .na .nf diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index c592b9a03..f5a90edfb 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -10575,13 +10575,14 @@ configuration parameter. See there for details.

%PARAM send_cyrus_sasl_authzid no -

When authenticating to a SASL server with the default setting -"no", send no authoriZation ID (authzid); send only the authentiCation -ID (authcid) plus the authcid's password.

+

When authenticating to a remote SMTP or LMTP server with the +default setting "no", send no SASL authoriZation ID (authzid); send +only the SASL authentiCation ID (authcid) plus the authcid's password. +

The non-default setting "yes" enables the behavior of older -Postfix versions. These always send an authzid that is equal to -the authcid, but this causes inter-operability problems with some -SMTP servers.

+Postfix versions. These always send a SASL authzid that is equal +to the SASL authcid, but this causes inter-operability problems +with some SMTP servers.

This feature is available in Postfix 2.4.4 and later.

diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index a1bca38e8..d260a5ce2 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 "20070711" -#define MAIL_VERSION_NUMBER "2.4.4-RC3" +#define MAIL_RELEASE_DATE "20070720" +#define MAIL_VERSION_NUMBER "2.4.4-RC4" #ifdef SNAPSHOT # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index a3b2e364e..2753d7c4b 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -64,6 +64,10 @@ #include #include +#ifndef SHUT_RDWR +#define SHUT_RDWR 2 +#endif + /* Sendmail 8 Milter protocol. */ #ifdef USE_LIBMILTER_INCLUDES @@ -437,7 +441,22 @@ static int milter8_conf_error(MILTER8 *milter) { const char *reply; + /* + * While reading the following, keep in mind that a client-side Milter + * socket is shared between the Postfix SMTP server and the cleanup + * server. The SMTP server reports only the SMTP events to the Milter. + * The cleanup server reports the headers and body to the Milter, and + * receives the header or body modification requests from the Milter. + * + * XXX When the cleanup server closes its end of the Milter socket after + * some local/remote configuration error, the SMTP server is left out of + * sync with the Milter. Sending an ABORT to the Milters will not restore + * synchronization, because there may be any number of Milter replies + * already in flight. Workaround: poison the socket and force the SMTP + * server to abandon it. + */ if (milter->fp != 0) { + (void) shutdown(vstream_fileno(milter->fp), SHUT_RDWR); (void) vstream_fclose(milter->fp); milter->fp = 0; } @@ -456,7 +475,22 @@ static int milter8_comm_error(MILTER8 *milter) { const char *reply; + /* + * While reading the following, keep in mind that a client-side Milter + * socket is shared between the Postfix SMTP server and the cleanup + * server. The SMTP server reports only the SMTP events to the Milter. + * The cleanup server reports the headers and body to the Milter, and + * receives the header or body modification requests from the Milter. + * + * XXX When the cleanup server closes its end of the Milter socket after + * some local or remote remote protocol error, the SMTP server is left + * out of sync with the Milter. Sending an ABORT to the Milters will not + * restore synchronization, because there may be any number of Milter + * replies already in flight. Workaround: poison the socket and force the + * SMTP server to abandon it. + */ if (milter->fp != 0) { + (void) shutdown(vstream_fileno(milter->fp), SHUT_RDWR); (void) vstream_fclose(milter->fp); milter->fp = 0; } @@ -475,28 +509,6 @@ static int milter8_comm_error(MILTER8 *milter) return (milter->state = MILTER8_STAT_ERROR); } -/* milter8_edit_error - local queue file update error */ - -static void milter8_edit_error(MILTER8 *milter, const char *reply) -{ - - /* - * Close the socket, so we don't have to skip pending replies from this - * Milter instance. - */ - if (milter->fp != 0) { - (void) vstream_fclose(milter->fp); - milter->fp = 0; - } - - /* - * Set the socket state to ERROR, so we don't try to send further MTA - * events to this Milter instance. - */ - milter8_def_reply(milter, reply); - milter->state = MILTER8_STAT_ERROR; -} - /* milter8_close_stream - close stream to milter application */ static void milter8_close_stream(MILTER8 *milter) @@ -895,6 +907,7 @@ static const char *milter8_event(MILTER8 *milter, int event, const char *retval = 0; VSTRING *body_line_buf = 0; int done = 0; + int body_edit_lockout = 0; #define DONT_SKIP_REPLY 0 @@ -1000,6 +1013,22 @@ static const char *milter8_event(MILTER8 *milter, int event, * processing. * * XXX Bound the loop iteration count. + * + * While reading the following, keep in mind that a client-side Milter + * socket is shared between the Postfix SMTP server and the cleanup + * server. The SMTP server reports only the SMTP events to the Milter. + * The cleanup server reports the headers and body to the Milter, and + * receives the header or body modification requests from the Milter. + * + * In the end-of-body stage, the Milter may reply with one or more queue + * file edit requests before it replies with its final decision: accept, + * reject, etc. After a local queue file edit error, do not close the + * Milter socket in the cleanup server. Instead skip all further Milter + * replies until the final decision. This way the Postfix SMTP server + * stays in sync with the Milter, and Postfix doesn't have to lose the + * ability to handle multiple deliveries within the same SMTP session. + * This requires that the Postfix SMTP server uses something other than + * CLEANUP_STAT_WRITE when it loses contact with the cleanup server. */ #define IN_CONNECT_EVENT(e) ((e) == SMFIC_CONNECT || (e) == SMFIC_HELO) @@ -1027,10 +1056,18 @@ static const char *milter8_event(MILTER8 *milter, int event, /* * Handle unfinished message body replacement first. + * + * XXX When SMFIR_REPLBODY is followed by some different request, we + * assume that the body replacement operation is complete. The queue + * file editing implementation currently does not support sending + * part 1 of the body replacement text, doing some other queue file + * updates, and then sending part 2 of the body replacement text. To + * avoid loss of data, we log an error when SMFIR_REPLBODY requests + * are alternated with other requests. */ if (body_line_buf != 0 && cmd != SMFIR_REPLBODY) { /* In case the last body replacement line didn't end in CRLF. */ - if (LEN(body_line_buf) > 0) + if (edit_resp == 0 && LEN(body_line_buf) > 0) edit_resp = parent->repl_body(parent->chg_context, MILTER_BODY_LINE, body_line_buf); @@ -1038,10 +1075,7 @@ static const char *milter8_event(MILTER8 *milter, int event, edit_resp = parent->repl_body(parent->chg_context, MILTER_BODY_END, (VSTRING *) 0); - if (edit_resp) { - milter8_edit_error(milter, edit_resp); - MILTER8_EVENT_BREAK(milter->def_reply); - } + body_edit_lockout = 1; vstring_free(body_line_buf); body_line_buf = 0; } @@ -1095,7 +1129,6 @@ static const char *milter8_event(MILTER8 *milter, int event, if (IN_CONNECT_EVENT(event)) { msg_warn("milter %s: DISCARD action is not allowed " "for connect or helo", milter->m.name); - milter8_conf_error(milter); MILTER8_EVENT_BREAK(milter->def_reply); } else { /* No more events for this message. */ @@ -1231,6 +1264,9 @@ static const char *milter8_event(MILTER8 *milter, int event, MILTER8_DATA_STRING, milter->body, MILTER8_DATA_END) != 0) MILTER8_EVENT_BREAK(milter->def_reply); + /* Skip to the next request after previous edit error. */ + if (edit_resp) + continue; /* XXX Sendmail 8 compatibility. */ if (index == 0) index = 1; @@ -1255,10 +1291,6 @@ static const char *milter8_event(MILTER8 *milter, int event, edit_resp = parent->del_header(parent->chg_context, (ssize_t) index, STR(milter->buf)); - if (edit_resp) { - milter8_edit_error(milter, edit_resp); - MILTER8_EVENT_BREAK(milter->def_reply); - } continue; #endif @@ -1271,13 +1303,12 @@ static const char *milter8_event(MILTER8 *milter, int event, MILTER8_DATA_STRING, milter->body, MILTER8_DATA_END) != 0) MILTER8_EVENT_BREAK(milter->def_reply); + /* Skip to the next request after previous edit error. */ + if (edit_resp) + continue; edit_resp = parent->add_header(parent->chg_context, STR(milter->buf), STR(milter->body)); - if (edit_resp) { - milter8_edit_error(milter, edit_resp); - MILTER8_EVENT_BREAK(milter->def_reply); - } continue; /* @@ -1294,6 +1325,9 @@ static const char *milter8_event(MILTER8 *milter, int event, MILTER8_DATA_STRING, milter->body, MILTER8_DATA_END) != 0) MILTER8_EVENT_BREAK(milter->def_reply); + /* Skip to the next request after previous edit error. */ + if (edit_resp) + continue; if ((ssize_t) index + 1 < 1) { msg_warn("milter %s: bad insert header index: %ld", milter->m.name, (long) index); @@ -1304,10 +1338,6 @@ static const char *milter8_event(MILTER8 *milter, int event, (ssize_t) index + 1, STR(milter->buf), STR(milter->body)); - if (edit_resp) { - milter8_edit_error(milter, edit_resp); - MILTER8_EVENT_BREAK(milter->def_reply); - } continue; #endif @@ -1319,12 +1349,11 @@ static const char *milter8_event(MILTER8 *milter, int event, MILTER8_DATA_STRING, milter->buf, MILTER8_DATA_END) != 0) MILTER8_EVENT_BREAK(milter->def_reply); + /* Skip to the next request after previous edit error. */ + if (edit_resp) + continue; edit_resp = parent->add_rcpt(parent->chg_context, STR(milter->buf)); - if (edit_resp) { - milter8_edit_error(milter, edit_resp); - MILTER8_EVENT_BREAK(milter->def_reply); - } continue; /* @@ -1335,12 +1364,11 @@ static const char *milter8_event(MILTER8 *milter, int event, MILTER8_DATA_STRING, milter->buf, MILTER8_DATA_END) != 0) MILTER8_EVENT_BREAK(milter->def_reply); + /* Skip to the next request after previous edit error. */ + if (edit_resp) + continue; edit_resp = parent->del_rcpt(parent->chg_context, STR(milter->buf)); - if (edit_resp) { - milter8_edit_error(milter, edit_resp); - MILTER8_EVENT_BREAK(milter->def_reply); - } continue; /* @@ -1348,10 +1376,20 @@ static const char *milter8_event(MILTER8 *milter, int event, * update the message size. */ case SMFIR_REPLBODY: + if (body_edit_lockout) { + msg_warn("milter %s: body replacement requests can't " + "currently be mixed with other requests", + milter->m.name); + milter8_conf_error(milter); + MILTER8_EVENT_BREAK(milter->def_reply); + } if (milter8_read_data(milter, data_size, MILTER8_DATA_BUFFER, milter->body, MILTER8_DATA_END) != 0) MILTER8_EVENT_BREAK(milter->def_reply); + /* Skip to the next request after previous edit error. */ + if (edit_resp) + continue; /* Start body replacement. */ if (body_line_buf == 0) { body_line_buf = vstring_alloc(var_line_limit); @@ -1376,10 +1414,6 @@ static const char *milter8_event(MILTER8 *milter, int event, VSTRING_ADDCH(body_line_buf, ch); } } - if (edit_resp) { - milter8_edit_error(milter, edit_resp); - MILTER8_EVENT_BREAK(milter->def_reply); - } continue; } } @@ -1410,6 +1444,15 @@ static const char *milter8_event(MILTER8 *milter, int event, if (body_line_buf) vstring_free(body_line_buf); + /* + * XXX Some cleanup clients ask the cleanup server to bounce mail for + * them. In that case we must override a hard reject retval result after + * queue file update failure. This is not a big problem; the odds are + * small that a Milter application sends a hard reject after replacing + * the message body. + */ + if (edit_resp && (retval == 0 || strchr("DS4", retval[0]) == 0)) + retval = edit_resp; return (retval); } diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index 40ffcade5..0c226697e 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -207,9 +207,9 @@ /* .PP /* Available in Postfix version 2.4.4 and later: /* .IP "\fBsend_cyrus_sasl_authzid (no)\fR" -/* When authenticating to a SASL server with the default setting -/* "no", send no authoriZation ID (authzid); send only the authentiCation -/* ID (authcid) plus the authcid's password. +/* When authenticating to a remote SMTP or LMTP server with the +/* default setting "no", send no SASL authoriZation ID (authzid); send +/* only the SASL authentiCation ID (authcid) plus the authcid's password. /* MIME PROCESSING CONTROLS /* .ad /* .fi diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 601a1f538..a0fa7e9cf 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -2736,6 +2736,24 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) state->cleanup = 0; } + /* + * XXX If we lost the cleanup server, the Postfix SMTP server will be out + * of sync with Milter applications. Sending an ABORT to the Milters is + * not sufficient to restore synchronization, because there may be any + * number of Milter replies already in flight. Destroying and recreating + * the Milters (and faking the connect and ehlo events) is too much + * trouble for testing and maintenance. Workaround: force the Postfix + * SMTP server to hang up with a 421 response in the rare case that the + * cleanup server breaks AND that the remote SMTP client continues the + * session after end-of-data. + * + * XXX Should use something other than CLEANUP_STAT_WRITE when we lose + * contact with the cleanup server. This requires changes to among others + * the mail_stream module. + */ + if (smtpd_milters != 0 && (state->err & CLEANUP_STAT_WRITE) != 0) + state->access_denied = mystrdup("421 4.3.0 Mail system error"); + /* * Handle any errors. One message may suffer from multiple errors, so * complain only about the most severe error. Forgive any previous client