util/dnsname: don't validate the contents of DNS labels.

DNS names consist of labels, but outside of length limits, DNS
itself permits any content within the labels. Some records require
labels to conform to hostname limitations (which is what we implemented
before), but not all.

Fixes #2024.

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson 2021-05-31 19:31:29 -07:00 committed by Dave Anderson
parent 2802a01b81
commit caaefa00a0
2 changed files with 17 additions and 24 deletions

View File

@ -48,21 +48,6 @@ func ToFQDN(s string) (FQDN, error) {
return FQDN(s + "."), nil return FQDN(s + "."), nil
} }
func validLabel(s string) bool {
if len(s) == 0 || len(s) > maxLabelLength {
return false
}
if !isalphanum(s[0]) || !isalphanum(s[len(s)-1]) {
return false
}
for i := 1; i < len(s)-1; i++ {
if !isalphanum(s[i]) && s[i] != '-' {
return false
}
}
return true
}
// WithTrailingDot returns f as a string, with a trailing dot. // WithTrailingDot returns f as a string, with a trailing dot.
func (f FQDN) WithTrailingDot() string { func (f FQDN) WithTrailingDot() string {
return string(f) return string(f)
@ -120,23 +105,30 @@ func isValidFQDN(s string) bool {
continue continue
} }
label := s[st:i] label := s[st:i]
if len(label) == 0 || len(label) > maxLabelLength { if !validLabel(label) {
return false return false
} }
if !isalphanum(label[0]) || !isalphanum(label[len(label)-1]) {
return false
}
for j := 1; j < len(label)-1; j++ {
if !isalphanum(label[j]) && label[j] != '-' {
return false
}
}
st = i + 1 st = i + 1
} }
return true return true
} }
func validLabel(s string) bool {
// You might be tempted to do further validation of the
// contents of labels here, based on the hostname rules in RFC
// 1123. However, DNS labels are not always subject to
// hostname rules. In general, they can contain any non-zero
// byte sequence, even though in practice a more restricted
// set is used.
//
// See https://github.com/tailscale/tailscale/issues/2024 for more.
if len(s) == 0 || len(s) > maxLabelLength {
return false
}
return true
}
// SanitizeLabel takes a string intended to be a DNS name label // SanitizeLabel takes a string intended to be a DNS name label
// and turns it into a valid name label according to RFC 1035. // and turns it into a valid name label according to RFC 1035.
func SanitizeLabel(label string) string { func SanitizeLabel(label string) string {

View File

@ -24,6 +24,7 @@ func TestFQDN(t *testing.T) {
{".foo.com", "foo.com.", false, 2}, {".foo.com", "foo.com.", false, 2},
{"com", "com.", false, 1}, {"com", "com.", false, 1},
{"www.tailscale.com", "www.tailscale.com.", false, 3}, {"www.tailscale.com", "www.tailscale.com.", false, 3},
{"_ssh._tcp.tailscale.com", "_ssh._tcp.tailscale.com.", false, 4},
{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", "", true, 0}, {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", "", true, 0},
{strings.Repeat("aaaaa.", 60) + "com", "", true, 0}, {strings.Repeat("aaaaa.", 60) + "com", "", true, 0},
{"foo..com", "", true, 0}, {"foo..com", "", true, 0},