]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20050726
authorWietse Venema <wietse@porcupine.org>
Tue, 26 Jul 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:31:26 +0000 (06:31 +0000)
14 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/proto/postconf.proto
postfix/src/cleanup/cleanup_message.c
postfix/src/dns/dns.h
postfix/src/dns/dns_lookup.c
postfix/src/dns/test_dns_lookup.c
postfix/src/global/mail_version.h
postfix/src/lmtp/lmtp_addr.c
postfix/src/smtp/smtp_addr.c
postfix/src/smtp/smtp_unalias.c
postfix/src/smtpd/smtpd_check.c

index a2c77fa9f24d3abfa0022ae031113994aa030661..6e43b4d9f962d31571c78f63478bbbc1c8ee6a19 100644 (file)
@@ -11050,6 +11050,18 @@ Apologies for any names omitted.
        client IP address).  Files: global/mail_params.h,
        smtpd/smtpd_peer.c, smtpd/smtpd.c, smtpd/smtpd_check.c.
 
+20050726
+
+       Horror: total rewrite of DNS client error handling because
+       some misguided proposal attempts to give special meaning
+       to some syntactically invalid MX hostname lookup result.
+       Not only that, people expect sensible results with
+       reject_unknown_sender_domain etc.  Files: dns/dns_lookup.c,
+       smtp/smtp_addr.c smtpd/smtpd_check.c, lmtp/lmtp_addr.c.
+
+       Cleanup: HOLD action executes only once, to reduce noise
+       in the logfile. Files: cleanup/cleanup_message.c, smtpd/smtpd.c.
+
 Open problems:
 
        Med: when the cleanup server bounces local mail that should
index f1ef928e0d5ecbef91ea723b42bfb68c435852f5..0106ff4cbe7131f879320ec22e146a459bceb0da 100644 (file)
@@ -17,7 +17,32 @@ Incompatibility with Postfix 2.1 and earlier
 If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
 before proceeding.
 
-Incompatibility with snapshot 20050715
+Incompatibility with snapshot 20050726
+======================================
+
+Name server replies that contain a malformed hostname are now flagged
+as permanent errors instead of transient errors. This change works
+around a questionable proposal to use syntactically invalid hostnames
+in MX records.
+
+Major changes with snapshot 20050724
+====================================
+
+SMTPD Access control based on the existence of an address->name
+mapping, with reject_unknown_reverse_client_hostname. There is
+no corresponding access table lookup feature, because the name
+is not validated in any way (except that it has proper syntax).
+
+Several confusing SMTPD access restrictions were renamed:
+
+    reject_unknown_client -> reject_unknown_client_hostname,
+    reject_unknown_hostname -> reject_unknown_helo_hostname,
+    reject_invalid_hostname -> reject_invalid_helo_hostname,
+    reject_non_fqdn_hostname -> reject_non_fqdn_helo_hostname.
+
+The old names are still recognized and documented.
+
+Incompatibility with snapshot 20050716
 ======================================
 
 Internal interfaces have changed; this may break third-party patches
@@ -40,7 +65,7 @@ report "(unsigned) int" versus "(s)size_t" format string argument
 mis-matches on 32-bit systems; they can be found only on 64-bit
 systems.
 
-Major changes with snapshot 2005071
+Major changes with snapshot 20050716
 ====================================
 
 Improved portability to LP64 systems, by converting the type of
index 63556b06967200e34fb99c078b746005769065d7..3da5f89e0457df2e37ff1d67b3f35463b57623f4 100644 (file)
@@ -8132,11 +8132,13 @@ code for rejected requests (default: 554). </dd>
 
 <dt><b><a name="reject_unknown_recipient_domain">reject_unknown_recipient_domain</a></b></dt>
 
-<dd>Reject the request when the RCPT TO address has no DNS A or MX
-record and Postfix is not final destination for the recipient
-address. <br> The <a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies
-the response code for rejected requests (default: 450).  The response
-is always 450 in case of a temporary DNS error.</dd>
+<dd>Reject the request when Postfix is not final destination for
+the recipient address, and the RCPT TO address has no DNS A or MX
+record, or when it has a malformed MX record such as a record with
+a zero-length MX hostname (Postfix 2.3 and later). <br> The
+<a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies the response code
+for rejected requests (default: 450).  The response is always 450
+in case of a temporary DNS error.</dd>
 
 <dt><b><a name="reject_unlisted_recipient">reject_unlisted_recipient</a></b> (with Postfix 2.0: check_recipient_maps)</dt>
 
@@ -8602,11 +8604,13 @@ Postfix version 2.1 and later. </dd>
 
 <dt><b><a name="reject_unknown_sender_domain">reject_unknown_sender_domain</a></b></dt>
 
-<dd>Reject the request when the MAIL FROM address has no DNS A or
-MX record and Postfix is not final destination for the sender
-address. <br> The <a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies
-the response code for rejected requests (default: 450).  The response
-is always 450 in case of a temporary DNS error. </dd>
+<dd>Reject the request when Postfix is not final destination for
+the sender address, and the MAIL FROM address has no DNS A or MX
+record, or when it has a malformed MX record such as a record with
+a zero-length MX hostname (Postfix 2.3 and later). <br> The
+<a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies the response code
+for rejected requests (default: 450).  The response is always 450
+in case of a temporary DNS error.  </dd>
 
 <dt><b><a name="reject_unlisted_sender">reject_unlisted_sender</a></b></dt>
 
index 9963a365f612a576eaba17b469deb468663779ec..0ab835d27ae3dbe6d1f669b69e470f96e363d56f 100644 (file)
@@ -4648,13 +4648,15 @@ no sender-specified routing (user@elsewhere@domain).
  The relay_domains_reject_code parameter specifies the response
 code for rejected requests (default: 554).
 .IP "\fBreject_unknown_recipient_domain\fR"
-Reject the request when the RCPT TO address has no DNS A or MX
-record and Postfix is not final destination for the recipient
-address.
+Reject the request when Postfix is not final destination for
+the recipient address, and the RCPT TO address has no DNS A or MX
+record, or when it has a malformed MX record such as a record with
+a zero-length MX hostname (Postfix 2.3 and later).
 .br
-The unknown_address_reject_code parameter specifies
-the response code for rejected requests (default: 450).  The response
-is always 450 in case of a temporary DNS error.
+The
+unknown_address_reject_code parameter specifies the response code
+for rejected requests (default: 450).  The response is always 450
+in case of a temporary DNS error.
 .IP "\fBreject_unlisted_recipient\fR (with Postfix 2.0: check_recipient_maps)"
 Reject the request when the RCPT TO address is not listed in
 the list of valid recipients for its domain class. See the
@@ -4953,13 +4955,15 @@ Enforces the reject_sender_login_mismatch restriction for
 unauthenticated clients only. This feature is available in
 Postfix version 2.1 and later.
 .IP "\fBreject_unknown_sender_domain\fR"
-Reject the request when the MAIL FROM address has no DNS A or
-MX record and Postfix is not final destination for the sender
-address.
+Reject the request when Postfix is not final destination for
+the sender address, and the MAIL FROM address has no DNS A or MX
+record, or when it has a malformed MX record such as a record with
+a zero-length MX hostname (Postfix 2.3 and later).
 .br
-The unknown_address_reject_code parameter specifies
-the response code for rejected requests (default: 450).  The response
-is always 450 in case of a temporary DNS error.
+The
+unknown_address_reject_code parameter specifies the response code
+for rejected requests (default: 450).  The response is always 450
+in case of a temporary DNS error.
 .IP "\fBreject_unlisted_sender\fR"
 Reject the request when the MAIL FROM address is not listed in
 the list of valid recipients for its domain class. See the
index 09b0a55693c0b98ca11d1e60e2b9c5d109bca69e..7875e54e91a3492c0040f34f59ce98c105e7daea 100644 (file)
@@ -5150,11 +5150,13 @@ code for rejected requests (default: 554). </dd>
 
 <dt><b><a name="reject_unknown_recipient_domain">reject_unknown_recipient_domain</a></b></dt>
 
-<dd>Reject the request when the RCPT TO address has no DNS A or MX
-record and Postfix is not final destination for the recipient
-address. <br> The unknown_address_reject_code parameter specifies
-the response code for rejected requests (default: 450).  The response
-is always 450 in case of a temporary DNS error.</dd>
+<dd>Reject the request when Postfix is not final destination for
+the recipient address, and the RCPT TO address has no DNS A or MX
+record, or when it has a malformed MX record such as a record with
+a zero-length MX hostname (Postfix 2.3 and later). <br> The
+unknown_address_reject_code parameter specifies the response code
+for rejected requests (default: 450).  The response is always 450
+in case of a temporary DNS error.</dd>
 
 <dt><b><a name="reject_unlisted_recipient">reject_unlisted_recipient</a></b> (with Postfix 2.0: check_recipient_maps)</dt>
 
@@ -5488,11 +5490,13 @@ Postfix version 2.1 and later. </dd>
 
 <dt><b><a name="reject_unknown_sender_domain">reject_unknown_sender_domain</a></b></dt>
 
-<dd>Reject the request when the MAIL FROM address has no DNS A or
-MX record and Postfix is not final destination for the sender
-address. <br> The unknown_address_reject_code parameter specifies
-the response code for rejected requests (default: 450).  The response
-is always 450 in case of a temporary DNS error. </dd>
+<dd>Reject the request when Postfix is not final destination for
+the sender address, and the MAIL FROM address has no DNS A or MX
+record, or when it has a malformed MX record such as a record with
+a zero-length MX hostname (Postfix 2.3 and later). <br> The
+unknown_address_reject_code parameter specifies the response code
+for rejected requests (default: 450).  The response is always 450
+in case of a temporary DNS error.  </dd>
 
 <dt><b><a name="reject_unlisted_sender">reject_unlisted_sender</a></b></dt>
 
index 81ab2e145a8d675f067b9a7b3ffa1e16ff5d1193..95d54fc7e5cb99920aa0ae72d5ab3a855e8fa332 100644 (file)
@@ -316,8 +316,8 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context,
            if (*optional_text) {
                state->reason = dsn_prepend("5.7.1", 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);
+                   msg_warn("bad DSN action in %s -- need 4.x.x or 5.x.x",
+                            optional_text);
                    *state->reason = '4';
                }
            } else {
@@ -356,8 +356,10 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context,
        return (buf);
     }
     if (STREQUAL(value, "HOLD", command_len)) {
-       cleanup_act_log(state, "hold", context, buf, optional_text);
-       state->flags |= CLEANUP_FLAG_HOLD;
+       if ((state->flags & CLEANUP_FLAG_HOLD) == 0) {
+           cleanup_act_log(state, "hold", context, buf, optional_text);
+           state->flags |= CLEANUP_FLAG_HOLD;
+       }
        return (buf);
     }
     if (STREQUAL(value, "PREPEND", command_len)) {
index a54d9a808feab44997a27bb3909dc04b5e6e77a2..ab32fe444b07b63f1d3d510f0e1c19bd59d23481 100644 (file)
@@ -157,13 +157,15 @@ extern int dns_lookup_v(const char *, unsigned, DNS_RR **, VSTRING *,
  /*
   * Request flags.
   */
-#define DNS_REQ_FLAG_ANY       (1<<0)
-#define DNS_REQ_FLAG_ALL       (1<<1)
+#define DNS_REQ_FLAG_STOP_OK   (1<<0)
+#define DNS_REQ_FLAG_STOP_INVAL        (1<<1)
+#define DNS_REQ_FLAG_NONE      (0)
 
  /*
   * Status codes. Failures must have negative codes so they will not collide
   * with valid counts of answer records etc.
   */
+#define DNS_INVAL      (-5)            /* query ok, malformed reply */
 #define DNS_FAIL       (-4)            /* query failed, don't retry */
 #define DNS_NOTFOUND   (-3)            /* query ok, data not found */
 #define DNS_RETRY      (-2)            /* query failed, try again */
index 98676b55accfbdd9fff20e85771036e501e6ccb6..5739947690f8eac37b1058f9989ecc79758be229 100644 (file)
@@ -37,7 +37,8 @@
 /*     number of CNAME indirections. All result names (including
 /*     null terminator) will fit a buffer of size DNS_NAME_LEN.
 /*     All name results are validated by \fIvalid_hostname\fR();
-/*     an invalid name is reported as a transient error.
+/*     an invalid name is reported as a DNS_INVAL result, while
+/*     malformed replies are reported as transient errors.
 /*
 /*     dns_lookup_l() and dns_lookup_v() allow the user to specify
 /*     a list of resource types.
@@ -46,6 +47,8 @@
 /* .fi
 /* .IP name
 /*     The name to be looked up in the domain name system.
+/*     This name must pass the valid_hostname() test; it
+/*     must not be an IP address.
 /* .IP type
 /*     The resource record type to be looked up (T_A, T_MX etc.).
 /* .IP rflags
 /*     Append local domain to unqualified names.
 /* .RE
 /* .IP lflags
-/*     Multi-type request control for dns_lookup_l() and
-/*     dns_lookup_v(). This is one of the following:
+/*     Multi-type request control for dns_lookup_l() and dns_lookup_v().
+/*     For convenience, DNS_REQ_FLAG_NONE requests no special
+/*     processing. Invoke dns_lookup() for all specified resource
+/*     record types in the specified order, and merge their results.
+/*     Otherwise, specify one or more of the following:
 /* .RS
-/* .IP DNS_REQ_FLAG_ANY
-/*     Call dns_lookup() for each specified resource record type
-/*     in the specified order, until the list is exhausted or
-/*     until some result is DNS_OK.
-/* .IP DNS_REQ_FLAG_ALL
-/*     Call dns_lookup() for all specified resource record types
-/*     in the specified order, and merge their results.
+/* .IP DNS_REQ_FLAG_STOP_INVAL
+/*     Invoke dns_lookup() for the resource types in the order as
+/*     specified, and return when dns_lookup() returns DNS_INVAL.
+/* .IP DNS_REQ_FLAG_STOP_OK
+/*     Invoke dns_lookup() for the resource types in the order as
+/*     specified, and return when dns_lookup() returns DNS_OK.
 /* .RE
 /* .IP ltype
 /*     The resource record types to be looked up. In the case of
 /*     The DNS query succeeded.
 /* .IP DNS_NOTFOUND
 /*     The DNS query succeeded; the requested information was not found.
+/* .IP DNS_INVAL
+/*     The DNS query succeeded; the result failed the valid_hostname() test.
 /* .IP DNS_RETRY
-/*     The query failed; the problem is transient.
+/*     The query failed, or the reply was malformed.
+/*     The problem is considered transient.
 /* .IP DNS_FAIL
 /*     The query failed.
 /* BUGS
  /*
   * Structure to keep track of things while decoding a name server reply.
   */
-#define DEF_DNS_REPLY_SIZE     4096            /* in case we're using TCP */
-#define MAX_DNS_REPLY_SIZE     32768           /* in case we're using TCP */
+#define DEF_DNS_REPLY_SIZE     4096    /* in case we're using TCP */
+#define MAX_DNS_REPLY_SIZE     32768   /* in case we're using TCP */
 
 typedef struct DNS_REPLY {
     unsigned char *buf;                        /* raw reply data */
@@ -341,8 +349,8 @@ static int valid_rr_name(const char *name, const char *location,
 
 /* dns_get_rr - extract resource record from name server reply */
 
-static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
-                                 char *rr_name, DNS_FIXED *fixed)
+static int dns_get_rr(DNS_RR **list, DNS_REPLY *reply, unsigned char *pos,
+                             char *rr_name, DNS_FIXED *fixed)
 {
     char    temp[DNS_NAME_LEN];
     ssize_t data_len;
@@ -353,8 +361,9 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
 
 #define MIN2(a, b)     ((unsigned)(a) < (unsigned)(b) ? (a) : (b))
 
+    *list = 0;
     if (pos + fixed->length > reply->end)
-       return (0);
+       return (DNS_RETRY);
 
     switch (fixed->type) {
     default:
@@ -367,23 +376,23 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
     case T_NS:
     case T_PTR:
        if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
-           return (0);
+           return (DNS_RETRY);
        if (!valid_rr_name(temp, "resource data", fixed->type, reply))
-           return (0);
+           return (DNS_INVAL);
        data_len = strlen(temp) + 1;
        break;
     case T_MX:
        GETSHORT(pref, pos);
        if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
-           return (0);
+           return (DNS_RETRY);
        if (!valid_rr_name(temp, "resource data", fixed->type, reply))
-           return (0);
+           return (DNS_INVAL);
        data_len = strlen(temp) + 1;
        break;
     case T_A:
        if (fixed->length != INET_ADDR_LEN) {
            msg_warn("extract_answer: bad address length: %d", fixed->length);
-           return (0);
+           return (DNS_RETRY);
        }
        if (fixed->length > sizeof(temp))
            msg_panic("dns_get_rr: length %d > DNS_NAME_LEN",
@@ -395,7 +404,7 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
     case T_AAAA:
        if (fixed->length != INET6_ADDR_LEN) {
            msg_warn("extract_answer: bad address length: %d", fixed->length);
-           return (0);
+           return (DNS_RETRY);
        }
        if (fixed->length > sizeof(temp))
            msg_panic("dns_get_rr: length %d > DNS_NAME_LEN",
@@ -414,8 +423,9 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
        *dst = 0;
        break;
     }
-    return (dns_rr_create(rr_name, fixed->type, fixed->class, fixed->ttl,
-                         pref, temp, data_len));
+    *list = dns_rr_create(rr_name, fixed->type, fixed->class, fixed->ttl,
+                         pref, temp, data_len);
+    return (DNS_OK);
 }
 
 /* dns_get_alias - extract CNAME from name server reply */
@@ -428,7 +438,7 @@ static int dns_get_alias(DNS_REPLY *reply, unsigned char *pos,
     if (dn_expand(reply->buf, reply->end, pos, cname, c_len) < 0)
        return (DNS_RETRY);
     if (!valid_rr_name(cname, "resource data", fixed->type, reply))
-       return (DNS_RETRY);
+       return (DNS_INVAL);
     return (DNS_OK);
 }
 
@@ -445,14 +455,15 @@ static int dns_get_answer(DNS_REPLY *reply, int type,
     DNS_RR *rr;
     int     resource_found = 0;
     int     cname_found = 0;
-    int     not_found_status = DNS_NOTFOUND;
+    int     not_found_status = DNS_RETRY;      /* can't happen */
+    int     status;
 
     /*
      * Initialize. Skip over the name server query if we haven't yet.
      */
     if (reply->answer_start == 0)
-       if (dns_skip_query(reply) < 0)
-           return (DNS_RETRY);
+       if ((status = dns_skip_query(reply)) < 0)
+           return (status);
     pos = reply->answer_start;
     if (rrlist)
        *rrlist = 0;
@@ -461,12 +472,12 @@ static int dns_get_answer(DNS_REPLY *reply, int type,
      * Either this, or use a GOTO for emergency exits. The purpose is to
      * prevent incomplete answers from being passed back to the caller.
      */
-#define CORRUPT { \
+#define CORRUPT(status) { \
        if (rrlist && *rrlist) { \
            dns_rr_free(*rrlist); \
            *rrlist = 0; \
        } \
-       return (DNS_RETRY); \
+       return (status); \
     }
 
     /*
@@ -478,21 +489,21 @@ static int dns_get_answer(DNS_REPLY *reply, int type,
         * Optionally extract the fully-qualified domain name.
         */
        if (pos >= reply->end)
-           CORRUPT;
+           CORRUPT(DNS_RETRY);
        len = dn_expand(reply->buf, reply->end, pos, rr_name, DNS_NAME_LEN);
        if (len < 0)
-           CORRUPT;
+           CORRUPT(DNS_RETRY);
        pos += len;
 
        /*
         * Extract the fixed reply data: type, class, ttl, length.
         */
        if (pos + RRFIXEDSZ > reply->end)
-           CORRUPT;
-       if (dns_get_fixed(pos, &fixed) != DNS_OK)
-           CORRUPT;
+           CORRUPT(DNS_RETRY);
+       if ((status = dns_get_fixed(pos, &fixed)) != DNS_OK)
+           CORRUPT(status);
        if (!valid_rr_name(rr_name, "resource name", fixed.type, reply))
-           CORRUPT;
+           CORRUPT(DNS_INVAL);
        if (fqdn)
            vstring_strcpy(fqdn, rr_name);
        if (msg_verbose)
@@ -504,21 +515,21 @@ static int dns_get_answer(DNS_REPLY *reply, int type,
         * Optionally extract the requested resource or CNAME data.
         */
        if (pos + fixed.length > reply->end)
-           CORRUPT;
+           CORRUPT(DNS_RETRY);
        if (type == fixed.type || type == T_ANY) {      /* requested type */
            if (rrlist) {
-               if ((rr = dns_get_rr(reply, pos, rr_name, &fixed)) != 0) {
+               if ((status = dns_get_rr(&rr, reply, pos, rr_name, &fixed)) == DNS_OK) {
                    resource_found++;
                    *rrlist = dns_rr_append(*rrlist, rr);
-               } else
-                   not_found_status = DNS_RETRY;
+               } else if (not_found_status != DNS_RETRY)
+                   not_found_status = status;
            } else
                resource_found++;
        } else if (fixed.type == T_CNAME) {     /* cname resource */
            cname_found++;
            if (cname && c_len > 0)
-               if (dns_get_alias(reply, pos, &fixed, cname, c_len) != DNS_OK)
-                   CORRUPT;
+               if ((status = dns_get_alias(reply, pos, &fixed, cname, c_len)) != DNS_OK)
+                   CORRUPT(status);
        }
        pos += fixed.length;
     }
@@ -591,10 +602,9 @@ int     dns_lookup(const char *name, unsigned type, unsigned flags,
        default:
            if (why)
                vstring_sprintf(why, "Name service error for name=%s type=%s: "
-                               "Malformed name server reply",
+                               "Malformed or unexpected name server reply",
                                name, dns_strtype(type));
        case DNS_OK:
-       case DNS_NOTFOUND:
            return (status);
        case DNS_RECURSE:
            if (msg_verbose)
@@ -633,7 +643,10 @@ int     dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist,
            non_err = 1;
            if (rrlist)
                *rrlist = dns_rr_append(*rrlist, rr);
-           if (lflags == DNS_REQ_FLAG_ANY)
+           if (lflags & DNS_REQ_FLAG_STOP_OK)
+               break;
+       } else if (status == DNS_INVAL) {
+           if (lflags & DNS_REQ_FLAG_STOP_INVAL)
                break;
        } else if (status == DNS_RETRY) {
            soft_err = 1;
@@ -667,7 +680,10 @@ int     dns_lookup_v(const char *name, unsigned flags, DNS_RR **rrlist,
            non_err = 1;
            if (rrlist)
                *rrlist = dns_rr_append(*rrlist, rr);
-           if (lflags == DNS_REQ_FLAG_ANY)
+           if (lflags & DNS_REQ_FLAG_STOP_OK)
+               break;
+       } else if (status == DNS_INVAL) {
+           if (lflags & DNS_REQ_FLAG_STOP_INVAL)
                break;
        } else if (status == DNS_RETRY) {
            soft_err = 1;
index a5388f009ae122d49e1db5e6b3004fdd7c1973ec..e1350fd755b055b52449f9174b0d29a15aacbe07 100644 (file)
@@ -100,7 +100,7 @@ int     main(int argc, char **argv)
     name = argv[2];
     msg_verbose = 1;
     switch (dns_lookup_v(name, RES_DEFNAMES | RES_DEBUG, &rr, fqdn, why,
-                        DNS_REQ_FLAG_ALL, types)) {
+                        DNS_REQ_FLAG_NONE, types)) {
     default:
        msg_fatal("%s", vstring_str(why));
     case DNS_OK:
index 9e97d7f5f3743b654d635763aa9ca09dd039d874..fc0ae899319674e12688ca5c879b330739525e25 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      "20050724"
+#define MAIL_RELEASE_DATE      "20050726"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #ifdef SNAPSHOT
index 75736af47d0e53c389b427f106badd3809730983..e23849b28943c88f96d7de57704385904ecc0652 100644 (file)
@@ -191,7 +191,7 @@ static DNS_RR *lmtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
      * Append the addresses for this host to the address list.
      */
     switch (dns_lookup_v(host, RES_DEFNAMES, &addr, (VSTRING *) 0, why->reason,
-                        DNS_REQ_FLAG_ALL, proto_info->dns_atype_list)) {
+                        DNS_REQ_FLAG_NONE, proto_info->dns_atype_list)) {
     case DNS_OK:
        for (rr = addr; rr; rr = rr->next)
            rr->pref = pref;
@@ -207,6 +207,7 @@ static DNS_RR *lmtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
                        "5.4.3", 550, "550 Name server failure");
        lmtp_errno = LMTP_FAIL;
        break;
+    case DNS_INVAL:
     case DNS_NOTFOUND:
        lmtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
                        "5.4.4", 550, "550 Host not found");
index 55fcfdc7c7cd9c01dd208e69884fa1b78c848fd3..855007efcaeaebef101fabcc02a505065b55e518 100644 (file)
@@ -162,7 +162,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
      */
     if (smtp_host_lookup_mask & SMTP_HOST_FLAG_DNS) {
        switch (dns_lookup_v(host, RES_DEFNAMES, &addr, (VSTRING *) 0,
-                            why->reason, DNS_REQ_FLAG_ALL,
+                            why->reason, DNS_REQ_FLAG_NONE,
                             proto_info->dns_atype_list)) {
        case DNS_OK:
            for (rr = addr; rr; rr = rr->next)
@@ -180,6 +180,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
            if (smtp_errno != SMTP_ERR_RETRY)
                smtp_errno = SMTP_ERR_FAIL;
            return (addr_list);
+       case DNS_INVAL:
        case DNS_NOTFOUND:
            smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
                            "5.4.4", 550, "550 Host not found");
@@ -474,6 +475,11 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
            addr_list = dns_rr_sort(addr_list, smtp_compare_pref);
        }
        break;
+    case DNS_INVAL:
+       smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
+                       "5.4.4", 550, "550 Host not found");
+       smtp_errno = SMTP_ERR_FAIL;
+       break;
     case DNS_NOTFOUND:
        addr_list = smtp_host_addr(name, misc_flags, why);
        break;
index 4e9a81acebaa3010c4ca23de9ce40dbdf2b7bdeb..1c4d34d9492883a4293a510711d34c919840cba9 100644 (file)
@@ -86,7 +86,7 @@ const char *smtp_unalias_name(const char *name)
     if ((result = htable_find(cache, name)) == 0) {
        fqdn = vstring_alloc(10);
        if (dns_lookup_l(name, smtp_unalias_flags, (DNS_RR **) 0, fqdn,
-                            (VSTRING *) 0, DNS_REQ_FLAG_ANY, T_MX, T_A,
+                            (VSTRING *) 0, DNS_REQ_FLAG_NONE, T_MX, T_A,
 #ifdef HAS_IPV6
                             T_AAAA,
 #endif
index 9a44c443f8ed5990909ae2f137778075cd4529fc..00e0dd60a6455a9b746a77388343180ce1b115ec 100644 (file)
@@ -966,7 +966,7 @@ static int reject_unknown_client(SMTPD_STATE *state)
 
     if (state->name_status != SMTPD_PEER_CODE_OK)
        return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
-                                  state->name_status == SMTPD_PEER_CODE_PERM ?
+                               state->name_status == SMTPD_PEER_CODE_PERM ?
                                   var_unk_client_code : 450, "4.7.1",
                    "Client host rejected: cannot find your hostname, [%s]",
                                   state->addr));
@@ -1155,18 +1155,20 @@ static int reject_unknown_hostname(SMTPD_STATE *state, char *name,
 #endif
 
     dns_status = dns_lookup_l(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
-                             (VSTRING *) 0, DNS_REQ_FLAG_ANY,
+                             (VSTRING *) 0, DNS_REQ_FLAG_STOP_OK,
                              RR_ADDR_TYPES, T_MX, 0);
-    if (dns_status == DNS_NOTFOUND)
-       return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
-                                  var_unk_name_code, "4.7.1",
-                                  "<%s>: %s rejected: Host not found",
-                                  reply_name, reply_class));
-    else if (dns_status != DNS_OK)
-       DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
-                        450, "4.7.1",
-                        "<%s>: %s rejected: Host not found",
-                        reply_name, reply_class);
+    if (dns_status != DNS_OK) {                        /* incl. DNS_INVAL */
+       if (dns_status != DNS_RETRY)
+           return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
+                                      var_unk_name_code, "4.7.1",
+                                      "<%s>: %s rejected: Host not found",
+                                      reply_name, reply_class));
+       else
+           DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
+                            450, "4.7.1",
+                            "<%s>: %s rejected: Host not found",
+                            reply_name, reply_class);
+    }
     return (SMTPD_CHECK_DUNNO);
 }
 
@@ -1181,22 +1183,26 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
     if (msg_verbose)
        msg_info("%s: %s", myname, name);
 
+#define MAILHOST_LOOKUP_FLAGS  (DNS_REQ_FLAG_STOP_OK | DNS_REQ_FLAG_STOP_INVAL)
+
     dns_status = dns_lookup_l(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
-                             (VSTRING *) 0, DNS_REQ_FLAG_ANY,
-                             RR_ADDR_TYPES, T_MX, 0);
-    if (dns_status == DNS_NOTFOUND)
-       return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
-                                  var_unk_addr_code,
+                             (VSTRING *) 0, MAILHOST_LOOKUP_FLAGS,
+                             T_MX, RR_ADDR_TYPES, 0);
+    if (dns_status != DNS_OK) {                        /* incl. DNS_INVAL */
+       if (dns_status != DNS_RETRY)
+           return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
+                                      var_unk_addr_code,
                               strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
-                                  "4.1.8" : "4.1.2",
-                                  "<%s>: %s rejected: Domain not found",
-                                  reply_name, reply_class));
-    else if (dns_status != DNS_OK)
-       DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
-                        450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
-                        "4.1.8" : "4.1.2",
-                        "<%s>: %s rejected: Domain not found",
-                        reply_name, reply_class);
+                                      "4.1.8" : "4.1.2",
+                                      "<%s>: %s rejected: Domain not found",
+                                      reply_name, reply_class));
+       else
+           DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY,
+                         450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
+                            "4.1.8" : "4.1.2",
+                            "<%s>: %s rejected: Domain not found",
+                            reply_name, reply_class);
+    }
     return (SMTPD_CHECK_DUNNO);
 }
 
@@ -1395,8 +1401,8 @@ static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
      * Verify that all host addresses are within permit_mx_backup_networks.
      */
     dns_status = dns_lookup_v(host, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0,
-                      DNS_REQ_FLAG_ALL, inet_proto_info()->dns_atype_list);
-    if (dns_status != DNS_OK) {
+                     DNS_REQ_FLAG_NONE, inet_proto_info()->dns_atype_list);
+    if (dns_status != DNS_OK) {                        /* incl. DNS_INVAL */
        DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
                         450, "4.4.4",
           "<%s>: %s rejected: Unable to look up host %s as mail exchanger",
@@ -1622,11 +1628,12 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient,
     if (dns_status == DNS_NOTFOUND)
        return (has_my_addr(state, domain, reply_name, reply_class) ?
                SMTPD_CHECK_OK : SMTPD_CHECK_DUNNO);
-    if (dns_status != DNS_OK) {
-       DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
-                        450, "4.4.4",
-         "<%s>: %s rejected: Unable to look up mail exchanger information",
-                        reply_name, reply_class);
+    if (dns_status != DNS_OK) {                        /* incl. DNS_INVAL */
+       if (dns_status == DNS_RETRY)
+           DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
+                            450, "4.4.4",
+                            "<%s>: %s rejected: Unable to look up mail exchanger information",
+                            reply_name, reply_class);
        return (SMTPD_CHECK_DUNNO);
     }
 
@@ -1961,7 +1968,8 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
      */
     if (STREQUAL(value, "HOLD", cmd_len)) {
 #ifndef TEST
-       if (can_delegate_action(state, table, "HOLD", reply_class) == 0)
+       if (can_delegate_action(state, table, "HOLD", reply_class) == 0
+           || (state->saved_flags & CLEANUP_FLAG_HOLD))
            return (SMTPD_CHECK_DUNNO);
 #endif
        vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
@@ -3502,7 +3510,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
                forbid_whitelist(state, name, status, state->helo_name);
            }
        } else if (strcasecmp(name, REJECT_NON_FQDN_HELO_HOSTNAME) == 0
-                  ||strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
+                  || strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
            if (state->helo_name) {
                if (*state->helo_name != '[')
                    status = reject_non_fqdn_hostname(state, state->helo_name,