]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.7-20090607
authorWietse Venema <wietse@porcupine.org>
Sun, 7 Jun 2009 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:35:33 +0000 (06:35 +0000)
25 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/conf/postmulti-script
postfix/html/cleanup.8.html
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/man/man8/cleanup.8
postfix/proto/postconf.proto
postfix/src/cleanup/Makefile.in
postfix/src/cleanup/cleanup.c
postfix/src/cleanup/cleanup_milter.c
postfix/src/cleanup/cleanup_milter.in15h [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.in15i [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref14d2
postfix/src/cleanup/cleanup_milter.ref15d2
postfix/src/cleanup/cleanup_milter.ref15h1 [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref15h2 [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref15i1 [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref15i2 [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.reg15h [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.reg15i [new file with mode: 0644]
postfix/src/global/mail_version.h
postfix/src/milter/test-milter.c
postfix/src/postconf/Makefile.in
postfix/src/util/sys_defs.h

index fbb21dce70c0c3405770319fe38df715e56195e4..8021755cf0f3a876749484c45b2bd171364a6041 100644 (file)
@@ -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.
index e10c3a338953c216939482e8c6d61566da39f5e1..620a44132a7ec8da5a8ee391c79e90100686d10b 100644 (file)
@@ -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.
index 13fffe7fb22ecf95df3b25cad0e431e70cd74458..1c3f3ad886da540c4f40b03b9a57d9655a69d9e2 100644 (file)
@@ -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
     ;;
 
index 61952c1f39aaca40ec5da1b31f6a1aadfdc90973..ff8859c1f4dd28fe71391b7f6623845b424a64ab 100644 (file)
@@ -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:
 
        <b><a href="postconf.5.html#milter_header_checks">milter_header_checks</a> (empty)</b>
               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.
 
 <b>MIME PROCESSING CONTROLS</b>
        Available in Postfix version 2.0 and later:
index 85d6e2a4ace64fab467b0b66334248ff66545284..95db4fa31562fc21ac13f2a0e5aca487f8d7ee8a 100644 (file)
@@ -5694,15 +5694,14 @@ of available macro names and their meanings.  </p>
 <DT><b><a name="milter_header_checks">milter_header_checks</a>
 (default: empty)</b></DT><DD>
 
-<p>
-Optional lookup tables for content inspection of primary
-message headers that are produced by Milter applications.
-See the <a href="header_checks.5.html">header_checks(5)</a> manual page for usage.
+<p> Optional lookup tables for content inspection of message headers
+that are produced by Milter applications.  See the <a href="header_checks.5.html">header_checks(5)</a>
+manual page available actions. Currently, PREPEND is not implemented.
 </p>
 
-<p> The following example sends mail that is marked as SPAM to a
-spam sanization machine. Note that matches are case-insensitive by
-default. </p>
+<p> The following example sends all mail that is marked as SPAM to
+a spam handling machine. Note that matches are case-insensitive
+by default. </p>
 
 <blockquote>
 <pre>
@@ -5715,6 +5714,13 @@ default. </p>
 </pre>
 </blockquote>
 
+<p> The <a href="postconf.5.html#milter_header_checks">milter_header_checks</a> 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. </p>
+
+<p> This feature is available in Postfix 2.7, and as an optional
+patch for Postfix 2.6. </p>
+
 
 </DD>
 
index 5ab7bbdcf54f0f991df217781e4e6167346e92e9..964641b03e5c4bb76638801a6baced6523af8ca9 100644 (file)
@@ -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
index 5bba18db9c8c1415c126a3d040b8cad05e22d157..a6b678fedc6d39b818e58ebe90a3a7632c932850 100644 (file)
@@ -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
index 1a08bda44f0f0ae49f64931f2a4714598d9fe31c..d15ab4c7476b5f3125ea6b9cba4eabdd32374591 100644 (file)
@@ -12302,15 +12302,14 @@ parameter. See there for details. </p>
 
 %PARAM milter_header_checks
 
-<p>
-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.
+<p> 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.
 </p>
 
-<p> The following example sends mail that is marked as SPAM to a
-spam sanization machine. Note that matches are case-insensitive by
-default. </p>
+<p> The following example sends all mail that is marked as SPAM to
+a spam handling machine. Note that matches are case-insensitive
+by default. </p>
 
 <blockquote>
 <pre>
@@ -12322,3 +12321,10 @@ default. </p>
     /^X-SPAM-FLAG:\s+YES]/ FILTER mysmtp:sanitizer.example.com:25
 </pre>
 </blockquote> 
+
+<p> 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. </p>
+
+<p> This feature is available in Postfix 2.7, and as an optional
+patch for Postfix 2.6. </p>
index f59f9bb408f47be8f22bd3c43d8b403debf098e2..f997030387b6d85d0a05c3aa5ce6daf855102332 100644 (file)
@@ -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.in14f 2>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.in14g 2>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.in15f 2>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.in15g 2>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.in15h 2>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.in15i 2>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 \
index 2caa775dcb17f5a8969891af0d105bbda9d17912..461ebf84eec1330d7edfdc2b9d7af851b4602e3d 100644 (file)
 /*     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
index b42367a113ae5e7af08f709b3cd7355867d8579a..74816dfb52f8260c15a5697699a39a8df783e61b 100644 (file)
@@ -262,16 +262,41 @@ static char *cleanup_milter_hbc_extend(void *context, const char *command,
 
 #define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 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 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.
+     * 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.
      * 
-     * As enforced elsewhere, this code is not called when (state->flags &
-     * CLEANUP_FLAG_FILTER_ALL) == 0.
-     */
+     * 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 (file)
index 0000000..3538f79
--- /dev/null
@@ -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 (file)
index 0000000..454036a
--- /dev/null
@@ -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
index b544187cc59d8bc56708764e8827914fbbdf3fcd..dece3d57f6416bbe88ef928d200fe220f945c1d5 100644 (file)
@@ -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
index 773fd407140469023ad27d3378366b79f130b634..746a13bc1fba44c027d5eac45d01586ffb97c077 100644 (file)
@@ -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 (file)
index 0000000..bb51e0e
--- /dev/null
@@ -0,0 +1,3 @@
+./cleanup_milter: NOQUEUE: milter-header-reject: header X-SPAM-FLAG: YES from client_name[client_addr]; from=<sender> to=<recipient>: 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 (file)
index 0000000..936f022
--- /dev/null
@@ -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 (file)
index 0000000..b561728
--- /dev/null
@@ -0,0 +1,3 @@
+./cleanup_milter: NOQUEUE: milter-header-filter: header X-SPAM-FLAG: NO from client_name[client_addr]; from=<sender> to=<recipient>: x:y:z
+./cleanup_milter: NOQUEUE: milter-header-reject: header X-SPAM-FLAG: YES from client_name[client_addr]; from=<sender> to=<recipient>: 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 (file)
index 0000000..531ac4c
--- /dev/null
@@ -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 (file)
index 0000000..8c97639
--- /dev/null
@@ -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 (file)
index 0000000..8c97639
--- /dev/null
@@ -0,0 +1,2 @@
+/YES/ reject whatever
+/NO/  filter x:y:z
index 8545f9f484b0927c1238771f96f12b3fc6f643e3..fcc5cebf8d5cb970e48cea27cca884eb8501ddd1 100644 (file)
@@ -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
index 9e50729946a4e5660819ead56ce725b73473865e..2fa88c81a3788a7eb26c942144472ca9b60212f3 100644 (file)
@@ -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)
index bcc4dcbd0169c5b11030f645e15f6e87b4a497ab..90217f04084b980e9db3ecd6bec9e04f32c59855 100644 (file)
@@ -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
index 0119d5274a9371919772bc271238239a6a856cba..92c7927ec6eeaa75a17097b34f7701c53c638e6e 100644 (file)
@@ -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)