From: Wietse Venema Date: Mon, 21 Aug 2023 05:00:00 +0000 (-0500) Subject: postfix-3.9-20230821 X-Git-Tag: v3.9.0~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ef0d0218204ba384b639e0c42e9c8911fa51b3e9;p=thirdparty%2Fpostfix.git postfix-3.9-20230821 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 89cbcdbbd..8038271b2 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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. diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history index bec21dd74..d0e837eb9 100644 --- a/postfix/proto/stop.double-history +++ b/postfix/proto/stop.double-history @@ -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 diff --git a/postfix/src/dns/dns_lookup.c b/postfix/src/dns/dns_lookup.c index d44cae7ee..06028c804 100644 --- a/postfix/src/dns/dns_lookup.c +++ b/postfix/src/dns/dns_lookup.c @@ -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", diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index a62800c8e..7d6a25f33 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20230820" +#define MAIL_RELEASE_DATE "20230821" #define MAIL_VERSION_NUMBER "3.9" #ifdef SNAPSHOT diff --git a/postfix/src/util/valid_hostname.c b/postfix/src/util/valid_hostname.c index 07c9eca68..457d1f1da 100644 --- a/postfix/src/util/valid_hostname.c +++ b/postfix/src/util/valid_hostname.c @@ -6,9 +6,9 @@ /* SYNOPSIS /* #include /* -/* 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; @@ -32,6 +32,10 @@ /* 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); } diff --git a/postfix/src/util/valid_hostname.h b/postfix/src/util/valid_hostname.h index b06fc1758..463bc6ef8 100644 --- a/postfix/src/util/valid_hostname.h +++ b/postfix/src/util/valid_hostname.h @@ -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); diff --git a/postfix/src/util/valid_hostname.in b/postfix/src/util/valid_hostname.in index 608c0d110..4cdf019d5 100644 --- a/postfix/src/util/valid_hostname.in +++ b/postfix/src/util/valid_hostname.in @@ -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* +* diff --git a/postfix/src/util/valid_hostname.ref b/postfix/src/util/valid_hostname.ref index 08b23b8ce..eccc5585e 100644 --- a/postfix/src/util/valid_hostname.ref +++ b/postfix/src/util/valid_hostname.ref @@ -141,3 +141,13 @@ ./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: "*"