]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-1.1.11-20020823
authorWietse Venema <wietse@porcupine.org>
Fri, 23 Aug 2002 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:28:11 +0000 (06:28 +0000)
14 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/conf/access
postfix/html/access.5.html
postfix/html/postconf.1.html
postfix/man/man1/postconf.1
postfix/man/man5/access.5
postfix/proto/access
postfix/src/global/mail_version.h
postfix/src/postconf/postconf.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_state.c
postfix/src/util/dict_db.c

index f901f057fec93992fb9509d114f8a1f12194b7fb..4f496021f38f36a29a9b738e7dfc813c19beaf56 100644 (file)
@@ -6867,6 +6867,27 @@ Apologies for any names omitted.
        Patches by Will Day, Georgia Tech, and Carsten Hoeger,
        SUSE.  File: util/dict_ldap.c.
 
+20020823
+
+       Bugfix: added a missing memset() call to wipe the lookup
+       key in dict_db_delete(). This is needed by some Berkeley
+       DB implementations. Patch by Katsu Yamamoto, Fujitsu.
+
+       Bugfix: when permit_mx_backup is unable to make a decision
+       due to DNS problems, set the "defer if reject" flag so that
+       other restrictions will not cause mail to be rejected.
+       File: smtpd/smtpd_check.c.
+
+       Feature: instead of giving up immediately after DNS failure,
+       turn on the "defer_if_permit" flag when reject_unknown_hostname,
+       reject_unknown_sender_domain or reject_unknown_recipient_domain
+       are unable to make a decision, and see if any subsequent
+       restrictions would still cause the mail to be rejected.
+       File:  smtpd/smtpd_check.c.
+
+       Feature: "FILTER transport:nexthop" is now also available
+       in SMTPD access tables.
+
 Open problems:
 
        Low: smtpd should log queue ID with reject/warn/hold/discard
index 2a2f1907e369c06a908ba2273f021fe0db4e9ff6..47bdd6777a4bcf10b5b5cec8b3aad9a3d0e97ba0 100644 (file)
@@ -12,6 +12,21 @@ snapshot release).  Patches change the patchlevel and the release
 date. Snapshots change only the release date, unless they include
 the same bugfixes as a patch release.
 
+Major changes with Postfix snapshot 1.1.11-20020823
+===================================================
+
+More sophisticated handling of UCE-related DNS lookup errors.
+These cause Postfix to not give up so easily, so that some deliveries
+will not have to be deferred after all.  This affects the following
+restrictions:  permit_mx_backup (defer the request if any subsequent
+restriction would cause the request to be rejected, accept the
+request if any subsequent restriction would cause the request to
+be accepted); reject_unknown_hostname, reject_unknown_sender_domain
+and reject_unknown_recipient_domain (defer the request if any
+subsequent restriction would cause the request to be accepted,
+reject the request if any subsequent restriction would cause the
+request to be rejected).
+
 Incompatible changes with Postfix snapshot 1.1.11-20020819
 ==========================================================
 
@@ -38,7 +53,7 @@ rather than $myhostname. This seems to work better with Cyrus SASL
 version 2. This change may cause incompatibility with the saslpasswd2
 command.
 
-Major changes with Postfix snapshot 1.1.11-20020818
+Major changes with Postfix snapshot 1.1.11-20020819
 ===================================================
 
 When the Postfix local delivery agent detects a mail delivery loop
index 45cd464aa9dacbb64dca36e952f4bbf69629dec0..0270277761ebf97563a43217e7f5c6e091ffb6cc 100644 (file)
 #               Claim successful delivery and silently discard  the
 #               message.
 # 
+#        FILTER transport:destination
+#               After  the  message is queued, send the entire mes-
+#               sage through a content  filter.   More  information
+#               about  content  filters  is  in  the  Postfix  FIL-
+#               TER_README file.
+# 
 #        restriction...
 #               Apply the named UCE restriction(s) (permit, reject,
 #               reject_unauth_destination, and so on).
 # 
 # REGULAR EXPRESSION TABLES
-#        This section describes how the table lookups  change  when
+#        This  section  describes how the table lookups change when
 #        the table is given in the form of regular expressions. For
-#        a description of regular expression lookup  table  syntax,
+#        a  description  of regular expression lookup table syntax,
 #        see regexp_table(5) or pcre_table(5).
 # 
-#        Each  pattern  is  a regular expression that is applied to
+#        Each pattern is a regular expression that  is  applied  to
 #        the entire string being looked up. Depending on the appli-
-#        cation,  that  string  is  an  entire  client hostname, an
+#        cation, that string  is  an  entire  client  hostname,  an
 #        entire client IP address, or an entire mail address. Thus,
 #        no  parent  domain  or  parent  network  search  is  done,
-#        user@domain mail addresses are not broken  up  into  their
+#        user@domain  mail  addresses  are not broken up into their
 #        user@ and domain constituent parts, nor is user+foo broken
 #        up into user and foo.
 # 
-#        Patterns are applied in the  order  as  specified  in  the
-#        table,  until  a  pattern is found that matches the search
+#        Patterns  are  applied  in  the  order as specified in the
+#        table, until a pattern is found that  matches  the  search
 #        string.
 # 
-#        Actions are the same as with indexed  file  lookups,  with
-#        the  additional feature that parenthesized substrings from
+#        Actions  are  the  same as with indexed file lookups, with
+#        the additional feature that parenthesized substrings  from
 #        the pattern can be interpolated as $1, $2 and so on.
 # 
 # BUGS
-#        The table format does not understand quoting  conventions.
+#        The  table format does not understand quoting conventions.
 # 
 # SEE ALSO
 #        postmap(1) create mapping table
 #        regexp_table(5) format of POSIX regular expression tables
 # 
 # LICENSE
-#        The  Secure  Mailer  license must be distributed with this
+#        The Secure Mailer license must be  distributed  with  this
 #        software.
 # 
 # AUTHOR(S)
index ff70e7979e26efbb96471226eeb69bf369fc0800..e05788024385b3bcc128c98625faab450745f603 100644 (file)
@@ -132,35 +132,41 @@ ACCESS(5)                                               ACCESS(5)
               Claim successful delivery and silently discard  the
               message.
 
+       <b>FILTER</b> <i>transport:destination</i>
+              After  the  message is queued, send the entire mes-
+              sage through a content  filter.   More  information
+              about  content  filters  is  in  the  Postfix  FIL-
+              TER_README file.
+
        <i>restriction...</i>
               Apply the named UCE restriction(s) (<b>permit</b>, <b>reject</b>,
               <b>reject</b><i>_</i><b>unauth</b><i>_</i><b>destination</b>, and so on).
 
 <b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b>
-       This section describes how the table lookups  change  when
+       This  section  describes how the table lookups change when
        the table is given in the form of regular expressions. For
-       a description of regular expression lookup  table  syntax,
+       a  description  of regular expression lookup table syntax,
        see <a href="regexp_table.5.html"><b>regexp</b><i>_</i><b>table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>.
 
-       Each  pattern  is  a regular expression that is applied to
+       Each pattern is a regular expression that  is  applied  to
        the entire string being looked up. Depending on the appli-
-       cation,  that  string  is  an  entire  client hostname, an
+       cation, that string  is  an  entire  client  hostname,  an
        entire client IP address, or an entire mail address. Thus,
        no  parent  domain  or  parent  network  search  is  done,
-       <i>user@domain</i> mail addresses are not broken  up  into  their
+       <i>user@domain</i>  mail  addresses  are not broken up into their
        <i>user@</i> and <i>domain</i> constituent parts, nor is <i>user+foo</i> broken
        up into <i>user</i> and <i>foo</i>.
 
-       Patterns are applied in the  order  as  specified  in  the
-       table,  until  a  pattern is found that matches the search
+       Patterns  are  applied  in  the  order as specified in the
+       table, until a pattern is found that  matches  the  search
        string.
 
-       Actions are the same as with indexed  file  lookups,  with
-       the  additional feature that parenthesized substrings from
+       Actions  are  the  same as with indexed file lookups, with
+       the additional feature that parenthesized substrings  from
        the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on.
 
 <b>BUGS</b>
-       The table format does not understand quoting  conventions.
+       The  table format does not understand quoting conventions.
 
 <b>SEE</b> <b>ALSO</b>
        <a href="postmap.1.html">postmap(1)</a> create mapping table
@@ -169,7 +175,7 @@ ACCESS(5)                                               ACCESS(5)
        <a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index c3c8038bc6e24d0d0fa64de1546dff30c7eb7089..2fd3a7539b45ae442672051554947cded65d801a 100644 (file)
@@ -126,6 +126,10 @@ POSTCONF(1)                                           POSTCONF(1)
 <b>DIAGNOSTICS</b>
        Problems are reported to the standard error stream.
 
+<b>ENVIRONMENT</b>
+       <b>MAIL</b><i>_</i><b>CONFIG</b>
+              Directory with Postfix configuration files.
+
 <b>LICENSE</b>
        The  Secure  Mailer  license must be distributed with this
        software.
index 5bab9c5467d188bc156e8128d7117016fd9bbc8f..8c0a4e339a080698ecd26bd7845600ec7dd1e969 100644 (file)
@@ -109,6 +109,13 @@ options make the software increasingly verbose.
 .ad
 .fi
 Problems are reported to the standard error stream.
+.SH ENVIRONMENT
+.na
+.nf
+.ad
+.fi
+.IP \fBMAIL_CONFIG\fR
+Directory with Postfix configuration files.
 .SH LICENSE
 .na
 .nf
index c1f3161c4e4e948801b0dbfadc35f15a2ada90a4..9bc3af64b4aa0e2461b65f3e76aed4a5268eadab 100644 (file)
@@ -126,6 +126,10 @@ Mail that is placed on hold can be examined with the
 the \fBpostsuper\fR(1) command.
 .IP \fBDISCARD\fR
 Claim successful delivery and silently discard the message.
+.IP "\fBFILTER \fItransport:destination\fR"
+After the message is queued, send the entire message through
+a content filter.  More information about content filters
+is in the Postfix FILTER_README file.
 .IP \fIrestriction...\fR
 Apply the named UCE restriction(s) (\fBpermit\fR, \fBreject\fR,
 \fBreject_unauth_destination\fR, and so on).
index b0564d06c59c350823a21a372c784078c4f3758e..02e99839eec2bc9f6e45472996d46e1008d3601f 100644 (file)
 #      the \fBpostsuper\fR(1) command.
 # .IP \fBDISCARD\fR
 #      Claim successful delivery and silently discard the message.
+# .IP "\fBFILTER \fItransport:destination\fR"
+#      After the message is queued, send the entire message through
+#       a content filter.  More information about content filters
+#      is in the Postfix FILTER_README file.
 # .IP \fIrestriction...\fR
 #      Apply the named UCE restriction(s) (\fBpermit\fR, \fBreject\fR,
 #      \fBreject_unauth_destination\fR, and so on).
index 91c70bfb70fc68fb25d76fc29a2cc8b3bb2c0806..e32bf3bf91d11ce85ddc21a6419f91fce23a9785 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only, unless they include the same bugfix as a patch release.
   */
-#define MAIL_RELEASE_DATE      "20020822"
+#define MAIL_RELEASE_DATE      "20020823"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #define DEF_MAIL_VERSION       "1.1.11-" MAIL_RELEASE_DATE
index 7fd9a63cce1bee48b5adca3ea093e4b6870b80f8..6854a57eb7b0978b618d51722b1fdad6262128ce 100644 (file)
 /*     options make the software increasingly verbose.
 /* DIAGNOSTICS
 /*     Problems are reported to the standard error stream.
+/* ENVIRONMENT
+/* .ad
+/* .fi
+/* .IP \fBMAIL_CONFIG\fR
+/*     Directory with Postfix configuration files.
 /* LICENSE
 /* .ad
 /* .fi
index 1aa9c21c35fbd958667acfb81e57b4e6077201f2..9f04b72e68ab698bd09ce99a72bfbb3170899603 100644 (file)
@@ -81,6 +81,10 @@ typedef struct SMTPD_STATE {
     VSTRING *sasl_decoded;
 #endif
     int     warn_if_reject;
+    int     defer_if_reject;           /* force reject into deferral */
+    int     defer_if_permit;           /* force permit into deferral */
+    VSTRING *defer_reason;             /* reason why we force deferral */
+    int     defer_class;               /* forced deferral error class */
 } SMTPD_STATE;
 
 extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
index ab7e01cfe6bdf6e958cbf058fd5c1590e4471bab..9c0a756138c70aba49e6ea0201706d0a57b79d11 100644 (file)
@@ -315,11 +315,6 @@ static jmp_buf smtpd_check_buf;
 #define SMTPD_CHECK_OK         1       /* explicitly permit */
 #define SMTPD_CHECK_REJECT     2       /* explicitly reject */
 
- /*
-  * XXX For now define SMTPD_CHECK_TRYAGAIN as SMTPD_CHECK_OK.
-  */
-#define SMTPD_CHECK_TRYAGAIN   1       /* return 4xx try again */
-
  /*
   * Intermediate results. These are static to avoid unnecessary stress on the
   * memory manager routines.
@@ -387,6 +382,13 @@ static int generic_checks(SMTPD_STATE *, ARGV *, const char *, const char *, con
 #define STR    vstring_str
 #define CONST_STR(x)   ((const char *) vstring_str(x))
 
+ /*
+  * If some decision can't be made due to a temporary error, then change
+  * other decisions in to deferrals.
+  */
+static void PRINTFLIKE(3, 4) defer_if_reject(SMTPD_STATE *, int, const char *, ...);
+static void PRINTFLIKE(3, 4) defer_if_permit(SMTPD_STATE *, int, const char *, ...);
+
 /* resolve_pagein - page in an address resolver result */
 
 static void *resolve_pagein(const char *addr, void *unused_context)
@@ -622,6 +624,11 @@ void    smtpd_check_init(void)
 static void log_whatsup(SMTPD_STATE *state, const char *whatsup,
                                const char *text)
 {
+
+    /*
+     * XXX should include queue ID but that will break all existing logfile
+     * parsers.
+     */
     if (state->recipient && state->sender) {
        msg_info("%s: %s from %s: %s; from=<%s> to=<%s>",
                 whatsup, state->where, state->namaddr, text,
@@ -700,8 +707,15 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class,
      * the UCE restrictions only. This would be at odds with documentation
      * which says soft_bounce changes all 5xx replies into 4xx ones.
      */
-    if (var_soft_bounce && STR(error_text)[0] == '5')
-       STR(error_text)[0] = '4';
+    if (STR(error_text)[0] == '5') {
+       if (state->defer_if_reject) {
+           state->defer_if_reject = 0;
+           return (smtpd_check_reject(state, state->defer_class,
+                                      "%s", STR(state->defer_reason)));
+       }
+       if (var_soft_bounce)
+           STR(error_text)[0] = '4';
+    }
 
     /*
      * Log what is happening. When the sysadmin discards policy violation
@@ -713,6 +727,38 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class,
     return (warn_if_reject ? 0 : SMTPD_CHECK_REJECT);
 }
 
+/* defer_if_reject - prepare to change our mind */
+
+static void defer_if_reject(SMTPD_STATE *state, int error_class,
+                                   const char *fmt,...)
+{
+    va_list ap;
+
+    if (state->defer_reason == 0)
+       state->defer_reason = vstring_alloc(10);
+    state->defer_class = error_class;
+    va_start(ap, fmt);
+    vstring_vsprintf(state->defer_reason, fmt, ap);
+    va_end(ap);
+    state->defer_if_reject = 1;
+}
+
+/* defer_if_permit - prepare to change our mind */
+
+static void defer_if_permit(SMTPD_STATE *state, int error_class,
+                                   const char *fmt,...)
+{
+    va_list ap;
+
+    if (state->defer_reason == 0)
+       state->defer_reason = vstring_alloc(10);
+    state->defer_class = error_class;
+    va_start(ap, fmt);
+    vstring_vsprintf(state->defer_reason, fmt, ap);
+    va_end(ap);
+    state->defer_if_permit = 1;
+}
+
 /* reject_dict_retry - reject with temporary failure if dict lookup fails */
 
 static void reject_dict_retry(SMTPD_STATE *state, const char *reply_name)
@@ -980,12 +1026,15 @@ static int reject_unknown_hostname(SMTPD_STATE *state, char *name,
 
     dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
                                  (VSTRING *) 0, RR_ADDR_TYPES, T_MX, 0);
-    if (dns_status != DNS_OK)
+    if (dns_status == DNS_NOTFOUND)
        return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
                                   "%d <%s>: %s rejected: Host not found",
-                                  dns_status == DNS_NOTFOUND ?
-                                  var_unk_name_code : 450,
+                                  var_unk_name_code,
                                   reply_name, reply_class));
+    else if (dns_status != DNS_OK)
+       defer_if_permit(state, MAIL_ERROR_POLICY,
+                       "450 <%s>: %s rejected: Host not found",
+                       reply_name, reply_class);
     return (SMTPD_CHECK_DUNNO);
 }
 
@@ -1002,12 +1051,15 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
 
     dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
                                  (VSTRING *) 0, RR_ADDR_TYPES, T_MX, 0);
-    if (dns_status != DNS_OK)
+    if (dns_status == DNS_NOTFOUND)
        return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
                                   "%d <%s>: %s rejected: Domain not found",
-                                  dns_status == DNS_NOTFOUND ?
-                                  var_unk_addr_code : 450,
+                                  var_unk_addr_code,
                                   reply_name, reply_class));
+    else if (dns_status != DNS_OK)
+       defer_if_permit(state, MAIL_ERROR_POLICY,
+                       "450 <%s>: %s rejected: Domain not found",
+                       reply_name, reply_class);
     return (SMTPD_CHECK_DUNNO);
 }
 
@@ -1136,7 +1188,7 @@ static int reject_unauth_pipelining(SMTPD_STATE *state)
 
 /* all_auth_mx_addr - match host addresses against permit_mx_backup_networks */
 
-static int all_auth_mx_addr(char *host)
+static int all_auth_mx_addr(SMTPD_STATE *state, char *host)
 {
     char   *myname = "all_auth_mx_addr";
     struct in_addr addr;
@@ -1148,23 +1200,25 @@ static int all_auth_mx_addr(char *host)
        msg_info("%s: host %s", myname, host);
 
     /*
-     * If we can't lookup the host, try again.
+     * If we can't lookup the host, defer.
      */
 #define NOPE           0
 #define YUP            1
-#define TRYAGAIN       2
 
     /*
      * Verify that all host addresses are within permit_mx_backup_networks.
      */
     dns_status = dns_lookup(host, T_A, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0);
-    if (dns_status != DNS_OK)
-       return (TRYAGAIN);
-
+    if (dns_status != DNS_OK) {
+       defer_if_reject(state, MAIL_ERROR_POLICY,
+                     "450 Unable to look up host %s as mail exchanger: %s",
+                       host, dns_strerror(h_errno));
+       return (NOPE);
+    }
     for (rr = addr_list; rr != 0; rr = rr->next) {
        if (rr->data_len > sizeof(addr)) {
-           msg_warn("skipping address length %d for host %s",
-                    rr->data_len, host);
+           msg_warn("%s: skipping address length %d for host %s",
+                    state->queue_id, rr->data_len, host);
            continue;
        }
        memcpy((char *) &addr, rr->data, sizeof(addr));
@@ -1190,7 +1244,7 @@ static int all_auth_mx_addr(char *host)
 
 /* has_my_addr - see if this host name lists one of my network addresses */
 
-static int has_my_addr(const char *host)
+static int has_my_addr(SMTPD_STATE *state, const char *host)
 {
     char   *myname = "has_my_addr";
     struct in_addr addr;
@@ -1201,20 +1255,21 @@ static int has_my_addr(const char *host)
        msg_info("%s: host %s", myname, host);
 
     /*
-     * If we can't lookup the host, play safe and assume it is OK.
+     * If we can't lookup the host, defer rather than reject.
      */
 #define YUP    1
 #define NOPE   0
 
     if ((hp = gethostbyname(host)) == 0) {
-       if (msg_verbose)
-           msg_info("%s: host %s: not found", myname, host);
-       return (YUP);
+       defer_if_reject(state, MAIL_ERROR_POLICY,
+                     "450 Unable to look up host %s as mail exchanger: %s",
+                       host, dns_strerror(h_errno));
+       return (NOPE);
     }
     if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) {
        msg_warn("address type %d length %d for %s",
                 hp->h_addrtype, hp->h_length, host);
-       return (YUP);
+       return (NOPE);
     }
     for (cpp = hp->h_addr_list; *cpp; cpp++) {
        memcpy((char *) &addr, *cpp, sizeof(addr));
@@ -1231,7 +1286,7 @@ static int has_my_addr(const char *host)
 
 /* i_am_mx - is this machine listed as MX relay */
 
-static int i_am_mx(DNS_RR *mx_list)
+static int i_am_mx(SMTPD_STATE *state, DNS_RR *mx_list)
 {
     const char *myname = "permit_mx_backup";
     DNS_RR *mx;
@@ -1253,7 +1308,7 @@ static int i_am_mx(DNS_RR *mx_list)
     for (mx = mx_list; mx != 0; mx = mx->next) {
        if (msg_verbose)
            msg_info("%s: address lookup: %s", myname, (char *) mx->data);
-       if (has_my_addr((char *) mx->data))
+       if (has_my_addr(state, (char *) mx->data))
            return (YUP);
     }
 
@@ -1267,11 +1322,10 @@ static int i_am_mx(DNS_RR *mx_list)
 
 /* permit_mx_primary - authorize primary MX relays */
 
-static int permit_mx_primary(DNS_RR *mx_list)
+static int permit_mx_primary(SMTPD_STATE *state, DNS_RR *mx_list)
 {
     DNS_RR *mx;
     unsigned int best_pref;
-    int     status;
 
     /*
      * Find the preference of the primary MX hosts.
@@ -1287,18 +1341,15 @@ static int permit_mx_primary(DNS_RR *mx_list)
     for (mx = mx_list; mx != 0; mx = mx->next) {
        if (mx->pref != best_pref)
            continue;
-       switch (status = all_auth_mx_addr((char *) mx->data)) {
-       case TRYAGAIN:
-       case NOPE:
-           return (status);
-       }
+       if (!all_auth_mx_addr(state, (char *) mx->data))
+           return (NOPE);
     }
 
     /*
      * All IP addresses of the best MX hosts are within
      * permit_mx_backup_networks.
      */
-    return (YUP);
+    return (mx_list ? YUP : NOPE);
 }
 
 /* permit_mx_backup - permit use of me as MX backup for recipient domain */
@@ -1355,19 +1406,23 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient)
      * Look up the list of MX host names for this domain. If no MX host is
      * found, perhaps it is a CNAME for the local machine. Clients aren't
      * supposed to send CNAMEs in SMTP commands, but it happens anyway. If we
-     * can't look up the destination, play safe and assume it is OK.
+     * can't look up the destination, play safe and turn reject into defer.
      */
     dns_status = dns_lookup(domain, T_MX, 0, &mx_list,
                            (VSTRING *) 0, (VSTRING *) 0);
     if (dns_status == DNS_NOTFOUND)
-       return (has_my_addr(domain) ? SMTPD_CHECK_OK : SMTPD_CHECK_DUNNO);
-    if (dns_status != DNS_OK)
-       return (SMTPD_CHECK_TRYAGAIN);
+       return (has_my_addr(state, domain) ? SMTPD_CHECK_OK : SMTPD_CHECK_DUNNO);
+    if (dns_status != DNS_OK) {
+       defer_if_reject(state, MAIL_ERROR_POLICY,
+                    "450 Unable to look up mail exchanger information: %s",
+                       dns_strerror(h_errno));
+       return (SMTPD_CHECK_DUNNO);
+    }
 
     /*
      * First, see if we match any of the MX host names listed.
      */
-    if (!i_am_mx(mx_list)) {
+    if (!i_am_mx(state, mx_list)) {
        dns_rr_free(mx_list);
        return (SMTPD_CHECK_DUNNO);
     }
@@ -1376,7 +1431,7 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient)
      * Optionally, see if the primary MX hosts are in a restricted list of
      * networks.
      */
-    if (*var_perm_mx_networks && !permit_mx_primary(mx_list)) {
+    if (*var_perm_mx_networks && !permit_mx_primary(state, mx_list)) {
        dns_rr_free(mx_list);
        return (SMTPD_CHECK_DUNNO);
     }
@@ -1508,6 +1563,26 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
                                   "%d <%s>: %s rejected: Access denied",
                             var_access_map_code, reply_name, reply_class));
 
+    /*
+     * FILTER means deliver to content filter. But we may still change our
+     * mind, and reject/discard the message for other reasons.
+     */
+#define FILTER_LEN     (sizeof("FILTER") - 1)
+
+    if (strncasecmp(value, "FILTER", FILTER_LEN) == 0
+       && (value[FILTER_LEN] == 0 || ISSPACE(value[FILTER_LEN]))) {
+       value += FILTER_LEN;
+       while (ISSPACE(*value))
+           value++;
+       vstring_sprintf(error_text, "<%s>: %s triggers FILTER %s",
+                       reply_name, reply_class, value);
+       log_whatsup(state, "hold", STR(error_text));
+#ifndef TEST
+       rec_fprintf(state->dest->stream, REC_TYPE_FILT, "%s", value);
+#endif
+       return (SMTPD_CHECK_DUNNO);
+    }
+
     /*
      * HOLD means deliver later. But we may still change our mind, and
      * reject/discard the message for other reasons.
@@ -2292,6 +2367,10 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
 
     state->recursion = saved_recursion;
 
+    if (status == SMTPD_CHECK_REJECT || status == SMTPD_CHECK_DUNNO)
+       if (state->defer_if_permit)
+           status = smtpd_check_reject(state, state->defer_class,
+                                       "450 %s", STR(state->defer_reason));
     return (status);
 }
 
@@ -2311,6 +2390,9 @@ char   *smtpd_check_client(SMTPD_STATE *state)
      * Apply restrictions in the order as specified.
      */
     state->recursion = 1;
+    state->warn_if_reject = 0;
+    state->defer_if_reject = 0;
+    state->defer_if_permit = 0;
     status = setjmp(smtpd_check_buf);
     if (status == 0 && client_restrctions->argc)
        status = generic_checks(state, client_restrctions, state->namaddr,
@@ -2357,6 +2439,9 @@ char   *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
      * Apply restrictions in the order as specified.
      */
     state->recursion = 1;
+    state->warn_if_reject = 0;
+    state->defer_if_reject = 0;
+    state->defer_if_permit = 0;
     status = setjmp(smtpd_check_buf);
     if (status == 0 && helo_restrctions->argc)
        status = generic_checks(state, helo_restrctions, state->helo_name,
@@ -2393,6 +2478,9 @@ char   *smtpd_check_mail(SMTPD_STATE *state, char *sender)
      * Apply restrictions in the order as specified.
      */
     state->recursion = 1;
+    state->warn_if_reject = 0;
+    state->defer_if_reject = 0;
+    state->defer_if_permit = 0;
     status = setjmp(smtpd_check_buf);
     if (status == 0 && mail_restrctions->argc)
        status = generic_checks(state, mail_restrctions, sender,
@@ -2447,6 +2535,9 @@ char   *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
      * Apply restrictions in the order as specified.
      */
     state->recursion = 1;
+    state->warn_if_reject = 0;
+    state->defer_if_reject = 0;
+    state->defer_if_permit = 0;
     status = setjmp(smtpd_check_buf);
     if (status == 0 && rcpt_restrctions->argc)
        status = generic_checks(state, rcpt_restrctions,
@@ -2492,6 +2583,9 @@ char   *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
      * Apply restrictions in the order as specified.
      */
     state->recursion = 1;
+    state->warn_if_reject = 0;
+    state->defer_if_reject = 0;
+    state->defer_if_permit = 0;
     status = setjmp(smtpd_check_buf);
     if (status == 0 && etrn_restrctions->argc)
        status = generic_checks(state, etrn_restrctions, domain,
index 6e7236543e90a8a2fe655a0bcd9f8c736fc29705..cc07eeeaf0e5e55765f4594f26dbdca686d23d67 100644 (file)
@@ -91,7 +91,7 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     state->recursion = 0;
     state->msg_size = 0;
     state->junk_cmds = 0;
-    state->warn_if_reject = 0;
+    state->defer_reason = 0;
 
 #ifdef USE_SASL_AUTH
     if (SMTPD_STAND_ALONE(state))
@@ -124,6 +124,8 @@ void    smtpd_state_reset(SMTPD_STATE *state)
     if (state->buffer)
        vstring_free(state->buffer);
     smtpd_peer_reset(state);
+    if (state->defer_reason)
+       vstring_free(state->defer_reason);
 
 #ifdef USE_SASL_AUTH
     if (var_smtpd_sasl_enable)
index c6be63537b9a3344e8230fccfe342bd1a6c597fd..41eea2118458d594c5b116623c8f0ae24bac91ad 100644 (file)
@@ -302,6 +302,8 @@ static int dict_db_delete(DICT *dict, const char *name)
     int     status = 1;
     int     flags = 0;
 
+    memset(&db_key, 0, sizeof(db_key));
+
     /*
      * Acquire an exclusive lock.
      */