From e3121fd2b86d57d27a518285c0f57eaf7a1f33f6 Mon Sep 17 00:00:00 2001
From: Wietse Venema
Date: Sun, 7 Jun 2009 00:00:00 -0500
Subject: [PATCH] postfix-2.7-20090607
---
postfix/HISTORY | 7 ++
postfix/RELEASE_NOTES | 12 +-
postfix/conf/postmulti-script | 40 +++----
postfix/html/cleanup.8.html | 6 +-
postfix/html/postconf.5.html | 20 ++--
postfix/man/man5/postconf.5 | 19 ++-
postfix/man/man8/cleanup.8 | 6 +-
postfix/proto/postconf.proto | 20 ++--
postfix/src/cleanup/Makefile.in | 66 ++++++++++-
postfix/src/cleanup/cleanup.c | 6 +-
postfix/src/cleanup/cleanup_milter.c | 131 +++++++++++++++------
postfix/src/cleanup/cleanup_milter.in15h | 11 ++
postfix/src/cleanup/cleanup_milter.in15i | 11 ++
postfix/src/cleanup/cleanup_milter.ref14d2 | 4 +-
postfix/src/cleanup/cleanup_milter.ref15d2 | 4 +-
postfix/src/cleanup/cleanup_milter.ref15h1 | 3 +
postfix/src/cleanup/cleanup_milter.ref15h2 | 27 +++++
postfix/src/cleanup/cleanup_milter.ref15i1 | 3 +
postfix/src/cleanup/cleanup_milter.ref15i2 | 29 +++++
postfix/src/cleanup/cleanup_milter.reg15h | 2 +
postfix/src/cleanup/cleanup_milter.reg15i | 2 +
postfix/src/global/mail_version.h | 2 +-
postfix/src/milter/test-milter.c | 4 +-
postfix/src/postconf/Makefile.in | 2 +-
postfix/src/util/sys_defs.h | 2 +-
25 files changed, 336 insertions(+), 103 deletions(-)
create mode 100644 postfix/src/cleanup/cleanup_milter.in15h
create mode 100644 postfix/src/cleanup/cleanup_milter.in15i
create mode 100644 postfix/src/cleanup/cleanup_milter.ref15h1
create mode 100644 postfix/src/cleanup/cleanup_milter.ref15h2
create mode 100644 postfix/src/cleanup/cleanup_milter.ref15i1
create mode 100644 postfix/src/cleanup/cleanup_milter.ref15i2
create mode 100644 postfix/src/cleanup/cleanup_milter.reg15h
create mode 100644 postfix/src/cleanup/cleanup_milter.reg15i
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)