From 7ca2be95a9a9e489f193296068b947777ac6090f Mon Sep 17 00:00:00 2001 From: Tom Thorogood Date: Thu, 4 Oct 2018 16:09:45 +0930 Subject: [PATCH] NSEC type bitmap packing bug (#768) * Add test case for NSEC after packing and unpacking This is ported from: https://gist.github.com/cesarkuroiwa/ebc2b4fb1103a7e88824865184f0c73c * Clear msg data after pointer in packDomainName --- msg.go | 6 ++++++ msg_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/msg.go b/msg.go index 154b65ee..182b2893 100644 --- a/msg.go +++ b/msg.go @@ -302,6 +302,12 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c } // If we did compression and we find something add the pointer here if pointer != -1 { + // Clear the msg buffer after the pointer location, otherwise + // packDataNsec writes the wrong data to msg. + tainted := msg[nameoffset:off] + for i := range tainted { + tainted[i] = 0 + } // We have two bytes (14 bits) to put the pointer in // if msg == nil, we will never do compression binary.BigEndian.PutUint16(msg[nameoffset:], uint16(pointer^0xC000)) diff --git a/msg_test.go b/msg_test.go index a9f516a0..e9dce7ec 100644 --- a/msg_test.go +++ b/msg_test.go @@ -141,3 +141,48 @@ func TestUnpackDomainName(t *testing.T) { } } } + +func TestPackDomainNameNSECTypeBitmap(t *testing.T) { + ownername := "some-very-long-ownername.com." + msg := &Msg{ + Compress: true, + Answer: []RR{ + &NS{ + Hdr: RR_Header{ + Name: ownername, + Rrtype: TypeNS, + Class: ClassINET, + }, + Ns: "ns1.server.com.", + }, + &NSEC{ + Hdr: RR_Header{ + Name: ownername, + Rrtype: TypeNSEC, + Class: ClassINET, + }, + NextDomain: "a.com.", + TypeBitMap: []uint16{TypeNS, TypeNSEC}, + }, + }, + } + + // Pack msg and then unpack into msg2 + buf, err := msg.Pack() + if err != nil { + t.Fatalf("msg.Pack failed: %v", err) + } + + var msg2 Msg + if err := msg2.Unpack(buf); err != nil { + t.Fatalf("msg2.Unpack failed: %v", err) + } + + if !IsDuplicate(msg.Answer[1], msg2.Answer[1]) { + t.Error("message differs after packing and unpacking") + + // Print NSEC RR for both cases + t.Logf("expected: %v", msg.Answer[1]) + t.Logf("got: %v", msg2.Answer[1]) + } +}