diff --git a/postfix/HISTORY b/postfix/HISTORY index fbb21dce7..8021755cf 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -15301,3 +15301,10 @@ Apologies for any names omitted. outside those those trees (e.g. by symlink race attacks). We don't want to be nailed with a bunch of CVEs for unsafe pathname handling. File: conf/postmulti-script. + +20090607 + + Cleanup: revise milter_header_checks action implementation, + and avoid redundant logging and work when milter_header_checks + and Milters make redundant or conflicting decisions. File: + cleanup_milter.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index e10c3a338..620a44132 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -21,13 +21,13 @@ The "postmulti -e destroy" command no longer attempts to remove files that are created AFTER "postmulti -e create". It still works as expected immediately after creating an instance by mistake. Trying to automatically remove other files is too risky because -Postfix-owned directories are not trusted. +Postfix-owned directories are by design not trusted. Major changes with snapshot 20090606 ==================================== -Support for header checks on headers that are generated by Milter -applications. This can be used, for example, to direct mail flow -based on headers that indicate spam levels. See postconf(5) for -"milter_header_checks. All header_checks features are implemented -except PREPEND. +Support for header checks on Milter-generated message headers. This +can be used, for example, to control mail flow with Milter-generated +headers with indicators for badness or goodness. For details, see +the postconf(5) section for "milter_header_checks". Currently, all +header_checks features are implemented except PREPEND. diff --git a/postfix/conf/postmulti-script b/postfix/conf/postmulti-script index 13fffe7fb..1c3f3ad88 100644 --- a/postfix/conf/postmulti-script +++ b/postfix/conf/postmulti-script @@ -27,13 +27,6 @@ umask 022 # multi_instance_group - New value for target instance # multi_instance_name - New value for target instance -# For security reasons we don't take pathnames from the file system -# when destroying instances. Instead we use known-to-be-safe names -# and nothing with a / because that could be subject to races. -QUEUE_DIRECTORIES="active bounce corrupt defer deferred flush hold incoming \ -maildrop pid private public saved trace" -#DEBUG=echo - : ${MAIL_CONFIG:?"do not invoke this command directly"} : ${command_directory:?"do not invoke this command directly"} : ${daemon_directory:?"do not invoke this command directly"} @@ -43,7 +36,6 @@ usage() { echo "$0: Error: Usage: $USAGE" >&2; exit 1; } TAG="$MAIL_LOGTAG/postmulti-script" fatal() { postlog -p fatal -t "$TAG" "$1"; exit 1; } -WARN="postlog -p warn -t $TAG" # args: add|del $dir # @@ -236,6 +228,22 @@ deport) ;; destroy) + + # "postmulti -e destroy" will remove an entire instance only + # when invoked immediately after "postmulti -e create". Trying + # to remove more files is too dangerous. + # + # By design, postfix-owned directory trees are not trusted, and + # any action within those directory trees must not affect files + # outside those trees (e.g. via symlink race attacks). Therefore + # we use only known-to-be-safe names and nothing with a / because + # that could be subject to races. + # + QUEUE_SUBDIRS="active bounce corrupt defer deferred flush hold \ + incoming maildrop pid private public saved trace" + #DEBUG=echo + WARN="postlog -p warn -t $TAG" + # Locate the target instance # [ -f "$config_directory/main.cf" ] || @@ -247,23 +255,15 @@ destroy) # Update multi_instance directories # and also (just in case) drop from alternate_config_directories # - $DEBUG update_cfdirs del $config_directory || exit 1 + $DEBUG update_cfdirs del "$config_directory" || exit 1 - # "postmulti -e destroy" will remove an entire instance only - # when invoked immediately after "postmulti -e create". Trying - # to remove more files is too dangerous. - # - # By design, postfix-owned directory trees are not trusted, and - # any action within those directory trees must not affect files - # outside those trees (e.g. via symlink race attacks). - # # XXX: Internal "postfix /some/cmd" interface. # postfix -c "$config_directory" /bin/sh -c " - for q in $QUEUE_DIRECTORIES + for q in $QUEUE_SUBDIRS do $DEBUG rmdir -- \$q || - $WARN `pwd`/\$q: please verify contents and remove by hand + $WARN \`pwd\`/\$q: please verify contents and remove by hand done " @@ -278,7 +278,7 @@ destroy) # In the configuration directory remove just the main.cf and master.cf # files. $DEBUG rm -f -- "$config_directory/master.cf" "$config_directory/main.cf" 2>/dev/null - $DEBUG rmdir -- "$config_directory" || + $DEBUG rmdir -- "$config_directory" || $WARN $config_directory: please verify contents and remove by hand ;; diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index 61952c1f3..ff8859c1f 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -224,12 +224,12 @@ CLEANUP(8) CLEANUP(8) The macros that are sent to Milter (mail filter) applications after the end of the message header. - Available in Postfix version 2.5 and later: + Available in Postfix version 2.7 and later: milter_header_checks (empty) Optional lookup tables for content inspection of - primary message headers that are produced by Milter - applications. + message headers that are produced by Milter appli- + cations. 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 85d6e2a4a..95db4fa31 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -5694,15 +5694,14 @@ of available macro names and their meanings.

milter_header_checks (default: empty)
-

-Optional lookup tables for content inspection of primary -message headers that are produced by Milter applications. -See the header_checks(5) manual page for usage. +

Optional lookup tables for content inspection of message headers +that are produced by Milter applications. See the header_checks(5) +manual page available actions. Currently, PREPEND is not implemented.

-

The following example sends mail that is marked as SPAM to a -spam sanization machine. Note that matches are case-insensitive by -default.

+

The following example sends all mail that is marked as SPAM to +a spam handling machine. Note that matches are case-insensitive +by default.

@@ -5715,6 +5714,13 @@ default. 

+

The milter_header_checks mechanism could also be used for +whitelisting. For example it could be used to skip heavy content +scanning for DKIM-signed mail from known friendly domains.

+ +

This feature is available in Postfix 2.7, and as an optional +patch for Postfix 2.6.

+
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 5ab7bbdcf..964641b03 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -3159,13 +3159,13 @@ of available macro names and their meanings. .PP This feature is available in Postfix 2.5 and later. .SH milter_header_checks (default: empty) -Optional lookup tables for content inspection of primary -message headers that are produced by Milter applications. -See the \fBheader_checks\fR(5) manual page for usage. +Optional lookup tables for content inspection of message headers +that are produced by Milter applications. See the \fBheader_checks\fR(5) +manual page available actions. Currently, PREPEND is not implemented. .PP -The following example sends mail that is marked as SPAM to a -spam sanization machine. Note that matches are case-insensitive by -default. +The following example sends all mail that is marked as SPAM to +a spam handling machine. Note that matches are case-insensitive +by default. .sp .in +4 .nf @@ -3185,6 +3185,13 @@ default. .ad .ft R .in -4 +.PP +The milter_header_checks mechanism could also be used for +whitelisting. For example it could be used to skip heavy content +scanning for DKIM-signed mail from known friendly domains. +.PP +This feature is available in Postfix 2.7, and as an optional +patch for Postfix 2.6. .SH milter_helo_macros (default: see "postconf -d" output) The macros that are sent to Milter (mail filter) applications after the SMTP HELO or EHLO command. See diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index 5bba18db9..a6b678fed 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -191,10 +191,10 @@ Available in Postfix version 2.5 and later: The macros that are sent to Milter (mail filter) applications after the end of the message header. .PP -Available in Postfix version 2.5 and later: +Available in Postfix version 2.7 and later: .IP "\fBmilter_header_checks (empty)\fR" -Optional lookup tables for content inspection of primary -message headers that are produced by Milter applications. +Optional lookup tables for content inspection of message headers +that are produced by Milter applications. .SH "MIME PROCESSING CONTROLS" .na .nf diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 1a08bda44..d15ab4c74 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -12302,15 +12302,14 @@ parameter. See there for details.

%PARAM milter_header_checks -

-Optional lookup tables for content inspection of primary -message headers that are produced by Milter applications. -See the header_checks(5) manual page for usage. +

Optional lookup tables for content inspection of message headers +that are produced by Milter applications. See the header_checks(5) +manual page available actions. Currently, PREPEND is not implemented.

-

The following example sends mail that is marked as SPAM to a -spam sanization machine. Note that matches are case-insensitive by -default.

+

The following example sends all mail that is marked as SPAM to +a spam handling machine. Note that matches are case-insensitive +by default.

@@ -12322,3 +12321,10 @@ default. 

/^X-SPAM-FLAG:\s+YES]/ FILTER mysmtp:sanitizer.example.com:25
+ +

The milter_header_checks mechanism could also be used for +whitelisting. For example it could be used to skip heavy content +scanning for DKIM-signed mail from known friendly domains.

+ +

This feature is available in Postfix 2.7, and as an optional +patch for Postfix 2.6.

diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index f59f9bb40..f99703038 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -78,9 +78,11 @@ milter_tests: cleanup_milter_test bug_tests \ cleanup_milter_test13a cleanup_milter_test13b cleanup_milter_test13c \ cleanup_milter_test13d \ cleanup_milter_test14a cleanup_milter_test14b cleanup_milter_test14c \ - cleanup_milter_test14d cleanup_milter_test14e \ + cleanup_milter_test14d cleanup_milter_test14e cleanup_milter_test14f \ + cleanup_milter_test14g \ cleanup_milter_test15a cleanup_milter_test15b cleanup_milter_test15c \ - cleanup_milter_test15d cleanup_milter_test15e + cleanup_milter_test15d cleanup_milter_test15e cleanup_milter_test15f \ + cleanup_milter_test15g cleanup_milter_test15h cleanup_milter_test15i root_tests: @@ -388,6 +390,26 @@ cleanup_milter_test14e: cleanup_milter test-queue-file14 cleanup_milter.in14e \ diff cleanup_milter.ref14e2 cleanup_milter.tmp2 rm -f test-queue-file14e.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 +cleanup_milter_test14f: cleanup_milter test-queue-file14 cleanup_milter.in14f \ + cleanup_milter.ref14f1 ../postcat/postcat cleanup_milter.ref14f2 + cp test-queue-file14 test-queue-file14f.tmp + chmod u+w test-queue-file14f.tmp + ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref14f1 cleanup_milter.tmp1 + ../postcat/postcat -ov test-queue-file14f.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref14f2 cleanup_milter.tmp2 + rm -f test-queue-file14f.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + +cleanup_milter_test14g: cleanup_milter test-queue-file14 cleanup_milter.in14g \ + cleanup_milter.ref14g1 ../postcat/postcat cleanup_milter.ref14g2 + cp test-queue-file14 test-queue-file14g.tmp + chmod u+w test-queue-file14g.tmp + ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref14g1 cleanup_milter.tmp1 + ../postcat/postcat -ov test-queue-file14g.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref14g2 cleanup_milter.tmp2 + rm -f test-queue-file14g.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + cleanup_milter_test15a: cleanup_milter test-queue-file15 cleanup_milter.in15a \ cleanup_milter.ref15a1 ../postcat/postcat cleanup_milter.ref15a2 cp test-queue-file15 test-queue-file15a.tmp @@ -438,6 +460,46 @@ cleanup_milter_test15e: cleanup_milter test-queue-file15 cleanup_milter.in15e \ diff cleanup_milter.ref15e2 cleanup_milter.tmp2 rm -f test-queue-file15e.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 +cleanup_milter_test15f: cleanup_milter test-queue-file15 cleanup_milter.in15f \ + cleanup_milter.ref15f1 ../postcat/postcat cleanup_milter.ref15f2 + cp test-queue-file15 test-queue-file15f.tmp + chmod u+w test-queue-file15f.tmp + ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref15f1 cleanup_milter.tmp1 + ../postcat/postcat -ov test-queue-file15f.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref15f2 cleanup_milter.tmp2 + rm -f test-queue-file15f.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + +cleanup_milter_test15g: cleanup_milter test-queue-file15 cleanup_milter.in15g \ + cleanup_milter.ref15g1 ../postcat/postcat cleanup_milter.ref15g2 + cp test-queue-file15 test-queue-file15g.tmp + chmod u+w test-queue-file15g.tmp + ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref15g1 cleanup_milter.tmp1 + ../postcat/postcat -ov test-queue-file15g.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref15g2 cleanup_milter.tmp2 + rm -f test-queue-file15g.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + +cleanup_milter_test15h: cleanup_milter test-queue-file15 cleanup_milter.in15h \ + cleanup_milter.ref15h1 ../postcat/postcat cleanup_milter.ref15h2 + cp test-queue-file15 test-queue-file15h.tmp + chmod u+w test-queue-file15h.tmp + ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref15h1 cleanup_milter.tmp1 + ../postcat/postcat -ov test-queue-file15h.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref15h2 cleanup_milter.tmp2 + rm -f test-queue-file15h.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + +cleanup_milter_test15i: cleanup_milter test-queue-file15 cleanup_milter.in15i \ + cleanup_milter.ref15i1 ../postcat/postcat cleanup_milter.ref15i2 + cp test-queue-file15 test-queue-file15i.tmp + chmod u+w test-queue-file15i.tmp + ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref15i1 cleanup_milter.tmp1 + ../postcat/postcat -ov test-queue-file15i.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref15i2 cleanup_milter.tmp2 + rm -f test-queue-file15i.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 2caa775dc..461ebf84e 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -171,10 +171,10 @@ /* The macros that are sent to Milter (mail filter) applications /* after the end of the message header. /* .PP -/* Available in Postfix version 2.5 and later: +/* Available in Postfix version 2.7 and later: /* .IP "\fBmilter_header_checks (empty)\fR" -/* Optional lookup tables for content inspection of primary -/* message headers that are produced by Milter applications. +/* Optional lookup tables for content inspection of message headers +/* that are produced by Milter applications. /* MIME PROCESSING CONTROLS /* .ad /* .fi diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index b42367a11..74816dfb5 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -263,15 +263,40 @@ static char *cleanup_milter_hbc_extend(void *context, const char *command, #define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0) /* - * We log all header/body-checks actions here, because we know the - * details of the message content that triggered the action. We also - * report detail-free milter-reply values to the caller through the - * milter_hbc_reply state member, so that up-stream code can stop sending - * requests after e.g., reject or discard. - * - * As enforced elsewhere, this code is not called when (state->flags & - * CLEANUP_FLAG_FILTER_ALL) == 0. + * These are currently our mutually-exclusive ways of not receiving mail: + * "reject" and "discard". Only these can be reported to the up-stream + * Postfix libmilter code, because sending any reply there causes Postfix + * libmilter to skip further "edit" requests. By way of safety net, each + * of these must also reset CLEANUP_FLAG_FILTER_ALL. */ +#define CLEANUP_MILTER_REJECTING_OR_DISCARDING_MESSAGE(state) \ + ((state->flags & CLEANUP_FLAG_DISCARD) || (state->errs & CLEANUP_STAT_CONT)) + + /* + * We log all header/body-checks actions here, because we know the + * details of the message content that triggered the action. We report + * detail-free milter-reply values (reject/discard, stored in the + * milter_hbc_reply state member) to the Postfix libmilter code, so that + * Postfix libmilter can stop sending requests. + * + * We also set all applicable cleanup flags here, because there is no + * guarantee that Postfix libmilter will propagate our own milter-reply + * value to cleanup_milter_inspect() which calls cleanup_milter_apply(). + * The latter translates responses from Milter applications into cleanup + * flags, and logs the response text. Postfix libmilter can convey only + * one milter-reply value per email message, and that reply may even come + * from outside Postfix. + * + * To suppress redundant logging, cleanup_milter_apply() does nothing when + * the milter-reply value matches the saved text in the milter_hbc_reply + * state member. As we remember only one milter-reply value, we can't + * report multiple milter-reply values per email message. We satisfy this + * constraint, because we already clear the CLEANUP_FLAG_FILTER_ALL flags + * to terminate further header inspection. + */ + if ((state->flags & CLEANUP_FLAG_FILTER_ALL) == 0) + return ((char *) buf); + if (STREQUAL(command, "REJECT", cmd_len)) { const CLEANUP_STAT_DETAIL *detail; @@ -288,9 +313,14 @@ static char *cleanup_milter_hbc_extend(void *context, const char *command, } else { state->reason = dsn_prepend(detail->dsn, detail->text); } + if (*state->reason == '4') + state->errs |= CLEANUP_STAT_DEFER; + else + state->errs |= CLEANUP_STAT_CONT; state->flags &= ~CLEANUP_FLAG_FILTER_ALL; - cleanup_milter_hbc_log((void *) state, "reject", where, buf, state->reason); - vstring_sprintf(state->milter_hbc_reply, "%d %s", detail->smtp, state->reason); + cleanup_milter_hbc_log(context, "reject", where, buf, state->reason); + vstring_sprintf(state->milter_hbc_reply, "%d %s", + detail->smtp, state->reason); STR(state->milter_hbc_reply)[0] = *state->reason; return ((char *) buf); } @@ -305,21 +335,22 @@ static char *cleanup_milter_hbc_extend(void *context, const char *command, if (state->filter) myfree(state->filter); state->filter = mystrdup(optional_text); - cleanup_milter_hbc_log((void *) state, "filter", where, buf, + cleanup_milter_hbc_log(context, "filter", where, buf, optional_text); } return ((char *) buf); } if (STREQUAL(command, "DISCARD", cmd_len)) { - cleanup_milter_hbc_log((void *) state, "discard", where, buf, optional_text); + cleanup_milter_hbc_log(context, "discard", where, buf, optional_text); vstring_strcpy(state->milter_hbc_reply, "D"); + state->flags |= CLEANUP_FLAG_DISCARD; state->flags &= ~CLEANUP_FLAG_FILTER_ALL; return ((char *) buf); } if (STREQUAL(command, "HOLD", cmd_len)) { - if ((state->flags & CLEANUP_FLAG_HOLD) == 0) { - cleanup_milter_hbc_log((void *) state, "hold", where, buf, optional_text); - vstring_strcpy(state->milter_hbc_reply, "H"); + if ((state->flags & (CLEANUP_FLAG_HOLD | CLEANUP_FLAG_DISCARD)) == 0) { + cleanup_milter_hbc_log(context, "hold", where, buf, optional_text); + state->flags |= CLEANUP_FLAG_HOLD; } return ((char *) buf); } @@ -332,7 +363,7 @@ static char *cleanup_milter_hbc_extend(void *context, const char *command, if (state->redirect) myfree(state->redirect); state->redirect = mystrdup(optional_text); - cleanup_milter_hbc_log((void *) state, "redirect", where, buf, + cleanup_milter_hbc_log(context, "redirect", where, buf, optional_text); state->flags &= ~CLEANUP_FLAG_FILTER_ALL; } @@ -367,17 +398,17 @@ static int cleanup_milter_header_checks(CLEANUP_STATE *state, VSTRING *buf) } } -/* cleanup_milter_hbc_add_meta - add REDIRECT or FILTER meta records */ +/* cleanup_milter_hbc_add_meta_records - add REDIRECT or FILTER meta records */ -static void cleanup_milter_hbc_add_meta(CLEANUP_STATE *state) +static void cleanup_milter_hbc_add_meta_records(CLEANUP_STATE *state) { - const char *myname = "cleanup_milter_hbc_add_meta"; + const char *myname = "cleanup_milter_hbc_add_meta_records"; off_t reverse_ptr_offset; off_t new_meta_offset; /* * Note: this code runs while the Milter infrastructure is being torn - * down. For this reason we handle all I/O errors here on the spot + * down. For this reason we handle all I/O errors here on the spot, * instead of reporting them back through the Milter infrastructure. */ @@ -395,7 +426,7 @@ static void cleanup_milter_hbc_add_meta(CLEANUP_STATE *state) * target of the old "meta record append" pointer record. This reverse * pointer record becomes the new "meta record append" pointer record. * Although the new "meta record append" pointer record will never be - * used we update it here to make the code more similar to other code + * used, we update it here to make the code more similar to other code * that inserts/appends content, so that common code can be factored out * later. */ @@ -436,6 +467,10 @@ static void cleanup_milter_hbc_add_meta(CLEANUP_STATE *state) * that was written while Postfix received the message. */ state->append_meta_pt_offset = reverse_ptr_offset; + + /* + * Note: state->append_meta_pt_target never changes. + */ } /* cleanup_milter_header_checks_init - initialize post-Milter header checks */ @@ -477,8 +512,10 @@ static void cleanup_milter_hbc_finish(CLEANUP_STATE *state) if (state->milter_hbc_reply) vstring_free(state->milter_hbc_reply); state->milter_hbc_reply = 0; - if (CLEANUP_OUT_OK(state) && (state->filter || state->redirect)) - cleanup_milter_hbc_add_meta(state); + if (CLEANUP_OUT_OK(state) + && !CLEANUP_MILTER_REJECTING_OR_DISCARDING_MESSAGE(state) + && (state->filter || state->redirect)) + cleanup_milter_hbc_add_meta_records(state); } /* @@ -577,7 +614,6 @@ static const char *cleanup_add_header(void *context, const char *name, buf = vstring_alloc(100); vstring_sprintf(buf, "%s:%s%s", name, space, value); if (state->milter_hbc_checks - && (state->flags & CLEANUP_FLAG_FILTER_ALL) && cleanup_milter_header_checks(state, buf) == 0) { vstring_free(buf); return (0); @@ -637,7 +673,7 @@ static const char *cleanup_add_header(void *context, const char *name, STR(state->milter_hbc_reply) : 0); /* - * Note: state->append_meta_pt_target never changes. + * Note: state->append_hdr_pt_target never changes. */ } @@ -960,7 +996,6 @@ static const char *cleanup_patch_header(CLEANUP_STATE *state, */ vstring_sprintf(buf, "%s:%s%s", new_hdr_name, hdr_space, new_hdr_value); if (state->milter_hbc_checks - && (state->flags & CLEANUP_FLAG_FILTER_ALL) && cleanup_milter_header_checks(state, buf) == 0) CLEANUP_PATCH_HEADER_RETURN(0); @@ -1786,6 +1821,29 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, if (msg_verbose) msg_info("%s: %s", myname, resp); + /* + * Don't process our own milter_header/body checks replies. See comments + * in cleanup_milter_hbc_extend(). + */ + if (state->milter_hbc_reply && + strcmp(resp, STR(state->milter_hbc_reply)) == 0) + return (0); + + /* + * Don't process Milter replies that are redundant because header/body + * checks already decided that we will not receive the message; or Milter + * replies that would have conflicting effect with the outcome of + * header/body checks (for example, header_checks "discard" action + * followed by Milter "reject" reply). Logging both actions would look + * silly. + */ + if (CLEANUP_MILTER_REJECTING_OR_DISCARDING_MESSAGE(state)) { + if (msg_verbose) + msg_info("%s: ignoring redundant or conflicting milter reply: %s", + state->queue_id, resp); + return (0); + } + /* * Sanity check. */ @@ -1847,13 +1905,6 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, default: msg_panic("%s: unexpected mail filter reply: %s", myname, resp); } - - /* - * Don't log milter_header/body checks actions again. - */ - if (state->milter_hbc_reply && strcmp(resp, STR(state->milter_hbc_reply)) == 0) - return (ret); - vstring_sprintf(state->temp1, "%s: %s: %s from %s[%s]: %s;", state->queue_id, action, event, state->client_name, state->client_addr, text); @@ -2137,8 +2188,12 @@ static void usage(void) msg_warn(" ins_header index name [value]"); msg_warn(" upd_header index name [value]"); msg_warn(" del_header index name"); + msg_warn(" chg_from addr parameters"); msg_warn(" add_rcpt addr"); + msg_warn(" add_rcpt_par addr parameters"); msg_warn(" del_rcpt addr"); + msg_warn(" replbody pathname"); + msg_warn(" header_checks type:name"); } /* flatten_args - unparse partial command line */ @@ -2327,9 +2382,17 @@ int main(int unused_argc, char **argv) } else if (state->dst == 0) { msg_warn("no open queue file"); } else if (strcmp(argv->argv[0], "close") == 0) { - if (*var_milt_head_checks) + if (*var_milt_head_checks) { cleanup_milter_hbc_finish(state); + var_milt_head_checks = ""; + } close_queue_file(state); + } else if (state->milter_hbc_reply && LEN(state->milter_hbc_reply)) { + /* Postfix libmilter would skip further requests. */ + msg_info("ignoring: %s %s %s", argv->argv[0], + argv->argc > 1 ? argv->argv[1] : "", + argv->argc > 2 ? argv->argv[2] : ""); + continue; } else if (strcmp(argv->argv[0], "add_header") == 0) { if (argv->argc < 2) { msg_warn("bad add_header argument count: %d", argv->argc); diff --git a/postfix/src/cleanup/cleanup_milter.in15h b/postfix/src/cleanup/cleanup_milter.in15h new file mode 100644 index 000000000..3538f79b4 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.in15h @@ -0,0 +1,11 @@ +#verbose on +open test-queue-file15h.tmp + +# Test the CLEANUP_FILTER_FLAG_ALL feature. The first header with +# YES clears the flag, and the second add_header is ignored. + +header_checks regexp:cleanup_milter.reg15h +add_header X-SPAM-FLAG YES +add_header X-SPAM-FLAG NO + +close diff --git a/postfix/src/cleanup/cleanup_milter.in15i b/postfix/src/cleanup/cleanup_milter.in15i new file mode 100644 index 000000000..454036a55 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.in15i @@ -0,0 +1,11 @@ +#verbose on +open test-queue-file15i.tmp + +# Test the CLEANUP_STAT_CONT flag. The first header triggers FILTER, +# but the second header triggers REJECT, so the filter is not saved. + +header_checks regexp:cleanup_milter.reg15i +add_header X-SPAM-FLAG NO +add_header X-SPAM-FLAG YES + +close diff --git a/postfix/src/cleanup/cleanup_milter.ref14d2 b/postfix/src/cleanup/cleanup_milter.ref14d2 index b544187cc..dece3d57f 100644 --- a/postfix/src/cleanup/cleanup_milter.ref14d2 +++ b/postfix/src/cleanup/cleanup_milter.ref14d2 @@ -16,9 +16,7 @@ 402 regular_text: Message-Id: <20090605180519.DA4892510C1@ahost.example.com> 462 regular_text: Date: Fri, 5 Jun 2009 14:05:19 -0400 (EDT) 507 regular_text: From: wietse@ahost.example.com (Wietse Venema) - 555 pointer_record: 642 - 642 regular_text: X-SPAM-FLAG: YES - 660 pointer_record: 572 + 555 pointer_record: 0 572 regular_text: 574 regular_text: Fri Jun 5 14:05:19 EDT 2009 604 pointer_record: 0 diff --git a/postfix/src/cleanup/cleanup_milter.ref15d2 b/postfix/src/cleanup/cleanup_milter.ref15d2 index 773fd4071..746a13bc1 100644 --- a/postfix/src/cleanup/cleanup_milter.ref15d2 +++ b/postfix/src/cleanup/cleanup_milter.ref15d2 @@ -14,9 +14,7 @@ 367 regular_text: Message-Id: <20090605180634.06F8B2510C2@ahost.example.com> 427 regular_text: Date: Fri, 5 Jun 2009 14:06:34 -0400 (EDT) 472 regular_text: From: wietse@ahost.example.com (Wietse Venema) - 520 pointer_record: 641 - 641 regular_text: X-SPAM-FLAG: YES - 659 pointer_record: 537 + 520 pointer_record: 0 537 regular_text: 539 regular_text: Fri Jun 5 14:06:34 EDT 2009 569 pointer_record: 0 diff --git a/postfix/src/cleanup/cleanup_milter.ref15h1 b/postfix/src/cleanup/cleanup_milter.ref15h1 new file mode 100644 index 000000000..bb51e0e0a --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.ref15h1 @@ -0,0 +1,3 @@ +./cleanup_milter: NOQUEUE: milter-header-reject: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: 5.7.1 whatever +./cleanup_milter: ignoring: add_header X-SPAM-FLAG NO +./cleanup_milter: errs = message content rejected diff --git a/postfix/src/cleanup/cleanup_milter.ref15h2 b/postfix/src/cleanup/cleanup_milter.ref15h2 new file mode 100644 index 000000000..936f02216 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.ref15h2 @@ -0,0 +1,27 @@ +*** ENVELOPE RECORDS test-queue-file15h.tmp *** + 0 message_size: 365 221 1 0 365 + 81 message_arrival_time: Fri Jun 5 14:06:34 2009 + 99 create_time: Fri Jun 5 14:06:34 2009 + 123 named_attribute: rewrite_context=local + 146 sender_fullname: Wietse Venema + 161 sender: wietse@ahost.example.com + 187 pointer_record: 0 + 202 pointer_record: 0 + 219 *** MESSAGE CONTENTS test-queue-file15h.tmp *** + 221 regular_text: Received: by ahost.example.com (Postfix, from userid 1001) + 281 regular_text: id 06F8B2510C2; Fri, 5 Jun 2009 14:06:34 -0400 (EDT) + 337 regular_text: To: wietse@ahost.example.com + 367 regular_text: Message-Id: <20090605180634.06F8B2510C2@ahost.example.com> + 427 regular_text: Date: Fri, 5 Jun 2009 14:06:34 -0400 (EDT) + 472 regular_text: From: wietse@ahost.example.com (Wietse Venema) + 520 pointer_record: 641 + 641 regular_text: X-SPAM-FLAG: YES + 659 pointer_record: 537 + 537 regular_text: + 539 regular_text: Fri Jun 5 14:06:34 EDT 2009 + 569 pointer_record: 0 + 586 *** HEADER EXTRACTED test-queue-file15h.tmp *** + 588 pointer_record: 0 + 605 original_recipient: wietse + 613 recipient: wietse@ahost.example.com + 639 *** MESSAGE FILE END test-queue-file15h.tmp *** diff --git a/postfix/src/cleanup/cleanup_milter.ref15i1 b/postfix/src/cleanup/cleanup_milter.ref15i1 new file mode 100644 index 000000000..b56172852 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.ref15i1 @@ -0,0 +1,3 @@ +./cleanup_milter: NOQUEUE: milter-header-filter: header X-SPAM-FLAG: NO from client_name[client_addr]; from= to=: x:y:z +./cleanup_milter: NOQUEUE: milter-header-reject: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: 5.7.1 whatever +./cleanup_milter: errs = message content rejected diff --git a/postfix/src/cleanup/cleanup_milter.ref15i2 b/postfix/src/cleanup/cleanup_milter.ref15i2 new file mode 100644 index 000000000..531ac4c36 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.ref15i2 @@ -0,0 +1,29 @@ +*** ENVELOPE RECORDS test-queue-file15i.tmp *** + 0 message_size: 365 221 1 0 365 + 81 message_arrival_time: Fri Jun 5 14:06:34 2009 + 99 create_time: Fri Jun 5 14:06:34 2009 + 123 named_attribute: rewrite_context=local + 146 sender_fullname: Wietse Venema + 161 sender: wietse@ahost.example.com + 187 pointer_record: 0 + 202 pointer_record: 0 + 219 *** MESSAGE CONTENTS test-queue-file15i.tmp *** + 221 regular_text: Received: by ahost.example.com (Postfix, from userid 1001) + 281 regular_text: id 06F8B2510C2; Fri, 5 Jun 2009 14:06:34 -0400 (EDT) + 337 regular_text: To: wietse@ahost.example.com + 367 regular_text: Message-Id: <20090605180634.06F8B2510C2@ahost.example.com> + 427 regular_text: Date: Fri, 5 Jun 2009 14:06:34 -0400 (EDT) + 472 regular_text: From: wietse@ahost.example.com (Wietse Venema) + 520 pointer_record: 641 + 641 regular_text: X-SPAM-FLAG: NO + 658 pointer_record: 675 + 675 regular_text: X-SPAM-FLAG: YES + 693 pointer_record: 537 + 537 regular_text: + 539 regular_text: Fri Jun 5 14:06:34 EDT 2009 + 569 pointer_record: 0 + 586 *** HEADER EXTRACTED test-queue-file15i.tmp *** + 588 pointer_record: 0 + 605 original_recipient: wietse + 613 recipient: wietse@ahost.example.com + 639 *** MESSAGE FILE END test-queue-file15i.tmp *** diff --git a/postfix/src/cleanup/cleanup_milter.reg15h b/postfix/src/cleanup/cleanup_milter.reg15h new file mode 100644 index 000000000..8c97639b2 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.reg15h @@ -0,0 +1,2 @@ +/YES/ reject whatever +/NO/ filter x:y:z diff --git a/postfix/src/cleanup/cleanup_milter.reg15i b/postfix/src/cleanup/cleanup_milter.reg15i new file mode 100644 index 000000000..8c97639b2 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.reg15i @@ -0,0 +1,2 @@ +/YES/ reject whatever +/NO/ filter x:y:z diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 8545f9f48..fcc5cebf8 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20090606" +#define MAIL_RELEASE_DATE "20090607" #define MAIL_VERSION_NUMBER "2.7" #ifdef SNAPSHOT diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c index 9e5072994..2fa88c81a 100644 --- a/postfix/src/milter/test-milter.c +++ b/postfix/src/milter/test-milter.c @@ -39,7 +39,7 @@ /* Insert header at specified position. /* .IP "\fB-l\fR" /* Header values include leading space. Specify this option -/* before \fB-i\fR or \fB-r\fR. +/* before \fB-i\fR or \fB-h\fR. /* .IP "\fB-m connect|helo|mail|rcpt|data|eoh|eom\fR" /* The protocol stage that receives the list of macros specified /* with \fB-M\fR. The default protocol stage is \fBconnect\fR. @@ -342,8 +342,6 @@ static sfsistat test_eom(SMFICTX *ctx) #ifdef SMFIR_CHGFROM if (chg_from != 0 && smfi_chgfrom(ctx, chg_from, "whatever") == MI_FAILURE) fprintf(stderr, "smfi_chgfrom failed\n"); - else - printf("smfi_chgfrom OK\n"); #endif #ifdef SMFIR_INSHEADER if (ins_hdr && smfi_insheader(ctx, ins_idx, ins_hdr, ins_val) == MI_FAILURE) diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index bcc4dcbd0..90217f040 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -10,7 +10,7 @@ MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \ str_vars.h time_table.h time_vars.h raw_table.h raw_vars.h \ nint_table.h nint_vars.h AUTOS = auto_table.h auto_vars.h -DUMMIES = makes_dummy autos_dummy +DUMMIES = makes_dummy autos_dummy # for "make -j" PROG = postconf SAMPLES = ../../conf/main.cf.default INC_DIR = ../../include diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index 0119d5274..92c7927ec 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -1471,7 +1471,7 @@ typedef int pid_t; * sections above. */ #ifndef PRINTFLIKE -#if (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || __GNUC__ == 3 +#if (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || __GNUC__ >= 3 #define PRINTFLIKE(x,y) __attribute__ ((format (printf, (x), (y)))) #else #define PRINTFLIKE(x,y)