The DNS master zone and wire formats in RFC 1035 allow arbitrary binary strings within labels. This is explicitly reaffirmed in section 11 of RFC 2181: "Those [length] restrictions aside, any binary string whatever can be used as the label of any resource record. [...] Implementations of the DNS protocols must not place any restrictions on the labels that can be used."
However, currently the Go DNS resolver decodes DNS wire format domain names into dotted notation without accounting for dots within a label. For example, "dig" correctly resolves the following CNAME chain:
$ dig -t txt go.cname-bug.dempsky.org.
;; ANSWER SECTION:
go.cname-bug.dempsky.org. 300 IN CNAME foo\.bar.cname-bug.dempsky.org.
foo\.bar.cname-bug.dempsky.org. 300 IN CNAME foo.bar.cname-bug.dempsky.org.
foo.bar.cname-bug.dempsky.org. 300 IN TXT "ok"
 lookup foo.bar.cname-bug.dempsky.org. on 127.0.1.1:53: too many redirects
(I'm curious what it outputs on Windows and/or Plan 9, since Go uses the native OS resolver library on those platforms.)
Fixing net.LookupTXT would be relatively easy, but it's less clear what the other net.LookupFoo methods should return if they would need to return a dotted label to the caller.
For comparison, the BIND DNS client library's ns_name_ntop function uses RFC 1035 escaping: the "special" characters ".;\()@$ are escaped with a \, other "printable" characters (>0x20 && <0x7f) are encoded directly, and anything else uses a \ddd decimal escape sequence. (Decimal escapes aren't universal though; at least djbdns and AWS Route 53 use octal escapes instead.)
In issue #1167, @rsc interpreted RFC 2181 as saying "clients can impose whatever restrictions they choose"** to justify disallowing querying arbitrary domain names. Taking that as precedent, it could instead be appropriate to make these functions return a similar "invalid domain name" DNSError if a dotted label is discovered. And relevantly, the BIND DNS client library returns "host not found" errors if during host name resolution it finds a CNAME record that points to a non-host-name. E.g., running host gai.cname-bug.dempsky.org. succeeds, but using getaddrinfo on that name will fail, because _gai.cname-bug.dempsky.org is not a valid host name.
** Though I think that's a misinterpretation of "Clients of the DNS can impose whatever restrictions are appropriate to their circumstances on the values they use as keys for DNS lookup requests, and on the values returned by the DNS." I believe it's actually referring to how specific applications of DNS such as host name resolution might apply the stricter host name requirements from RFC 1123, even though domain names are more general. Notably, LookupHost and LookupIP are documented as resolving "host"s, whereas LookupMX, LookupNS, LookupSRV, and LookupTXT resolve "domain name"s.
The text was updated successfully, but these errors were encountered:
Ran into this writing a fuzzer for x/net/dns/dnsmessage, which exposes pack and unpack methods for DNS messages. In particular, a name like "\.z" (i.e., wire encoding "\x02.z\x00") gets decoded as ".z", which then fails to re-encode because of a zero-length segment.
To answer the past questions: I don't know of any evidence of it affecting real world applications. I think it would be reasonable to explicitly error when parsing packets that contain dots within labels. I think it's risky to mis-parse the packets though.