support nsec3 and nsec3param

This commit is contained in:
Miek Gieben 2011-02-03 20:39:43 +01:00
parent 1e111c9571
commit d87e7eff86
3 changed files with 85 additions and 13 deletions

86
msg.go
View File

@ -15,7 +15,6 @@
package dns package dns
import ( import (
// "fmt"
"os" "os"
"reflect" "reflect"
"net" "net"
@ -23,6 +22,7 @@ import (
"time" "time"
"strconv" "strconv"
"encoding/base64" "encoding/base64"
"encoding/base32"
"encoding/hex" "encoding/hex"
) )
@ -261,7 +261,7 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o
// for each code we should do something else // for each code we should do something else
h, e := hex.DecodeString(string(element.(*reflect.StructValue).Field(1).(*reflect.StringValue).Get())) h, e := hex.DecodeString(string(element.(*reflect.StructValue).Field(1).(*reflect.StringValue).Get()))
if e != nil { if e != nil {
//fmt.Fprintf(os.Stderr, "dns: failure packing OTP") //fmt.Fprintf(os.Stderr, "dns: failure packing OTP")
return len(msg), false return len(msg), false
} }
data := string(h) data := string(h)
@ -363,8 +363,23 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o
default: default:
//fmt.Fprintf(os.Stderr, "dns: unknown packing string tag %v", f.Tag) //fmt.Fprintf(os.Stderr, "dns: unknown packing string tag %v", f.Tag)
return len(msg), false return len(msg), false
case "base32":
b32, err := packBase32([]byte(s))
if err != nil {
//fmt.Fprintf(os.Stderr, "dns: overflow packing base32")
return len(msg), false
}
copy(msg[off:off+len(b32)], b32)
off += len(b32)
case "base64": case "base64":
// TODO(mg) use the Len as return from the conversion (not used right now) b64, err := packBase64([]byte(s))
if err != nil {
//fmt.Fprintf(os.Stderr, "dns: overflow packing base64")
return len(msg), false
}
copy(msg[off:off+len(b64)], b64)
off += len(b64)
/*
b64len := base64.StdEncoding.DecodedLen(len(s)) b64len := base64.StdEncoding.DecodedLen(len(s))
_, err := base64.StdEncoding.Decode(msg[off:off+b64len], []byte(s)) _, err := base64.StdEncoding.Decode(msg[off:off+b64len], []byte(s))
if err != nil { if err != nil {
@ -372,12 +387,14 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o
return len(msg), false return len(msg), false
} }
off += b64len off += b64len
*/
case "domain-name": case "domain-name":
off, ok = packDomainName(s, msg, off) off, ok = packDomainName(s, msg, off)
if !ok { if !ok {
//fmt.Fprintf(os.Stderr, "dns: overflow packing domain-name") //fmt.Fprintf(os.Stderr, "dns: overflow packing domain-name")
return len(msg), false return len(msg), false
} }
case "size-hex":
case "hex": case "hex":
// There is no length encoded here, for DS at least // There is no length encoded here, for DS at least
h, e := hex.DecodeString(s) h, e := hex.DecodeString(s)
@ -387,7 +404,7 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o
} }
copy(msg[off:off+hex.DecodedLen(len(s))], h) copy(msg[off:off+hex.DecodedLen(len(s))], h)
off += hex.DecodedLen(len(s)) off += hex.DecodedLen(len(s))
case "fixed-size": case "size":
// the size is already encoded in the RR, we can safely use the // the size is already encoded in the RR, we can safely use the
// length of string. String is RAW (not encoded in hex, nor base64) // length of string. String is RAW (not encoded in hex, nor base64)
copy(msg[off:off+len(s)], s) copy(msg[off:off+len(s)], s)
@ -612,7 +629,43 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
//fmt.Fprintf(os.Stderr, "dns: failure unpacking domain-name") //fmt.Fprintf(os.Stderr, "dns: failure unpacking domain-name")
return len(msg), false return len(msg), false
} }
case "fixed-size": case "size-base32":
var size int
switch val.Type().Name() {
case "RR_NSEC3":
switch f.Name {
case "NextDomain":
name := val.FieldByName("HashLength")
size = int(name.(*reflect.UintValue).Get())
}
}
if off+size > len(msg) {
//fmt.Fprintf(os.Stderr, "dns: failure unpacking size-base32 string")
return len(msg), false
}
s = unpackBase32(msg[off : off+size])
off += size
case "size-hex":
// a "size" string, but a it must be encoded in hex in the string
var size int
switch val.Type().Name() {
case "RR_NSEC3":
switch f.Name {
case "Salt":
name := val.FieldByName("SaltLength")
size = int(name.(*reflect.UintValue).Get())
case "NextDomain":
name := val.FieldByName("HashLength")
size = int(name.(*reflect.UintValue).Get())
}
}
if off+size > len(msg) {
//fmt.Fprintf(os.Stderr, "dns: failure unpacking hex-size string")
return len(msg), false
}
s = hex.EncodeToString(msg[off : off+size])
off += size
case "size":
// We should already know how many bytes we can expect // We should already know how many bytes we can expect
// TODO(mg) pack variant. Note that looks a bit like the EDNS0 // TODO(mg) pack variant. Note that looks a bit like the EDNS0
// Option parsing, maybe it should be merged. // Option parsing, maybe it should be merged.
@ -629,7 +682,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
} }
} }
if off+size > len(msg) { if off+size > len(msg) {
//fmt.Fprintf(os.Stderr, "dns: failure unpacking fixed-size string") //fmt.Fprintf(os.Stderr, "dns: failure unpacking size string")
return len(msg), false return len(msg), false
} }
s = string(msg[off : off+size]) s = string(msg[off : off+size])
@ -666,6 +719,12 @@ func unpackStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
return off, ok return off, ok
} }
func unpackBase32(b []byte) string {
b32 := make([]byte, base32.HexEncoding.EncodedLen(len(b)))
base32.HexEncoding.Encode(b32, b)
return string(b32)
}
func unpackBase64(b []byte) string { func unpackBase64(b []byte) string {
b64 := make([]byte, base64.StdEncoding.EncodedLen(len(b))) b64 := make([]byte, base64.StdEncoding.EncodedLen(len(b)))
base64.StdEncoding.Encode(b64, b) base64.StdEncoding.Encode(b64, b)
@ -684,6 +743,18 @@ func packBase64(s []byte) ([]byte, os.Error) {
return buf, nil return buf, nil
} }
// Helper function for packing, mostly used in dnssec.go
func packBase32(s []byte) ([]byte, os.Error) {
b32len := base32.HexEncoding.DecodedLen(len(s))
buf := make([]byte, b32len)
n, err := base32.HexEncoding.Decode(buf, []byte(s))
if err != nil {
return nil, err
}
buf = buf[:n]
return buf, nil
}
// Resource record packer. // Resource record packer.
func packRR(rr RR, msg []byte, off int) (off2 int, ok bool) { func packRR(rr RR, msg []byte, off int) (off2 int, ok bool) {
if rr == nil { if rr == nil {
@ -699,6 +770,7 @@ func packRR(rr RR, msg []byte, off int) (off2 int, ok bool) {
off1, ok = packStruct(rr.Header(), msg, off) off1, ok = packStruct(rr.Header(), msg, off)
off2, ok = packStruct(rr, msg, off) off2, ok = packStruct(rr, msg, off)
if !ok { if !ok {
println("WAAA")
return len(msg), false return len(msg), false
} }
@ -894,7 +966,7 @@ func (dns *Msg) Unpack(msg []byte) bool {
return false return false
} }
if off != len(msg) { if off != len(msg) {
// TODO(mg) remove eventually // TODO(mg) remove eventually
println("extra bytes in dns packet", off, "<", len(msg)) println("extra bytes in dns packet", off, "<", len(msg))
} }
return true return true

View File

@ -23,11 +23,11 @@ type RR_TSIG struct {
TimeSigned uint64 TimeSigned uint64
Fudge uint16 Fudge uint16
MACSize uint16 MACSize uint16
MAC string "fixed-size" MAC string "size-hex"
OrigId uint16 OrigId uint16
Error uint16 Error uint16
OtherLen uint16 OtherLen uint16
OtherData string "fixed-size" OtherData string "size-hex"
} }
func (rr *RR_TSIG) Header() *RR_Header { func (rr *RR_TSIG) Header() *RR_Header {
@ -60,7 +60,7 @@ type tsigWireFmt struct {
// MACSize, MAC and OrigId excluded // MACSize, MAC and OrigId excluded
Error uint16 Error uint16
OtherLen uint16 OtherLen uint16
OtherData string "fixed-size" OtherData string "size-hex"
} }
// Generate the HMAC for message. The TSIG RR is modified // Generate the HMAC for message. The TSIG RR is modified

View File

@ -534,9 +534,9 @@ type RR_NSEC3 struct {
Flags uint8 Flags uint8
Iterations uint16 Iterations uint16
SaltLength uint8 SaltLength uint8
Salt string "hex" Salt string "size-hex"
HashLength uint8 HashLength uint8
NextDomain string "domain-name" NextDomain string "size-base32"
TypeBitMap []uint16 "NSEC" TypeBitMap []uint16 "NSEC"
} }
@ -553,7 +553,7 @@ func (rr *RR_NSEC3) String() string {
" " + rr.NextDomain // must base32? " " + rr.NextDomain // must base32?
for i := 0; i < len(rr.TypeBitMap); i++ { for i := 0; i < len(rr.TypeBitMap); i++ {
// Check if map exists, otherwise "TYPE" + strcov.Itoa(int(rr.TypeBitMap[i])) // Check if map exists, otherwise "TYPE" + strcov.Itoa(int(rr.TypeBitMap[i]))
s = s + " " + Rr_str[rr.TypeBitMap[i]] s += " " + Rr_str[rr.TypeBitMap[i]]
} }
return s return s
} }