diff --git a/postfix/HISTORY b/postfix/HISTORY
index 693173fe0..fbb21dce7 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -15278,3 +15278,26 @@ Apologies for any names omitted.
does not like the workaround. We now default back to the
non-workaround code and turn on the workaround dynamically.
Files: util/unix_send_fd.c, unix_recv_fd.c, unix_pass_fd_fix.c.
+
+20090605
+
+ Portability: modern kernels below ancient user-land. File:
+ makedefs.
+
+20090606
+
+ Feature: post-Milter header checks, with all actions except
+ PREPEND. To enable, specify for example "milter_header_checks
+ = pcre:/path/to/file". Files: cleanup/cleanup_init.c,
+ cleanup/cleanup_milter.c, cleanup/cleanup_extracted.c,
+ cleanup/cleanup_state.c.
+
+ Bugfix: non-portable command pathname in postmulti-script.
+
+ Safety: "postmulti -e destroy" no longer attempts to remove
+ files that are created AFTER "postmulti -e create". Rationale:
+ by design, postfix queue/data directories are not trusted;
+ actions within those directory trees must not affect files
+ 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.
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
index 68fe1e2e6..e10c3a338 100644
--- a/postfix/RELEASE_NOTES
+++ b/postfix/RELEASE_NOTES
@@ -13,3 +13,21 @@ specifies the release date of a stable release or snapshot release.
If you upgrade from Postfix 2.5 or earlier, read RELEASE_NOTES-2.6
before proceeding.
+
+Incompatibility with snapshot 20090606
+======================================
+
+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.
+
+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.
diff --git a/postfix/WISHLIST b/postfix/WISHLIST
index b3e7caf4a..f5a351f3d 100644
--- a/postfix/WISHLIST
+++ b/postfix/WISHLIST
@@ -2,9 +2,11 @@ Wish list:
Remove this file from the stable release.
- Apply header_checks and body_checks when Milters add or
- modify the message content. Use case: Milters that add
- spamminess headers.
+ Fix the header_body_checks API, so that the name of the map
+ class (e.g. milter_header_checks) is available for logging.
+
+ Fix the mime_state and header_body_checks APIs, so that
+ they use VSTRINGs. This simplifies REPLACE actions.
Update FILTER_README for multi-instance support, and rename
the old document to FILTER_LEGACY_README.
diff --git a/postfix/conf/postmulti-script b/postfix/conf/postmulti-script
index 3f1333be3..13fffe7fb 100644
--- a/postfix/conf/postmulti-script
+++ b/postfix/conf/postmulti-script
@@ -27,6 +27,13 @@ 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"}
@@ -36,6 +43,7 @@ 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,57 +244,44 @@ destroy)
postfix -c "$config_directory" status >/dev/null 2>&1 &&
fatal "Instance '$config_directory' is not stopped"
- # XXX: Internal "postfix /some/cmd" interface via /bin/env for execvp().
- #
- for q in maildrop incoming active deferred hold
- do
- postfix -c "$config_directory" /bin/env \
- find "$q" ! -name "$q" ! -name "?" -perm 0700 -print |
- grep "^" >/dev/null &&
- fatal "Instance '$config_directory' $q queue is not empty"
- done
-
# Update multi_instance directories
# and also (just in case) drop from alternate_config_directories
#
- update_cfdirs del $config_directory || exit 1
+ $DEBUG update_cfdirs del $config_directory || exit 1
- # Change default personalities:
- MAIL_CONFIG="$config_directory"; export MAIL_CONFIG
-
- # Full steam ahead, instance will be at least partly destroyed!
-
- # Try to remove data_directory, but not sub-directories.
- # Note: care with "$TAG" insertion into sh -c 'script'.
+ # "postmulti -e destroy" will remove an entire instance only
+ # when invoked immediately after "postmulti -e create". Trying
+ # to remove more files is too dangerous.
#
- postfix /bin/sh -c \
- 'cd $data_directory; rm -f -- *; cd ..; rmdir $data_directory; \
- PATH=$command_directory:$PATH; export PATH; \
- test -d $data_directory && \
- postlog -p warn -t "'"$TAG"'" \
- "$data_directory partly removed" 2>&1' 2>/dev/null
+ # 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
+ do
+ $DEBUG rmdir -- \$q ||
+ $WARN `pwd`/\$q: please verify contents and remove by hand
+ done
+ "
- # Remove Postfix-owned files in the queue directory.
- # Remove all files in the "pid" sub-directory.
- # Remove empty directories.
- # Note: care with "$TAG" insertion into sh -c 'script'.
- postfix /bin/sh -c \
- 'find . -user $mail_owner ! -type d -exec rm -f -- "{}" ";"; \
- find . -depth -user $mail_owner -type d -exec rmdir -- "{}" ";"; \
- rm -f -- pid/*; rmdir *; cd ..; rmdir $queue_directory; \
- PATH=$command_directory:$PATH; export PATH; \
- test -d $queue_directory && \
- postlog -p warn -t "'"$TAG"'" \
- "$queue_directory partly removed" 2>&1' 2>/dev/null
+ postfix -c "$config_directory" /bin/sh -c "
+ for dir in \$data_directory \$queue_directory
+ do
+ $DEBUG rmdir -- \$dir ||
+ $WARN \$dir: please verify contents and remove by hand
+ done
+ "
# In the configuration directory remove just the main.cf and master.cf
# files.
- rm -f -- "$MAIL_CONFIG/master.cf" "$MAIL_CONFIG/main.cf" 2>/dev/null
- rmdir -- "$MAIL_CONFIG" 2>/dev/null
- test -d "$MAIL_CONFIG" && \
- postlog -p warn -t "$TAG" \
- "$MAIL_CONFIG partly removed" 2>&1
+ $DEBUG rm -f -- "$config_directory/master.cf" "$config_directory/main.cf" 2>/dev/null
+ $DEBUG rmdir -- "$config_directory" ||
+ $WARN $config_directory: please verify contents and remove by hand
;;
+
enable)
postconf -c "$config_directory" -e \
"multi_instance_enable = yes" || exit 1;;
diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html
index 9c6196aff..61952c1f3 100644
--- a/postfix/html/cleanup.8.html
+++ b/postfix/html/cleanup.8.html
@@ -224,6 +224,13 @@ 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:
+
+ milter_header_checks (empty)
+ Optional lookup tables for content inspection of
+ primary message headers that are produced by Milter
+ applications.
+
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 f351fdd76..85d6e2a4a 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -5689,6 +5689,33 @@ of available macro names and their meanings.
This feature is available in Postfix 2.5 and later.
+
+
+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.
+
+
+ The following example sends mail that is marked as SPAM to a
+spam sanization machine. Note that matches are case-insensitive by
+default.
+
+
+
+/etc/postfix/main.cf:
+ milter_header_checks = pcre:/etc/postfix/milter_header_checks
+
+
+/etc/postfix/milter_header_checks:
+ /^X-SPAM-FLAG:\s+YES]/ FILTER mysmtp:sanitizer.example.com:25
+
+
+
+
milter_helo_macros
diff --git a/postfix/makedefs b/postfix/makedefs
index ee4643610..071a30ef0 100644
--- a/postfix/makedefs
+++ b/postfix/makedefs
@@ -298,7 +298,15 @@ case "$SYSTEM.$RELEASE" in
case "$RELEASE" in
2.[0-5].*) CCARGS="$CCARGS -DNO_EPOLL";;
# Workaround for retarded libc
- 2.6.*) trap 'rm -f makedefs.test makedefs.test.[co]' 1 2 3 15
+ 2.6.*)
+ if [ `expr "X$CCARGS" : "X.*-DNO_EPOLL"` -gt 0 ]
+ then
+ :
+ elif [ ! -e /usr/include/sys/epoll.h ]
+ then
+ echo CCARGS="$CCARGS -DNO_EPOLL"
+ else
+ trap 'rm -f makedefs.test makedefs.test.[co]' 1 2 3 15
cat >makedefs.test.c <<'EOF'
#include
#include
@@ -320,7 +328,8 @@ EOF
${CC-gcc} -o makedefs.test makedefs.test.c || exit 1
./makedefs.test 2>/dev/null ||
CCARGS="$CCARGS -DNO_EPOLL"
- rm -f makedefs.test makedefs.test.[co];;
+ rm -f makedefs.test makedefs.test.[co]
+ fi;;
esac
;;
GNU.0*|GNU/kFreeBSD.[567]*)
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index 48a38dcfe..5ab7bbdcf 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -3158,6 +3158,33 @@ after the end of the message header. See MILTER_README for a list
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.
+.PP
+The following example sends mail that is marked as SPAM to a
+spam sanization machine. Note that matches are case-insensitive by
+default.
+.sp
+.in +4
+.nf
+.na
+.ft C
+/etc/postfix/main.cf:
+ milter_header_checks = pcre:/etc/postfix/milter_header_checks
+.fi
+.ad
+.ft R
+.nf
+.na
+.ft C
+/etc/postfix/milter_header_checks:
+ /^X-SPAM-FLAG:\es+YES]/ FILTER mysmtp:sanitizer.example.com:25
+.fi
+.ad
+.ft R
+.in -4
.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 de5f912f0..5bba18db9 100644
--- a/postfix/man/man8/cleanup.8
+++ b/postfix/man/man8/cleanup.8
@@ -190,6 +190,11 @@ Available in Postfix version 2.5 and later:
.IP "\fBmilter_end_of_header_macros (see 'postconf -d' output)\fR"
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:
+.IP "\fBmilter_header_checks (empty)\fR"
+Optional lookup tables for content inspection of primary
+message headers that are produced by Milter applications.
.SH "MIME PROCESSING CONTROLS"
.na
.nf
diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink
index 7d4d59e52..31fa892cb 100755
--- a/postfix/mantools/postlink
+++ b/postfix/mantools/postlink
@@ -868,6 +868,7 @@ while (<>) {
s;\bmilter_unknown_command_macros\b;$&;g;
s;\bmilter_end_of_data_macros\b;$&;g;
s;\bmilter_end_of_header_macros\b;$&;g;
+ s;\bmilter_header_checks\b;$&;g;
# Multi-instance support
s;\bmulti_instance_directo[-]*\n*[ ]*ries\b;$&;g;
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index 6fd144ef2..1a08bda44 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -12300,3 +12300,25 @@ parameter. See there for details.
This feature is available in Postfix 2.5 and later.
+%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.
+
+
+ The following example sends mail that is marked as SPAM to a
+spam sanization machine. Note that matches are case-insensitive by
+default.
+
+
+
+/etc/postfix/main.cf:
+ milter_header_checks = pcre:/etc/postfix/milter_header_checks
+
+
+/etc/postfix/milter_header_checks:
+ /^X-SPAM-FLAG:\s+YES]/ FILTER mysmtp:sanitizer.example.com:25
+
+
diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in
index 161ebf2dd..f59f9bb40 100644
--- a/postfix/src/cleanup/Makefile.in
+++ b/postfix/src/cleanup/Makefile.in
@@ -76,7 +76,11 @@ milter_tests: cleanup_milter_test bug_tests \
cleanup_milter_test10b cleanup_milter_test10c cleanup_milter_test10d \
cleanup_milter_test10e cleanup_milter_test11 cleanup_milter_test12 \
cleanup_milter_test13a cleanup_milter_test13b cleanup_milter_test13c \
- cleanup_milter_test13d
+ cleanup_milter_test13d \
+ cleanup_milter_test14a cleanup_milter_test14b cleanup_milter_test14c \
+ cleanup_milter_test14d cleanup_milter_test14e \
+ cleanup_milter_test15a cleanup_milter_test15b cleanup_milter_test15c \
+ cleanup_milter_test15d cleanup_milter_test15e
root_tests:
@@ -334,6 +338,106 @@ cleanup_milter_test13d: cleanup_milter test-queue-file13d cleanup_milter.in13d \
diff cleanup_milter.ref13d cleanup_milter.tmp
rm -f test-queue-file13d.tmp cleanup_milter.tmp
+cleanup_milter_test14a: cleanup_milter test-queue-file14 cleanup_milter.in14a \
+ cleanup_milter.ref14a1 ../postcat/postcat cleanup_milter.ref14a2
+ cp test-queue-file14 test-queue-file14a.tmp
+ chmod u+w test-queue-file14a.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref14a1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file14a.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref14a2 cleanup_milter.tmp2
+ rm -f test-queue-file14a.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test14b: cleanup_milter test-queue-file14 cleanup_milter.in14b \
+ cleanup_milter.ref14b1 ../postcat/postcat cleanup_milter.ref14b2
+ cp test-queue-file14 test-queue-file14b.tmp
+ chmod u+w test-queue-file14b.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref14b1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file14b.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref14b2 cleanup_milter.tmp2
+ rm -f test-queue-file14b.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test14c: cleanup_milter test-queue-file14 cleanup_milter.in14c \
+ cleanup_milter.ref14c1 ../postcat/postcat cleanup_milter.ref14c2
+ cp test-queue-file14 test-queue-file14c.tmp
+ chmod u+w test-queue-file14c.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref14c1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file14c.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref14c2 cleanup_milter.tmp2
+ rm -f test-queue-file14c.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test14d: cleanup_milter test-queue-file14 cleanup_milter.in14d \
+ cleanup_milter.ref14d1 ../postcat/postcat cleanup_milter.ref14d2
+ cp test-queue-file14 test-queue-file14d.tmp
+ chmod u+w test-queue-file14d.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref14d1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file14d.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref14d2 cleanup_milter.tmp2
+ rm -f test-queue-file14d.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test14e: cleanup_milter test-queue-file14 cleanup_milter.in14e \
+ cleanup_milter.ref14e1 ../postcat/postcat cleanup_milter.ref14e2
+ cp test-queue-file14 test-queue-file14e.tmp
+ chmod u+w test-queue-file14e.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref14e1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file14e.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref14e2 cleanup_milter.tmp2
+ rm -f test-queue-file14e.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
+ chmod u+w test-queue-file15a.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref15a1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file15a.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref15a2 cleanup_milter.tmp2
+ rm -f test-queue-file15a.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test15b: cleanup_milter test-queue-file15 cleanup_milter.in15b \
+ cleanup_milter.ref15b1 ../postcat/postcat cleanup_milter.ref15b2
+ cp test-queue-file15 test-queue-file15b.tmp
+ chmod u+w test-queue-file15b.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref15b1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file15b.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref15b2 cleanup_milter.tmp2
+ rm -f test-queue-file15b.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test15c: cleanup_milter test-queue-file15 cleanup_milter.in15c \
+ cleanup_milter.ref15c1 ../postcat/postcat cleanup_milter.ref15c2
+ cp test-queue-file15 test-queue-file15c.tmp
+ chmod u+w test-queue-file15c.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref15c1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file15c.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref15c2 cleanup_milter.tmp2
+ rm -f test-queue-file15c.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test15d: cleanup_milter test-queue-file15 cleanup_milter.in15d \
+ cleanup_milter.ref15d1 ../postcat/postcat cleanup_milter.ref15d2
+ cp test-queue-file15 test-queue-file15d.tmp
+ chmod u+w test-queue-file15d.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref15d1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file15d.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref15d2 cleanup_milter.tmp2
+ rm -f test-queue-file15d.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test15e: cleanup_milter test-queue-file15 cleanup_milter.in15e \
+ cleanup_milter.ref15e1 ../postcat/postcat cleanup_milter.ref15e2
+ cp test-queue-file15 test-queue-file15e.tmp
+ chmod u+w test-queue-file15e.tmp
+ ./cleanup_milter cleanup_milter.tmp1
+ diff cleanup_milter.ref15e1 cleanup_milter.tmp1
+ ../postcat/postcat -ov test-queue-file15e.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref15e2 cleanup_milter.tmp2
+ rm -f test-queue-file15e.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 \
@@ -349,6 +453,7 @@ cleanup.o: ../../include/attr.h
cleanup.o: ../../include/been_here.h
cleanup.o: ../../include/cleanup_user.h
cleanup.o: ../../include/dict.h
+cleanup.o: ../../include/header_body_checks.h
cleanup.o: ../../include/header_opts.h
cleanup.o: ../../include/htable.h
cleanup.o: ../../include/iostuff.h
@@ -385,6 +490,7 @@ cleanup_addr.o: ../../include/cleanup_user.h
cleanup_addr.o: ../../include/dict.h
cleanup_addr.o: ../../include/dsn_mask.h
cleanup_addr.o: ../../include/ext_prop.h
+cleanup_addr.o: ../../include/header_body_checks.h
cleanup_addr.o: ../../include/header_opts.h
cleanup_addr.o: ../../include/htable.h
cleanup_addr.o: ../../include/iostuff.h
@@ -422,6 +528,7 @@ cleanup_api.o: ../../include/deliver_request.h
cleanup_api.o: ../../include/dict.h
cleanup_api.o: ../../include/dsn.h
cleanup_api.o: ../../include/dsn_buf.h
+cleanup_api.o: ../../include/header_body_checks.h
cleanup_api.o: ../../include/header_opts.h
cleanup_api.o: ../../include/htable.h
cleanup_api.o: ../../include/iostuff.h
@@ -456,6 +563,7 @@ cleanup_body_edit.o: ../../include/attr.h
cleanup_body_edit.o: ../../include/been_here.h
cleanup_body_edit.o: ../../include/cleanup_user.h
cleanup_body_edit.o: ../../include/dict.h
+cleanup_body_edit.o: ../../include/header_body_checks.h
cleanup_body_edit.o: ../../include/header_opts.h
cleanup_body_edit.o: ../../include/htable.h
cleanup_body_edit.o: ../../include/mail_conf.h
@@ -490,6 +598,7 @@ cleanup_bounce.o: ../../include/dsn.h
cleanup_bounce.o: ../../include/dsn_buf.h
cleanup_bounce.o: ../../include/dsn_mask.h
cleanup_bounce.o: ../../include/dsn_util.h
+cleanup_bounce.o: ../../include/header_body_checks.h
cleanup_bounce.o: ../../include/header_opts.h
cleanup_bounce.o: ../../include/htable.h
cleanup_bounce.o: ../../include/iostuff.h
@@ -527,6 +636,7 @@ cleanup_envelope.o: ../../include/been_here.h
cleanup_envelope.o: ../../include/cleanup_user.h
cleanup_envelope.o: ../../include/dict.h
cleanup_envelope.o: ../../include/dsn_mask.h
+cleanup_envelope.o: ../../include/header_body_checks.h
cleanup_envelope.o: ../../include/header_opts.h
cleanup_envelope.o: ../../include/htable.h
cleanup_envelope.o: ../../include/iostuff.h
@@ -545,6 +655,7 @@ cleanup_envelope.o: ../../include/nvtable.h
cleanup_envelope.o: ../../include/qmgr_user.h
cleanup_envelope.o: ../../include/rec_attr_map.h
cleanup_envelope.o: ../../include/rec_type.h
+cleanup_envelope.o: ../../include/recipient_list.h
cleanup_envelope.o: ../../include/record.h
cleanup_envelope.o: ../../include/resolve_clnt.h
cleanup_envelope.o: ../../include/string_list.h
@@ -563,6 +674,7 @@ cleanup_extracted.o: ../../include/been_here.h
cleanup_extracted.o: ../../include/cleanup_user.h
cleanup_extracted.o: ../../include/dict.h
cleanup_extracted.o: ../../include/dsn_mask.h
+cleanup_extracted.o: ../../include/header_body_checks.h
cleanup_extracted.o: ../../include/header_opts.h
cleanup_extracted.o: ../../include/htable.h
cleanup_extracted.o: ../../include/iostuff.h
@@ -597,6 +709,7 @@ cleanup_final.o: ../../include/attr.h
cleanup_final.o: ../../include/been_here.h
cleanup_final.o: ../../include/cleanup_user.h
cleanup_final.o: ../../include/dict.h
+cleanup_final.o: ../../include/header_body_checks.h
cleanup_final.o: ../../include/header_opts.h
cleanup_final.o: ../../include/htable.h
cleanup_final.o: ../../include/mail_conf.h
@@ -626,6 +739,7 @@ cleanup_init.o: ../../include/cleanup_user.h
cleanup_init.o: ../../include/dict.h
cleanup_init.o: ../../include/ext_prop.h
cleanup_init.o: ../../include/flush_clnt.h
+cleanup_init.o: ../../include/header_body_checks.h
cleanup_init.o: ../../include/header_opts.h
cleanup_init.o: ../../include/htable.h
cleanup_init.o: ../../include/iostuff.h
@@ -658,6 +772,7 @@ cleanup_map11.o: ../../include/attr.h
cleanup_map11.o: ../../include/been_here.h
cleanup_map11.o: ../../include/cleanup_user.h
cleanup_map11.o: ../../include/dict.h
+cleanup_map11.o: ../../include/header_body_checks.h
cleanup_map11.o: ../../include/header_opts.h
cleanup_map11.o: ../../include/htable.h
cleanup_map11.o: ../../include/mail_addr_map.h
@@ -687,6 +802,7 @@ cleanup_map1n.o: ../../include/attr.h
cleanup_map1n.o: ../../include/been_here.h
cleanup_map1n.o: ../../include/cleanup_user.h
cleanup_map1n.o: ../../include/dict.h
+cleanup_map1n.o: ../../include/header_body_checks.h
cleanup_map1n.o: ../../include/header_opts.h
cleanup_map1n.o: ../../include/htable.h
cleanup_map1n.o: ../../include/mail_addr_map.h
@@ -717,6 +833,7 @@ cleanup_masquerade.o: ../../include/attr.h
cleanup_masquerade.o: ../../include/been_here.h
cleanup_masquerade.o: ../../include/cleanup_user.h
cleanup_masquerade.o: ../../include/dict.h
+cleanup_masquerade.o: ../../include/header_body_checks.h
cleanup_masquerade.o: ../../include/header_opts.h
cleanup_masquerade.o: ../../include/htable.h
cleanup_masquerade.o: ../../include/mail_conf.h
@@ -750,6 +867,7 @@ cleanup_message.o: ../../include/conv_time.h
cleanup_message.o: ../../include/dict.h
cleanup_message.o: ../../include/dsn_util.h
cleanup_message.o: ../../include/ext_prop.h
+cleanup_message.o: ../../include/header_body_checks.h
cleanup_message.o: ../../include/header_opts.h
cleanup_message.o: ../../include/htable.h
cleanup_message.o: ../../include/iostuff.h
@@ -790,6 +908,8 @@ cleanup_milter.o: ../../include/been_here.h
cleanup_milter.o: ../../include/cleanup_user.h
cleanup_milter.o: ../../include/dict.h
cleanup_milter.o: ../../include/dsn_mask.h
+cleanup_milter.o: ../../include/dsn_util.h
+cleanup_milter.o: ../../include/header_body_checks.h
cleanup_milter.o: ../../include/header_opts.h
cleanup_milter.o: ../../include/htable.h
cleanup_milter.o: ../../include/iostuff.h
@@ -828,6 +948,7 @@ cleanup_out.o: ../../include/attr.h
cleanup_out.o: ../../include/been_here.h
cleanup_out.o: ../../include/cleanup_user.h
cleanup_out.o: ../../include/dict.h
+cleanup_out.o: ../../include/header_body_checks.h
cleanup_out.o: ../../include/header_opts.h
cleanup_out.o: ../../include/htable.h
cleanup_out.o: ../../include/lex_822.h
@@ -865,6 +986,7 @@ cleanup_out_recipient.o: ../../include/dsn.h
cleanup_out_recipient.o: ../../include/dsn_buf.h
cleanup_out_recipient.o: ../../include/dsn_mask.h
cleanup_out_recipient.o: ../../include/ext_prop.h
+cleanup_out_recipient.o: ../../include/header_body_checks.h
cleanup_out_recipient.o: ../../include/header_opts.h
cleanup_out_recipient.o: ../../include/htable.h
cleanup_out_recipient.o: ../../include/iostuff.h
@@ -899,6 +1021,7 @@ cleanup_region.o: ../../include/attr.h
cleanup_region.o: ../../include/been_here.h
cleanup_region.o: ../../include/cleanup_user.h
cleanup_region.o: ../../include/dict.h
+cleanup_region.o: ../../include/header_body_checks.h
cleanup_region.o: ../../include/header_opts.h
cleanup_region.o: ../../include/htable.h
cleanup_region.o: ../../include/mail_conf.h
@@ -925,6 +1048,7 @@ cleanup_rewrite.o: ../../include/attr.h
cleanup_rewrite.o: ../../include/been_here.h
cleanup_rewrite.o: ../../include/cleanup_user.h
cleanup_rewrite.o: ../../include/dict.h
+cleanup_rewrite.o: ../../include/header_body_checks.h
cleanup_rewrite.o: ../../include/header_opts.h
cleanup_rewrite.o: ../../include/htable.h
cleanup_rewrite.o: ../../include/iostuff.h
@@ -956,6 +1080,7 @@ cleanup_state.o: ../../include/attr.h
cleanup_state.o: ../../include/been_here.h
cleanup_state.o: ../../include/cleanup_user.h
cleanup_state.o: ../../include/dict.h
+cleanup_state.o: ../../include/header_body_checks.h
cleanup_state.o: ../../include/header_opts.h
cleanup_state.o: ../../include/htable.h
cleanup_state.o: ../../include/iostuff.h
diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c
index 36f4f7948..2caa775dc 100644
--- a/postfix/src/cleanup/cleanup.c
+++ b/postfix/src/cleanup/cleanup.c
@@ -170,6 +170,11 @@
/* .IP "\fBmilter_end_of_header_macros (see 'postconf -d' output)\fR"
/* 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:
+/* .IP "\fBmilter_header_checks (empty)\fR"
+/* Optional lookup tables for content inspection of primary
+/* message headers that are produced by Milter applications.
/* MIME PROCESSING CONTROLS
/* .ad
/* .fi
diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h
index d8bfe08f8..b21b6fc02 100644
--- a/postfix/src/cleanup/cleanup.h
+++ b/postfix/src/cleanup/cleanup.h
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
/*
* Milter library.
@@ -78,6 +79,8 @@ typedef struct CLEANUP_STATE {
off_t append_rcpt_pt_target; /* target of above record */
off_t append_hdr_pt_offset; /* append header here */
off_t append_hdr_pt_target; /* target of above record */
+ off_t append_meta_pt_offset; /* append meta record here */
+ off_t append_meta_pt_target; /* target of above record */
ssize_t rcpt_count; /* recipient count */
char *reason; /* failure reason */
char *smtp_reply; /* failure reason, SMTP-style */
@@ -108,6 +111,8 @@ typedef struct CLEANUP_STATE {
VSTRING *milter_ext_from; /* externalized sender */
VSTRING *milter_ext_rcpt; /* externalized recipient */
VSTRING *milter_err_text; /* milter call-back reply */
+ HBC_CHECKS *milter_hbc_checks; /* Milter header checks */
+ VSTRING *milter_hbc_reply; /* Milter header checks reply */
/*
* Support for Milter body replacement requests.
diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c
index 2253fa17a..1f5aa51f1 100644
--- a/postfix/src/cleanup/cleanup_envelope.c
+++ b/postfix/src/cleanup/cleanup_envelope.c
@@ -385,7 +385,8 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
cleanup_addr_sender(state, buf);
if (state->milters || cleanup_milters) {
/* Make room to replace sender. */
- rec_pad(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_PAYL_SIZE);
+ if ((len = strlen(state->sender)) < REC_TYPE_PTR_PAYL_SIZE)
+ rec_pad(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_PAYL_SIZE - len);
/* Remember the after-sender record offset. */
if ((state->sender_pt_target = vstream_ftell(state->dst)) < 0)
msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
diff --git a/postfix/src/cleanup/cleanup_extracted.c b/postfix/src/cleanup/cleanup_extracted.c
index cf66c5dde..81bca0858 100644
--- a/postfix/src/cleanup/cleanup_extracted.c
+++ b/postfix/src/cleanup/cleanup_extracted.c
@@ -188,6 +188,14 @@ void cleanup_extracted_process(CLEANUP_STATE *state, int type,
cleanup_out_format(state, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ENCODING, encoding);
state->flags |= CLEANUP_FLAG_INRCPT;
+ /* Make room to append more meta records. */
+ if (state->milters || cleanup_milters) {
+ if ((state->append_meta_pt_offset = vstream_ftell(state->dst)) < 0)
+ msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
+ cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT, 0L);
+ if ((state->append_meta_pt_target = vstream_ftell(state->dst)) < 0)
+ msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
+ }
}
/*
diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c
index 67a27a8d9..bc4eb9ffd 100644
--- a/postfix/src/cleanup/cleanup_init.c
+++ b/postfix/src/cleanup/cleanup_init.c
@@ -161,6 +161,7 @@ char *var_milt_eoh_macros; /* end-of-header macros */
char *var_milt_eod_macros; /* end-of-data macros */
char *var_milt_unk_macros; /* unknown command macros */
char *var_cleanup_milters; /* non-SMTP mail */
+char *var_milt_head_checks; /* post-Milter header checks */
int var_auto_8bit_enc_hdr; /* auto-detect 8bit encoding header */
int var_always_add_hdrs; /* always add missing headers */
@@ -227,6 +228,7 @@ CONFIG_STR_TABLE cleanup_str_table[] = {
VAR_MILT_EOD_MACROS, DEF_MILT_EOD_MACROS, &var_milt_eod_macros, 0, 0,
VAR_MILT_UNK_MACROS, DEF_MILT_UNK_MACROS, &var_milt_unk_macros, 0, 0,
VAR_CLEANUP_MILTERS, DEF_CLEANUP_MILTERS, &var_cleanup_milters, 0, 0,
+ VAR_MILT_HEAD_CHECKS, DEF_MILT_HEAD_CHECKS, &var_milt_head_checks, 0, 0,
0,
};
diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c
index fdab9f5cc..b42367a11 100644
--- a/postfix/src/cleanup/cleanup_milter.c
+++ b/postfix/src/cleanup/cleanup_milter.c
@@ -105,6 +105,7 @@
#include
#include
#include
+#include
/* Application-specific. */
@@ -216,6 +217,270 @@
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
+/* cleanup_milter_hbc_log - log post-milter header/body_checks action */
+
+static void cleanup_milter_hbc_log(void *context, const char *action,
+ const char *where, const char *line,
+ const char *optional_text)
+{
+ const CLEANUP_STATE *state = (CLEANUP_STATE *) context;
+ const char *attr;
+
+ vstring_sprintf(state->temp1, "%s: milter-%s-%s: %s %.60s from %s[%s];",
+ state->queue_id, where, action, where, line,
+ state->client_name, state->client_addr);
+ if (state->sender)
+ vstring_sprintf_append(state->temp1, " from=<%s>", state->sender);
+ if (state->recip)
+ vstring_sprintf_append(state->temp1, " to=<%s>", state->recip);
+ if ((attr = nvtable_find(state->attr, MAIL_ATTR_LOG_PROTO_NAME)) != 0)
+ vstring_sprintf_append(state->temp1, " proto=%s", attr);
+ if ((attr = nvtable_find(state->attr, MAIL_ATTR_LOG_HELO_NAME)) != 0)
+ vstring_sprintf_append(state->temp1, " helo=<%s>", attr);
+ if (optional_text)
+ vstring_sprintf_append(state->temp1, ": %s", optional_text);
+ msg_info("%s", vstring_str(state->temp1));
+}
+
+/* cleanup_milter_header_prepend - prepend header to milter-generated header */
+
+static void cleanup_milter_header_prepend(void *context, int rec_type,
+ const char *buf, ssize_t len, off_t offset)
+{
+ msg_warn("the milter_header/body_checks prepend action is not implemented");
+}
+
+/* cleanup_milter_hbc_extend - additional header/body_checks actions */
+
+static char *cleanup_milter_hbc_extend(void *context, const char *command,
+ int cmd_len, const char *optional_text,
+ const char *where, const char *buf,
+ ssize_t buf_len, off_t offset)
+{
+ CLEANUP_STATE *state = (CLEANUP_STATE *) context;
+ const char *map_class = VAR_MILT_HEAD_CHECKS; /* XXX */
+
+#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.
+ */
+ if (STREQUAL(command, "REJECT", cmd_len)) {
+ const CLEANUP_STAT_DETAIL *detail;
+
+ if (state->reason)
+ myfree(state->reason);
+ detail = cleanup_stat_detail(CLEANUP_STAT_CONT);
+ if (*optional_text) {
+ state->reason = dsn_prepend(detail->dsn, optional_text);
+ if (*state->reason != '4' && *state->reason != '5') {
+ msg_warn("bad DSN action in %s -- need 4.x.x or 5.x.x",
+ optional_text);
+ *state->reason = '4';
+ }
+ } else {
+ state->reason = dsn_prepend(detail->dsn, detail->text);
+ }
+ 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);
+ STR(state->milter_hbc_reply)[0] = *state->reason;
+ return ((char *) buf);
+ }
+ if (STREQUAL(command, "FILTER", cmd_len)) {
+ if (*optional_text == 0) {
+ msg_warn("missing FILTER command argument in %s map", map_class);
+ } else if (strchr(optional_text, ':') == 0) {
+ msg_warn("bad FILTER command %s in %s -- "
+ "need transport:destination",
+ optional_text, map_class);
+ } else {
+ if (state->filter)
+ myfree(state->filter);
+ state->filter = mystrdup(optional_text);
+ cleanup_milter_hbc_log((void *) state, "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);
+ vstring_strcpy(state->milter_hbc_reply, "D");
+ 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");
+ }
+ return ((char *) buf);
+ }
+ if (STREQUAL(command, "REDIRECT", cmd_len)) {
+ if (strchr(optional_text, '@') == 0) {
+ msg_warn("bad REDIRECT target \"%s\" in %s map -- "
+ "need user@domain",
+ optional_text, map_class);
+ } else {
+ if (state->redirect)
+ myfree(state->redirect);
+ state->redirect = mystrdup(optional_text);
+ cleanup_milter_hbc_log((void *) state, "redirect", where, buf,
+ optional_text);
+ state->flags &= ~CLEANUP_FLAG_FILTER_ALL;
+ }
+ return ((char *) buf);
+ }
+ msg_warn("unknown command in %s map: %s", map_class, command);
+ return ((char *) buf);
+}
+
+/* cleanup_milter_header_checks - inspect Milter-generated header */
+
+static int cleanup_milter_header_checks(CLEANUP_STATE *state, VSTRING *buf)
+{
+ char *ret;
+
+ /*
+ * Milter application "add/insert/replace header" requests happen at the
+ * end-of-message stage, therefore all the header operations are relative
+ * to the primary message header.
+ */
+ ret = hbc_header_checks((void *) state, state->milter_hbc_checks,
+ MIME_HDR_PRIMARY, (HEADER_OPTS *) 0,
+ buf, (off_t) 0);
+ if (ret == 0) {
+ return (0);
+ } else {
+ if (ret != STR(buf)) {
+ vstring_strcpy(buf, ret);
+ myfree(ret);
+ }
+ return (1);
+ }
+}
+
+/* cleanup_milter_hbc_add_meta - add REDIRECT or FILTER meta records */
+
+static void cleanup_milter_hbc_add_meta(CLEANUP_STATE *state)
+{
+ const char *myname = "cleanup_milter_hbc_add_meta";
+ 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
+ * instead of reporting them back through the Milter infrastructure.
+ */
+
+ /*
+ * Sanity check.
+ */
+ if (state->append_meta_pt_offset < 0)
+ msg_panic("%s: no meta append pointer location", myname);
+ if (state->append_meta_pt_target < 0)
+ msg_panic("%s: no meta append pointer target", myname);
+
+ /*
+ * Allocate space after the end of the queue file, and write the meta
+ * record(s), followed by a reverse pointer record that points to the
+ * 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
+ * that inserts/appends content, so that common code can be factored out
+ * later.
+ */
+ if ((new_meta_offset = vstream_fseek(state->dst, (off_t) 0, SEEK_END)) < 0) {
+ msg_warn("%s: seek file %s: %m", myname, cleanup_path);
+ state->errs |= CLEANUP_STAT_WRITE;
+ return;
+ }
+ if (state->filter != 0)
+ cleanup_out_string(state, REC_TYPE_FILT, state->filter);
+ if (state->redirect != 0)
+ cleanup_out_string(state, REC_TYPE_RDR, state->redirect);
+ if ((reverse_ptr_offset = vstream_ftell(state->dst)) < 0) {
+ msg_warn("%s: vstream_ftell file %s: %m", myname, cleanup_path);
+ state->errs |= CLEANUP_STAT_WRITE;
+ return;
+ }
+ cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT,
+ (long) state->append_meta_pt_target);
+
+ /*
+ * Pointer flipping: update the old "meta record append" pointer record
+ * value with the location of the new meta record.
+ */
+ if (vstream_fseek(state->dst, state->append_meta_pt_offset, SEEK_SET) < 0) {
+ msg_warn("%s: seek file %s: %m", myname, cleanup_path);
+ state->errs |= CLEANUP_STAT_WRITE;
+ return;
+ }
+ cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT,
+ (long) new_meta_offset);
+
+ /*
+ * Update the in-memory "meta append" pointer record location with the
+ * location of the reverse pointer record that follows the new meta
+ * record. The target of the "meta append" pointer record does not
+ * change; it's always the record that follows the dummy pointer record
+ * that was written while Postfix received the message.
+ */
+ state->append_meta_pt_offset = reverse_ptr_offset;
+}
+
+/* cleanup_milter_header_checks_init - initialize post-Milter header checks */
+
+static void cleanup_milter_header_checks_init(CLEANUP_STATE *state)
+{
+#define NO_NESTED_HDR_NAME ""
+#define NO_NESTED_HDR_VALUE ""
+#define NO_MIME_HDR_NAME ""
+#define NO_MIME_HDR_VALUE ""
+
+ static /* XXX not const */ HBC_CALL_BACKS call_backs = {
+ cleanup_milter_hbc_log,
+ cleanup_milter_header_prepend,
+ cleanup_milter_hbc_extend,
+ };
+
+ state->milter_hbc_checks =
+ hbc_header_checks_create(VAR_MILT_HEAD_CHECKS, var_milt_head_checks,
+ NO_MIME_HDR_NAME, NO_MIME_HDR_VALUE,
+ NO_NESTED_HDR_NAME, NO_NESTED_HDR_VALUE,
+ &call_backs);
+ state->milter_hbc_reply = vstring_alloc(100);
+ if (state->filter)
+ myfree(state->filter);
+ state->filter = 0;
+ if (state->redirect)
+ myfree(state->redirect);
+ state->redirect = 0;
+}
+
+/* cleanup_milter_hbc_finish - finalize post-Milter header checks */
+
+static void cleanup_milter_hbc_finish(CLEANUP_STATE *state)
+{
+ if (state->milter_hbc_checks)
+ hbc_header_checks_free(state->milter_hbc_checks);
+ state->milter_hbc_checks = 0;
+ 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);
+}
+
/*
* Milter replies.
*/
@@ -305,6 +570,19 @@ static const char *cleanup_add_header(void *context, const char *name,
if (state->append_hdr_pt_target < 0)
msg_panic("%s: no header append pointer target", myname);
+ /*
+ * Return early when Milter header checks request that this header record
+ * be dropped.
+ */
+ 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);
+ }
+
/*
* Allocate space after the end of the queue file, and write the header
* record(s), followed by a reverse pointer record that points to the
@@ -313,10 +591,9 @@ static const char *cleanup_add_header(void *context, const char *name,
*/
if ((new_hdr_offset = vstream_fseek(state->dst, (off_t) 0, SEEK_END)) < 0) {
msg_warn("%s: seek file %s: %m", myname, cleanup_path);
+ vstring_free(buf);
return (cleanup_milter_error(state, errno));
}
- buf = vstring_alloc(100);
- vstring_sprintf(buf, "%s:%s%s", name, space, value);
cleanup_out_header(state, buf); /* Includes padding */
vstring_free(buf);
if ((reverse_ptr_offset = vstream_ftell(state->dst)) < 0) {
@@ -355,7 +632,13 @@ static const char *cleanup_add_header(void *context, const char *name,
/*
* In case of error while doing record output.
*/
- return (CLEANUP_OUT_OK(state) ? 0 : cleanup_milter_error(state, 0));
+ return (CLEANUP_OUT_OK(state) == 0 ? cleanup_milter_error(state, 0) :
+ state->milter_hbc_reply && LEN(state->milter_hbc_reply) ?
+ STR(state->milter_hbc_reply) : 0);
+
+ /*
+ * Note: state->append_meta_pt_target never changes.
+ */
}
/* cleanup_find_header_start - find specific header instance */
@@ -671,6 +954,16 @@ static const char *cleanup_patch_header(CLEANUP_STATE *state,
* record. It is ignored when the to-be-saved record is a pointer record.
*/
+ /*
+ * Return early when Milter header checks request that this header record
+ * be dropped.
+ */
+ 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);
+
/*
* Write the new header to a new location after the end of the queue
* file.
@@ -679,7 +972,6 @@ static const char *cleanup_patch_header(CLEANUP_STATE *state,
msg_warn("%s: seek file %s: %m", myname, cleanup_path);
CLEANUP_PATCH_HEADER_RETURN(cleanup_milter_error(state, errno));
}
- vstring_sprintf(buf, "%s:%s%s", new_hdr_name, hdr_space, new_hdr_value);
cleanup_out_header(state, buf); /* Includes padding */
if (msg_verbose > 1)
msg_info("%s: %ld: write %.*s", myname, (long) new_hdr_offset,
@@ -734,8 +1026,10 @@ static const char *cleanup_patch_header(CLEANUP_STATE *state,
/*
* In case of error while doing record output.
*/
- CLEANUP_PATCH_HEADER_RETURN(CLEANUP_OUT_OK(state) ? 0 :
- cleanup_milter_error(state, 0));
+ CLEANUP_PATCH_HEADER_RETURN(
+ CLEANUP_OUT_OK(state) == 0 ? cleanup_milter_error(state, 0) :
+ state->milter_hbc_reply && LEN(state->milter_hbc_reply) ?
+ STR(state->milter_hbc_reply) : 0);
/*
* Note: state->append_hdr_pt_target never changes.
@@ -1553,6 +1847,13 @@ 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);
@@ -1618,6 +1919,12 @@ void cleanup_milter_inspect(CLEANUP_STATE *state, MILTERS *milters)
if (state->client_name == 0)
cleanup_milter_client_init(state);
+ /*
+ * Prologue: prepare for Milter header/body checks.
+ */
+ if (*var_milt_head_checks)
+ cleanup_milter_header_checks_init(state);
+
/*
* Process mail filter replies. The reply format is verified by the mail
* filter library.
@@ -1625,6 +1932,13 @@ void cleanup_milter_inspect(CLEANUP_STATE *state, MILTERS *milters)
if ((resp = milter_message(milters, state->handle->stream,
state->data_offset)) != 0)
cleanup_milter_apply(state, "END-OF-MESSAGE", resp);
+
+ /*
+ * Epilogue: finalize Milter header/body checks.
+ */
+ if (*var_milt_head_checks)
+ cleanup_milter_hbc_finish(state);
+
if (msg_verbose)
msg_info("leave %s", myname);
}
@@ -1779,6 +2093,7 @@ MAPS *cleanup_virt_alias_maps;
char *var_milt_daemon_name = "host.example.com";
char *var_milt_v = DEF_MILT_V;
MILTERS *cleanup_milters = (MILTERS *) ((char *) sizeof(*cleanup_milters));
+char *var_milt_head_checks = "";
/* Dummies to satisfy unused external references. */
@@ -1898,6 +2213,15 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path)
if ((state->append_rcpt_pt_target =
vstream_ftell(state->dst)) < 0)
msg_fatal("file %s: vstream_ftell: %m", cleanup_path);
+ } else if (curr_offset > state->xtra_offset
+ && state->append_meta_pt_offset < 0) {
+ state->append_meta_pt_offset = curr_offset;
+ if (atol(STR(buf)) != 0)
+ msg_fatal("file %s: bad dummy meta PTR record: %s",
+ cleanup_path, STR(buf));
+ if ((state->append_meta_pt_target =
+ vstream_ftell(state->dst)) < 0)
+ msg_fatal("file %s: vstream_ftell: %m", cleanup_path);
}
} else {
if (state->append_hdr_pt_offset < 0) {
@@ -1912,7 +2236,9 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path)
}
}
if (state->append_rcpt_pt_offset > 0
- && state->append_hdr_pt_offset > 0)
+ && state->append_hdr_pt_offset > 0
+ && (rec_type == REC_TYPE_END
+ || state->append_meta_pt_offset > 0))
break;
}
if (msg_verbose) {
@@ -1944,6 +2270,11 @@ int main(int unused_argc, char **argv)
CLEANUP_STATE *state = cleanup_state_alloc((VSTREAM *) 0);
state->queue_id = mystrdup("NOQUEUE");
+ state->sender = mystrdup("sender");
+ state->recip = mystrdup("recipient");
+ state->client_name = "client_name";
+ state->client_addr = "client_addr";
+ state->flags |= CLEANUP_FLAG_FILTER_ALL;
msg_vstream_init(argv[0], VSTREAM_ERR);
var_line_limit = DEF_LINE_LIMIT;
@@ -1952,6 +2283,7 @@ int main(int unused_argc, char **argv)
for (;;) {
ARGV *argv;
ssize_t index;
+ const char *resp = 0;
if (istty) {
vstream_printf("- ");
@@ -1995,13 +2327,15 @@ 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)
+ cleanup_milter_hbc_finish(state);
close_queue_file(state);
} else if (strcmp(argv->argv[0], "add_header") == 0) {
if (argv->argc < 2) {
msg_warn("bad add_header argument count: %d", argv->argc);
} else {
flatten_args(arg_buf, argv->argv + 2);
- cleanup_add_header(state, argv->argv[1], " ", STR(arg_buf));
+ resp = cleanup_add_header(state, argv->argv[1], " ", STR(arg_buf));
}
} else if (strcmp(argv->argv[0], "ins_header") == 0) {
if (argv->argc < 3) {
@@ -2010,7 +2344,7 @@ int main(int unused_argc, char **argv)
msg_warn("bad ins_header index value");
} else {
flatten_args(arg_buf, argv->argv + 3);
- cleanup_ins_header(state, index, argv->argv[2], " ", STR(arg_buf));
+ resp = cleanup_ins_header(state, index, argv->argv[2], " ", STR(arg_buf));
}
} else if (strcmp(argv->argv[0], "upd_header") == 0) {
if (argv->argc < 3) {
@@ -2019,7 +2353,7 @@ int main(int unused_argc, char **argv)
msg_warn("bad upd_header index value");
} else {
flatten_args(arg_buf, argv->argv + 3);
- cleanup_upd_header(state, index, argv->argv[2], " ", STR(arg_buf));
+ resp = cleanup_upd_header(state, index, argv->argv[2], " ", STR(arg_buf));
}
} else if (strcmp(argv->argv[0], "del_header") == 0) {
if (argv->argc != 3) {
@@ -2072,13 +2406,30 @@ int main(int unused_argc, char **argv)
vstream_fclose(fp);
}
}
+ } else if (strcmp(argv->argv[0], "header_checks") == 0) {
+ if (argv->argc != 2) {
+ msg_warn("bad header_checks argument count: %d", argv->argc);
+ } else if (*var_milt_head_checks) {
+ msg_warn("can't change header checks");
+ } else {
+ var_milt_head_checks = mystrdup(argv->argv[1]);
+ cleanup_milter_header_checks_init(state);
+ }
} else {
msg_warn("bad command: %s", argv->argv[0]);
}
argv_free(argv);
+ if (resp)
+ cleanup_milter_apply(state, "END-OF-MESSAGE", resp);
}
vstring_free(inbuf);
vstring_free(arg_buf);
+ if (state->append_meta_pt_offset >= 0) {
+ if (state->flags)
+ msg_info("flags = %s", cleanup_strflags(state->flags));
+ if (state->errs)
+ msg_info("errs = %s", cleanup_strerror(state->errs));
+ }
cleanup_state_free(state);
return (0);
diff --git a/postfix/src/cleanup/cleanup_milter.in14a b/postfix/src/cleanup/cleanup_milter.in14a
new file mode 100644
index 000000000..6fc21f595
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in14a
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file14a.tmp
+
+header_checks regexp:cleanup_milter.reg14a
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in14b b/postfix/src/cleanup/cleanup_milter.in14b
new file mode 100644
index 000000000..539112c6d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in14b
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file14b.tmp
+
+header_checks regexp:cleanup_milter.reg14b
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in14c b/postfix/src/cleanup/cleanup_milter.in14c
new file mode 100644
index 000000000..0a247b2fa
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in14c
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file14c.tmp
+
+header_checks regexp:cleanup_milter.reg14c
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in14d b/postfix/src/cleanup/cleanup_milter.in14d
new file mode 100644
index 000000000..13aa2efe9
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in14d
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file14d.tmp
+
+header_checks regexp:cleanup_milter.reg14d
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in14e b/postfix/src/cleanup/cleanup_milter.in14e
new file mode 100644
index 000000000..f54ccd0a2
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in14e
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file14e.tmp
+
+header_checks regexp:cleanup_milter.reg14e
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in14f b/postfix/src/cleanup/cleanup_milter.in14f
new file mode 100644
index 000000000..68124a7cd
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in14f
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file14f.tmp
+
+header_checks regexp:cleanup_milter.reg14f
+ins_header 2 X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in14g b/postfix/src/cleanup/cleanup_milter.in14g
new file mode 100644
index 000000000..ebd866fd4
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in14g
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file14g.tmp
+
+header_checks regexp:cleanup_milter.reg14g
+upd_header 1 X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in15a b/postfix/src/cleanup/cleanup_milter.in15a
new file mode 100644
index 000000000..8c2be9e73
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in15a
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file15a.tmp
+
+header_checks regexp:cleanup_milter.reg15a
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in15b b/postfix/src/cleanup/cleanup_milter.in15b
new file mode 100644
index 000000000..fb209ade1
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in15b
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file15b.tmp
+
+header_checks regexp:cleanup_milter.reg15b
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in15c b/postfix/src/cleanup/cleanup_milter.in15c
new file mode 100644
index 000000000..3b3ef3607
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in15c
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file15c.tmp
+
+header_checks regexp:cleanup_milter.reg15c
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in15d b/postfix/src/cleanup/cleanup_milter.in15d
new file mode 100644
index 000000000..a00b143a3
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in15d
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file15d.tmp
+
+header_checks regexp:cleanup_milter.reg15d
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in15e b/postfix/src/cleanup/cleanup_milter.in15e
new file mode 100644
index 000000000..1c26f5949
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in15e
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file15e.tmp
+
+header_checks regexp:cleanup_milter.reg15e
+add_header X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in15f b/postfix/src/cleanup/cleanup_milter.in15f
new file mode 100644
index 000000000..8dc6a26b1
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in15f
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file15f.tmp
+
+header_checks regexp:cleanup_milter.reg15f
+ins_header 2 X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in15g b/postfix/src/cleanup/cleanup_milter.in15g
new file mode 100644
index 000000000..0e90d9fb5
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.in15g
@@ -0,0 +1,7 @@
+#verbose on
+open test-queue-file15g.tmp
+
+header_checks regexp:cleanup_milter.reg15g
+ins_header 2 X-SPAM-FLAG YES
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.ref14a1 b/postfix/src/cleanup/cleanup_milter.ref14a1
new file mode 100644
index 000000000..9006f9a0d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14a1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-reject: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: 5.7.1 message content rejected
+./cleanup_milter: errs = message content rejected
diff --git a/postfix/src/cleanup/cleanup_milter.ref14a2 b/postfix/src/cleanup/cleanup_milter.ref14a2
new file mode 100644
index 000000000..cb690d802
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14a2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file14a.tmp ***
+ 0 message_size: 365 256 1 0 365
+ 81 message_arrival_time: Fri Jun 5 14:05:19 2009
+ 100 create_time: Fri Jun 5 14:05:19 2009
+ 124 named_attribute: rewrite_context=local
+ 147 sender_fullname: Wietse Venema
+ 162 sender: wietse@ahost.example.com
+ 188 pointer_record: 0
+ 203 original_recipient: wietse
+ 211 recipient: wietse@ahost.example.com
+ 237 pointer_record: 0
+ 254 *** MESSAGE CONTENTS test-queue-file14a.tmp ***
+ 256 regular_text: Received: by ahost.example.com (Postfix, from userid 1001)
+ 316 regular_text: id DA4892510C1; Fri, 5 Jun 2009 14:05:19 -0400 (EDT)
+ 372 regular_text: To: wietse@ahost.example.com
+ 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
+ 572 regular_text:
+ 574 regular_text: Fri Jun 5 14:05:19 EDT 2009
+ 604 pointer_record: 0
+ 621 *** HEADER EXTRACTED test-queue-file14a.tmp ***
+ 623 pointer_record: 0
+ 640 *** MESSAGE FILE END test-queue-file14a.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref14b1 b/postfix/src/cleanup/cleanup_milter.ref14b1
new file mode 100644
index 000000000..5608b8144
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14b1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-filter: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: transport:nexthop:port
+./cleanup_milter: flags = enable_header_body_filter enable_milters
diff --git a/postfix/src/cleanup/cleanup_milter.ref14b2 b/postfix/src/cleanup/cleanup_milter.ref14b2
new file mode 100644
index 000000000..209bf2b06
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14b2
@@ -0,0 +1,29 @@
+*** ENVELOPE RECORDS test-queue-file14b.tmp ***
+ 0 message_size: 365 256 1 0 365
+ 81 message_arrival_time: Fri Jun 5 14:05:19 2009
+ 100 create_time: Fri Jun 5 14:05:19 2009
+ 124 named_attribute: rewrite_context=local
+ 147 sender_fullname: Wietse Venema
+ 162 sender: wietse@ahost.example.com
+ 188 pointer_record: 0
+ 203 original_recipient: wietse
+ 211 recipient: wietse@ahost.example.com
+ 237 pointer_record: 0
+ 254 *** MESSAGE CONTENTS test-queue-file14b.tmp ***
+ 256 regular_text: Received: by ahost.example.com (Postfix, from userid 1001)
+ 316 regular_text: id DA4892510C1; Fri, 5 Jun 2009 14:05:19 -0400 (EDT)
+ 372 regular_text: To: wietse@ahost.example.com
+ 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
+ 572 regular_text:
+ 574 regular_text: Fri Jun 5 14:05:19 EDT 2009
+ 604 pointer_record: 0
+ 621 *** HEADER EXTRACTED test-queue-file14b.tmp ***
+ 623 pointer_record: 677
+ 677 content_filter: transport:nexthop:port
+ 701 pointer_record: 640
+ 640 *** MESSAGE FILE END test-queue-file14b.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref14c1 b/postfix/src/cleanup/cleanup_milter.ref14c1
new file mode 100644
index 000000000..26b8ffd5d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14c1
@@ -0,0 +1 @@
+./cleanup_milter: NOQUEUE: milter-header-redirect: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: foo@examle.com
diff --git a/postfix/src/cleanup/cleanup_milter.ref14c2 b/postfix/src/cleanup/cleanup_milter.ref14c2
new file mode 100644
index 000000000..8d2be319d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14c2
@@ -0,0 +1,29 @@
+*** ENVELOPE RECORDS test-queue-file14c.tmp ***
+ 0 message_size: 365 256 1 0 365
+ 81 message_arrival_time: Fri Jun 5 14:05:19 2009
+ 100 create_time: Fri Jun 5 14:05:19 2009
+ 124 named_attribute: rewrite_context=local
+ 147 sender_fullname: Wietse Venema
+ 162 sender: wietse@ahost.example.com
+ 188 pointer_record: 0
+ 203 original_recipient: wietse
+ 211 recipient: wietse@ahost.example.com
+ 237 pointer_record: 0
+ 254 *** MESSAGE CONTENTS test-queue-file14c.tmp ***
+ 256 regular_text: Received: by ahost.example.com (Postfix, from userid 1001)
+ 316 regular_text: id DA4892510C1; Fri, 5 Jun 2009 14:05:19 -0400 (EDT)
+ 372 regular_text: To: wietse@ahost.example.com
+ 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
+ 572 regular_text:
+ 574 regular_text: Fri Jun 5 14:05:19 EDT 2009
+ 604 pointer_record: 0
+ 621 *** HEADER EXTRACTED test-queue-file14c.tmp ***
+ 623 pointer_record: 677
+ 677 redirect_to: foo@examle.com
+ 693 pointer_record: 640
+ 640 *** MESSAGE FILE END test-queue-file14c.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref14d1 b/postfix/src/cleanup/cleanup_milter.ref14d1
new file mode 100644
index 000000000..2cea8d230
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14d1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-discard: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=:
+./cleanup_milter: flags = discard_message
diff --git a/postfix/src/cleanup/cleanup_milter.ref14d2 b/postfix/src/cleanup/cleanup_milter.ref14d2
new file mode 100644
index 000000000..b544187cc
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14d2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file14d.tmp ***
+ 0 message_size: 365 256 1 0 365
+ 81 message_arrival_time: Fri Jun 5 14:05:19 2009
+ 100 create_time: Fri Jun 5 14:05:19 2009
+ 124 named_attribute: rewrite_context=local
+ 147 sender_fullname: Wietse Venema
+ 162 sender: wietse@ahost.example.com
+ 188 pointer_record: 0
+ 203 original_recipient: wietse
+ 211 recipient: wietse@ahost.example.com
+ 237 pointer_record: 0
+ 254 *** MESSAGE CONTENTS test-queue-file14d.tmp ***
+ 256 regular_text: Received: by ahost.example.com (Postfix, from userid 1001)
+ 316 regular_text: id DA4892510C1; Fri, 5 Jun 2009 14:05:19 -0400 (EDT)
+ 372 regular_text: To: wietse@ahost.example.com
+ 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
+ 572 regular_text:
+ 574 regular_text: Fri Jun 5 14:05:19 EDT 2009
+ 604 pointer_record: 0
+ 621 *** HEADER EXTRACTED test-queue-file14d.tmp ***
+ 623 pointer_record: 0
+ 640 *** MESSAGE FILE END test-queue-file14d.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref14e1 b/postfix/src/cleanup/cleanup_milter.ref14e1
new file mode 100644
index 000000000..d08c06fdb
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14e1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-hold: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=:
+./cleanup_milter: flags = enable_header_body_filter hold_message enable_milters
diff --git a/postfix/src/cleanup/cleanup_milter.ref14e2 b/postfix/src/cleanup/cleanup_milter.ref14e2
new file mode 100644
index 000000000..e6e5cc0ef
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14e2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file14e.tmp ***
+ 0 message_size: 365 256 1 0 365
+ 81 message_arrival_time: Fri Jun 5 14:05:19 2009
+ 100 create_time: Fri Jun 5 14:05:19 2009
+ 124 named_attribute: rewrite_context=local
+ 147 sender_fullname: Wietse Venema
+ 162 sender: wietse@ahost.example.com
+ 188 pointer_record: 0
+ 203 original_recipient: wietse
+ 211 recipient: wietse@ahost.example.com
+ 237 pointer_record: 0
+ 254 *** MESSAGE CONTENTS test-queue-file14e.tmp ***
+ 256 regular_text: Received: by ahost.example.com (Postfix, from userid 1001)
+ 316 regular_text: id DA4892510C1; Fri, 5 Jun 2009 14:05:19 -0400 (EDT)
+ 372 regular_text: To: wietse@ahost.example.com
+ 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
+ 572 regular_text:
+ 574 regular_text: Fri Jun 5 14:05:19 EDT 2009
+ 604 pointer_record: 0
+ 621 *** HEADER EXTRACTED test-queue-file14e.tmp ***
+ 623 pointer_record: 0
+ 640 *** MESSAGE FILE END test-queue-file14e.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref14f1 b/postfix/src/cleanup/cleanup_milter.ref14f1
new file mode 100644
index 000000000..9006f9a0d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14f1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-reject: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: 5.7.1 message content rejected
+./cleanup_milter: errs = message content rejected
diff --git a/postfix/src/cleanup/cleanup_milter.ref14f2 b/postfix/src/cleanup/cleanup_milter.ref14f2
new file mode 100644
index 000000000..3fdbf2382
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14f2
@@ -0,0 +1,28 @@
+*** ENVELOPE RECORDS test-queue-file14f.tmp ***
+ 0 message_size: 365 256 1 0 365
+ 81 message_arrival_time: Fri Jun 5 14:05:19 2009
+ 100 create_time: Fri Jun 5 14:05:19 2009
+ 124 named_attribute: rewrite_context=local
+ 147 sender_fullname: Wietse Venema
+ 162 sender: wietse@ahost.example.com
+ 188 pointer_record: 0
+ 203 original_recipient: wietse
+ 211 recipient: wietse@ahost.example.com
+ 237 pointer_record: 0
+ 254 *** MESSAGE CONTENTS test-queue-file14f.tmp ***
+ 256 regular_text: Received: by ahost.example.com (Postfix, from userid 1001)
+ 316 regular_text: id DA4892510C1; Fri, 5 Jun 2009 14:05:19 -0400 (EDT)
+ 372 pointer_record: 642
+ 642 regular_text: X-SPAM-FLAG: YES
+ 660 regular_text: To: wietse@ahost.example.com
+ 690 pointer_record: 402
+ 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: 0
+ 572 regular_text:
+ 574 regular_text: Fri Jun 5 14:05:19 EDT 2009
+ 604 pointer_record: 0
+ 621 *** HEADER EXTRACTED test-queue-file14f.tmp ***
+ 623 pointer_record: 0
+ 640 *** MESSAGE FILE END test-queue-file14f.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref14g1 b/postfix/src/cleanup/cleanup_milter.ref14g1
new file mode 100644
index 000000000..9006f9a0d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14g1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-reject: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: 5.7.1 message content rejected
+./cleanup_milter: errs = message content rejected
diff --git a/postfix/src/cleanup/cleanup_milter.ref14g2 b/postfix/src/cleanup/cleanup_milter.ref14g2
new file mode 100644
index 000000000..1ee50e4cc
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref14g2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file14g.tmp ***
+ 0 message_size: 365 256 1 0 365
+ 81 message_arrival_time: Fri Jun 5 14:05:19 2009
+ 100 create_time: Fri Jun 5 14:05:19 2009
+ 124 named_attribute: rewrite_context=local
+ 147 sender_fullname: Wietse Venema
+ 162 sender: wietse@ahost.example.com
+ 188 pointer_record: 0
+ 203 original_recipient: wietse
+ 211 recipient: wietse@ahost.example.com
+ 237 pointer_record: 0
+ 254 *** MESSAGE CONTENTS test-queue-file14g.tmp ***
+ 256 regular_text: Received: by ahost.example.com (Postfix, from userid 1001)
+ 316 regular_text: id DA4892510C1; Fri, 5 Jun 2009 14:05:19 -0400 (EDT)
+ 372 regular_text: To: wietse@ahost.example.com
+ 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
+ 572 regular_text:
+ 574 regular_text: Fri Jun 5 14:05:19 EDT 2009
+ 604 pointer_record: 0
+ 621 *** HEADER EXTRACTED test-queue-file14g.tmp ***
+ 623 pointer_record: 0
+ 640 *** MESSAGE FILE END test-queue-file14g.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref15a1 b/postfix/src/cleanup/cleanup_milter.ref15a1
new file mode 100644
index 000000000..9006f9a0d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15a1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-reject: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: 5.7.1 message content rejected
+./cleanup_milter: errs = message content rejected
diff --git a/postfix/src/cleanup/cleanup_milter.ref15a2 b/postfix/src/cleanup/cleanup_milter.ref15a2
new file mode 100644
index 000000000..56c5d3e1c
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15a2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file15a.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-file15a.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-file15a.tmp ***
+ 588 pointer_record: 0
+ 605 original_recipient: wietse
+ 613 recipient: wietse@ahost.example.com
+ 639 *** MESSAGE FILE END test-queue-file15a.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref15b1 b/postfix/src/cleanup/cleanup_milter.ref15b1
new file mode 100644
index 000000000..5608b8144
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15b1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-filter: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: transport:nexthop:port
+./cleanup_milter: flags = enable_header_body_filter enable_milters
diff --git a/postfix/src/cleanup/cleanup_milter.ref15b2 b/postfix/src/cleanup/cleanup_milter.ref15b2
new file mode 100644
index 000000000..c38c0a383
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15b2
@@ -0,0 +1,29 @@
+*** ENVELOPE RECORDS test-queue-file15b.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-file15b.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-file15b.tmp ***
+ 588 pointer_record: 676
+ 676 content_filter: transport:nexthop:port
+ 700 pointer_record: 605
+ 605 original_recipient: wietse
+ 613 recipient: wietse@ahost.example.com
+ 639 *** MESSAGE FILE END test-queue-file15b.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref15c1 b/postfix/src/cleanup/cleanup_milter.ref15c1
new file mode 100644
index 000000000..26b8ffd5d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15c1
@@ -0,0 +1 @@
+./cleanup_milter: NOQUEUE: milter-header-redirect: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: foo@examle.com
diff --git a/postfix/src/cleanup/cleanup_milter.ref15c2 b/postfix/src/cleanup/cleanup_milter.ref15c2
new file mode 100644
index 000000000..7725f487a
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15c2
@@ -0,0 +1,29 @@
+*** ENVELOPE RECORDS test-queue-file15c.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-file15c.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-file15c.tmp ***
+ 588 pointer_record: 676
+ 676 redirect_to: foo@examle.com
+ 692 pointer_record: 605
+ 605 original_recipient: wietse
+ 613 recipient: wietse@ahost.example.com
+ 639 *** MESSAGE FILE END test-queue-file15c.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref15d1 b/postfix/src/cleanup/cleanup_milter.ref15d1
new file mode 100644
index 000000000..2cea8d230
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15d1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-discard: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=:
+./cleanup_milter: flags = discard_message
diff --git a/postfix/src/cleanup/cleanup_milter.ref15d2 b/postfix/src/cleanup/cleanup_milter.ref15d2
new file mode 100644
index 000000000..773fd4071
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15d2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file15d.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-file15d.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-file15d.tmp ***
+ 588 pointer_record: 0
+ 605 original_recipient: wietse
+ 613 recipient: wietse@ahost.example.com
+ 639 *** MESSAGE FILE END test-queue-file15d.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref15e1 b/postfix/src/cleanup/cleanup_milter.ref15e1
new file mode 100644
index 000000000..d08c06fdb
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15e1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-hold: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=:
+./cleanup_milter: flags = enable_header_body_filter hold_message enable_milters
diff --git a/postfix/src/cleanup/cleanup_milter.ref15e2 b/postfix/src/cleanup/cleanup_milter.ref15e2
new file mode 100644
index 000000000..13f9cb461
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15e2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file15e.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-file15e.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-file15e.tmp ***
+ 588 pointer_record: 0
+ 605 original_recipient: wietse
+ 613 recipient: wietse@ahost.example.com
+ 639 *** MESSAGE FILE END test-queue-file15e.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref15f1 b/postfix/src/cleanup/cleanup_milter.ref15f1
new file mode 100644
index 000000000..b9d602153
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15f1
@@ -0,0 +1 @@
+./cleanup_milter: NOQUEUE: milter-header-redirect: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: x@y.z
diff --git a/postfix/src/cleanup/cleanup_milter.ref15f2 b/postfix/src/cleanup/cleanup_milter.ref15f2
new file mode 100644
index 000000000..45dca53c1
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15f2
@@ -0,0 +1,30 @@
+*** ENVELOPE RECORDS test-queue-file15f.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-file15f.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 pointer_record: 641
+ 641 regular_text: X-SPAM-FLAG: YES
+ 659 regular_text: To: wietse@ahost.example.com
+ 689 pointer_record: 367
+ 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: 0
+ 537 regular_text:
+ 539 regular_text: Fri Jun 5 14:06:34 EDT 2009
+ 569 pointer_record: 0
+ 586 *** HEADER EXTRACTED test-queue-file15f.tmp ***
+ 588 pointer_record: 706
+ 706 redirect_to: x@y.z
+ 713 pointer_record: 605
+ 605 original_recipient: wietse
+ 613 recipient: wietse@ahost.example.com
+ 639 *** MESSAGE FILE END test-queue-file15f.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref15g1 b/postfix/src/cleanup/cleanup_milter.ref15g1
new file mode 100644
index 000000000..295690ae1
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15g1
@@ -0,0 +1,2 @@
+./cleanup_milter: NOQUEUE: milter-header-filter: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: x:y:z
+./cleanup_milter: flags = enable_header_body_filter enable_milters
diff --git a/postfix/src/cleanup/cleanup_milter.ref15g2 b/postfix/src/cleanup/cleanup_milter.ref15g2
new file mode 100644
index 000000000..fc67e5658
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.ref15g2
@@ -0,0 +1,30 @@
+*** ENVELOPE RECORDS test-queue-file15g.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-file15g.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 pointer_record: 641
+ 641 regular_text: X-SPAM-FLAG: YES
+ 659 regular_text: To: wietse@ahost.example.com
+ 689 pointer_record: 367
+ 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: 0
+ 537 regular_text:
+ 539 regular_text: Fri Jun 5 14:06:34 EDT 2009
+ 569 pointer_record: 0
+ 586 *** HEADER EXTRACTED test-queue-file15g.tmp ***
+ 588 pointer_record: 706
+ 706 content_filter: x:y:z
+ 713 pointer_record: 605
+ 605 original_recipient: wietse
+ 613 recipient: wietse@ahost.example.com
+ 639 *** MESSAGE FILE END test-queue-file15g.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.reg14a b/postfix/src/cleanup/cleanup_milter.reg14a
new file mode 100644
index 000000000..1a9ccf1f8
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg14a
@@ -0,0 +1 @@
+/./ reject
diff --git a/postfix/src/cleanup/cleanup_milter.reg14b b/postfix/src/cleanup/cleanup_milter.reg14b
new file mode 100644
index 000000000..332ba69df
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg14b
@@ -0,0 +1 @@
+/./ FILTER transport:nexthop:port
diff --git a/postfix/src/cleanup/cleanup_milter.reg14c b/postfix/src/cleanup/cleanup_milter.reg14c
new file mode 100644
index 000000000..04219767d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg14c
@@ -0,0 +1 @@
+/./ REDIRECT foo@examle.com
diff --git a/postfix/src/cleanup/cleanup_milter.reg14d b/postfix/src/cleanup/cleanup_milter.reg14d
new file mode 100644
index 000000000..78647a331
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg14d
@@ -0,0 +1 @@
+/./ DISCARD
diff --git a/postfix/src/cleanup/cleanup_milter.reg14e b/postfix/src/cleanup/cleanup_milter.reg14e
new file mode 100644
index 000000000..c88ee2cb1
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg14e
@@ -0,0 +1 @@
+/./ HOLD
diff --git a/postfix/src/cleanup/cleanup_milter.reg14f b/postfix/src/cleanup/cleanup_milter.reg14f
new file mode 100644
index 000000000..1a9ccf1f8
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg14f
@@ -0,0 +1 @@
+/./ reject
diff --git a/postfix/src/cleanup/cleanup_milter.reg14g b/postfix/src/cleanup/cleanup_milter.reg14g
new file mode 100644
index 000000000..1a9ccf1f8
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg14g
@@ -0,0 +1 @@
+/./ reject
diff --git a/postfix/src/cleanup/cleanup_milter.reg15a b/postfix/src/cleanup/cleanup_milter.reg15a
new file mode 100644
index 000000000..1a9ccf1f8
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg15a
@@ -0,0 +1 @@
+/./ reject
diff --git a/postfix/src/cleanup/cleanup_milter.reg15b b/postfix/src/cleanup/cleanup_milter.reg15b
new file mode 100644
index 000000000..332ba69df
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg15b
@@ -0,0 +1 @@
+/./ FILTER transport:nexthop:port
diff --git a/postfix/src/cleanup/cleanup_milter.reg15c b/postfix/src/cleanup/cleanup_milter.reg15c
new file mode 100644
index 000000000..04219767d
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg15c
@@ -0,0 +1 @@
+/./ REDIRECT foo@examle.com
diff --git a/postfix/src/cleanup/cleanup_milter.reg15d b/postfix/src/cleanup/cleanup_milter.reg15d
new file mode 100644
index 000000000..78647a331
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg15d
@@ -0,0 +1 @@
+/./ DISCARD
diff --git a/postfix/src/cleanup/cleanup_milter.reg15e b/postfix/src/cleanup/cleanup_milter.reg15e
new file mode 100644
index 000000000..c88ee2cb1
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg15e
@@ -0,0 +1 @@
+/./ HOLD
diff --git a/postfix/src/cleanup/cleanup_milter.reg15f b/postfix/src/cleanup/cleanup_milter.reg15f
new file mode 100644
index 000000000..a629bf2bc
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg15f
@@ -0,0 +1 @@
+/./ redirect x@y.z
diff --git a/postfix/src/cleanup/cleanup_milter.reg15g b/postfix/src/cleanup/cleanup_milter.reg15g
new file mode 100644
index 000000000..0a25be300
--- /dev/null
+++ b/postfix/src/cleanup/cleanup_milter.reg15g
@@ -0,0 +1 @@
+/./ filter x:y:z
diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c
index 7ce732cd2..8d9085262 100644
--- a/postfix/src/cleanup/cleanup_state.c
+++ b/postfix/src/cleanup/cleanup_state.c
@@ -97,6 +97,10 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src)
state->append_rcpt_pt_target = -1;
state->append_hdr_pt_offset = -1;
state->append_hdr_pt_target = -1;
+ state->append_meta_pt_offset = -1;
+ state->append_meta_pt_target = -1;
+ state->milter_hbc_checks = 0;
+ state->milter_hbc_reply = 0;
state->rcpt_count = 0;
state->reason = 0;
state->smtp_reply = 0;
diff --git a/postfix/src/cleanup/test-queue-file14 b/postfix/src/cleanup/test-queue-file14
new file mode 100644
index 000000000..e9b388a88
Binary files /dev/null and b/postfix/src/cleanup/test-queue-file14 differ
diff --git a/postfix/src/cleanup/test-queue-file15 b/postfix/src/cleanup/test-queue-file15
new file mode 100644
index 000000000..088bdfd24
Binary files /dev/null and b/postfix/src/cleanup/test-queue-file15 differ
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 04c3f5747..d67a2a6bc 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -2982,6 +2982,10 @@ extern char *var_milt_daemon_name;
#define DEF_MILT_V "$" VAR_MAIL_NAME " $" VAR_MAIL_VERSION
extern char *var_milt_v;
+#define VAR_MILT_HEAD_CHECKS "milter_header_checks"
+#define DEF_MILT_HEAD_CHECKS ""
+extern char *var_milt_head_checks;
+
/*
* What internal mail do we inspect/stamp/etc.? This is not yet safe enough
* to enable world-wide.
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index f17139bfc..8545f9f48 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 "20090603"
+#define MAIL_RELEASE_DATE "20090606"
#define MAIL_VERSION_NUMBER "2.7"
#ifdef SNAPSHOT
diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in
index a91c9b95a..bcc4dcbd0 100644
--- a/postfix/src/postconf/Makefile.in
+++ b/postfix/src/postconf/Makefile.in
@@ -10,6 +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
PROG = postconf
SAMPLES = ../../conf/main.cf.default
INC_DIR = ../../include
@@ -43,11 +44,17 @@ update: ../../bin/$(PROG) $(SAMPLES)
../../bin/$(PROG): $(PROG)
cp $(PROG) ../../bin
-$(MAKES): $(INC_DIR)/mail_params.h ../global/mail_params.c
- $(AWK) -f extract.awk ../*/*.c | $(SHELL)
+$(MAKES): makes_dummy
-$(AUTOS): auto.awk
+makes_dummy: $(INC_DIR)/mail_params.h ../global/mail_params.c
+ $(AWK) -f extract.awk ../*/*.c | $(SHELL)
+ touch makes_dummy
+
+$(AUTOS): autos_dummy
+
+autos_dummy: auto.awk
$(AWK) -f auto.awk
+ touch autos_dummy
printfck: $(OBJS) $(PROG)
rm -rf printfck
@@ -61,7 +68,7 @@ lint:
lint $(DEFS) $(SRCS) $(LINTFIX)
clean:
- rm -f *.o *core $(PROG) $(TESTPROG) junk $(MAKES) $(AUTOS)
+ rm -f *.o *core $(PROG) $(TESTPROG) junk $(MAKES) $(AUTOS) $(DUMMIES)
rm -rf printfck
tidy: clean
diff --git a/postfix/src/util/unix_send_fd.c b/postfix/src/util/unix_send_fd.c
index d9266244a..bb6bd1282 100644
--- a/postfix/src/util/unix_send_fd.c
+++ b/postfix/src/util/unix_send_fd.c
@@ -105,22 +105,28 @@ int unix_send_fd(int fd, int sendfd)
msg.msg_iovlen = 1;
/*
- * The CMSG_LEN workaround was originally developed for OpenBSD 3.6 on
- * 64-bit SPARC (later also confirmed on AMD64). It was hard-coded with
- * Postfix 2.3 for all platforms because of increasing pressure to work
- * on other things.
+ * The CMSG_LEN send/receive workaround was originally developed for
+ * OpenBSD 3.6 on SPARC64. After the workaround was verified to not break
+ * Solaris 8 on SPARC64, it was hard-coded with Postfix 2.3 for all
+ * platforms because of increasing pressure to work on other things. The
+ * workaround does nothing for 32-bit systems.
*
* The investigation was reopened with Postfix 2.7 because the workaround
- * broke on NetBSD 5.0. This time it was found that OpenBSD on AMD64
- * needs the workaround for sending only. We assume that OpenBSD on AMD64
- * and SPARC64 are similar, and turn on the workaround on-the-fly. The
- * OpenBSD problem was fixed for AMD64 and SPARC64 with OpenBSD 4.4 or
- * 4.5.
+ * broke with NetBSD 5.0 on 64-bit architectures. This time it was found
+ * that OpenBSD <= 4.3 on AMD64 and SPARC64 needed the workaround for
+ * sending only. The following platforms worked with and without the
+ * workaround: OpenBSD 4.5 on AMD64 and SPARC64, FreeBSD 7.2 on AMD64,
+ * Solaris 8 on SPARC64, and Linux 2.6-11 on x86_64.
*
- * The workaround was made run-time configurable to make the investigation
- * possible on many different platforms. Though the code is over-kill for
- * this particular problem, it is left in place so that it can serve as
- * an example of how to add run-time configurable workarounds to Postfix.
+ * As this appears to have been an OpenBSD-specific problem, we revert to
+ * the Postfix 2.2 behavior. Instead of hard-coding the workaround for
+ * all platforms, we now detect sendmsg() errors at run time and turn on
+ * the workaround dynamically.
+ *
+ * The workaround was made run-time configurable to investigate the problem
+ * on multiple platforms. Though set_unix_pass_fd_fix() is over-kill for
+ * this specific problem, it is left in place so that it can serve as an
+ * example of how to add run-time configurable workarounds to Postfix.
*/
if (sendmsg(fd, &msg, 0) >= 0)
return (0);