From e78ef64a54b96e72a0c9e227732c99f21ae0aa51 Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Tue, 15 Mar 2011 19:36:03 +0100 Subject: [PATCH] TSIG works for AXFR (also with multiple message envelopes) --- TODO | 4 +-- resolver.go | 11 ++++---- tsig.go | 72 +++++++++++++++++++++++++++++++++-------------------- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/TODO b/TODO index 7d60e98d..283e2d62 100644 --- a/TODO +++ b/TODO @@ -2,10 +2,7 @@ Todo: * Private key file parsing use io.Reader (or the like) - NewReader, NewWriter? * Parsing from strings, going with goyacc and .cz lexer? * encoding NSEC3/NSEC bitmaps, DEcoding works -* AXFR/IXFR with TSIG validation -* Failed Xfr triggers nil error? * Use callback in IXFR/AXFR to make tsig happen (and other cool stuff in FunkenSturm) -* A New for all type with some defaults filled in * Take a good look at hash.Hash take over the digest sizes and names * HIP RR (needs list of domain names, need slice stuff for that) @@ -13,6 +10,7 @@ Issues: * Check the network order, it works now, but this is on Intel?? * Make the testsuite work with public DNS servers * pack/Unpack smaller. EDNS 'n stuff can be folded in +* SetDefaults() for *all* types? Examples: * Test impl of nameserver, with a small zone, 1 KSK and online signing diff --git a/resolver.go b/resolver.go index c42a3ecf..36f7eff0 100644 --- a/resolver.go +++ b/resolver.go @@ -293,12 +293,13 @@ Server: if tsig && len(in.Extra) > 0 { // What if not included? t := in.Extra[len(in.Extra)-1] - switch t.(type) { - case *RR_TSIG: - if t.(*RR_TSIG).Verify(inb, secret, reqmac) { - println("Validates") + if t.Header().Rrtype == TypeTSIG { + if t.(*RR_TSIG).Verify(inb, secret, reqmac, first) { + println("Validates!!!!!") + // Set the MAC for the next round. + reqmac = t.(*RR_TSIG).MAC } else { - println("DOES NOT validate") + println("DOES NOT validate :-(") } } } diff --git a/tsig.go b/tsig.go index b98f3837..d1797abd 100644 --- a/tsig.go +++ b/tsig.go @@ -73,12 +73,19 @@ type tsigWireFmt struct { OtherData string "size-hex" } -// If we have the MAC use this type to convert it to wiredata +// If we have the MAC use this type to convert it to wiredata. +// Section 3.4.3. Request MAC type macWireFmt struct { MACSize uint16 MAC string "size-hex" } +// 3.3. Time values used in TSIG calculations +type timerWireFmt struct { + TimeSigned uint64 + Fudge uint16 +} + // Generate the HMAC for message. The TSIG RR is modified // to include the MAC and MACSize. Note the the msg Id must // already be set, otherwise the MAC will not be correct when @@ -92,13 +99,13 @@ func (t *RR_TSIG) Generate(m *Msg, secret string) bool { t.OrigId = m.MsgHdr.Id msg, ok := m.Pack() - if !ok { - return false - } - buf, ok1 := tsigToBuf(t, msg, "") - if !ok1 { - return false - } + if !ok { + return false + } + buf, ok1 := tsigToBuf(t, msg, "", true) + if !ok1 { + return false + } h := hmac.NewMD5([]byte(rawsecret)) io.WriteString(h, string(buf)) @@ -114,7 +121,7 @@ func (t *RR_TSIG) Generate(m *Msg, secret string) bool { // the TSIG record still attached (as the last rr in the Additional // section). Return true on success. // The secret is a base64 encoded string with the secret. -func (t *RR_TSIG) Verify(msg []byte, secret, reqmac string) bool { +func (t *RR_TSIG) Verify(msg []byte, secret, reqmac string, timers bool) bool { rawsecret, err := packBase64([]byte(secret)) if err != nil { return false @@ -129,7 +136,7 @@ func (t *RR_TSIG) Verify(msg []byte, secret, reqmac string) bool { if !ok { return false } - buf, ok := tsigToBuf(t, stripped, reqmac) + buf, ok := tsigToBuf(t, stripped, reqmac, timers) if !ok { return false } @@ -140,10 +147,10 @@ func (t *RR_TSIG) Verify(msg []byte, secret, reqmac string) bool { } // Create the buffer which we use for the MAC calculation. -func tsigToBuf(rr *RR_TSIG, msg []byte, reqmac string) ([]byte, bool) { +func tsigToBuf(rr *RR_TSIG, msg []byte, reqmac string, timers bool) ([]byte, bool) { var ( - macbuf []byte - buf []byte + macbuf []byte + buf []byte ) if reqmac != "" { @@ -159,21 +166,32 @@ func tsigToBuf(rr *RR_TSIG, msg []byte, reqmac string) ([]byte, bool) { } tsigvar := make([]byte, DefaultMsgSize) - tsig := new(tsigWireFmt) - tsig.Name = strings.ToLower(rr.Header().Name) - tsig.Class = rr.Header().Class - tsig.Ttl = rr.Header().Ttl - tsig.Algorithm = strings.ToLower(rr.Algorithm) - tsig.TimeSigned = rr.TimeSigned - tsig.Fudge = rr.Fudge - tsig.Error = rr.Error - tsig.OtherLen = rr.OtherLen - tsig.OtherData = rr.OtherData - n, ok1 := packStruct(tsig, tsigvar, 0) - if !ok1 { - return nil, false + if timers { + tsig := new(tsigWireFmt) + tsig.Name = strings.ToLower(rr.Header().Name) + tsig.Class = rr.Header().Class + tsig.Ttl = rr.Header().Ttl + tsig.Algorithm = strings.ToLower(rr.Algorithm) + tsig.TimeSigned = rr.TimeSigned + tsig.Fudge = rr.Fudge + tsig.Error = rr.Error + tsig.OtherLen = rr.OtherLen + tsig.OtherData = rr.OtherData + n, ok1 := packStruct(tsig, tsigvar, 0) + if !ok1 { + return nil, false + } + tsigvar = tsigvar[:n] + } else { + tsig := new(timerWireFmt) + tsig.TimeSigned = rr.TimeSigned + tsig.Fudge = rr.Fudge + n, ok1 := packStruct(tsig, tsigvar, 0) + if !ok1 { + return nil, false + } + tsigvar = tsigvar[:n] } - tsigvar = tsigvar[:n] if reqmac != "" { x := append(macbuf, msg...) buf = append(x, tsigvar...)