Fix parsing of RRSIGs
This commit is contained in:
parent
c52f05f9f5
commit
00f8254ae1
2
Makefile
2
Makefile
|
@ -36,6 +36,8 @@ examples:
|
|||
# yes, hardcoded path, yes ugly, yes, deal with it
|
||||
zparse.go: zparse.rl types.rl
|
||||
/home/miekg/svn/ragel/ragel/ragel -Z -G2 -o $@ $<
|
||||
gofmt -w zparse.go
|
||||
|
||||
kparse.go: kparse.rl
|
||||
/home/miekg/svn/ragel/ragel/ragel -Z -G2 -o $@ $<
|
||||
gofmt -w kparse.go
|
||||
|
|
|
@ -16,8 +16,9 @@ things that need to be fixed.
|
|||
- DNSSEC ready
|
||||
* String compression *inside* the library, so the string
|
||||
miek.nl is stored once and all RRs reference it. Would be
|
||||
a major memory saver.
|
||||
* Check base64/base32/hex validity when parsing RRs
|
||||
a major memory saver;
|
||||
* Check base64/base32/hex validity when parsing RRs;
|
||||
* Include os.Error in ParseError too? (more info).
|
||||
|
||||
## Issues
|
||||
|
||||
|
|
|
@ -108,19 +108,26 @@ func TestParse(t *testing.T) {
|
|||
"miek.nl. IN A 127.0.0.1": "miek.nl.\t0\tIN\tA\t127.0.0.1",
|
||||
"miek.nl. IN DNSKEY 256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ": "miek.nl.\t0\tIN\tDNSKEY\t256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ",
|
||||
"nlnetlabs.nl. 3175 IN DNSKEY 256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh": "nlnetlabs.nl.\t3175\tIN\tDNSKEY\t256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh",
|
||||
"dnsex.nl. 86400 IN SOA elektron.atoom.net. miekg.atoom.net. 1299256910 14400 3600 604800 86400": "dnsex.nl.\t86400\tIN\tSOA\telektron.atoom.net. miekg.atoom.net. 1299256910 14400 3600 604800 86400",
|
||||
"dnsex.nl. 86400 IN RRSIG SOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQ vmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchc m+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW 5Cg=": "dnsex.nl.\t86400\tIN\tRRSIG\tSOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQvmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchcm+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW5Cg=",
|
||||
}
|
||||
for test, result := range tests {
|
||||
p := NewParser(strings.NewReader(test))
|
||||
z, err := p.Zone()
|
||||
if err != nil || z == nil {
|
||||
if err != nil {
|
||||
t.Logf("Error of nil r %v %s\n", err, test)
|
||||
t.Fail()
|
||||
}
|
||||
r := z.Pop().(RR)
|
||||
if r.String() != result {
|
||||
t.Logf("\"%s\" should be equal to\n\"%s\"\n", r, result)
|
||||
t.Fail()
|
||||
}
|
||||
r := z.Pop()
|
||||
if r == nil {
|
||||
t.Log("Empty RR")
|
||||
t.Fail()
|
||||
} else {
|
||||
if r.(RR).String() != result {
|
||||
t.Logf("\"%s\" should be equal to\n\"%s\"\n", r, result)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
4
types.go
4
types.go
|
@ -784,7 +784,7 @@ func timeToDate(t uint32) string {
|
|||
|
||||
// If needed assume wrap around(s)
|
||||
ti := time.SecondsToUTC(int64(t) + (mod * Year68)) // abs()? TODO
|
||||
return ti.Format("20060102030405")
|
||||
return ti.Format("20060102150405")
|
||||
}
|
||||
|
||||
// Translate the TSIG time signed into a date. There is no
|
||||
|
@ -792,7 +792,7 @@ func timeToDate(t uint32) string {
|
|||
func tsigTimeToDate(t uint64) string {
|
||||
// only use the lower 48 bits, TODO(mg), check for 48 bit size
|
||||
ti := time.SecondsToUTC(int64(t))
|
||||
return ti.Format("20060102030405")
|
||||
return ti.Format("20060102150405")
|
||||
}
|
||||
|
||||
// Map of constructors for each RR wire type.
|
||||
|
|
96
types.rl
96
types.rl
|
@ -7,7 +7,7 @@
|
|||
rr.Hdr.Rrtype = TypeA
|
||||
rr.A = net.ParseIP(rdf[0])
|
||||
if rr.A == nil {
|
||||
return z, &ParseError{Error: "bad A: " + rdf[0], line: l}
|
||||
return z, &ParseError{Error: "bad A", name: rdf[0], line: l}
|
||||
}
|
||||
z.Push(rr)
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
|||
rr.Hdr.Rrtype = TypeAAAA
|
||||
rr.AAAA = net.ParseIP(rdf[0])
|
||||
if rr.AAAA == nil {
|
||||
return z, &ParseError{Error: "bad AAAA: " + rdf[0], line: l}
|
||||
return z, &ParseError{Error: "bad AAAA", name: rdf[0], line: l}
|
||||
}
|
||||
z.Push(rr)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
|||
rr.Hdr.Rrtype = TypeNS
|
||||
rr.Ns = rdf[0]
|
||||
if ! IsDomainName(rdf[0]) {
|
||||
return z, &ParseError{Error: "bad NS: " + rdf[0], line: l}
|
||||
return z, &ParseError{Error: "bad NS", name: rdf[0], line: l}
|
||||
}
|
||||
z.Push(rr)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@
|
|||
rr.Pref = uint16(i)
|
||||
rr.Mx = rdf[1]
|
||||
if err != nil {
|
||||
return z, &ParseError{Error: "bad MX: " + rdf[0], line: l}
|
||||
return z, &ParseError{Error: "bad MX", name: rdf[0], line: l}
|
||||
}
|
||||
z.Push(rr)
|
||||
}
|
||||
|
@ -57,14 +57,14 @@
|
|||
rr.Hdr.Rrtype = TypeCNAME
|
||||
rr.Cname = rdf[0]
|
||||
if ! IsDomainName(rdf[0]) {
|
||||
return z, &ParseError{Error: "bad CNAME: " + rdf[0], line: l}
|
||||
return z, &ParseError{Error: "bad CNAME", name: rdf[0], line: l}
|
||||
}
|
||||
z.Push(rr)
|
||||
}
|
||||
|
||||
action setSOA {
|
||||
var (
|
||||
i int
|
||||
i uint
|
||||
err os.Error
|
||||
)
|
||||
rdf := fields(data[mark:p], 7)
|
||||
|
@ -73,20 +73,23 @@
|
|||
rr.Hdr.Rrtype = TypeSOA
|
||||
rr.Ns = rdf[0]
|
||||
rr.Mbox = rdf[1]
|
||||
if ! IsDomainName(rdf[0]) || ! IsDomainName(rdf[1]) {
|
||||
return z, &ParseError{Error: "bad SOA: " + rdf[0] + "," + rdf[1], line: l}
|
||||
if ! IsDomainName(rdf[0]) {
|
||||
return z, &ParseError{Error: "bad SOA", name: rdf[0], line: l}
|
||||
}
|
||||
for j, _ := range rdf[2:7] {
|
||||
if i, err = strconv.Atoi(rdf[j]); err != nil {
|
||||
return z, &ParseError{Error: "bad SOA: " + rdf[j], line: l}
|
||||
}
|
||||
switch j {
|
||||
case 2: rr.Serial = uint32(i)
|
||||
case 3: rr.Refresh = uint32(i)
|
||||
case 4: rr.Retry = uint32(i)
|
||||
case 5: rr.Expire = uint32(i)
|
||||
case 6: rr.Minttl = uint32(i)
|
||||
}
|
||||
if ! IsDomainName(rdf[1]) {
|
||||
return z, &ParseError{Error: "bad SOA", name: rdf[1], line: l}
|
||||
}
|
||||
for j, s := range rdf[2:7] {
|
||||
if i, err = strconv.Atoui(s); err != nil {
|
||||
return z, &ParseError{Error: "bad SOA", name: s, line: l}
|
||||
}
|
||||
switch j {
|
||||
case 0: rr.Serial = uint32(i)
|
||||
case 1: rr.Refresh = uint32(i)
|
||||
case 2: rr.Retry = uint32(i)
|
||||
case 3: rr.Expire = uint32(i)
|
||||
case 4: rr.Minttl = uint32(i)
|
||||
}
|
||||
}
|
||||
z.Push(rr)
|
||||
}
|
||||
|
@ -140,19 +143,54 @@
|
|||
}
|
||||
|
||||
action setRRSIG {
|
||||
var (
|
||||
i uint
|
||||
j uint32
|
||||
err os.Error
|
||||
)
|
||||
rdf := fields(data[mark:p], 9)
|
||||
rr := new(RR_RRSIG)
|
||||
rr.Hdr = hdr
|
||||
rr.Hdr.Rrtype = TypeRRSIG
|
||||
rr.TypeCovered = uint16(atoi(rdf[0]))
|
||||
rr.Algorithm = uint8(atoi(rdf[1]))
|
||||
rr.Labels = uint8(atoi(rdf[2]))
|
||||
rr.OrigTtl = uint32(atoi(rdf[3]))
|
||||
rr.Expiration = uint32(atoi(rdf[4]))
|
||||
rr.Inception = uint32(atoi(rdf[5]))
|
||||
rr.KeyTag = uint16(atoi(rdf[6]))
|
||||
|
||||
if _, ok := str_rr[rdf[0]]; !ok {
|
||||
return z, &ParseError{Error: "bad RRSIG", name: rdf[0], line: l}
|
||||
}
|
||||
rr.TypeCovered = str_rr[rdf[0]]
|
||||
|
||||
if i, err = strconv.Atoui(rdf[1]); err != nil {
|
||||
return z, &ParseError{Error: "bad RRSIG", name: rdf[1], line: l}
|
||||
}
|
||||
rr.Algorithm = uint8(i)
|
||||
if i, err = strconv.Atoui(rdf[2]); err != nil {
|
||||
return z, &ParseError{Error: "bad RRSIG", name: rdf[2], line: l}
|
||||
}
|
||||
rr.Labels = uint8(i)
|
||||
if i, err = strconv.Atoui(rdf[3]); err != nil {
|
||||
return z, &ParseError{Error: "bad RRSIG", name: rdf[3], line: l}
|
||||
}
|
||||
rr.OrigTtl = uint32(i)
|
||||
|
||||
if j, err = dateToTime(rdf[4]); err != nil {
|
||||
return z, &ParseError{Error: "bad RRSIG", name: rdf[4], line: l}
|
||||
}
|
||||
rr.Expiration = j
|
||||
if j, err = dateToTime(rdf[5]); err != nil {
|
||||
return z, &ParseError{Error: "bad RRSIG", name: rdf[5], line: l}
|
||||
}
|
||||
rr.Inception = j
|
||||
|
||||
if i, err = strconv.Atoui(rdf[6]); err != nil {
|
||||
return z, &ParseError{Error: "bad RRSIG", name: rdf[3], line: l}
|
||||
}
|
||||
rr.KeyTag = uint16(i)
|
||||
|
||||
rr.SignerName = rdf[7]
|
||||
rr.Signature = rdf[9]
|
||||
if ! IsDomainName(rdf[7]) {
|
||||
return z, &ParseError{Error: "bad RRSIG", name: rdf[7], line: l}
|
||||
}
|
||||
// Check base64 TODO
|
||||
rr.Signature = rdf[8]
|
||||
z.Push(rr)
|
||||
}
|
||||
|
||||
|
@ -165,8 +203,8 @@
|
|||
rr.TypeBitMap = make([]uint16, len(rdf)-1)
|
||||
// Fill the Type Bit Map
|
||||
for i := 1; i < len(rdf); i++ {
|
||||
// Check if its there in the map TODO
|
||||
rr.TypeBitMap[i-1] = str_rr[rdf[i]]
|
||||
// Check if its there in the map TODO
|
||||
rr.TypeBitMap[i-1] = str_rr[rdf[i]]
|
||||
}
|
||||
z.Push(rr)
|
||||
}
|
||||
|
|
9
zone.go
9
zone.go
|
@ -20,15 +20,24 @@ func (z *Zone) Push(r RR) {
|
|||
|
||||
// Remove a RR from the zone.
|
||||
func (z *Zone) Pop() RR {
|
||||
if z == nil {
|
||||
return nil
|
||||
}
|
||||
return z.v.Pop().(RR)
|
||||
}
|
||||
|
||||
// Return the RR at index i of zone.
|
||||
func (z *Zone) At(i int) RR {
|
||||
if z == nil {
|
||||
return nil
|
||||
}
|
||||
return z.v.At(i).(RR)
|
||||
}
|
||||
|
||||
// The number of RRs in zone.
|
||||
func (z *Zone) Len() int {
|
||||
if z == nil {
|
||||
return 0
|
||||
}
|
||||
return z.v.Len()
|
||||
}
|
||||
|
|
26
zparse.rl
26
zparse.rl
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
"strings"
|
||||
"strconv"
|
||||
)
|
||||
|
@ -16,18 +17,19 @@ const _IOBUF = MaxMsgSize
|
|||
// A Parser represents a DNS parser for a
|
||||
// particular input stream.
|
||||
type Parser struct {
|
||||
// nothing here yet
|
||||
buf []byte
|
||||
// nothing here yet
|
||||
buf []byte
|
||||
}
|
||||
|
||||
type ParseError struct {
|
||||
Error string
|
||||
line int
|
||||
Error string
|
||||
name string
|
||||
line int
|
||||
}
|
||||
|
||||
func (e *ParseError) String() string {
|
||||
s := e.Error + " line: " + strconv.Itoa(e.line)
|
||||
return s
|
||||
s := e.Error + ": \"" + e.name + "\" at line: " + strconv.Itoa(e.line)
|
||||
return s
|
||||
}
|
||||
|
||||
// NewParser creates a new DNS file parser from r.
|
||||
|
@ -47,6 +49,18 @@ func NewParser(r io.Reader) *Parser {
|
|||
return p
|
||||
}
|
||||
|
||||
// Translate the RRSIG's incep. and expir. times from
|
||||
// string values ("20110403154150") to an integer.
|
||||
// Taking into account serial arithmetic (RFC 1982)
|
||||
func dateToTime(s string) (uint32, os.Error) {
|
||||
t, e := time.Parse("20060102150405", s)
|
||||
if e != nil {
|
||||
return 0, e
|
||||
}
|
||||
mod := t.Seconds() / Year68
|
||||
ti := uint32(t.Seconds() - (mod * Year68))
|
||||
return ti, nil
|
||||
}
|
||||
|
||||
// Return the rdata fields as a string slice.
|
||||
// All starting whitespace is deleted.
|
||||
|
|
Loading…
Reference in New Issue