]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.9-20230821
authorWietse Venema <wietse@porcupine.org>
Mon, 21 Aug 2023 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Sat, 26 Aug 2023 04:58:30 +0000 (00:58 -0400)
postfix/HISTORY
postfix/proto/stop.double-history
postfix/src/dns/dns_lookup.c
postfix/src/global/mail_version.h
postfix/src/util/valid_hostname.c
postfix/src/util/valid_hostname.h
postfix/src/util/valid_hostname.in
postfix/src/util/valid_hostname.ref

index 89cbcdbbd6e0e82e2c8f3a991434e593fd5566b0..8038271b2e65a26310e832cef09c34a22fe63bed 100644 (file)
@@ -27312,3 +27312,17 @@ Apologies for any names omitted.
        mantools/postlink, proto/postconf.proto, global/mail_params.h,
        smtp/lmtp_params.c, smtp/smtp.c, smtp/smtp_params.c,
        smtp/smtp_sasl_glue.c.
+
+20230819
+
+       Bugfix (defect introduced: 19980207): the valid_hostname()
+       check in the Postfix DNS client library was blocking unusual
+       but legitimate wildcard names (*.name) in some DNS lookup
+       results and lookup requests. Examples:
+
+            *.one.example   IN CNAME *.other.example
+            *.other.example IN A     10.0.0.1
+            *.other.example IN TLSA  ..certificate info...
+
+       Reported first in the context of TLSA record lookups.
+       Files: util/valid_hostname.[hc], dns/dns_lookup.c.
index bec21dd74de2b60ca98db0ad1bf4f68cba5c1d34..d0e837eb9f144792f189ad0f9470a12a6dedfbc3 100644 (file)
@@ -64,3 +64,4 @@ proto  proto aliases proto virtual proto ADDRESS_REWRITING_README html
  tls tls h tls tls_client c tls tls_dane c tls tls_fprint c 
  reported by Serg File smtp smtp h 
  smtp lmtp_params c smtp smtp c smtp smtp_params c 
+ plaintext Problem reported by Serg File smtp smtp h 
index d44cae7ee18a282fb995ea0437e17b96330af64f..06028c804f78befed2f3fb27037b217bd49a3020 100644 (file)
@@ -710,7 +710,7 @@ static int valid_rr_name(const char *name, const char *location,
     if (valid_hostaddr(name, DONT_GRIPE)) {
        result = PASS_NAME;
        gripe = "numeric domain name";
-    } else if (!valid_hostname(name, DO_GRIPE)) {
+    } else if (!valid_hostname(name, DO_GRIPE | DO_WILDCARD)) {
        result = REJECT_NAME;
        gripe = "malformed domain name";
     } else {
@@ -1045,7 +1045,7 @@ int     dns_lookup_x(const char *name, unsigned type, unsigned flags,
     /*
      * The Linux resolver misbehaves when given an invalid domain name.
      */
-    if (strcmp(name, ".") && !valid_hostname(name, DONT_GRIPE)) {
+    if (strcmp(name, ".") && !valid_hostname(name, DONT_GRIPE | DO_WILDCARD)) {
        if (why)
            vstring_sprintf(why,
                   "Name service error for %s: invalid host or domain name",
index a62800c8ea841b314d17223b48ecf6e134f4dfc5..7d6a25f33c7aa2bed66294610cf98222c7cd15b5 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      "20230820"
+#define MAIL_RELEASE_DATE      "20230821"
 #define MAIL_VERSION_NUMBER    "3.9"
 
 #ifdef SNAPSHOT
index 07c9eca681aa02f504063c9bdb3ff5977abb6210..457d1f1dacf8af67b77c899e9bf048983cf2293e 100644 (file)
@@ -6,9 +6,9 @@
 /* SYNOPSIS
 /*     #include <valid_hostname.h>
 /*
-/*     int     valid_hostname(name, gripe)
+/*     int     valid_hostname(name, flags)
 /*     const char *name;
-/*     int     gripe;
+/*     int     flags;
 /*
 /*     int     valid_hostaddr(addr, gripe)
 /*     const char *addr;
 /*     dots, no leading or trailing dots or hyphens, no labels
 /*     longer than VALID_LABEL_LEN characters, and it should not
 /*     be all numeric.
+/*     The flags argument is the bit-wise or of zero or more of
+/*     DO_GRIPE or DO_WILDCARD (the latter allows the "*." name
+/*     prefix, which is rare but valid in some DNS responses and
+/*     queries).
 /*
 /*     valid_hostaddr() requires that the input is a valid string
 /*     representation of an IPv4 or IPv6 network address as
@@ -83,7 +87,7 @@
 
 /* valid_hostname - screen out bad hostnames */
 
-int     valid_hostname(const char *name, int gripe)
+int     valid_hostname(const char *name, int flags)
 {
     const char *myname = "valid_hostname";
     const char *cp;
@@ -91,6 +95,7 @@ int     valid_hostname(const char *name, int gripe)
     int     label_count = 0;
     int     non_numeric = 0;
     int     ch;
+    int     gripe = flags & DO_GRIPE;
 
     /*
      * Trivial cases first.
@@ -116,6 +121,15 @@ int     valid_hostname(const char *name, int gripe)
            }
            if (!ISDIGIT(ch))
                non_numeric = 1;
+       } else if ((flags & DO_WILDCARD) && ch == '*') {
+           if (label_length || label_count || (cp[1] && cp[1] != '.')) {
+               if (gripe)
+                   msg_warn("%s: '*' can be the first label only: %.100s", myname, name);
+               return (0);
+           }
+           label_count++;
+           label_length++;
+           non_numeric = 1;
        } else if (ch == '.') {
            if (label_length == 0 || cp[1] == 0) {
                if (gripe)
@@ -393,8 +407,9 @@ int     main(int unused_argc, char **argv)
 
     while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
        msg_info("testing: \"%s\"", vstring_str(buffer));
-       valid_hostname(vstring_str(buffer), DO_GRIPE);
-       valid_hostaddr(vstring_str(buffer), DO_GRIPE);
+       valid_hostname(vstring_str(buffer), DO_GRIPE | DO_WILDCARD);
+       if (strchr(vstring_str(buffer), '*') == 0)
+           valid_hostaddr(vstring_str(buffer), DO_GRIPE);
     }
     exit(0);
 }
index b06fc175861d03fb91c03672d33812033c250949..463bc6ef88dad0da060ce7e520dd625a55b28017 100644 (file)
@@ -18,6 +18,8 @@
 
 #define DONT_GRIPE             0
 #define DO_GRIPE               1
+#define DONT_WILDCARD          0
+#define DO_WILDCARD            (1<<1)
 
 extern int valid_hostname(const char *, int);
 extern int valid_hostaddr(const char *, int);
index 608c0d110e70d883679e5494c8bfec06a53dd1f4..4cdf019d5d41a62e0e3250ce430ddd93dd04a5e8 100644 (file)
@@ -53,3 +53,9 @@ g:a:a:a:a:a:a:a
 a::b
 :a::b
 a::b:
+*.foo.bar
+*foo.bar
+foo.*.bar
+foo*bar
+foo.bar*
+*
index 08b23b8ce043fc0919f9d2e3c96682ef9c157bdb..eccc5585e5e8cac572ebbdfb05467de448f4b6bc 100644 (file)
 ./valid_hostname: testing: "a::b:"
 ./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a::b:
 ./valid_hostname: warning: valid_ipv6_hostaddr: bad null last field in IPv6 address: a::b:
+./valid_hostname: testing: "*.foo.bar"
+./valid_hostname: testing: "*foo.bar"
+./valid_hostname: warning: valid_hostname: '*' can be the first label only: *foo.bar
+./valid_hostname: testing: "foo.*.bar"
+./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo.*.bar
+./valid_hostname: testing: "foo*bar"
+./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo*bar
+./valid_hostname: testing: "foo.bar*"
+./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo.bar*
+./valid_hostname: testing: "*"