diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/HISTORY ./HISTORY
--- /var/tmp/postfix-2.12-20141015/HISTORY 2014-10-15 19:45:36.000000000 -0400
+++ ./HISTORY 2014-10-18 17:04:02.000000000 -0400
@@ -20666,3 +20666,16 @@
with similar code elsewhere. File: master/master_ent.c.
Backed out SMTP client TLS fallback due to multiple problems.
+
+20141018
+
+ Bugfix (introduced: Postfix 2.3): when a Milter inserted a
+ header ABOVE Postfix's own Received: header, Postfix would
+ expose its own Received: header to Milters (violating
+ protocol) and hide the Milter-inserted header from Milters
+ (wtf). Files: cleanup/cleanup.h, cleanup/cleanup_message.c,
+ cleanup/cleanup_state.c, milter/milter.[hc], milter/milter8.c.
+
+ Cleanup: revert the workaround that places headers inserted
+ with PREPEND actions or policy requests BELOW Postfix's own
+ Received: message header. File: smtpd/smtpd.c.
diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/src/cleanup/cleanup.h ./src/cleanup/cleanup.h
--- /var/tmp/postfix-2.12-20141015/src/cleanup/cleanup.h 2014-10-06 17:11:59.000000000 -0400
+++ ./src/cleanup/cleanup.h 2014-10-17 14:21:30.000000000 -0400
@@ -61,6 +61,7 @@
char *orig_rcpt; /* original recipient address */
char *return_receipt; /* return-receipt address */
char *errors_to; /* errors-to address */
+ ARGV *auto_hdrs; /* MTA's own header(s) */
int flags; /* processing options, status flags */
int qmgr_opts; /* qmgr processing options */
int errs; /* any badness experienced */
diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/src/cleanup/cleanup_message.c ./src/cleanup/cleanup_message.c
--- /var/tmp/postfix-2.12-20141015/src/cleanup/cleanup_message.c 2014-09-20 20:56:02.000000000 -0400
+++ ./src/cleanup/cleanup_message.c 2014-10-18 15:21:47.000000000 -0400
@@ -479,6 +479,10 @@
if (hdr_opts && (hdr_opts->flags & HDR_OPT_MIME))
header_class = MIME_HDR_MULTIPART;
+ /* Update the Received: header count before maybe dropping headers below. */
+ if (hdr_opts && hdr_opts->type == HDR_RECEIVED)
+ state->hop_count += 1;
+
if ((state->flags & CLEANUP_FLAG_FILTER)
&& (CHECK(MIME_HDR_PRIMARY, cleanup_header_checks, VAR_HEADER_CHECKS)
|| CHECK(MIME_HDR_MULTIPART, cleanup_mimehdr_checks, VAR_MIMEHDR_CHECKS)
@@ -579,12 +583,16 @@
msg_info("%s: message-id=%s", state->queue_id, hdrval);
if (hdr_opts->type == HDR_RESENT_MESSAGE_ID)
msg_info("%s: resent-message-id=%s", state->queue_id, hdrval);
- if (hdr_opts->type == HDR_RECEIVED)
- if (++state->hop_count >= var_hopcount_limit) {
+ if (hdr_opts->type == HDR_RECEIVED) {
+ if (state->hop_count >= var_hopcount_limit) {
msg_warn("%s: message rejected: hopcount exceeded",
state->queue_id);
state->errs |= CLEANUP_STAT_HOPS;
}
+ /* Save our Received: header after maybe updating headers above. */
+ if (state->hop_count == 1)
+ argv_add(state->auto_hdrs, vstring_str(header_buf), ARGV_END);
+ }
if (CLEANUP_OUT_OK(state)) {
if (hdr_opts->flags & HDR_OPT_RR)
state->resent = "Resent-";
@@ -623,6 +631,19 @@
return;
/*
+ * Future proofing: the Milter client's header suppression algorithm
+ * assumes that the MTA prepends its own Received: header. This
+ * assupmtion may be violated after some source-code update. The
+ * following check ensures consistency, at least for local submission.
+ */
+ if (state->hop_count < 1) {
+ msg_warn("%s: message rejected: no Received: header",
+ state->queue_id);
+ state->errs |= CLEANUP_STAT_BAD;
+ return;
+ }
+
+ /*
* Add a missing (Resent-)Message-Id: header. The message ID gives the
* time in GMT units, plus the local queue ID.
*
diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/src/cleanup/cleanup_milter.c ./src/cleanup/cleanup_milter.c
--- /var/tmp/postfix-2.12-20141015/src/cleanup/cleanup_milter.c 2013-11-23 20:25:40.000000000 -0500
+++ ./src/cleanup/cleanup_milter.c 2014-10-17 14:10:59.000000000 -0400
@@ -2020,7 +2020,7 @@
* filter library.
*/
if ((resp = milter_message(milters, state->handle->stream,
- state->data_offset)) != 0)
+ state->data_offset, state->auto_hdrs)) != 0)
cleanup_milter_apply(state, "END-OF-MESSAGE", resp);
/*
diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/src/cleanup/cleanup_state.c ./src/cleanup/cleanup_state.c
--- /var/tmp/postfix-2.12-20141015/src/cleanup/cleanup_state.c 2014-07-08 07:55:51.000000000 -0400
+++ ./src/cleanup/cleanup_state.c 2014-10-17 15:19:27.000000000 -0400
@@ -78,6 +78,7 @@
state->orig_rcpt = 0;
state->return_receipt = 0;
state->errors_to = 0;
+ state->auto_hdrs = argv_alloc(1);
state->flags = 0;
state->qmgr_opts = 0;
state->errs = 0;
@@ -152,6 +153,7 @@
myfree(state->return_receipt);
if (state->errors_to)
myfree(state->errors_to);
+ argv_free(state->auto_hdrs);
if (state->queue_name)
myfree(state->queue_name);
if (state->queue_id)
diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/src/milter/milter.c ./src/milter/milter.c
--- /var/tmp/postfix-2.12-20141015/src/milter/milter.c 2014-10-05 13:03:34.000000000 -0400
+++ ./src/milter/milter.c 2014-10-17 13:54:54.000000000 -0400
@@ -85,10 +85,11 @@
/* const char *milter_other_event(milters)
/* MILTERS *milters;
/*
-/* const char *milter_message(milters, qfile, data_offset)
+/* const char *milter_message(milters, qfile, data_offset, auto_hdrs)
/* MILTERS *milters;
/* VSTREAM *qfile;
/* off_t data_offset;
+/* ARGV *auto_hdrs;
/*
/* const char *milter_abort(milters)
/* MILTERS *milters;
@@ -483,7 +484,8 @@
/* milter_message - inspect message content */
-const char *milter_message(MILTERS *milters, VSTREAM *fp, off_t data_offset)
+const char *milter_message(MILTERS *milters, VSTREAM *fp, off_t data_offset,
+ ARGV *auto_hdrs)
{
const char *resp;
MILTER *m;
@@ -497,7 +499,8 @@
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next) {
any_eoh_macros = MILTER_MACRO_EVAL(global_eoh_macros, m, milters, eoh_macros);
any_eod_macros = MILTER_MACRO_EVAL(global_eod_macros, m, milters, eod_macros);
- resp = m->message(m, fp, data_offset, any_eoh_macros, any_eod_macros);
+ resp = m->message(m, fp, data_offset, any_eoh_macros, any_eod_macros,
+ auto_hdrs);
if (any_eoh_macros != global_eoh_macros)
argv_free(any_eoh_macros);
if (any_eod_macros != global_eod_macros)
diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/src/milter/milter.h ./src/milter/milter.h
--- /var/tmp/postfix-2.12-20141015/src/milter/milter.h 2009-04-27 10:53:56.000000000 -0400
+++ ./src/milter/milter.h 2014-10-17 13:49:00.000000000 -0400
@@ -40,7 +40,7 @@
const char *(*mail_event) (struct MILTER *, const char **, ARGV *);
const char *(*rcpt_event) (struct MILTER *, const char **, ARGV *);
const char *(*data_event) (struct MILTER *, ARGV *);
- const char *(*message) (struct MILTER *, VSTREAM *, off_t, ARGV *, ARGV *);
+ const char *(*message) (struct MILTER *, VSTREAM *, off_t, ARGV *, ARGV *, ARGV *);
const char *(*unknown_event) (struct MILTER *, const char *, ARGV *);
const char *(*other_event) (struct MILTER *);
void (*abort) (struct MILTER *);
@@ -136,7 +136,7 @@
extern const char *milter_mail_event(MILTERS *, const char **);
extern const char *milter_rcpt_event(MILTERS *, int, const char **);
extern const char *milter_data_event(MILTERS *);
-extern const char *milter_message(MILTERS *, VSTREAM *, off_t);
+extern const char *milter_message(MILTERS *, VSTREAM *, off_t, ARGV *);
extern const char *milter_unknown_event(MILTERS *, const char *);
extern const char *milter_other_event(MILTERS *);
extern void milter_abort(MILTERS *);
diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/src/milter/milter8.c ./src/milter/milter8.c
--- /var/tmp/postfix-2.12-20141015/src/milter/milter8.c 2014-09-25 16:34:37.000000000 -0400
+++ ./src/milter/milter8.c 2014-10-18 16:30:52.000000000 -0400
@@ -2285,6 +2285,8 @@
MILTER8 *milter; /* milter client */
ARGV *eoh_macros; /* end-of-header macros */
ARGV *eod_macros; /* end-of-body macros */
+ ARGV *auto_hdrs; /* auto-generated headers */
+ int auto_done; /* good enough for now */
int first_header; /* first header */
int first_body; /* first body line */
const char *resp; /* milter application response */
@@ -2301,6 +2303,8 @@
MILTER8 *milter = msg_ctx->milter;
char *cp;
int skip_reply;
+ char **cpp;
+ unsigned done;
/*
* XXX Workaround: mime_state_update() may invoke multiple call-backs
@@ -2329,10 +2333,11 @@
* XXX Sendmail compatibility. It eats the first space (not tab) after the
* header label and ":".
*/
- if (msg_ctx->first_header) {
- msg_ctx->first_header = 0;
- return;
- }
+ for (cpp = msg_ctx->auto_hdrs->argv, done = 1; *cpp; cpp++, done <<= 1)
+ if ((msg_ctx->auto_done & done) == 0 && strcmp(*cpp, STR(buf)) == 0) {
+ msg_ctx->auto_done |= done;
+ return;
+ }
/*
* Sendmail 8 sends multi-line headers as text separated by newline.
@@ -2507,7 +2512,8 @@
static const char *milter8_message(MILTER *m, VSTREAM *qfile,
off_t data_offset,
ARGV *eoh_macros,
- ARGV *eod_macros)
+ ARGV *eod_macros,
+ ARGV *auto_hdrs)
{
const char *myname = "milter8_message";
MILTER8 *milter = (MILTER8 *) m;
@@ -2541,6 +2547,8 @@
msg_ctx.milter = milter;
msg_ctx.eoh_macros = eoh_macros;
msg_ctx.eod_macros = eod_macros;
+ msg_ctx.auto_hdrs = auto_hdrs;
+ msg_ctx.auto_done = 0;
msg_ctx.first_header = 1;
msg_ctx.first_body = 1;
msg_ctx.resp = 0;
diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL --exclude=.indent.pro --exclude=Makefile.in -r -ur /var/tmp/postfix-2.12-20141015/src/smtpd/smtpd.c ./src/smtpd/smtpd.c
--- /var/tmp/postfix-2.12-20141015/src/smtpd/smtpd.c 2014-10-13 18:10:55.000000000 -0400
+++ ./src/smtpd/smtpd.c 2014-10-18 08:21:02.000000000 -0400
@@ -3115,6 +3115,13 @@
}
/*
+ * PREPEND message headers above our own Received: header.
+ */
+ if (state->prepend)
+ for (cpp = state->prepend->argv; *cpp; cpp++)
+ out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp);
+
+ /*
* Suppress our own Received: header in the unlikely case that we are an
* intermediate proxy.
*/
@@ -3204,17 +3211,6 @@
#endif
}
- /*
- * PREPEND message headers below our own Received: header. According
- * https://www.milter.org/developers/api/smfi_insheader, Milters see only
- * headers that have been sent by the SMTP client and those header
- * modifications by earlier filters. Based on this we allow Milters to
- * see headers added by access map or by policy service.
- */
- if (state->prepend)
- for (cpp = state->prepend->argv; *cpp; cpp++)
- out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp);
-
smtpd_chat_reply(state, "354 End data with .");
state->where = SMTPD_AFTER_DATA;