From 0eb1cb1ce0a0e02db03a9db2bc5f7155e7a3a2e9 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Sun, 19 Oct 2014 00:00:00 -0500 Subject: [PATCH] postfix-2.8.19 --- postfix/HISTORY | 13 +++++++++++++ postfix/src/cleanup/cleanup.h | 1 + postfix/src/cleanup/cleanup_message.c | 12 ++++++++++-- postfix/src/cleanup/cleanup_milter.c | 2 +- postfix/src/cleanup/cleanup_state.c | 2 ++ postfix/src/global/mail_version.h | 4 ++-- postfix/src/milter/milter.c | 9 ++++++--- postfix/src/milter/milter.h | 4 ++-- postfix/src/milter/milter8.c | 18 +++++++++++++----- postfix/src/smtpd/smtpd.c | 18 +++++++----------- 10 files changed, 57 insertions(+), 26 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index c98975b66..1a09e0779 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -17009,3 +17009,16 @@ Apologies for any names omitted. SPF policy plus DKIM Milter. PREPENDed headers are now added BELOW Postfix's own Received: header and remain visible to Milters. File: smtpd/smtpd.c. + +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 --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index a962f0078..22beca2b9 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -61,6 +61,7 @@ typedef struct CLEANUP_STATE { 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 --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 4de1aa530..bae16b97e 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -479,6 +479,10 @@ static void cleanup_header_callback(void *context, int header_class, 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) @@ -574,9 +578,13 @@ static void cleanup_header_callback(void *context, int header_class, 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) 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-"; diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index 4877611fe..4de31a41c 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -1982,7 +1982,7 @@ void cleanup_milter_inspect(CLEANUP_STATE *state, MILTERS *milters) * 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 --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index 8d9085262..87b006182 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -78,6 +78,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src) 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; @@ -150,6 +151,7 @@ void cleanup_state_free(CLEANUP_STATE *state) 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 --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 6f7098f92..a2b8edb02 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 "20141013" -#define MAIL_VERSION_NUMBER "2.8.18" +#define MAIL_RELEASE_DATE "20141019" +#define MAIL_VERSION_NUMBER "2.8.19" #ifdef SNAPSHOT # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff --git a/postfix/src/milter/milter.c b/postfix/src/milter/milter.c index ee38b0f23..9cddc6319 100644 --- a/postfix/src/milter/milter.c +++ b/postfix/src/milter/milter.c @@ -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; @@ -481,7 +482,8 @@ const char *milter_other_event(MILTERS *milters) /* 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; @@ -495,7 +497,8 @@ const char *milter_message(MILTERS *milters, VSTREAM *fp, off_t data_offset) 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 --git a/postfix/src/milter/milter.h b/postfix/src/milter/milter.h index 17d163dc4..bf25fccc0 100644 --- a/postfix/src/milter/milter.h +++ b/postfix/src/milter/milter.h @@ -40,7 +40,7 @@ typedef struct MILTER { 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_helo_event(MILTERS *, const char *, int); 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 --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index 22d4c419f..7e1a5da02 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -2270,6 +2270,8 @@ typedef struct { 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 */ @@ -2286,6 +2288,8 @@ static void milter8_header(void *ptr, int unused_header_class, MILTER8 *milter = msg_ctx->milter; char *cp; int skip_reply; + char **cpp; + unsigned done; /* * XXX Workaround: mime_state_update() may invoke multiple call-backs @@ -2314,10 +2318,11 @@ static void milter8_header(void *ptr, int unused_header_class, * 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. @@ -2492,7 +2497,8 @@ static void milter8_eob(void *ptr) 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; @@ -2526,6 +2532,8 @@ static const char *milter8_message(MILTER *m, VSTREAM *qfile, 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 --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 294986c23..b367580be 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -2829,6 +2829,13 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) rec_fputs(state->cleanup, REC_TYPE_MESG, ""); } + /* + * 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. @@ -2920,17 +2927,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) #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;