]> Cypherpunks repositories - gostls13.git/commitdiff
net: fix packDomainName encoding of root and invalid names
authorIan Gudger <igudger@google.com>
Thu, 18 Feb 2016 19:29:05 +0000 (11:29 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 19 Feb 2016 00:55:47 +0000 (00:55 +0000)
Fixes #14372

Change-Id: I40d594582639e87ef2574d37ac868e37ffaa17dc
Reviewed-on: https://go-review.googlesource.com/19623
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/net/dnsmsg.go
src/net/dnsmsg_test.go

index 93078fe849982bb440ed9f7cec8d700fcd431fc8..2ec4c8c3015a2663a98e63a9dd82e8ac41086b40 100644 (file)
@@ -406,6 +406,13 @@ func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
                s += "."
        }
 
+       // Allow root domain.
+       if s == "." {
+               msg[off] = 0
+               off++
+               return off, true
+       }
+
        // Each dot ends a segment of the name.
        // We trade each dot byte for a length byte.
        // There is also a trailing zero.
@@ -422,8 +429,13 @@ func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
                        if i-begin >= 1<<6 { // top two bits of length must be clear
                                return len(msg), false
                        }
+                       if i-begin == 0 {
+                               return len(msg), false
+                       }
+
                        msg[off] = byte(i - begin)
                        off++
+
                        for j := begin; j < i; j++ {
                                msg[off] = s[j]
                                off++
@@ -494,6 +506,9 @@ Loop:
                        return "", len(msg), false
                }
        }
+       if len(s) == 0 {
+               s = "."
+       }
        if ptr == 0 {
                off1 = off
        }
@@ -803,20 +818,32 @@ func (dns *dnsMsg) Pack() (msg []byte, ok bool) {
        // Pack it in: header and then the pieces.
        off := 0
        off, ok = packStruct(&dh, msg, off)
+       if !ok {
+               return nil, false
+       }
        for i := 0; i < len(question); i++ {
                off, ok = packStruct(&question[i], msg, off)
+               if !ok {
+                       return nil, false
+               }
        }
        for i := 0; i < len(answer); i++ {
                off, ok = packRR(answer[i], msg, off)
+               if !ok {
+                       return nil, false
+               }
        }
        for i := 0; i < len(ns); i++ {
                off, ok = packRR(ns[i], msg, off)
+               if !ok {
+                       return nil, false
+               }
        }
        for i := 0; i < len(extra); i++ {
                off, ok = packRR(extra[i], msg, off)
-       }
-       if !ok {
-               return nil, false
+               if !ok {
+                       return nil, false
+               }
        }
        return msg[0:off], true
 }
@@ -848,6 +875,9 @@ func (dns *dnsMsg) Unpack(msg []byte) bool {
 
        for i := 0; i < len(dns.question); i++ {
                off, ok = unpackStruct(&dns.question[i], msg, off)
+               if !ok {
+                       return false
+               }
        }
        for i := 0; i < int(dh.Ancount); i++ {
                rec, off, ok = unpackRR(msg, off)
index 1078d77ceb9dd2717146b39eb2aec4c0349315c1..339fb83c6299160420c00ed226683402f6a6f896 100644 (file)
@@ -10,6 +10,103 @@ import (
        "testing"
 )
 
+func TestStructPackUnpack(t *testing.T) {
+       want := dnsQuestion{
+               Name:   ".",
+               Qtype:  dnsTypeA,
+               Qclass: dnsClassINET,
+       }
+       buf := make([]byte, 50)
+       n, ok := packStruct(&want, buf, 0)
+       if !ok {
+               t.Fatal("packing failed")
+       }
+       buf = buf[:n]
+       got := dnsQuestion{}
+       n, ok = unpackStruct(&got, buf, 0)
+       if !ok {
+               t.Fatal("unpacking failed")
+       }
+       if n != len(buf) {
+               t.Error("unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
+       }
+       if !reflect.DeepEqual(got, want) {
+               t.Errorf("got = %+v, want = %+v", got, want)
+       }
+}
+
+func TestDomainNamePackUnpack(t *testing.T) {
+       tests := []struct {
+               in   string
+               want string
+               ok   bool
+       }{
+               {"", ".", true},
+               {".", ".", true},
+               {"google..com", "", false},
+               {"google.com", "google.com.", true},
+               {"google..com.", "", false},
+               {"google.com.", "google.com.", true},
+               {".google.com.", "", false},
+               {"www..google.com.", "", false},
+               {"www.google.com.", "www.google.com.", true},
+       }
+
+       for _, test := range tests {
+               buf := make([]byte, 30)
+               n, ok := packDomainName(test.in, buf, 0)
+               if ok != test.ok {
+                       t.Errorf("packing of %s: got ok = %t, want = %t", test.in, ok, test.ok)
+                       continue
+               }
+               if !test.ok {
+                       continue
+               }
+               buf = buf[:n]
+               got, n, ok := unpackDomainName(buf, 0)
+               if !ok {
+                       t.Errorf("unpacking for %s failed", test.in)
+                       continue
+               }
+               if n != len(buf) {
+                       t.Error(
+                               "unpacked different amount than packed for %s: got n = %d, want = %d",
+                               test.in,
+                               n,
+                               len(buf),
+                       )
+               }
+               if got != test.want {
+                       t.Errorf("unpacking packing of %s: got = %s, want = %s", test.in, got, test.want)
+               }
+       }
+}
+
+func TestDNSPackUnpack(t *testing.T) {
+       want := dnsMsg{
+               question: []dnsQuestion{{
+                       Name:   ".",
+                       Qtype:  dnsTypeAAAA,
+                       Qclass: dnsClassINET,
+               }},
+               answer: []dnsRR{},
+               ns:     []dnsRR{},
+               extra:  []dnsRR{},
+       }
+       b, ok := want.Pack()
+       if !ok {
+               t.Fatal("packing failed")
+       }
+       var got dnsMsg
+       ok = got.Unpack(b)
+       if !ok {
+               t.Fatal("unpacking failed")
+       }
+       if !reflect.DeepEqual(got, want) {
+               t.Errorf("got = %+v, want = %+v", got, want)
+       }
+}
+
 func TestDNSParseSRVReply(t *testing.T) {
        data, err := hex.DecodeString(dnsSRVReply)
        if err != nil {