diff --git a/client.go b/client.go index 9602aa84..3e45e858 100644 --- a/client.go +++ b/client.go @@ -346,7 +346,7 @@ func (w *reply) readClient(p []byte) (n int, err os.Error) { return } -// Send a msg to the address specified in w. +// Send sends a dns msg to the address specified in w. // If the message m contains a TSIG record the transaction // signature is calculated. func (w *reply) Send(m *Msg) os.Error { @@ -356,8 +356,10 @@ func (w *reply) Send(m *Msg) os.Error { if !ok { return ErrSecret } - m, _ = TsigGenerate(m, w.Client().TsigSecret[secret], w.tsigRequestMAC, w.tsigTimersOnly) - w.tsigRequestMAC = m.Extra[len(m.Extra)-1].(*RR_TSIG).MAC // Save the requestMAC + if err := TsigGenerate(m, w.Client().TsigSecret[secret], w.tsigRequestMAC, w.tsigTimersOnly); err != nil { + return err + } + w.tsigRequestMAC = m.Extra[len(m.Extra)-1].(*RR_TSIG).MAC // Save the requestMAC for the next packet } out, ok := m.Pack() if !ok { diff --git a/client_test.go b/client_test.go index 4a70e2c5..c104cb96 100644 --- a/client_test.go +++ b/client_test.go @@ -81,9 +81,11 @@ func TestClientTsigAXFR(t *testing.T) { m.SetAxfr("miek.nl") m.SetTsig("axfr", HmacMD5, 300, uint64(time.Seconds())) + TsigGenerate(m, "so6ZGir4GPAqINNh9U5c3A==", "", false) secrets := make(map[string]string) secrets["axfr"] = "so6ZGir4GPAqINNh9U5c3A==" + println(m.String()) c := NewClient() c.Net = "tcp" c.TsigSecret = secrets diff --git a/defaults.go b/defaults.go index 4d2e7a1d..2489181f 100644 --- a/defaults.go +++ b/defaults.go @@ -80,12 +80,15 @@ func (dns *Msg) SetAxfr(z string) { dns.Question[0] = Question{z, TypeAXFR, ClassINET} } -// SetTsig Calculates and appends a TSIG RR to the message. +// SetTsig appends a TSIG RR to the message. +// This is only a skeleton Tsig RR that added as the last RR in the +// additional section. The caller should then call TsigGenerate, +// to generate the complete TSIG from the secret. func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned uint64) { t := new(RR_TSIG) t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0} t.Algorithm = algo - t.Fudge = fudge + t.Fudge = 300 t.TimeSigned = timesigned dns.Extra = append(dns.Extra, t) } @@ -160,7 +163,8 @@ func (dns *Msg) IsIxfr() (ok bool) { return } -// IsTsig checks if the message has a TSIG record as the last record. +// IsTsig checks if the message has a TSIG record as the last record +// in the additional section. func (dns *Msg) IsTsig() (ok bool) { if len(dns.Extra) > 0 { return dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG diff --git a/tsig.go b/tsig.go index 42378924..690967d5 100644 --- a/tsig.go +++ b/tsig.go @@ -54,24 +54,23 @@ type timerWireFmt struct { // TsigGenerate add add TSIG RR to a message. The TSIG MAC is saved // in the Tsig RR that is added. When TsigGenerate is called for the -// first time requestMAC is generaly set to the empty string. TODO(mg): Really? -// If something went wrong an error is returned, otherwise nil. -func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) (*Msg, os.Error) { +// first time requestMAC is set to the empty string. +// If something goes wrong an error is returned, otherwise it is nil. +func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) os.Error { if !m.IsTsig() { + // panic? panic? panic("TSIG not last RR in additional") } + // If we barf here, the caller is to blame rawsecret, err := packBase64([]byte(secret)) - if err != nil { - return nil, err - } + if err != nil { + return err + } rr := m.Extra[len(m.Extra)-1].(*RR_TSIG) m.Extra = m.Extra[0 : len(m.Extra)-1] // kill the TSIG from the msg mbuf, _ := m.Pack() - buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly) - if err != nil { - return nil, err - } + buf := tsigBuffer(mbuf, rr, requestMAC, timersOnly) t := new(RR_TSIG) @@ -88,7 +87,7 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) (*Msg, os. t.OrigId = m.MsgHdr.Id m.Extra = append(m.Extra, t) - return m, nil + return nil } // TsigVerify verifies the TSIG on a message. @@ -105,10 +104,7 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) os.Error return err } - buf, err := tsigBuffer(stripped, tsig, requestMAC, timersOnly) - if err != nil { - return err - } + buf := tsigBuffer(stripped, tsig, requestMAC, timersOnly) /* if t.Name != "" { if t.Name != dns.Extra[i].Header().Name { @@ -137,7 +133,7 @@ func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) os.Error } // Create a wiredata buffer for the MAC calculation. -func tsigBuffer(msgbuf []byte, rr *RR_TSIG, requestMAC string, timersOnly bool) ([]byte, os.Error) { +func tsigBuffer(msgbuf []byte, rr *RR_TSIG, requestMAC string, timersOnly bool) []byte { var ( macbuf []byte buf []byte @@ -146,7 +142,7 @@ func tsigBuffer(msgbuf []byte, rr *RR_TSIG, requestMAC string, timersOnly bool) rr.TimeSigned = uint64(time.Seconds()) } if rr.Fudge == 0 { - rr.Fudge = 300 + rr.Fudge = 300 // Standard (RFC) default. } if requestMAC != "" { @@ -154,10 +150,7 @@ func tsigBuffer(msgbuf []byte, rr *RR_TSIG, requestMAC string, timersOnly bool) m.MACSize = uint16(len(requestMAC) / 2) m.MAC = requestMAC macbuf = make([]byte, len(requestMAC)) // reqmac should be twice as long - n, ok := packStruct(m, macbuf, 0) - if !ok { - return nil, ErrSigGen - } + n, _ := packStruct(m, macbuf, 0) macbuf = macbuf[:n] } @@ -166,10 +159,7 @@ func tsigBuffer(msgbuf []byte, rr *RR_TSIG, requestMAC string, timersOnly bool) tsig := new(timerWireFmt) tsig.TimeSigned = rr.TimeSigned tsig.Fudge = rr.Fudge - n, ok1 := packStruct(tsig, tsigvar, 0) - if !ok1 { - return nil, ErrSigGen - } + n, _ := packStruct(tsig, tsigvar, 0) tsigvar = tsigvar[:n] } else { tsig := new(tsigWireFmt) @@ -182,10 +172,7 @@ func tsigBuffer(msgbuf []byte, rr *RR_TSIG, requestMAC string, timersOnly bool) tsig.Error = rr.Error tsig.OtherLen = rr.OtherLen tsig.OtherData = rr.OtherData - n, ok1 := packStruct(tsig, tsigvar, 0) - if !ok1 { - return nil, ErrSigGen - } + n, _ := packStruct(tsig, tsigvar, 0) tsigvar = tsigvar[:n] } if rr.MAC != "" { @@ -194,7 +181,7 @@ func tsigBuffer(msgbuf []byte, rr *RR_TSIG, requestMAC string, timersOnly bool) } else { buf = append(msgbuf, tsigvar...) } - return buf, nil + return buf } // Strip the TSIG from the raw message