net: discard unrooted 254 byte names, not rooted ones

Fixes #54285

Change-Id: I20d4d6b9d0532d8a344582b99d446352ae94edcf
GitHub-Last-Rev: ad1337450c
GitHub-Pull-Request: golang/go#54293
Reviewed-on: https://go-review.googlesource.com/c/go/+/421674
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Mateusz Poliwczak 2022-08-06 05:42:25 +00:00 committed by Damien Neil
parent a526ec1569
commit 9e4638ad20
2 changed files with 129 additions and 1 deletions

View file

@ -482,7 +482,7 @@ func (conf *dnsConfig) nameList(name string) []string {
// Check name length (see isDomainName).
l := len(name)
rooted := l > 0 && name[l-1] == '.'
if l > 254 || l == 254 && rooted {
if l > 254 || l == 254 && !rooted {
return nil
}

View file

@ -2216,3 +2216,131 @@ func TestDNSPacketSize(t *testing.T) {
t.Errorf("lookup failed: %v", err)
}
}
func TestLongDNSNames(t *testing.T) {
const longDNSsuffix = ".go.dev."
const longDNSsuffixNoEndingDot = ".go.dev"
var longDNSPrefix = strings.Repeat("verylongdomainlabel.", 20)
var longDNSNamesTests = []struct {
req string
fail bool
}{
{req: longDNSPrefix[:255-len(longDNSsuffix)] + longDNSsuffix, fail: true},
{req: longDNSPrefix[:254-len(longDNSsuffix)] + longDNSsuffix},
{req: longDNSPrefix[:253-len(longDNSsuffix)] + longDNSsuffix},
{req: longDNSPrefix[:253-len(longDNSsuffixNoEndingDot)] + longDNSsuffixNoEndingDot},
{req: longDNSPrefix[:254-len(longDNSsuffixNoEndingDot)] + longDNSsuffixNoEndingDot, fail: true},
}
fake := fakeDNSServer{
rh: func(_, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
r := dnsmessage.Message{
Header: dnsmessage.Header{
ID: q.Header.ID,
Response: true,
RCode: dnsmessage.RCodeSuccess,
},
Questions: q.Questions,
Answers: []dnsmessage.Resource{
{
Header: dnsmessage.ResourceHeader{
Name: q.Questions[0].Name,
Type: q.Questions[0].Type,
Class: dnsmessage.ClassINET,
},
},
},
}
switch q.Questions[0].Type {
case dnsmessage.TypeA:
r.Answers[0].Body = &dnsmessage.AResource{A: TestAddr}
case dnsmessage.TypeAAAA:
r.Answers[0].Body = &dnsmessage.AAAAResource{AAAA: TestAddr6}
case dnsmessage.TypeTXT:
r.Answers[0].Body = &dnsmessage.TXTResource{TXT: []string{"."}}
case dnsmessage.TypeMX:
r.Answers[0].Body = &dnsmessage.MXResource{
MX: dnsmessage.MustNewName("go.dev."),
}
case dnsmessage.TypeNS:
r.Answers[0].Body = &dnsmessage.NSResource{
NS: dnsmessage.MustNewName("go.dev."),
}
case dnsmessage.TypeSRV:
r.Answers[0].Body = &dnsmessage.SRVResource{
Target: dnsmessage.MustNewName("go.dev."),
}
default:
panic("unknown dnsmessage type")
}
return r, nil
},
}
r := &Resolver{PreferGo: true, Dial: fake.DialContext}
methodTests := []string{"CNAME", "Host", "IP", "IPAddr", "MX", "NS", "NetIP", "SRV", "TXT"}
query := func(t string, req string) error {
switch t {
case "CNAME":
_, err := r.LookupCNAME(context.Background(), req)
return err
case "Host":
_, err := r.LookupHost(context.Background(), req)
return err
case "IP":
_, err := r.LookupIP(context.Background(), "ip", req)
return err
case "IPAddr":
_, err := r.LookupIPAddr(context.Background(), req)
return err
case "MX":
_, err := r.LookupMX(context.Background(), req)
return err
case "NS":
_, err := r.LookupNS(context.Background(), req)
return err
case "NetIP":
_, err := r.LookupNetIP(context.Background(), "ip", req)
return err
case "SRV":
const service = "service"
const proto = "proto"
req = req[len(service)+len(proto)+4:]
_, _, err := r.LookupSRV(context.Background(), service, proto, req)
return err
case "TXT":
_, err := r.LookupTXT(context.Background(), req)
return err
}
panic("unknown query method")
}
for i, v := range longDNSNamesTests {
for _, testName := range methodTests {
err := query(testName, v.req)
if v.fail {
if err == nil {
t.Errorf("%v: Lookup%v: unexpected success", i, testName)
break
}
expectedErr := DNSError{Err: errNoSuchHost.Error(), Name: v.req, IsNotFound: true}
var dnsErr *DNSError
errors.As(err, &dnsErr)
if dnsErr == nil || *dnsErr != expectedErr {
t.Errorf("%v: Lookup%v: unexpected error: %v", i, testName, err)
}
break
}
if err != nil {
t.Errorf("%v: Lookup%v: unexpected error: %v", i, testName, err)
}
}
}
}