Postfix 2.3 Patch 02 closes the remaining known defects with Postfix Milter support. Some corner cases had escaped testing and were found during deployment, with Larry Vaden being the guinea pig. - Corrupted queue file after a request to modify a short message header, but only when that header was the last one in the message. - Panic after spurious Milter request when a client was rejected with "smtpd_delay_reject = no". - The Milter client is now more tolerant for redundant "data cleanup" requests. This avoids panic() calls for completely harmless conditions such as "milter state 2". Prereq: "2.3.1" diff -cr /var/tmp/postfix-2.3.1/src/global/mail_version.h ./src/global/mail_version.h *** /var/tmp/postfix-2.3.1/src/global/mail_version.h Mon Jul 24 14:28:13 2006 --- ./src/global/mail_version.h Thu Jul 27 12:46:58 2006 *************** *** 20,27 **** * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ ! #define MAIL_RELEASE_DATE "20060724" ! #define MAIL_VERSION_NUMBER "2.3.1" #ifdef SNAPSHOT # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE --- 20,27 ---- * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ ! #define MAIL_RELEASE_DATE "20060727" ! #define MAIL_VERSION_NUMBER "2.3.2" #ifdef SNAPSHOT # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff -cr /var/tmp/postfix-2.3.1/HISTORY ./HISTORY *** /var/tmp/postfix-2.3.1/HISTORY Mon Jul 24 15:29:17 2006 --- ./HISTORY Thu Jul 27 12:46:04 2006 *************** *** 12611,12613 **** --- 12611,12639 ---- Bugfix: when updating the same header multiple times, the Postfix Milter client created a queue file that caused delivery agents to loop. File: cleanup/cleanup_milter.c. + + 20060725 + + Bugfix: damaged queue file record after a Milter request + to modify a message header when 1) it was the last header + in the unmodified message, and 2) the old header was less + than 15 characters long. File: cleanup/cleanup_milter.c. + + Bugfix: don't panic in smtp_rcpt_cleanup() after detecting + a damaged queue file record. File: smtp/smtp_proto.c. + + 20060726 + + Bugfix: the 20051013 change to enforce the message size + limit in the SMTP server didn't work for size limits close + enough to INT_MAX. File: smtpd/smtpd.c. + + Bugfix: after an SMTP client was rejected with "smtpd_delay_reject + = no", the SMTP server would panic as it generated spurious + Milter requests for unrecognized commands. File: smtpd/smtpd.c. + + 20060727 + + Cleanup: change redundant milter_abort() and milter_disc_event() + calls into NO-OPs. This avoids unnecessary panic() events + for completely harmless conditions. File: milter/milter8.c. diff -cr /var/tmp/postfix-2.3.1/README_FILES/DSN_README ./README_FILES/DSN_README *** /var/tmp/postfix-2.3.1/README_FILES/DSN_README Sat Dec 24 13:40:18 2005 --- ./README_FILES/DSN_README Thu Jul 27 07:12:13 2006 *************** *** 11,17 **** Specifically, DSN support gives an email sender the ability to specify: * What notifications are sent: success, failure, delay, or none. Normally, ! Postfix informs the sender only mail when delivery is delayed or when delivery fails. * What content is returned in case of failure: only the message headers, or --- 11,17 ---- Specifically, DSN support gives an email sender the ability to specify: * What notifications are sent: success, failure, delay, or none. Normally, ! Postfix informs the sender only when mail delivery is delayed or when delivery fails. * What content is returned in case of failure: only the message headers, or diff -cr /var/tmp/postfix-2.3.1/html/DSN_README.html ./html/DSN_README.html *** /var/tmp/postfix-2.3.1/html/DSN_README.html Sat Dec 24 13:40:18 2005 --- ./html/DSN_README.html Thu Jul 27 07:12:13 2006 *************** *** 30,36 ****
What notifications are sent: success, failure, delay, or ! none. Normally, Postfix informs the sender only mail when delivery is delayed or when delivery fails.
What content is returned in case of failure: only the --- 30,36 ----
What notifications are sent: success, failure, delay, or ! none. Normally, Postfix informs the sender only when mail delivery is delayed or when delivery fails.
What content is returned in case of failure: only the *************** *** 83,89 ****
! /etc/postfix/main.cf: smtpd_discard_ehlo_keyword_address_maps = cidr:/etc/postfix/esmtp_access --- 83,89 ----! /etc/postfix/main.cf: smtpd_discard_ehlo_keyword_address_maps = cidr:/etc/postfix/esmtp_access *************** *** 100,106 ****--- 100,106 ----! /etc/postfix/main.cf: smtpd_discard_ehlo_keywords = silent-discard, dsndiff -cr /var/tmp/postfix-2.3.1/proto/DSN_README.html ./proto/DSN_README.html *** /var/tmp/postfix-2.3.1/proto/DSN_README.html Sat Dec 24 13:40:15 2005 --- ./proto/DSN_README.html Thu Jul 27 07:11:42 2006 *************** *** 30,36 ****! /etc/postfix/main.cf: smtpd_discard_ehlo_keywords = silent-discard, dsn
What notifications are sent: success, failure, delay, or ! none. Normally, Postfix informs the sender only mail when delivery is delayed or when delivery fails.
What content is returned in case of failure: only the --- 30,36 ----
What notifications are sent: success, failure, delay, or ! none. Normally, Postfix informs the sender only when mail delivery is delayed or when delivery fails.
What content is returned in case of failure: only the diff -cr /var/tmp/postfix-2.3.1/src/cleanup/cleanup_milter.c ./src/cleanup/cleanup_milter.c *** /var/tmp/postfix-2.3.1/src/cleanup/cleanup_milter.c Mon Jul 24 14:59:37 2006 --- ./src/cleanup/cleanup_milter.c Tue Jul 25 16:21:42 2006 *************** *** 623,629 **** msg_warn("%s: seek file %s: %m", myname, cleanup_path); CLEANUP_PATCH_HEADER_RETURN(cleanup_milter_error(state, errno)); } ! CLEANUP_OUT_BUF(state, rec_type, buf); if (msg_verbose > 1) msg_info("%s: %ld: write %.*s", myname, (long) write_offset, LEN(buf) > 30 ? 30 : (int) LEN(buf), STR(buf)); --- 623,634 ---- msg_warn("%s: seek file %s: %m", myname, cleanup_path); CLEANUP_PATCH_HEADER_RETURN(cleanup_milter_error(state, errno)); } ! /* The saved "append header" pointer record may still contain "0". */ ! if (saved_read_offset == state->append_hdr_pt_offset) ! cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT, ! (long) state->append_hdr_pt_target); ! else ! CLEANUP_OUT_BUF(state, rec_type, buf); if (msg_verbose > 1) msg_info("%s: %ld: write %.*s", myname, (long) write_offset, LEN(buf) > 30 ? 30 : (int) LEN(buf), STR(buf)); *************** *** 825,830 **** --- 830,838 ---- CLEANUP_UPD_HEADER_RETURN(cleanup_milter_error(state, errno)); } if (rec_type == REC_TYPE_PTR) { + /* The "append header" pointer record content must be saved. */ + if (saved_read_offset == state->append_hdr_pt_offset) + break; if (jumped == 0) { /* Enough contiguous space for writing a PTR record. */ avail_space += read_offset - saved_read_offset; diff -cr /var/tmp/postfix-2.3.1/src/global/mail_params.h ./src/global/mail_params.h *** /var/tmp/postfix-2.3.1/src/global/mail_params.h Tue Jul 18 21:11:49 2006 --- ./src/global/mail_params.h Wed Jul 26 20:59:10 2006 *************** *** 1396,1405 **** #define DEF_SMTP_SASL_PASSWD "" extern char *var_smtp_sasl_passwd; - #define VAR_SMTP_SASL_ENFORCE "smtp_sasl_auth_enforce" - #define DEF_SMTP_SASL_ENFORCE 1 - extern bool var_smtp_sasl_enforce; - #define VAR_SMTP_SASL_OPTS "smtp_sasl_security_options" #define DEF_SMTP_SASL_OPTS "noplaintext, noanonymous" extern char *var_smtp_sasl_opts; --- 1396,1401 ---- *************** *** 1494,1502 **** #define VAR_LMTP_SASL_PASSWD "lmtp_sasl_password_maps" #define DEF_LMTP_SASL_PASSWD "" extern char *var_lmtp_sasl_passwd; - - #define VAR_LMTP_SASL_ENFORCE "lmtp_sasl_auth_enforce" - #define DEF_LMTP_SASL_ENFORCE 1 #define VAR_LMTP_SASL_OPTS "lmtp_sasl_security_options" #define DEF_LMTP_SASL_OPTS "noplaintext, noanonymous" --- 1490,1495 ---- diff -cr /var/tmp/postfix-2.3.1/src/milter/milter.c ./src/milter/milter.c *** /var/tmp/postfix-2.3.1/src/milter/milter.c Tue Jul 11 20:41:59 2006 --- ./src/milter/milter.c Thu Jul 27 12:42:41 2006 *************** *** 141,147 **** /* /* milter_disc_event() reports an SMTP client disconnection /* event to the specified milter instances. No events can ! /* reported after this call, not even abort() events. /* /* milter_helo_event() reports a HELO or EHLO event to the /* specified milter instances, after sending the macros that --- 141,149 ---- /* /* milter_disc_event() reports an SMTP client disconnection /* event to the specified milter instances. No events can ! /* reported after this call. To simplify usage, redundant calls ! /* of this function are NO-OPs and don't raise a run-time ! /* error. /* /* milter_helo_event() reports a HELO or EHLO event to the /* specified milter instances, after sending the macros that *************** *** 178,186 **** /* by a preceding milter. This function must be called with /* as argument an open Postfix queue file. /* ! /* milter_abort() cancels a mail transaction in progress. This ! /* function is safe to call anywhere between connect and ! /* disconnect events. /* /* milter_send() sends a list of mail filters over the specified /* stream. When given a null list pointer, a "no filter" --- 180,188 ---- /* by a preceding milter. This function must be called with /* as argument an open Postfix queue file. /* ! /* milter_abort() cancels a mail transaction in progress. To ! /* simplify usage, redundant calls of this function are NO-OPs ! /* and don't raise a run-time error. /* /* milter_send() sends a list of mail filters over the specified /* stream. When given a null list pointer, a "no filter" diff -cr /var/tmp/postfix-2.3.1/src/milter/milter8.c ./src/milter/milter8.c *** /var/tmp/postfix-2.3.1/src/milter/milter8.c Thu Jul 20 16:06:11 2006 --- ./src/milter/milter8.c Thu Jul 27 12:25:00 2006 *************** *** 1835,1840 **** --- 1835,1843 ---- * has to open a new MTA-to-filter socket for each SMTP client. */ switch (milter->state) { + case MILTER8_STAT_CLOSED: + case MILTER8_STAT_READY: + return; case MILTER8_STAT_ERROR: case MILTER8_STAT_ACCEPT_CON: case MILTER8_STAT_REJECT_CON: *************** *** 1869,1874 **** --- 1872,1880 ---- * has to open a new MTA-to-filter socket for each SMTP client. */ switch (milter->state) { + case MILTER8_STAT_CLOSED: + case MILTER8_STAT_READY: + return; case MILTER8_STAT_ERROR: #ifdef LIBMILTER_AUTO_DISCONNECT case MILTER8_STAT_ACCEPT_CON: diff -cr /var/tmp/postfix-2.3.1/src/smtp/smtp_proto.c ./src/smtp/smtp_proto.c *** /var/tmp/postfix-2.3.1/src/smtp/smtp_proto.c Wed Jul 19 20:47:51 2006 --- ./src/smtp/smtp_proto.c Tue Jul 25 17:10:57 2006 *************** *** 987,992 **** --- 987,994 ---- NOCLOBBER int mail_from_rejected; NOCLOBBER int downgrading; int mime_errs; + SMTP_RESP fake; + int fail_status; /* * Macros for readability. *************** *** 1696,1702 **** if (rec_type != REC_TYPE_XTRA) { msg_warn("%s: bad record type: %d in message content", request->queue_id, rec_type); ! RETURN(mark_corrupt(state->src)); } } --- 1698,1709 ---- if (rec_type != REC_TYPE_XTRA) { msg_warn("%s: bad record type: %d in message content", request->queue_id, rec_type); ! fail_status = smtp_mesg_fail(state, DSN_BY_LOCAL_MTA, ! SMTP_RESP_FAKE(&fake, "5.3.0"), ! "unreadable mail queue entry"); ! if (fail_status == 0) ! (void) mark_corrupt(state->src); ! RETURN(fail_status); } } diff -cr /var/tmp/postfix-2.3.1/src/smtpd/smtpd.c ./src/smtpd/smtpd.c *** /var/tmp/postfix-2.3.1/src/smtpd/smtpd.c Fri Jul 21 20:46:31 2006 --- ./src/smtpd/smtpd.c Wed Jul 26 20:47:39 2006 *************** *** 2643,2653 **** && (state->proxy == 0 ? (++start, --len) == 0 : len == 1)) break; if (state->err == CLEANUP_STAT_OK) { ! state->act_size += len + 2; ! if (var_message_limit > 0 && state->act_size > var_message_limit) state->err = CLEANUP_STAT_SIZE; ! else if (out_record(out_stream, curr_rec_type, start, len) < 0) ! state->err = out_error; } } state->where = SMTPD_AFTER_DOT; --- 2643,2655 ---- && (state->proxy == 0 ? (++start, --len) == 0 : len == 1)) break; if (state->err == CLEANUP_STAT_OK) { ! if (var_message_limit > 0 && var_message_limit - state->act_size < len + 2) state->err = CLEANUP_STAT_SIZE; ! else { ! state->act_size += len + 2; ! if (out_record(out_stream, curr_rec_type, start, len) < 0) ! state->err = out_error; ! } } } state->where = SMTPD_AFTER_DOT; *************** *** 3964,3969 **** --- 3966,3981 ---- smtpd_chat_reply(state, "221 2.7.0 Error: I can break rules, too. Goodbye."); break; } + } + /* XXX We use the real client for connect access control. */ + if (state->access_denied && cmdp->action != quit_cmd) { + smtpd_chat_reply(state, "503 5.7.0 Error: access denied for %s", + state->namaddr); /* RFC 2821 Sec 3.1 */ + state->error_count++; + continue; + } + /* state->access_denied == 0 || cmdp->action == quit_cmd */ + if (cmdp->name == 0) { if (smtpd_milters != 0 && SMTPD_STAND_ALONE(state) == 0 && (err = milter_unknown_event(smtpd_milters, *************** *** 3973,3985 **** } else smtpd_chat_reply(state, "502 5.5.2 Error: command not recognized"); state->error_mask |= MAIL_ERROR_PROTOCOL; - state->error_count++; - continue; - } - /* XXX We use the real client for connect access control. */ - if (state->access_denied && cmdp->action != quit_cmd) { - smtpd_chat_reply(state, "503 5.7.0 Error: access denied for %s", - state->namaddr); /* RFC 2821 Sec 3.1 */ state->error_count++; continue; } --- 3985,3990 ----