More TSIG changes. Curious if they amount to something

This commit is contained in:
Miek Gieben 2011-03-15 16:18:13 +01:00
parent 566b5f7d1a
commit 0059556516
3 changed files with 147 additions and 83 deletions

13
msg.go
View File

@ -16,7 +16,7 @@ package dns
import ( import (
"os" "os"
// "fmt" // "fmt"
"reflect" "reflect"
"net" "net"
"rand" "rand"
@ -770,6 +770,10 @@ func unpackBase64(b []byte) string {
} }
// Helper function for packing, mostly used in dnssec.go // Helper function for packing, mostly used in dnssec.go
func packUint16(i uint16) (byte, byte) {
return byte(i >> 8), byte(i)
}
func packBase64(s []byte) ([]byte, os.Error) { func packBase64(s []byte) ([]byte, os.Error) {
b64len := base64.StdEncoding.DecodedLen(len(s)) b64len := base64.StdEncoding.DecodedLen(len(s))
buf := make([]byte, b64len) buf := make([]byte, b64len)
@ -1022,27 +1026,34 @@ func (dns *Msg) String() string {
if len(dns.Question) > 0 { if len(dns.Question) > 0 {
s += "\n;; QUESTION SECTION:\n" s += "\n;; QUESTION SECTION:\n"
for i := 0; i < len(dns.Question); i++ { for i := 0; i < len(dns.Question); i++ {
// Need check if it exists? TODO(mg)
s += dns.Question[i].String() + "\n" s += dns.Question[i].String() + "\n"
} }
} }
if len(dns.Answer) > 0 { if len(dns.Answer) > 0 {
s += "\n;; ANSWER SECTION:\n" s += "\n;; ANSWER SECTION:\n"
for i := 0; i < len(dns.Answer); i++ { for i := 0; i < len(dns.Answer); i++ {
if dns.Answer[i] != nil {
s += dns.Answer[i].String() + "\n" s += dns.Answer[i].String() + "\n"
} }
} }
}
if len(dns.Ns) > 0 { if len(dns.Ns) > 0 {
s += "\n;; AUTHORITY SECTION:\n" s += "\n;; AUTHORITY SECTION:\n"
for i := 0; i < len(dns.Ns); i++ { for i := 0; i < len(dns.Ns); i++ {
if dns.Ns[i] != nil {
s += dns.Ns[i].String() + "\n" s += dns.Ns[i].String() + "\n"
} }
} }
}
if len(dns.Extra) > 0 { if len(dns.Extra) > 0 {
s += "\n;; ADDITIONAL SECTION:\n" s += "\n;; ADDITIONAL SECTION:\n"
for i := 0; i < len(dns.Extra); i++ { for i := 0; i < len(dns.Extra); i++ {
if dns.Extra[i] != nil {
s += dns.Extra[i].String() + "\n" s += dns.Extra[i].String() + "\n"
} }
} }
}
return s return s
} }

View File

@ -45,9 +45,10 @@ func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) {
// Check if there is a TSIG appended, if so, check it // Check if there is a TSIG appended, if so, check it
var ( var (
c net.Conn c net.Conn
in *Msg
port string port string
inb []byte
) )
in := new(Msg)
if len(res.Servers) == 0 { if len(res.Servers) == 0 {
return nil, &Error{Error: "No servers defined"} return nil, &Error{Error: "No servers defined"}
} }
@ -81,9 +82,12 @@ func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) {
continue continue
} }
if res.Tcp { if res.Tcp {
in, err = exchangeTCP(c, sending, res, true) inb, err = exchangeTCP(c, sending, res, true)
in.Unpack(inb)
} else { } else {
in, err = exchangeUDP(c, sending, res, true) inb, err = exchangeUDP(c, sending, res, true)
in.Unpack(inb)
} }
res.Rtt[server] = time.Nanoseconds() - t res.Rtt[server] = time.Nanoseconds() - t
@ -114,9 +118,12 @@ type Xfr struct {
// Channel m is closed when the IXFR ends. // Channel m is closed when the IXFR ends.
func (res *Resolver) Ixfr(q *Msg, m chan Xfr) { func (res *Resolver) Ixfr(q *Msg, m chan Xfr) {
// TSIG // TSIG
var port string var (
var in *Msg port string
var x Xfr x Xfr
inb []byte
)
in := new(Msg)
if res.Port == "" { if res.Port == "" {
port = "53" port = "53"
} else { } else {
@ -149,9 +156,11 @@ Server:
defer c.Close() defer c.Close()
for { for {
if first { if first {
in, err = exchangeTCP(c, sending, res, true) inb, err = exchangeTCP(c, sending, res, true)
in.Unpack(inb)
} else { } else {
in, err = exchangeTCP(c, sending, res, false) inb, err = exchangeTCP(c, sending, res, false)
in.Unpack(inb)
} }
if err != nil { if err != nil {
@ -220,8 +229,11 @@ Server:
// the zone as-is. Xfr.Add is always true. // the zone as-is. Xfr.Add is always true.
// The channel is closed to signal the end of the AXFR. // The channel is closed to signal the end of the AXFR.
func (res *Resolver) AxfrTSIG(q *Msg, m chan Xfr, secret string) { func (res *Resolver) AxfrTSIG(q *Msg, m chan Xfr, secret string) {
var port string var (
var in *Msg port string
inb []byte
)
in := new(Msg)
if res.Port == "" { if res.Port == "" {
port = "53" port = "53"
} else { } else {
@ -263,9 +275,17 @@ Server:
defer c.Close() // TODO(mg): if not open? defer c.Close() // TODO(mg): if not open?
for { for {
if first { if first {
in, err = exchangeTCP(c, sending, res, true) inb, err = exchangeTCP(c, sending, res, true)
stripTSIG(inb)
/*
pt2 := new(Msg)
pt2.Unpack(t2)
//println("P", pt2.String())
*/
in.Unpack(inb)
} else { } else {
in, err = exchangeTCP(c, sending, res, false) inb, err = exchangeTCP(c, sending, res, false)
in.Unpack(inb)
} }
if err != nil { if err != nil {
@ -282,7 +302,7 @@ Server:
t := in.Extra[len(in.Extra)-1] t := in.Extra[len(in.Extra)-1]
switch t.(type) { switch t.(type) {
case *RR_TSIG: case *RR_TSIG:
if t.(*RR_TSIG).Verify(in, secret, reqmac) { if t.(*RR_TSIG).Verify(inb, secret, reqmac) {
println("Validates") println("Validates")
} else { } else {
println("DOES NOT validate") println("DOES NOT validate")
@ -322,8 +342,11 @@ Server:
// the zone as-is. Xfr.Add is always true. // the zone as-is. Xfr.Add is always true.
// The channel is closed to signal the end of the AXFR. // The channel is closed to signal the end of the AXFR.
func (res *Resolver) Axfr(q *Msg, m chan Xfr) { func (res *Resolver) Axfr(q *Msg, m chan Xfr) {
var port string var (
var in *Msg port string
inb []byte
)
in := new(Msg)
if res.Port == "" { if res.Port == "" {
port = "53" port = "53"
} else { } else {
@ -343,17 +366,6 @@ func (res *Resolver) Axfr(q *Msg, m chan Xfr) {
return return
} }
/*
// Need the secret!
var tsig *RR_TSIG
// Check if there is a TSIG added
if len(q.Extra) > 0 {
lastrr := q.Extra[len(q.Extra)-1]
if lastrr.Header().Rrtype == TypeTSIG {
tsig = lastrr.(*RR_TSIG)
}
}
*/
Server: Server:
for i := 0; i < len(res.Servers); i++ { for i := 0; i < len(res.Servers); i++ {
server := res.Servers[i] + ":" + port server := res.Servers[i] + ":" + port
@ -365,9 +377,11 @@ Server:
defer c.Close() // TODO(mg): if not open? defer c.Close() // TODO(mg): if not open?
for { for {
if first { if first {
in, err = exchangeTCP(c, sending, res, true) inb, err = exchangeTCP(c, sending, res, true)
in.Unpack(inb)
} else { } else {
in, err = exchangeTCP(c, sending, res, false) inb, err = exchangeTCP(c, sending, res, false)
in.Unpack(inb)
} }
if err != nil { if err != nil {
@ -408,7 +422,7 @@ Server:
// Send a request on the connection and hope for a reply. // Send a request on the connection and hope for a reply.
// Up to res.Attempts attempts. If send is false, nothing // Up to res.Attempts attempts. If send is false, nothing
// is send. // is send.
func exchangeUDP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error) { func exchangeUDP(c net.Conn, m []byte, r *Resolver, send bool) ([]byte, os.Error) {
var timeout int64 var timeout int64
var attempts int var attempts int
if r.Mangle != nil { if r.Mangle != nil {
@ -443,18 +457,13 @@ func exchangeUDP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error)
} }
return nil, err return nil, err
} }
return buf, nil
in := new(Msg)
if !in.Unpack(buf) {
continue
}
return in, nil
} }
return nil, &Error{Error: servErr} return nil, &Error{Error: servErr}
} }
// Up to res.Attempts attempts. // Up to res.Attempts attempts.
func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error) { func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) ([]byte, os.Error) {
var timeout int64 var timeout int64
var attempts int var attempts int
if r.Mangle != nil { if r.Mangle != nil {
@ -484,7 +493,7 @@ func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error)
} }
c.SetReadTimeout(timeout * 1e9) // nanoseconds c.SetReadTimeout(timeout * 1e9) // nanoseconds
// The server replies with two bytes length // The server replies with two bytes length.
buf, err := recvTCP(c) buf, err := recvTCP(c)
if err != nil { if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() { if e, ok := err.(net.Error); ok && e.Timeout() {
@ -492,11 +501,7 @@ func exchangeTCP(c net.Conn, m []byte, r *Resolver, send bool) (*Msg, os.Error)
} }
return nil, err return nil, err
} }
in := new(Msg) return buf, nil
if !in.Unpack(buf) {
continue
}
return in, nil
} }
return nil, &Error{Error: servErr} return nil, &Error{Error: servErr}
} }
@ -510,7 +515,7 @@ func sendUDP(m []byte, c net.Conn) os.Error {
} }
func recvUDP(c net.Conn) ([]byte, os.Error) { func recvUDP(c net.Conn) ([]byte, os.Error) {
m := make([]byte, DefaultMsgSize) // More than enough??? m := make([]byte, DefaultMsgSize)
n, err := c.Read(m) n, err := c.Read(m)
if err != nil { if err != nil {
return nil, err return nil, err
@ -537,8 +542,7 @@ func sendTCP(m []byte, c net.Conn) os.Error {
} }
func recvTCP(c net.Conn) ([]byte, os.Error) { func recvTCP(c net.Conn) ([]byte, os.Error) {
l := make([]byte, 2) // receiver length l := make([]byte, 2) // The server replies with two bytes length.
// The server replies with two bytes length
_, err := c.Read(l) _, err := c.Read(l)
if err != nil { if err != nil {
return nil, err return nil, err

55
tsig.go
View File

@ -107,7 +107,7 @@ func (t *RR_TSIG) Generate(m *Msg, secret string) bool {
// the TSIG record still attached (as the last rr in the Additional // the TSIG record still attached (as the last rr in the Additional
// section). Return true on success. // section). Return true on success.
// The secret is a base64 encoded string with the secret. // The secret is a base64 encoded string with the secret.
func (t *RR_TSIG) Verify(m *Msg, secret, reqmac string) bool { func (t *RR_TSIG) Verify(m []byte, secret, reqmac string) bool {
rawsecret, err := packBase64([]byte(secret)) rawsecret, err := packBase64([]byte(secret))
if err != nil { if err != nil {
return false return false
@ -121,9 +121,8 @@ func (t *RR_TSIG) Verify(m *Msg, secret, reqmac string) bool {
if t.Header().Rrtype != TypeTSIG { if t.Header().Rrtype != TypeTSIG {
return false return false
} }
println(msg2.String())
msg2.MsgHdr.Id = t.OrigId msg2.MsgHdr.Id = t.OrigId
println(msg2.String())
msg2.Extra = msg2.Extra[:len(msg2.Extra)-1] // Strip off the TSIG msg2.Extra = msg2.Extra[:len(msg2.Extra)-1] // Strip off the TSIG
buf, ok := tsigToBuf(t, msg2, reqmac) buf, ok := tsigToBuf(t, msg2, reqmac)
if !ok { if !ok {
@ -182,3 +181,53 @@ func tsigToBuf(rr *RR_TSIG, msg *Msg, reqmac string) ([]byte, bool) {
} }
return buf, true return buf, true
} }
// Strip the TSIG from the pkt.
func stripTSIG(orig []byte) ([]byte, bool) {
// Copied from msg.go's Unpack()
// Header.
var dh Header
dns := new(Msg)
msg := make([]byte, len(orig))
copy(msg, orig) // fhhh.. another copy
off := 0
tsigoff := 0
var ok bool
if off, ok = unpackStruct(&dh, msg, off); !ok {
return nil, false
}
if dh.Arcount == 0 {
// No records at all in the additional.
return nil, false
}
// Arrays.
dns.Question = make([]Question, dh.Qdcount)
dns.Answer = make([]RR, dh.Ancount)
dns.Ns = make([]RR, dh.Nscount)
dns.Extra = make([]RR, dh.Arcount)
for i := 0; i < len(dns.Question); i++ {
off, ok = unpackStruct(&dns.Question[i], msg, off)
}
for i := 0; i < len(dns.Answer); i++ {
dns.Answer[i], off, ok = unpackRR(msg, off)
}
for i := 0; i < len(dns.Ns); i++ {
dns.Ns[i], off, ok = unpackRR(msg, off)
}
for i := 0; i < len(dns.Extra); i++ {
tsigoff = off
dns.Extra[i], off, ok = unpackRR(msg, off)
if dns.Extra[i].Header().Rrtype == TypeTSIG {
// Adjust Arcount.
arcount, _ := unpackUint16(msg, 10)
msg[10], msg[11] = packUint16(arcount-1)
break
}
}
if !ok {
return nil, false
}
return msg[:tsigoff], true
}