Fix parsing of RRSIGs

This commit is contained in:
Miek Gieben 2011-07-24 21:29:16 +02:00
parent c52f05f9f5
commit 00f8254ae1
8 changed files with 3604 additions and 2336 deletions

View File

@ -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

View File

@ -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

View File

@ -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()
}
}
}
}

View File

@ -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.

View File

@ -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)
}

View File

@ -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()
}

5779
zparse.go

File diff suppressed because it is too large Load Diff

View File

@ -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.