CanonicalName function to return domain name in canonical form (#1073)

* add Canonical function to get name in canonical form

* replace strings.ToLower with Canonical

* rename Canonical to CanonicalName

* replace Fqdn with CanonicalName in ServeMux
This commit is contained in:
Jan Včelák 2020-03-18 11:21:59 +01:00 committed by GitHub
parent 438e446f5c
commit 524a80c35d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 36 deletions

View File

@ -317,6 +317,12 @@ func Fqdn(s string) string {
return s + "."
}
// CanonicalName returns the domain name in canonical form. A name in canonical
// form is lowercase and fully qualified. See Section 6.2 in RFC 4034.
func CanonicalName(s string) string {
return strings.ToLower(Fqdn(s))
}
// Copied from the official Go code.
// ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP

View File

@ -200,7 +200,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
wire = wire[:n]
owner := make([]byte, 255)
off, err1 := PackDomainName(strings.ToLower(k.Hdr.Name), owner, 0, nil, false)
off, err1 := PackDomainName(CanonicalName(k.Hdr.Name), owner, 0, nil, false)
if err1 != nil {
return nil
}
@ -285,7 +285,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
sigwire.Inception = rr.Inception
sigwire.KeyTag = rr.KeyTag
// For signing, lowercase this name
sigwire.SignerName = strings.ToLower(rr.SignerName)
sigwire.SignerName = CanonicalName(rr.SignerName)
// Create the desired binary blob
signdata := make([]byte, DefaultMsgSize)
@ -423,7 +423,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
sigwire.Expiration = rr.Expiration
sigwire.Inception = rr.Inception
sigwire.KeyTag = rr.KeyTag
sigwire.SignerName = strings.ToLower(rr.SignerName)
sigwire.SignerName = CanonicalName(rr.SignerName)
// Create the desired binary blob
signeddata := make([]byte, DefaultMsgSize)
n, err := packSigWire(sigwire, signeddata)
@ -659,7 +659,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
}
// RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
h.Name = strings.ToLower(h.Name)
h.Name = CanonicalName(h.Name)
// 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
// NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
// HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
@ -672,49 +672,49 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
// conversion.
switch x := r1.(type) {
case *NS:
x.Ns = strings.ToLower(x.Ns)
x.Ns = CanonicalName(x.Ns)
case *MD:
x.Md = strings.ToLower(x.Md)
x.Md = CanonicalName(x.Md)
case *MF:
x.Mf = strings.ToLower(x.Mf)
x.Mf = CanonicalName(x.Mf)
case *CNAME:
x.Target = strings.ToLower(x.Target)
x.Target = CanonicalName(x.Target)
case *SOA:
x.Ns = strings.ToLower(x.Ns)
x.Mbox = strings.ToLower(x.Mbox)
x.Ns = CanonicalName(x.Ns)
x.Mbox = CanonicalName(x.Mbox)
case *MB:
x.Mb = strings.ToLower(x.Mb)
x.Mb = CanonicalName(x.Mb)
case *MG:
x.Mg = strings.ToLower(x.Mg)
x.Mg = CanonicalName(x.Mg)
case *MR:
x.Mr = strings.ToLower(x.Mr)
x.Mr = CanonicalName(x.Mr)
case *PTR:
x.Ptr = strings.ToLower(x.Ptr)
x.Ptr = CanonicalName(x.Ptr)
case *MINFO:
x.Rmail = strings.ToLower(x.Rmail)
x.Email = strings.ToLower(x.Email)
x.Rmail = CanonicalName(x.Rmail)
x.Email = CanonicalName(x.Email)
case *MX:
x.Mx = strings.ToLower(x.Mx)
x.Mx = CanonicalName(x.Mx)
case *RP:
x.Mbox = strings.ToLower(x.Mbox)
x.Txt = strings.ToLower(x.Txt)
x.Mbox = CanonicalName(x.Mbox)
x.Txt = CanonicalName(x.Txt)
case *AFSDB:
x.Hostname = strings.ToLower(x.Hostname)
x.Hostname = CanonicalName(x.Hostname)
case *RT:
x.Host = strings.ToLower(x.Host)
x.Host = CanonicalName(x.Host)
case *SIG:
x.SignerName = strings.ToLower(x.SignerName)
x.SignerName = CanonicalName(x.SignerName)
case *PX:
x.Map822 = strings.ToLower(x.Map822)
x.Mapx400 = strings.ToLower(x.Mapx400)
x.Map822 = CanonicalName(x.Map822)
x.Mapx400 = CanonicalName(x.Mapx400)
case *NAPTR:
x.Replacement = strings.ToLower(x.Replacement)
x.Replacement = CanonicalName(x.Replacement)
case *KX:
x.Exchanger = strings.ToLower(x.Exchanger)
x.Exchanger = CanonicalName(x.Exchanger)
case *SRV:
x.Target = strings.ToLower(x.Target)
x.Target = CanonicalName(x.Target)
case *DNAME:
x.Target = strings.ToLower(x.Target)
x.Target = CanonicalName(x.Target)
}
// 6.2. Canonical RR Form. (5) - origTTL
wire := make([]byte, Len(r1)+1) // +1 to be safe(r)

View File

@ -231,6 +231,22 @@ func TestIsFqdnEscaped(t *testing.T) {
}
}
func TestCanonicalName(t *testing.T) {
for s, expect := range map[string]string{
"": ".",
".": ".",
"tld": "tld.",
"tld.": "tld.",
"example.test": "example.test.",
"Lower.CASE.test.": "lower.case.test.",
"*.Test": "*.test.",
} {
if got := CanonicalName(s); got != expect {
t.Errorf("CanonicalName(%q) = %q, expected %q", s, got, expect)
}
}
}
func BenchmarkSplitLabels(b *testing.B) {
for i := 0; i < b.N; i++ {
Split("www.example.com.")

View File

@ -1,7 +1,6 @@
package dns
import (
"strings"
"sync"
)
@ -36,7 +35,7 @@ func (mux *ServeMux) match(q string, t uint16) Handler {
return nil
}
q = strings.ToLower(q)
q = CanonicalName(q)
var handler Handler
for off, end := 0, false; !end; off, end = NextLabel(q, off) {
@ -66,7 +65,7 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
if mux.z == nil {
mux.z = make(map[string]Handler)
}
mux.z[Fqdn(pattern)] = handler
mux.z[CanonicalName(pattern)] = handler
mux.m.Unlock()
}
@ -81,7 +80,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
panic("dns: invalid pattern " + pattern)
}
mux.m.Lock()
delete(mux.z, Fqdn(pattern))
delete(mux.z, CanonicalName(pattern))
mux.m.Unlock()
}

View File

@ -115,7 +115,7 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
t := new(TSIG)
var h hash.Hash
switch strings.ToLower(rr.Algorithm) {
switch CanonicalName(rr.Algorithm) {
case HmacMD5:
h = hmac.New(md5.New, rawsecret)
case HmacSHA1:
@ -182,7 +182,7 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error {
}
var h hash.Hash
switch strings.ToLower(tsig.Algorithm) {
switch CanonicalName(tsig.Algorithm) {
case HmacMD5:
h = hmac.New(md5.New, rawsecret)
case HmacSHA1:
@ -232,10 +232,10 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
tsigvar = tsigvar[:n]
} else {
tsig := new(tsigWireFmt)
tsig.Name = strings.ToLower(rr.Hdr.Name)
tsig.Name = CanonicalName(rr.Hdr.Name)
tsig.Class = ClassANY
tsig.Ttl = rr.Hdr.Ttl
tsig.Algorithm = strings.ToLower(rr.Algorithm)
tsig.Algorithm = CanonicalName(rr.Algorithm)
tsig.TimeSigned = rr.TimeSigned
tsig.Fudge = rr.Fudge
tsig.Error = rr.Error