Add support for TKEY RRs (#567)
* Add support for TKEY RRs - make sure Key and Data fields are variable length hex fields - checkin output from 'go generate' - add a TKEY specific test to ensure this stays working * go format changes * address review comments * add ability to parse TKEY via string * handle review comments - change TKEY string output
This commit is contained in:
parent
5ec0c6d20f
commit
052efef004
53
dns_test.go
53
dns_test.go
|
@ -1,6 +1,7 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -317,8 +318,9 @@ func TestNoRdataPack(t *testing.T) {
|
||||||
func TestNoRdataUnpack(t *testing.T) {
|
func TestNoRdataUnpack(t *testing.T) {
|
||||||
data := make([]byte, 1024)
|
data := make([]byte, 1024)
|
||||||
for typ, fn := range TypeToRR {
|
for typ, fn := range TypeToRR {
|
||||||
if typ == TypeSOA || typ == TypeTSIG {
|
if typ == TypeSOA || typ == TypeTSIG || typ == TypeTKEY {
|
||||||
// SOA, TSIG will not be seen (like this) in dyn. updates?
|
// SOA, TSIG will not be seen (like this) in dyn. updates?
|
||||||
|
// TKEY requires length fields to be present for the Key and OtherData fields
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
r := fn()
|
r := fn()
|
||||||
|
@ -405,3 +407,52 @@ func TestMsgPackBuffer(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we can decode a TKEY packet from the string, modify the RR, and then pack it again.
|
||||||
|
func TestTKEY(t *testing.T) {
|
||||||
|
// An example TKEY RR captured. There is no known accepted standard text format for a TKEY
|
||||||
|
// record so we do this from a hex string instead of from a text readable string.
|
||||||
|
tkeyStr := "0737362d6d732d370932322d3332633233332463303439663961662d633065612d313165372d363839362d6463333937396666656666640000f900ff0000000000d2086773732d747369670059fd01f359fe53730003000000b8a181b53081b2a0030a0100a10b06092a864882f712010202a2819d04819a60819706092a864886f71201020202006f8187308184a003020105a10302010fa2783076a003020112a26f046db29b1b1d2625da3b20b49dafef930dd1e9aad335e1c5f45dcd95e0005d67a1100f3e573d70506659dbed064553f1ab890f68f65ae10def0dad5b423b39f240ebe666f2886c5fe03819692d29182bbed87b83e1f9d16b7334ec16a3c4fc5ad4a990088e0be43f0c6957916f5fe60000"
|
||||||
|
tkeyBytes, err := hex.DecodeString(tkeyStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unable to decode TKEY string ", err)
|
||||||
|
}
|
||||||
|
// Decode the RR
|
||||||
|
rr, tkeyLen, unPackErr := UnpackRR(tkeyBytes, 0)
|
||||||
|
if unPackErr != nil {
|
||||||
|
t.Fatal("unable to decode TKEY RR", unPackErr)
|
||||||
|
}
|
||||||
|
// make space for it with some fudge room
|
||||||
|
msg := make([]byte, tkeyLen+1000)
|
||||||
|
offset, packErr := PackRR(rr, msg, 0, nil, false)
|
||||||
|
if packErr != nil {
|
||||||
|
t.Fatal("unable to pack TKEY RR", packErr)
|
||||||
|
}
|
||||||
|
if offset != len(tkeyBytes) {
|
||||||
|
t.Fatalf("mismatched TKEY RR size %d != %d", len(tkeyBytes), offset)
|
||||||
|
}
|
||||||
|
if bytes.Compare(tkeyBytes, msg[0:offset]) != 0 {
|
||||||
|
t.Fatal("mismatched TKEY data after rewriting bytes")
|
||||||
|
}
|
||||||
|
t.Logf("got TKEY of: " + rr.String())
|
||||||
|
// Now add some bytes to this and make sure we can encode OtherData properly
|
||||||
|
tkey := rr.(*TKEY)
|
||||||
|
tkey.OtherData = "abcd"
|
||||||
|
tkey.OtherLen = 2
|
||||||
|
offset, packErr = PackRR(tkey, msg, 0, nil, false)
|
||||||
|
if packErr != nil {
|
||||||
|
t.Fatal("unable to pack TKEY RR after modification", packErr)
|
||||||
|
}
|
||||||
|
if offset != (len(tkeyBytes) + 2) {
|
||||||
|
t.Fatalf("mismatched TKEY RR size %d != %d", offset, len(tkeyBytes)+2)
|
||||||
|
}
|
||||||
|
t.Logf("modified to TKEY of: " + rr.String())
|
||||||
|
|
||||||
|
// Make sure we can parse our string output
|
||||||
|
tkey.Hdr.Class = ClassINET // https://github.com/miekg/dns/issues/577
|
||||||
|
newRR, newError := NewRR(tkey.String())
|
||||||
|
if newError != nil {
|
||||||
|
t.Fatalf("unable to parse TKEY string: %s", newError)
|
||||||
|
}
|
||||||
|
t.Log("got reparsed TKEY of newRR: " + newRR.String())
|
||||||
|
}
|
||||||
|
|
46
scan_rr.go
46
scan_rr.go
|
@ -2084,6 +2084,51 @@ func setCAA(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||||
return rr, nil, c1
|
return rr, nil, c1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setTKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||||
|
rr := new(TKEY)
|
||||||
|
rr.Hdr = h
|
||||||
|
|
||||||
|
l := <-c
|
||||||
|
|
||||||
|
// Algorithm
|
||||||
|
if l.value != zString {
|
||||||
|
return nil, &ParseError{f, "bad TKEY algorithm", l}, ""
|
||||||
|
}
|
||||||
|
rr.Algorithm = l.token
|
||||||
|
<-c // zBlank
|
||||||
|
|
||||||
|
// Get the key length and key values
|
||||||
|
l = <-c
|
||||||
|
i, err := strconv.ParseUint(l.token, 10, 8)
|
||||||
|
if err != nil || l.err {
|
||||||
|
return nil, &ParseError{f, "bad TKEY key length", l}, ""
|
||||||
|
}
|
||||||
|
rr.KeySize = uint16(i)
|
||||||
|
<-c // zBlank
|
||||||
|
l = <-c
|
||||||
|
if l.value != zString {
|
||||||
|
return nil, &ParseError{f, "bad TKEY key", l}, ""
|
||||||
|
}
|
||||||
|
rr.Key = l.token
|
||||||
|
<-c // zBlank
|
||||||
|
|
||||||
|
// Get the otherdata length and string data
|
||||||
|
l = <-c
|
||||||
|
i, err = strconv.ParseUint(l.token, 10, 8)
|
||||||
|
if err != nil || l.err {
|
||||||
|
return nil, &ParseError{f, "bad TKEY otherdata length", l}, ""
|
||||||
|
}
|
||||||
|
rr.OtherLen = uint16(i)
|
||||||
|
<-c // zBlank
|
||||||
|
l = <-c
|
||||||
|
if l.value != zString {
|
||||||
|
return nil, &ParseError{f, "bad TKEY otherday", l}, ""
|
||||||
|
}
|
||||||
|
rr.OtherData = l.token
|
||||||
|
|
||||||
|
return rr, nil, ""
|
||||||
|
}
|
||||||
|
|
||||||
var typeToparserFunc = map[uint16]parserFunc{
|
var typeToparserFunc = map[uint16]parserFunc{
|
||||||
TypeAAAA: {setAAAA, false},
|
TypeAAAA: {setAAAA, false},
|
||||||
TypeAFSDB: {setAFSDB, false},
|
TypeAFSDB: {setAFSDB, false},
|
||||||
|
@ -2150,4 +2195,5 @@ var typeToparserFunc = map[uint16]parserFunc{
|
||||||
TypeUINFO: {setUINFO, true},
|
TypeUINFO: {setUINFO, true},
|
||||||
TypeURI: {setURI, true},
|
TypeURI: {setURI, true},
|
||||||
TypeX25: {setX25, false},
|
TypeX25: {setX25, false},
|
||||||
|
TypeTKEY: {setTKEY, true},
|
||||||
}
|
}
|
||||||
|
|
12
types.go
12
types.go
|
@ -1013,14 +1013,18 @@ type TKEY struct {
|
||||||
Mode uint16
|
Mode uint16
|
||||||
Error uint16
|
Error uint16
|
||||||
KeySize uint16
|
KeySize uint16
|
||||||
Key string
|
Key string `dns:"size-hex:KeySize"`
|
||||||
OtherLen uint16
|
OtherLen uint16
|
||||||
OtherData string
|
OtherData string `dns:"size-hex:OtherLen"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TKEY has no official presentation format, but this will suffice.
|
||||||
func (rr *TKEY) String() string {
|
func (rr *TKEY) String() string {
|
||||||
// It has no presentation format
|
s := "\n;; TKEY PSEUDOSECTION:\n"
|
||||||
return ""
|
s += rr.Hdr.String() + " " + rr.Algorithm + " " +
|
||||||
|
strconv.Itoa(int(rr.KeySize)) + " " + rr.Key + " " +
|
||||||
|
strconv.Itoa(int(rr.OtherLen)) + " " + rr.OtherData
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC3597 represents an unknown/generic RR. See RFC 3597.
|
// RFC3597 represents an unknown/generic RR. See RFC 3597.
|
||||||
|
|
11
zmsg.go
11
zmsg.go
|
@ -1325,7 +1325,7 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
off, err = packString(rr.Key, msg, off)
|
off, err = packStringHex(rr.Key, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
|
@ -1333,7 +1333,7 @@ func (rr *TKEY) pack(msg []byte, off int, compression map[string]int, compress b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
off, err = packString(rr.OtherData, msg, off)
|
off, err = packStringHex(rr.OtherData, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
|
@ -3318,13 +3318,10 @@ func unpackTKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
if off == len(msg) {
|
if off == len(msg) {
|
||||||
return rr, off, nil
|
return rr, off, nil
|
||||||
}
|
}
|
||||||
rr.Key, off, err = unpackString(msg, off)
|
rr.Key, off, err = unpackStringHex(msg, off, off+int(rr.KeySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
if off == len(msg) {
|
|
||||||
return rr, off, nil
|
|
||||||
}
|
|
||||||
rr.OtherLen, off, err = unpackUint16(msg, off)
|
rr.OtherLen, off, err = unpackUint16(msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
|
@ -3332,7 +3329,7 @@ func unpackTKEY(h RR_Header, msg []byte, off int) (RR, int, error) {
|
||||||
if off == len(msg) {
|
if off == len(msg) {
|
||||||
return rr, off, nil
|
return rr, off, nil
|
||||||
}
|
}
|
||||||
rr.OtherData, off, err = unpackString(msg, off)
|
rr.OtherData, off, err = unpackStringHex(msg, off, off+int(rr.OtherLen))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue