Implementation of zone digest (ZONEMD) (#1208)
* adding ZONEMD * adding ZONEMD * deleting extra cod * updating constants * updating mod * updating release * Moving ZONEMD Implementation to project structure * re adding indirect tools import * case-insensitive digest * fixing if zone has rfc 3597 RRs * remove .idea folder * restore go.mod imports * gofmt files * pseudo rollback * after go generate... * parsing zonemd in rfc3597 * removing the check for a STRING as HAsh Algorithm in ZONEMD, RFC says only numbers go there * adding ZONEMD constants * Reverting changes in generate.go un-gofmt ing generate.go file * Reverting changes in generate.go un-gofmt ing generate.go file * remove ZoneMD reserved types * remove zonemd RFC3597 branch in ZONEMD parser * revert rfc3597 related modifications * revert rfc3597 related modifications * removing unintentional changes from go.sum and types.go * add line break to go.sum * removing spaces from types.go * Use ZONEMD official RFC link as reference * Add ZONEMD parsing test * Update parse_test.go Co-authored-by: Miek Gieben <miek@miek.nl> Co-authored-by: Eduardo <eriveros@dcc.uchile.cl> Co-authored-by: Eduardo <e.sdfbsadjhgskndwegit@xor.cl> Co-authored-by: Eduardo <e.git@xor.cl> Co-authored-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
parent
883641f4a9
commit
375601dc88
|
@ -1921,3 +1921,74 @@ func TestUnpackRRWithHeaderInvalidLengths(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseZONEMD(t *testing.T) {
|
||||||
|
// Uses examples from https://tools.ietf.org/html/rfc8976
|
||||||
|
dt := map[string]string{
|
||||||
|
// Simple Zone
|
||||||
|
`example. 86400 IN ZONEMD 2018031900 1 1 (
|
||||||
|
c68090d90a7aed71
|
||||||
|
6bc459f9340e3d7c
|
||||||
|
1370d4d24b7e2fc3
|
||||||
|
a1ddc0b9a87153b9
|
||||||
|
a9713b3c9ae5cc27
|
||||||
|
777f98b8e730044c )
|
||||||
|
`: "example.\t86400\tIN\tZONEMD\t2018031900 1 1 c68090d90a7aed716bc459f9340e3d7c1370d4d24b7e2fc3a1ddc0b9a87153b9a9713b3c9ae5cc27777f98b8e730044c",
|
||||||
|
// Complex Zone
|
||||||
|
`example. 86400 IN ZONEMD 2018031900 1 1 (
|
||||||
|
a3b69bad980a3504
|
||||||
|
e1cffcb0fd6397f9
|
||||||
|
3848071c93151f55
|
||||||
|
2ae2f6b1711d4bd2
|
||||||
|
d8b39808226d7b9d
|
||||||
|
b71e34b72077f8fe )
|
||||||
|
`: "example.\t86400\tIN\tZONEMD\t2018031900 1 1 a3b69bad980a3504e1cffcb0fd6397f93848071c93151f552ae2f6b1711d4bd2d8b39808226d7b9db71e34b72077f8fe",
|
||||||
|
// Multiple Digests Zone
|
||||||
|
`example. 86400 IN ZONEMD 2018031900 1 1 (
|
||||||
|
62e6cf51b02e54b9
|
||||||
|
b5f967d547ce4313
|
||||||
|
6792901f9f88e637
|
||||||
|
493daaf401c92c27
|
||||||
|
9dd10f0edb1c56f8
|
||||||
|
080211f8480ee306 )
|
||||||
|
`: "example.\t86400\tIN\tZONEMD\t2018031900 1 1 62e6cf51b02e54b9b5f967d547ce43136792901f9f88e637493daaf401c92c279dd10f0edb1c56f8080211f8480ee306",
|
||||||
|
`example. 86400 IN ZONEMD 2018031900 1 2 (
|
||||||
|
08cfa1115c7b948c
|
||||||
|
4163a901270395ea
|
||||||
|
226a930cd2cbcf2f
|
||||||
|
a9a5e6eb85f37c8a
|
||||||
|
4e114d884e66f176
|
||||||
|
eab121cb02db7d65
|
||||||
|
2e0cc4827e7a3204
|
||||||
|
f166b47e5613fd27 )
|
||||||
|
`: "example.\t86400\tIN\tZONEMD\t2018031900 1 2 08cfa1115c7b948c4163a901270395ea226a930cd2cbcf2fa9a5e6eb85f37c8a4e114d884e66f176eab121cb02db7d652e0cc4827e7a3204f166b47e5613fd27",
|
||||||
|
`example. 86400 IN ZONEMD 2018031900 1 240 (
|
||||||
|
e2d523f654b9422a
|
||||||
|
96c5a8f44607bbee )
|
||||||
|
`: "example. 86400 IN ZONEMD 2018031900 1 240 e2d523f654b9422a96c5a8f44607bbee",
|
||||||
|
`example. 86400 IN ZONEMD 2018031900 241 1 (
|
||||||
|
e1846540e33a9e41
|
||||||
|
89792d18d5d131f6
|
||||||
|
05fc283e )
|
||||||
|
`: "example. 86400 IN ZONEMD 2018031900 241 1 e1846540e33a9e4189792d18d5d131f605fc283e",
|
||||||
|
// URI.ARPA zone
|
||||||
|
`uri.arpa. 3600 IN ZONEMD 2018100702 1 1 (
|
||||||
|
0dbc3c4dbfd75777c12ca19c337854b1577799901307c482e9d91d5d15
|
||||||
|
cd934d16319d98e30c4201cf25a1d5a0254960 )`: "uri.arpa.\t3600\tIN\tZONEMD\t2018100702 1 1 0dbc3c4dbfd75777c12ca19c337854b1577799901307c482e9d91d5d15cd934d16319d98e30c4201cf25a1d5a0254960",
|
||||||
|
// ROOT-SERVERS.NET Zone
|
||||||
|
`root-servers.net. 3600000 IN ZONEMD 2018091100 1 1 (
|
||||||
|
f1ca0ccd91bd5573d9f431c00ee0101b2545c97602be0a97
|
||||||
|
8a3b11dbfc1c776d5b3e86ae3d973d6b5349ba7f04340f79 )
|
||||||
|
`: "root-servers.net.\t3600000\tIN\tZONEMD\t2018091100 1 1 f1ca0ccd91bd5573d9f431c00ee0101b2545c97602be0a978a3b11dbfc1c776d5b3e86ae3d973d6b5349ba7f04340f79",
|
||||||
|
}
|
||||||
|
for i, o := range dt {
|
||||||
|
rr, err := NewRR(i)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to parse RR: ", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if rr.String() != o {
|
||||||
|
t.Errorf("`%s' should be equal to\n`%s', but is `%s'", i, o, rr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
32
scan_rr.go
32
scan_rr.go
|
@ -846,6 +846,38 @@ func (rr *CSYNC) parse(c *zlexer, o string) *ParseError {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *ZONEMD) parse(c *zlexer, o string) *ParseError {
|
||||||
|
l, _ := c.Next()
|
||||||
|
i, e := strconv.ParseUint(l.token, 10, 32)
|
||||||
|
if e != nil || l.err {
|
||||||
|
return &ParseError{"", "bad ZONEMD Serial", l}
|
||||||
|
}
|
||||||
|
rr.Serial = uint32(i)
|
||||||
|
|
||||||
|
c.Next() // zBlank
|
||||||
|
l, _ = c.Next()
|
||||||
|
i, e1 := strconv.ParseUint(l.token, 10, 8)
|
||||||
|
if e1 != nil || l.err {
|
||||||
|
return &ParseError{"", "bad ZONEMD Scheme", l}
|
||||||
|
}
|
||||||
|
rr.Scheme = uint8(i)
|
||||||
|
|
||||||
|
c.Next() // zBlank
|
||||||
|
l, _ = c.Next()
|
||||||
|
i, err := strconv.ParseUint(l.token, 10, 8);
|
||||||
|
if err != nil || l.err {
|
||||||
|
return &ParseError{"", "bad ZONEMD Hash Algorithm", l}
|
||||||
|
}
|
||||||
|
rr.Hash = uint8(i)
|
||||||
|
|
||||||
|
s, e2 := endingToString(c, "bad ZONEMD Digest")
|
||||||
|
if e2 != nil {
|
||||||
|
return e2
|
||||||
|
}
|
||||||
|
rr.Digest = s
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (rr *SIG) parse(c *zlexer, o string) *ParseError { return rr.RRSIG.parse(c, o) }
|
func (rr *SIG) parse(c *zlexer, o string) *ParseError { return rr.RRSIG.parse(c, o) }
|
||||||
|
|
||||||
func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
|
func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
|
||||||
|
|
29
types.go
29
types.go
|
@ -81,6 +81,7 @@ const (
|
||||||
TypeCDNSKEY uint16 = 60
|
TypeCDNSKEY uint16 = 60
|
||||||
TypeOPENPGPKEY uint16 = 61
|
TypeOPENPGPKEY uint16 = 61
|
||||||
TypeCSYNC uint16 = 62
|
TypeCSYNC uint16 = 62
|
||||||
|
TypeZONEMD uint16 = 63
|
||||||
TypeSVCB uint16 = 64
|
TypeSVCB uint16 = 64
|
||||||
TypeHTTPS uint16 = 65
|
TypeHTTPS uint16 = 65
|
||||||
TypeSPF uint16 = 99
|
TypeSPF uint16 = 99
|
||||||
|
@ -150,6 +151,17 @@ const (
|
||||||
OpcodeUpdate = 5
|
OpcodeUpdate = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Used in ZONEMD https://tools.ietf.org/html/rfc8976
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ZoneMD Accepted Schemes
|
||||||
|
ZoneMDSchemeSimple = 1
|
||||||
|
|
||||||
|
// ZoneMD Hash Algorithms
|
||||||
|
ZoneMDHashAlgSHA384 = 1
|
||||||
|
ZoneMDHashAlgSHA512 = 2
|
||||||
|
)
|
||||||
|
|
||||||
// Header is the wire format for the DNS packet header.
|
// Header is the wire format for the DNS packet header.
|
||||||
type Header struct {
|
type Header struct {
|
||||||
Id uint16
|
Id uint16
|
||||||
|
@ -1361,6 +1373,23 @@ func (rr *CSYNC) len(off int, compression map[string]struct{}) int {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ZONEMD RR, from draft-ietf-dnsop-dns-zone-digest
|
||||||
|
type ZONEMD struct {
|
||||||
|
Hdr RR_Header
|
||||||
|
Serial uint32
|
||||||
|
Scheme uint8
|
||||||
|
Hash uint8
|
||||||
|
Digest string `dns:"hex"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *ZONEMD) String() string {
|
||||||
|
return rr.Hdr.String() +
|
||||||
|
strconv.Itoa(int(rr.Serial)) +
|
||||||
|
" " + strconv.Itoa(int(rr.Scheme)) +
|
||||||
|
" " + strconv.Itoa(int(rr.Hash)) +
|
||||||
|
" " + rr.Digest
|
||||||
|
}
|
||||||
|
|
||||||
// APL RR. See RFC 3123.
|
// APL RR. See RFC 3123.
|
||||||
type APL struct {
|
type APL struct {
|
||||||
Hdr RR_Header
|
Hdr RR_Header
|
||||||
|
|
|
@ -1317,3 +1317,24 @@ func (r1 *X25) isDuplicate(_r2 RR) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r1 *ZONEMD) isDuplicate(_r2 RR) bool {
|
||||||
|
r2, ok := _r2.(*ZONEMD)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_ = r2
|
||||||
|
if r1.Serial != r2.Serial {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Scheme != r2.Scheme {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Hash != r2.Hash {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Digest != r2.Digest {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
52
zmsg.go
52
zmsg.go
|
@ -1118,6 +1118,26 @@ func (rr *X25) pack(msg []byte, off int, compression compressionMap, compress bo
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *ZONEMD) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
|
||||||
|
off, err = packUint32(rr.Serial, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
off, err = packUint8(rr.Scheme, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
off, err = packUint8(rr.Hash, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
off, err = packStringHex(rr.Digest, msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
||||||
// unpack*() functions
|
// unpack*() functions
|
||||||
|
|
||||||
func (rr *A) unpack(msg []byte, off int) (off1 int, err error) {
|
func (rr *A) unpack(msg []byte, off int) (off1 int, err error) {
|
||||||
|
@ -2821,3 +2841,35 @@ func (rr *X25) unpack(msg []byte, off int) (off1 int, err error) {
|
||||||
}
|
}
|
||||||
return off, nil
|
return off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rr *ZONEMD) unpack(msg []byte, off int) (off1 int, err error) {
|
||||||
|
rdStart := off
|
||||||
|
_ = rdStart
|
||||||
|
|
||||||
|
rr.Serial, off, err = unpackUint32(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
if off == len(msg) {
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
rr.Scheme, off, err = unpackUint8(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
if off == len(msg) {
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
rr.Hash, off, err = unpackUint8(msg, off)
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
if off == len(msg) {
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
rr.Digest, off, err = unpackStringHex(msg, off, rdStart+int(rr.Hdr.Rdlength))
|
||||||
|
if err != nil {
|
||||||
|
return off, err
|
||||||
|
}
|
||||||
|
return off, nil
|
||||||
|
}
|
||||||
|
|
14
ztypes.go
14
ztypes.go
|
@ -82,6 +82,7 @@ var TypeToRR = map[uint16]func() RR{
|
||||||
TypeUINFO: func() RR { return new(UINFO) },
|
TypeUINFO: func() RR { return new(UINFO) },
|
||||||
TypeURI: func() RR { return new(URI) },
|
TypeURI: func() RR { return new(URI) },
|
||||||
TypeX25: func() RR { return new(X25) },
|
TypeX25: func() RR { return new(X25) },
|
||||||
|
TypeZONEMD: func() RR { return new(ZONEMD) },
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeToString is a map of strings for each RR type.
|
// TypeToString is a map of strings for each RR type.
|
||||||
|
@ -168,6 +169,7 @@ var TypeToString = map[uint16]string{
|
||||||
TypeUNSPEC: "UNSPEC",
|
TypeUNSPEC: "UNSPEC",
|
||||||
TypeURI: "URI",
|
TypeURI: "URI",
|
||||||
TypeX25: "X25",
|
TypeX25: "X25",
|
||||||
|
TypeZONEMD: "ZONEMD",
|
||||||
TypeNSAPPTR: "NSAP-PTR",
|
TypeNSAPPTR: "NSAP-PTR",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +247,7 @@ func (rr *UID) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *UINFO) Header() *RR_Header { return &rr.Hdr }
|
func (rr *UINFO) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *URI) Header() *RR_Header { return &rr.Hdr }
|
func (rr *URI) Header() *RR_Header { return &rr.Hdr }
|
||||||
func (rr *X25) Header() *RR_Header { return &rr.Hdr }
|
func (rr *X25) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
func (rr *ZONEMD) Header() *RR_Header { return &rr.Hdr }
|
||||||
|
|
||||||
// len() functions
|
// len() functions
|
||||||
func (rr *A) len(off int, compression map[string]struct{}) int {
|
func (rr *A) len(off int, compression map[string]struct{}) int {
|
||||||
|
@ -684,6 +687,14 @@ func (rr *X25) len(off int, compression map[string]struct{}) int {
|
||||||
l += len(rr.PSDNAddress) + 1
|
l += len(rr.PSDNAddress) + 1
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
func (rr *ZONEMD) len(off int, compression map[string]struct{}) int {
|
||||||
|
l := rr.Hdr.len(off, compression)
|
||||||
|
l += 4 // Serial
|
||||||
|
l++ // Scheme
|
||||||
|
l++ // Hash
|
||||||
|
l += len(rr.Digest) / 2
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
// copy() functions
|
// copy() functions
|
||||||
func (rr *A) copy() RR {
|
func (rr *A) copy() RR {
|
||||||
|
@ -936,3 +947,6 @@ func (rr *URI) copy() RR {
|
||||||
func (rr *X25) copy() RR {
|
func (rr *X25) copy() RR {
|
||||||
return &X25{rr.Hdr, rr.PSDNAddress}
|
return &X25{rr.Hdr, rr.PSDNAddress}
|
||||||
}
|
}
|
||||||
|
func (rr *ZONEMD) copy() RR {
|
||||||
|
return &ZONEMD{rr.Hdr, rr.Serial, rr.Scheme, rr.Hash, rr.Digest}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue