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.
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
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 {
/*
* 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",
* 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
/* 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
/* 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;
int label_count = 0;
int non_numeric = 0;
int ch;
+ int gripe = flags & DO_GRIPE;
/*
* Trivial cases first.
}
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)
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);
}
#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);
a::b
:a::b
a::b:
+*.foo.bar
+*foo.bar
+foo.*.bar
+foo*bar
+foo.bar*
+*
./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: "*"