This commit is contained in:
Miek Gieben 2011-07-23 23:43:43 +02:00
parent b56e9b4e04
commit da0603089a
14 changed files with 6154 additions and 4164 deletions

View File

@ -108,7 +108,7 @@ func (mux *QueryMux) HandleQueryFunc(pattern string, handler func(RequestWriter,
func (mux *QueryMux) QueryDNS(w RequestWriter, r *Msg) { func (mux *QueryMux) QueryDNS(w RequestWriter, r *Msg) {
h := mux.match(r.Question[0].Name) h := mux.match(r.Question[0].Name)
if h == nil { if h == nil {
panic("dns: no handler found for " + r.Question[0].Name) panic("dns: no handler found for " + r.Question[0].Name)
} }
h.QueryDNS(w, r) h.QueryDNS(w, r)
} }
@ -122,7 +122,7 @@ type Client struct {
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret> TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>
// LocalAddr string // Local address to use // LocalAddr string // Local address to use
} }
// Create a new client, with some defaults. // Create a new client, with some defaults.
@ -144,7 +144,7 @@ func (q *Query) Query() os.Error {
if handler == nil { if handler == nil {
handler = DefaultQueryMux handler = DefaultQueryMux
} }
//forever: //forever:
for { for {
select { select {
case in := <-q.ChannelQuery: case in := <-q.ChannelQuery:
@ -210,7 +210,7 @@ func (c *Client) Exchange(m *Msg, a string) *Msg {
return nil return nil
} }
p = p[:n] p = p[:n]
r := new(Msg) r := new(Msg)
if ok := r.Unpack(p); !ok { if ok := r.Unpack(p); !ok {
return nil return nil
} }

View File

@ -2,7 +2,7 @@ package dns
import ( import (
"testing" "testing"
"time" "time"
) )
func TestClientSync(t *testing.T) { func TestClientSync(t *testing.T) {
@ -80,19 +80,19 @@ func TestClientTsigAXFR(t *testing.T) {
m := new(Msg) m := new(Msg)
m.SetAxfr("miek.nl") m.SetAxfr("miek.nl")
m.SetTsig("axfr", HmacMD5, 300, uint64(time.Seconds())) m.SetTsig("axfr", HmacMD5, 300, uint64(time.Seconds()))
secrets := make(map[string]string) secrets := make(map[string]string)
secrets["axfr"] = "so6ZGir4GPAqINNh9U5c3A==" secrets["axfr"] = "so6ZGir4GPAqINNh9U5c3A=="
c := NewClient() c := NewClient()
c.Net = "tcp" c.Net = "tcp"
c.TsigSecret = secrets c.TsigSecret = secrets
c.XfrReceive(m, "85.223.71.124:53") c.XfrReceive(m, "85.223.71.124:53")
/* /*
if err != nil { if err != nil {
t.Log("%s\n", err.String()) t.Log("%s\n", err.String())
t.Fail() t.Fail()
} }
*/ */
} }

View File

@ -38,7 +38,7 @@ func ClientConfigFromFile(conf string) (*ClientConfig, os.Error) {
b := bufio.NewReader(file) b := bufio.NewReader(file)
c.Servers = make([]string, 3)[0:0] // small, but the standard limit c.Servers = make([]string, 3)[0:0] // small, but the standard limit
c.Search = make([]string, 0) c.Search = make([]string, 0)
c.Port = "53" c.Port = "53"
c.Ndots = 1 c.Ndots = 1
c.Timeout = 5 c.Timeout = 5
c.Attempts = 2 c.Attempts = 2

192
dnssec.go
View File

@ -6,8 +6,8 @@ import (
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/rsa" "crypto/rsa"
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
@ -22,25 +22,25 @@ import (
// DNSSEC encryption algorithm codes. // DNSSEC encryption algorithm codes.
const ( const (
RSAMD5 = 1 RSAMD5 = 1
DH = 2 DH = 2
DSA = 3 DSA = 3
ECC = 4 ECC = 4
RSASHA1 = 5 RSASHA1 = 5
RSASHA256 = 8 RSASHA256 = 8
RSASHA512 = 10 RSASHA512 = 10
ECCGOST = 12 ECCGOST = 12
ECDSAP256SHA256 = 13 ECDSAP256SHA256 = 13
ECDSAP384SHA384 = 14 ECDSAP384SHA384 = 14
) )
// DNSSEC hashing algorithm codes. // DNSSEC hashing algorithm codes.
const ( const (
_ = iota _ = iota
SHA1 // RFC 4034 SHA1 // RFC 4034
SHA256 // RFC 4509 SHA256 // RFC 4509
GOST94 // RFC 5933 GOST94 // RFC 5933
SHA384 // Experimental SHA384 // Experimental
) )
// DNSKEY flag values. // DNSKEY flag values.
@ -151,8 +151,8 @@ func (k *RR_DNSKEY) ToDS(h int) *RR_DS {
s := sha256.New() s := sha256.New()
io.WriteString(s, string(digest)) io.WriteString(s, string(digest))
ds.Digest = hex.EncodeToString(s.Sum()) ds.Digest = hex.EncodeToString(s.Sum())
case SHA384: case SHA384:
s := sha512.New384() s := sha512.New384()
io.WriteString(s, string(digest)) io.WriteString(s, string(digest))
ds.Digest = hex.EncodeToString(s.Sum()) ds.Digest = hex.EncodeToString(s.Sum())
case GOST94: case GOST94:
@ -213,49 +213,49 @@ func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool {
} }
signdata = append(signdata, wire...) signdata = append(signdata, wire...)
var sighash []byte var sighash []byte
var h hash.Hash var h hash.Hash
var ch crypto.Hash // Only need for RSA var ch crypto.Hash // Only need for RSA
switch s.Algorithm { switch s.Algorithm {
case RSAMD5: case RSAMD5:
h = md5.New() h = md5.New()
ch = crypto.MD5 ch = crypto.MD5
case RSASHA1: case RSASHA1:
h = sha1.New() h = sha1.New()
ch = crypto.SHA1 ch = crypto.SHA1
case RSASHA256, ECDSAP256SHA256: case RSASHA256, ECDSAP256SHA256:
h = sha256.New() h = sha256.New()
ch = crypto.SHA256 ch = crypto.SHA256
case ECDSAP384SHA384: case ECDSAP384SHA384:
h = sha512.New384() h = sha512.New384()
case RSASHA512: case RSASHA512:
h = sha512.New() h = sha512.New()
ch = crypto.SHA512 ch = crypto.SHA512
default: default:
return false // Illegal alg return false // Illegal alg
} }
io.WriteString(h, string(signdata)) io.WriteString(h, string(signdata))
sighash = h.Sum() sighash = h.Sum()
switch p := k.(type) { switch p := k.(type) {
case *rsa.PrivateKey: case *rsa.PrivateKey:
signature, err := rsa.SignPKCS1v15(rand.Reader, p, ch, sighash) signature, err := rsa.SignPKCS1v15(rand.Reader, p, ch, sighash)
if err != nil { if err != nil {
return false return false
} }
s.Signature = unpackBase64(signature) s.Signature = unpackBase64(signature)
case *ecdsa.PrivateKey: case *ecdsa.PrivateKey:
r1, s1, err := ecdsa.Sign(rand.Reader, p, sighash) r1, s1, err := ecdsa.Sign(rand.Reader, p, sighash)
if err != nil { if err != nil {
return false return false
} }
signature := r1.Bytes() signature := r1.Bytes()
signature = append(signature, s1.Bytes()...) signature = append(signature, s1.Bytes()...)
s.Signature =unpackBase64(signature) s.Signature = unpackBase64(signature)
default: default:
// Not given the correct key // Not given the correct key
return false return false
} }
return true return true
} }
@ -394,23 +394,23 @@ func (k *RR_DNSKEY) pubKeyRSA() *rsa.PublicKey {
// Extract the Curve public key from the Key record // Extract the Curve public key from the Key record
func (k *RR_DNSKEY) pubKeyCurve() *ecdsa.PublicKey { func (k *RR_DNSKEY) pubKeyCurve() *ecdsa.PublicKey {
keybuf, err := packBase64([]byte(k.PublicKey)) keybuf, err := packBase64([]byte(k.PublicKey))
if err != nil { if err != nil {
return nil return nil
} }
var c *elliptic.Curve var c *elliptic.Curve
switch k.Algorithm { switch k.Algorithm {
case ECDSAP256SHA256: case ECDSAP256SHA256:
c = elliptic.P256() c = elliptic.P256()
case ECDSAP384SHA384: case ECDSAP384SHA384:
c = elliptic.P384() c = elliptic.P384()
} }
x, y := c.Unmarshal(keybuf) x, y := c.Unmarshal(keybuf)
pubkey := new(ecdsa.PublicKey) pubkey := new(ecdsa.PublicKey)
pubkey.X = x pubkey.X = x
pubkey.Y = y pubkey.Y = y
pubkey.Curve = c pubkey.Curve = c
return pubkey return pubkey
} }
// Set the public key (the value E and N) // Set the public key (the value E and N)
@ -426,12 +426,12 @@ func (k *RR_DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool {
// Set the public key for Elliptic Curves // Set the public key for Elliptic Curves
func (k *RR_DNSKEY) setPublicKeyCurve(_X, _Y *big.Int) bool { func (k *RR_DNSKEY) setPublicKeyCurve(_X, _Y *big.Int) bool {
if _X == nil || _Y == nil { if _X == nil || _Y == nil {
return false return false
} }
buf := curveToBuf(_X, _Y) buf := curveToBuf(_X, _Y)
k.PublicKey = unpackBase64(buf) k.PublicKey = unpackBase64(buf)
return true return true
} }
// Set the public key (the values E and N) for RSA // Set the public key (the values E and N) for RSA
@ -455,9 +455,9 @@ func exponentToBuf(_E int) []byte {
// Set the public key for X and Y for Curve // Set the public key for X and Y for Curve
// Experimental // Experimental
func curveToBuf(_X, _Y *big.Int) []byte { func curveToBuf(_X, _Y *big.Int) []byte {
buf := _X.Bytes() buf := _X.Bytes()
buf = append(buf, _Y.Bytes()...) buf = append(buf, _Y.Bytes()...)
return buf return buf
} }
// return a saw signature data // return a saw signature data
@ -500,13 +500,13 @@ func rawSignatureData(rrset RRset, s *RR_RRSIG) (buf []byte) {
// Map for algorithm names. // Map for algorithm names.
var alg_str = map[uint8]string{ var alg_str = map[uint8]string{
RSAMD5: "RSAMD5", RSAMD5: "RSAMD5",
DH: "DH", DH: "DH",
DSA: "DSA", DSA: "DSA",
RSASHA1: "RSASHA1", RSASHA1: "RSASHA1",
RSASHA256: "RSASHA256", RSASHA256: "RSASHA256",
RSASHA512: "RSASHA512", RSASHA512: "RSASHA512",
ECCGOST: "ECC-GOST", ECCGOST: "ECC-GOST",
ECDSAP256SHA256: "ECDSAP256SHA256", ECDSAP256SHA256: "ECDSAP256SHA256",
ECDSAP384SHA384: "ECDSAP384SHA384", ECDSAP384SHA384: "ECDSAP384SHA384",
} }

View File

@ -119,10 +119,10 @@ func TestSignVerify(t *testing.T) {
} }
func TestKeyGen(t *testing.T) { func TestKeyGen(t *testing.T) {
algs := []uint8{RSASHA256, ECDSAP256SHA256} algs := []uint8{RSASHA256, ECDSAP256SHA256}
bits := []int{1024, 256} bits := []int{1024, 256}
i := 0 i := 0
key := new(RR_DNSKEY) key := new(RR_DNSKEY)
key.Hdr.Name = "keygen.miek.nl." key.Hdr.Name = "keygen.miek.nl."
key.Hdr.Rrtype = TypeDNSKEY key.Hdr.Rrtype = TypeDNSKEY
@ -130,13 +130,13 @@ func TestKeyGen(t *testing.T) {
key.Hdr.Ttl = 3600 key.Hdr.Ttl = 3600
key.Flags = 256 key.Flags = 256
key.Protocol = 3 key.Protocol = 3
for _, v := range algs { for _, v := range algs {
key.Algorithm = v key.Algorithm = v
key.Generate(bits[i]) key.Generate(bits[i])
i++ i++
t.Logf("%s\n", key) t.Logf("%s\n", key)
} }
//Really hard to figure out what to check here... Parse it back to a proper key? //Really hard to figure out what to check here... Parse it back to a proper key?
} }
/* /*

200
keygen.go
View File

@ -2,12 +2,12 @@ package dns
import ( import (
"os" "os"
"io" "io"
"big" "big"
"strconv" "strconv"
"crypto/rsa" "crypto/rsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
) )
@ -31,14 +31,14 @@ func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) {
if bits < 1024 || bits > 4096 { if bits < 1024 || bits > 4096 {
return nil, ErrKeySize return nil, ErrKeySize
} }
case ECDSAP256SHA256: case ECDSAP256SHA256:
if bits != 256 { if bits != 256 {
return nil, ErrKeySize return nil, ErrKeySize
} }
case ECDSAP384SHA384: case ECDSAP384SHA384:
if bits != 384 { if bits != 384 {
return nil, ErrKeySize return nil, ErrKeySize
} }
} }
switch r.Algorithm { switch r.Algorithm {
@ -47,22 +47,22 @@ func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
r.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N) r.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
return priv, nil
case ECDSAP256SHA256, ECDSAP384SHA384:
var c *elliptic.Curve
switch r.Algorithm {
case ECDSAP256SHA256:
c = elliptic.P256()
case ECDSAP384SHA384:
c = elliptic.P384()
}
priv, err := ecdsa.GenerateKey(c, rand.Reader)
if err != nil {
return nil, err
}
r.setPublicKeyCurve(priv.PublicKey.X, priv.PublicKey.Y)
return priv, nil return priv, nil
case ECDSAP256SHA256, ECDSAP384SHA384:
var c *elliptic.Curve
switch r.Algorithm {
case ECDSAP256SHA256:
c = elliptic.P256()
case ECDSAP384SHA384:
c = elliptic.P384()
}
priv, err := ecdsa.GenerateKey(c, rand.Reader)
if err != nil {
return nil, err
}
r.setPublicKeyCurve(priv.PublicKey.X, priv.PublicKey.Y)
return priv, nil
default: default:
return nil, ErrAlg return nil, ErrAlg
} }
@ -106,81 +106,81 @@ func (r *RR_DNSKEY) PrivateKeyString(p PrivateKey) (s string) {
"Exponent1: " + exponent1 + "\n" + "Exponent1: " + exponent1 + "\n" +
"Exponent2: " + exponent2 + "\n" + "Exponent2: " + exponent2 + "\n" +
"Coefficient: " + coefficient + "\n" "Coefficient: " + coefficient + "\n"
case *ecdsa.PrivateKey: case *ecdsa.PrivateKey:
// //
} }
return return
} }
func (k *RR_DNSKEY) Read(q io.Reader) os.Error { func (k *RR_DNSKEY) Read(q io.Reader) os.Error {
p := NewParser(q) p := NewParser(q)
r := p.RR() r := p.RR()
if r == nil { if r == nil {
return nil return nil
} }
if _, ok := r.(*RR_DNSKEY); !ok { if _, ok := r.(*RR_DNSKEY); !ok {
panic("did not read a DNSKEY") panic("did not read a DNSKEY")
} }
k.Hdr = r.(*RR_DNSKEY).Hdr k.Hdr = r.(*RR_DNSKEY).Hdr
k.Flags = r.(*RR_DNSKEY).Flags k.Flags = r.(*RR_DNSKEY).Flags
k.Protocol = r.(*RR_DNSKEY).Protocol k.Protocol = r.(*RR_DNSKEY).Protocol
k.Algorithm = r.(*RR_DNSKEY).Algorithm k.Algorithm = r.(*RR_DNSKEY).Algorithm
k.PublicKey = r.(*RR_DNSKEY).PublicKey k.PublicKey = r.(*RR_DNSKEY).PublicKey
return nil return nil
} }
func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader) (PrivateKey, os.Error) { func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader) (PrivateKey, os.Error) {
p := NewParser(q) p := NewParser(q)
kv, _ := p.PrivateKey() kv, _ := p.PrivateKey()
if _, ok := kv["private-key-format"]; !ok { if _, ok := kv["private-key-format"]; !ok {
return nil, ErrPrivKey return nil, ErrPrivKey
} }
if kv["private-key-format"] != "v1.2" && kv["private-key-format"] != "v1.3" { if kv["private-key-format"] != "v1.2" && kv["private-key-format"] != "v1.3" {
return nil, ErrPrivKey return nil, ErrPrivKey
} }
switch kv["algorithm"] { switch kv["algorithm"] {
case "RSAMD5", "RSASHA1", "RSASHA256", "RSASHA512": case "RSAMD5", "RSASHA1", "RSASHA256", "RSASHA512":
return k.readPrivateKeyRSA(kv) return k.readPrivateKeyRSA(kv)
case "ECDSAP256SHA256", "ECDSAP384SHA384": case "ECDSAP256SHA256", "ECDSAP384SHA384":
return k.readPrivateKeyECDSA(kv) return k.readPrivateKeyECDSA(kv)
} }
return nil, ErrPrivKey return nil, ErrPrivKey
} }
// Read a private key (file) string and create a public key. Return the private key. // Read a private key (file) string and create a public key. Return the private key.
func (k *RR_DNSKEY) readPrivateKeyRSA(kv map[string]string) (PrivateKey, os.Error) { func (k *RR_DNSKEY) readPrivateKeyRSA(kv map[string]string) (PrivateKey, os.Error) {
p := new(rsa.PrivateKey) p := new(rsa.PrivateKey)
p.Primes = []*big.Int{nil,nil} p.Primes = []*big.Int{nil, nil}
for k, v := range kv { for k, v := range kv {
switch k { switch k {
case "modulus", "publicexponent", "privateexponent", "prime1", "prime2": case "modulus", "publicexponent", "privateexponent", "prime1", "prime2":
v1, err := packBase64([]byte(v)) v1, err := packBase64([]byte(v))
if err != nil { if err != nil {
return nil, err return nil, err
} }
switch k { switch k {
case "modulus": case "modulus":
p.PublicKey.N = big.NewInt(0) p.PublicKey.N = big.NewInt(0)
p.PublicKey.N.SetBytes(v1) p.PublicKey.N.SetBytes(v1)
case "publicexponent": case "publicexponent":
i := big.NewInt(0) i := big.NewInt(0)
i.SetBytes(v1) i.SetBytes(v1)
p.PublicKey.E = int(i.Int64()) // int64 should be large enough p.PublicKey.E = int(i.Int64()) // int64 should be large enough
case "privateexponent": case "privateexponent":
p.D = big.NewInt(0) p.D = big.NewInt(0)
p.D.SetBytes(v1) p.D.SetBytes(v1)
case "prime1": case "prime1":
p.Primes[0] = big.NewInt(0) p.Primes[0] = big.NewInt(0)
p.Primes[0].SetBytes(v1) p.Primes[0].SetBytes(v1)
case "prime2": case "prime2":
p.Primes[1] = big.NewInt(0) p.Primes[1] = big.NewInt(0)
p.Primes[1].SetBytes(v1) p.Primes[1].SetBytes(v1)
} }
case "exponent1", "exponent2", "coefficient": case "exponent1", "exponent2", "coefficient":
// not used in Go (yet) // not used in Go (yet)
case "created", "publish", "activate": case "created", "publish", "activate":
// not used in Go (yet) // not used in Go (yet)
} }
} }
return p, nil return p, nil
} }
@ -188,18 +188,18 @@ func (k *RR_DNSKEY) readPrivateKeyRSA(kv map[string]string) (PrivateKey, os.Erro
func (k *RR_DNSKEY) readPrivateKeyECDSA(kv map[string]string) (PrivateKey, os.Error) { func (k *RR_DNSKEY) readPrivateKeyECDSA(kv map[string]string) (PrivateKey, os.Error) {
p := new(ecdsa.PrivateKey) p := new(ecdsa.PrivateKey)
p.D = big.NewInt(0) p.D = big.NewInt(0)
// Need to check if we have everything // Need to check if we have everything
for k, v := range kv { for k, v := range kv {
switch k { switch k {
case "privatekey:": case "privatekey:":
v1, err := packBase64([]byte(v)) v1, err := packBase64([]byte(v))
if err != nil { if err != nil {
return nil, err return nil, err
} }
p.D.SetBytes(v1) p.D.SetBytes(v1)
case "created:", "publish:", "activate:": case "created:", "publish:", "activate:":
/* not used in Go (yet) */ /* not used in Go (yet) */
} }
} }
return p, nil return p, nil
} }

3963
kparse.go

File diff suppressed because it is too large Load Diff

10
msg.go
View File

@ -127,7 +127,7 @@ var Class_str = map[uint16]string{
ClassCSNET: "CS", ClassCSNET: "CS",
ClassCHAOS: "CH", ClassCHAOS: "CH",
ClassHESIOD: "HS", ClassHESIOD: "HS",
ClassNONE: "NONE", ClassNONE: "NONE",
ClassANY: "ANY", ClassANY: "ANY",
} }
@ -363,8 +363,8 @@ func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool)
i := fv.Uint() i := fv.Uint()
switch fv.Type().Kind() { switch fv.Type().Kind() {
default: default:
//fmt.Fprintf(os.Stderr, "dns: unknown packing type %v\n", f.Type) //fmt.Fprintf(os.Stderr, "dns: unknown packing type %v\n", f.Type)
return len(msg), false return len(msg), false
case reflect.Uint8: case reflect.Uint8:
if off+1 > len(msg) { if off+1 > len(msg) {
//fmt.Fprintf(os.Stderr, "dns: overflow packing uint8") //fmt.Fprintf(os.Stderr, "dns: overflow packing uint8")
@ -597,8 +597,8 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
switch fv.Type().Kind() { switch fv.Type().Kind() {
default: default:
//fmt.Fprintf(os.Stderr, "dns: unknown packing type %v\n", f.Type) //fmt.Fprintf(os.Stderr, "dns: unknown packing type %v\n", f.Type)
return len(msg), false return len(msg), false
case reflect.Uint8: case reflect.Uint8:
if off+1 > len(msg) { if off+1 > len(msg) {

View File

@ -1,10 +1,10 @@
package dns package dns
import ( import (
"os" "os"
"time" "time"
"bufio" "bufio"
"strings" "strings"
"testing" "testing"
"crypto/rsa" "crypto/rsa"
) )
@ -27,21 +27,21 @@ Publish: 20110302104537
Activate: 20110302104537` Activate: 20110302104537`
k := new(RR_DNSKEY) k := new(RR_DNSKEY)
k.Read(strings.NewReader(pub)) k.Read(strings.NewReader(pub))
p, err := k.ReadPrivateKey(strings.NewReader(priv)) p, err := k.ReadPrivateKey(strings.NewReader(priv))
if err != nil { if err != nil {
t.Logf("%v\n", err) t.Logf("%v\n", err)
t.Fail() t.Fail()
} }
switch priv := p.(type) { switch priv := p.(type) {
case *rsa.PrivateKey: case *rsa.PrivateKey:
if 65537 != priv.PublicKey.E { if 65537 != priv.PublicKey.E {
t.Log("Exponenent should be 65537") t.Log("Exponenent should be 65537")
t.Fail() t.Fail()
} }
default: default:
t.Logf("We should have read an RSA key: %v", priv) t.Logf("We should have read an RSA key: %v", priv)
t.Fail() t.Fail()
} }
if k.KeyTag() != 37350 { if k.KeyTag() != 37350 {
t.Logf("%d %v\n", k.KeyTag(), k) t.Logf("%d %v\n", k.KeyTag(), k)
@ -68,113 +68,111 @@ Activate: 20110302104537`
sig.Algorithm = k.Algorithm sig.Algorithm = k.Algorithm
sig.Sign(p, []RR{soa}) sig.Sign(p, []RR{soa})
if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" { if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" {
t.Log("Signature is not correct") t.Log("Signature is not correct")
t.Logf("%v\n", sig) t.Logf("%v\n", sig)
t.Fail() t.Fail()
} }
} }
func TestDotInName(t *testing.T) { func TestDotInName(t *testing.T) {
buf := make([]byte, 20) buf := make([]byte, 20)
packDomainName("aa\\.bb.nl.", buf, 0) packDomainName("aa\\.bb.nl.", buf, 0)
// index 3 must be a real dot // index 3 must be a real dot
if buf[3] != '.' { if buf[3] != '.' {
t.Log("Dot should be a real dot") t.Log("Dot should be a real dot")
t.Fail() t.Fail()
} }
if buf[6] != 2 { if buf[6] != 2 {
t.Log("This must have the value 2") t.Log("This must have the value 2")
t.Fail() t.Fail()
} }
dom, _, _ := unpackDomainName(buf, 0) dom, _, _ := unpackDomainName(buf, 0)
// printing it should yield the backspace again // printing it should yield the backspace again
if dom != "aa\\.bb.nl." { if dom != "aa\\.bb.nl." {
t.Log("Dot should have been escaped: " + dom) t.Log("Dot should have been escaped: " + dom)
t.Fail() t.Fail()
} }
} }
// Make this a decend test case. For now, good enough // Make this a decend test case. For now, good enough
// New style (Ragel) parsing // New style (Ragel) parsing
func TestParse(t *testing.T) { func TestParse(t *testing.T) {
tests := map[string]string{ tests := map[string]string{
"miek.nl. 3600 IN A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1", "miek.nl. 3600 IN A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1",
"miek.nl. 3600 IN MX 10 elektron.atoom.net.": "miek.nl.\t3600\tIN\tMX\t10 elektron.atoom.net.", "miek.nl. 3600 IN MX 10 elektron.atoom.net.": "miek.nl.\t3600\tIN\tMX\t10 elektron.atoom.net.",
"miek.nl. IN 3600 A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1", "miek.nl. IN 3600 A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1",
"miek.nl. A 127.0.0.1": "miek.nl.\t0\tCLASS0\tA\t127.0.0.1", "miek.nl. A 127.0.0.1": "miek.nl.\t0\tCLASS0\tA\t127.0.0.1",
"miek.nl. IN AAAA ::1": "miek.nl.\t0\tIN\tAAAA\t::1", "miek.nl. IN AAAA ::1": "miek.nl.\t0\tIN\tAAAA\t::1",
"miek.nl. IN A 127.0.0.1": "miek.nl.\t0\tIN\tA\t127.0.0.1", "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. IN DNSKEY 256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ": "miek.nl.\t0\tIN\tDNSKEY\t256 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",
"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", for test, result := range tests {
} p := NewParser(strings.NewReader(test))
for test, result := range tests { z, err := p.Zone()
p := NewParser(strings.NewReader(test)) if err != nil || z == nil {
z, err := p.Zone() t.Logf("Error of nil r %v %s\n", err, test)
if err != nil || z == nil{ t.Fail()
t.Logf("Error of nil r %v %s\n", err, test) }
t.Fail() r := z.Pop().(RR)
} if r.String() != result {
r := z.Pop().(RR) t.Logf("\"%s\" should be equal to\n\"%s\"\n", r, result)
if r.String() != result { t.Fail()
t.Logf("\"%s\" should be equal to\n\"%s\"\n", r, result) }
t.Fail() }
}
}
} }
func TestSetString(t *testing.T) { func TestSetString(t *testing.T) {
a := NewRR("miek.nl. IN A 127.0.0.1") a := NewRR("miek.nl. IN A 127.0.0.1")
if a.String() != "miek.nl.\t0\tIN\tA\t127.0.0.1" { if a.String() != "miek.nl.\t0\tIN\tA\t127.0.0.1" {
t.Log(a.String(), "!= miek.nl. IN A 127.0.0.1") t.Log(a.String(), "!= miek.nl. IN A 127.0.0.1")
t.Fail() t.Fail()
} }
b := NewRR("miek.nl. IN AAAA ::1") b := NewRR("miek.nl. IN AAAA ::1")
if b.String() != "miek.nl.\t0\tIN\tAAAA\t::1" { if b.String() != "miek.nl.\t0\tIN\tAAAA\t::1" {
t.Log(b.String(), "!= miek.nl. IN AAAA ::1") t.Log(b.String(), "!= miek.nl. IN AAAA ::1")
t.Fail() t.Fail()
} }
c := NewRR("miek.nl. IN MX 10 miek.nl.") c := NewRR("miek.nl. IN MX 10 miek.nl.")
if c.String() != "miek.nl.\t0\tIN\tMX\t10 miek.nl." { if c.String() != "miek.nl.\t0\tIN\tMX\t10 miek.nl." {
t.Log(c.String(), "!= miek.nl. IN MX 10 miek.nl.") t.Log(c.String(), "!= miek.nl. IN MX 10 miek.nl.")
t.Fail() t.Fail()
} }
d := NewRR("miek.nl. IN NS ns1.miek.nl") d := NewRR("miek.nl. IN NS ns1.miek.nl")
if d.String() != "miek.nl.\t0\tIN\tNS\tns1.miek.nl" { if d.String() != "miek.nl.\t0\tIN\tNS\tns1.miek.nl" {
t.Log(d.String(), "!= miek.nl. IN NS ns1.miek.nl") t.Log(d.String(), "!= miek.nl. IN NS ns1.miek.nl")
t.Fail() t.Fail()
} }
} }
func BenchmarkZoneParsing(b *testing.B) { func BenchmarkZoneParsing(b *testing.B) {
file, err := os.Open("miek.nl") file, err := os.Open("miek.nl")
defer file.Close() defer file.Close()
if err != nil { if err != nil {
return return
} }
p := NewParser(bufio.NewReader(file)) p := NewParser(bufio.NewReader(file))
// Don't care about errors (there shouldn't be any) // Don't care about errors (there shouldn't be any)
p.Zone() p.Zone()
} }
func TestZoneParsing(t *testing.T) { func TestZoneParsing(t *testing.T) {
file, err := os.Open("miek.nl") file, err := os.Open("miek.nl")
defer file.Close() defer file.Close()
if err != nil { if err != nil {
return return
} }
p := NewParser(bufio.NewReader(file)) p := NewParser(bufio.NewReader(file))
// Don't care about errors (there shouldn't be any) // Don't care about errors (there shouldn't be any)
start := time.Nanoseconds() start := time.Nanoseconds()
z, err := p.Zone() z, err := p.Zone()
if err != nil { if err != nil {
t.Logf("error %v\n", err.String()) t.Logf("error %v\n", err.String())
t.Fail() t.Fail()
} }
delta := time.Nanoseconds() - start delta := time.Nanoseconds() - start
t.Logf("%d RRs parsed in %.2f s (%.2f RR/s)", z.Len()-1, float32(delta)/1e9, float32(z.Len()-1)/(float32(delta)/1e9)) t.Logf("%d RRs parsed in %.2f s (%.2f RR/s)", z.Len()-1, float32(delta)/1e9, float32(z.Len()-1)/(float32(delta)/1e9))
} }

View File

@ -23,7 +23,7 @@ type Handler interface {
type ResponseWriter interface { type ResponseWriter interface {
// RemoteAddr returns the net.Addr of the client that sent the current request. // RemoteAddr returns the net.Addr of the client that sent the current request.
RemoteAddr() net.Addr RemoteAddr() net.Addr
// Write a reply back to the client. // Write a reply back to the client.
Write([]byte) (int, os.Error) Write([]byte) (int, os.Error)
} }
@ -164,12 +164,12 @@ func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
// A Server defines parameters for running an DNS server. // A Server defines parameters for running an DNS server.
// Note how much it starts to look like 'Client struct' // Note how much it starts to look like 'Client struct'
type Server struct { type Server struct {
Addr string // address to listen on, ":dns" if empty Addr string // address to listen on, ":dns" if empty
Net string // if "tcp" it will invoke a TCP listener, otherwise an UDP one Net string // if "tcp" it will invoke a TCP listener, otherwise an UDP one
Handler Handler // handler to invoke, dns.DefaultServeMux if nil Handler Handler // handler to invoke, dns.DefaultServeMux if nil
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret> TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>
} }
// ... // ...
@ -333,7 +333,7 @@ func (w *response) Write(data []byte) (n int, err os.Error) {
case w.conn._UDP != nil: case w.conn._UDP != nil:
n, err = w.conn._UDP.WriteTo(data, w.conn.remoteAddr) n, err = w.conn._UDP.WriteTo(data, w.conn.remoteAddr)
if err != nil { if err != nil {
println(err.String()) println(err.String())
return 0, err return 0, err
} }
case w.conn._TCP != nil: case w.conn._TCP != nil:

View File

@ -28,19 +28,19 @@ func TestServing(t *testing.T) {
} }
func BenchmarkServing(b *testing.B) { func BenchmarkServing(b *testing.B) {
b.StopTimer() b.StopTimer()
// Again start a server // Again start a server
HandleFunc("miek.nl.", HelloServer) HandleFunc("miek.nl.", HelloServer)
go func() { go func() {
ListenAndServe("127.0.0.1:8053", "udp", nil) ListenAndServe("127.0.0.1:8053", "udp", nil)
}() }()
c := NewClient() c := NewClient()
m := new(Msg) m := new(Msg)
m.SetQuestion("miek.nl", TypeSOA) m.SetQuestion("miek.nl", TypeSOA)
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
c.Exchange(m, "127.0.0.1:8053") c.Exchange(m, "127.0.0.1:8053")
} }
} }

View File

@ -149,11 +149,11 @@ func (q *Question) String() string {
// NewRR returns the last RR contained in s. // NewRR returns the last RR contained in s.
func NewRR(s string) RR { func NewRR(s string) RR {
p := NewParser(strings.NewReader(s)) p := NewParser(strings.NewReader(s))
x := p.RR() x := p.RR()
if x == nil { if x == nil {
return nil return nil
} }
return x return x
} }
type RR_CNAME struct { type RR_CNAME struct {

12
zone.go
View File

@ -5,30 +5,30 @@
package dns package dns
import ( import (
"container/vector" "container/vector"
) )
// Zone implements the concept of RFC 1035 master zone files. // Zone implements the concept of RFC 1035 master zone files.
type Zone struct { type Zone struct {
v vector.Vector v vector.Vector
} }
// Add a new RR to the zone. // Add a new RR to the zone.
func (z *Zone) Push(r RR) { func (z *Zone) Push(r RR) {
z.v.Push(r) z.v.Push(r)
} }
// Remove a RR from the zone. // Remove a RR from the zone.
func (z *Zone) Pop() RR { func (z *Zone) Pop() RR {
return z.v.Pop().(RR) return z.v.Pop().(RR)
} }
// Return the RR at index i of zone. // Return the RR at index i of zone.
func (z *Zone) At(i int) RR { func (z *Zone) At(i int) RR {
return z.v.At(i).(RR) return z.v.At(i).(RR)
} }
// The number of RRs in zone. // The number of RRs in zone.
func (z *Zone) Len() int { func (z *Zone) Len() int {
return z.v.Len() return z.v.Len()
} }

5645
zparse.go

File diff suppressed because it is too large Load Diff