Elegant Tsig handling in the server
Lowlevel, but flexible. i.e. usable when building a server
This commit is contained in:
parent
acba7a84fc
commit
fd6bdd4bba
10
client.go
10
client.go
|
@ -7,14 +7,15 @@ package dns
|
|||
// setup for server - a HANDLER function that gets run
|
||||
// when the query returns.
|
||||
|
||||
// TsigStatus here too? TODO
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Check incoming TSIG message. TODO(mg)
|
||||
// Need a tsigstatus for that too? Don't know yet. TODO(mg)
|
||||
|
||||
// Incoming (just as in os.Signal)
|
||||
type QueryHandler interface {
|
||||
QueryDNS(w RequestWriter, q *Msg)
|
||||
|
@ -38,6 +39,7 @@ type reply struct {
|
|||
conn net.Conn
|
||||
tsigRequestMAC string
|
||||
tsigTimersOnly bool
|
||||
tsigStatus int
|
||||
}
|
||||
|
||||
// A Request is a incoming message from a Client.
|
||||
|
@ -296,7 +298,6 @@ func (w *reply) Receive() (*Msg, error) {
|
|||
if ok := m.Unpack(p); !ok {
|
||||
return nil, ErrUnpack
|
||||
}
|
||||
// Tsig
|
||||
if m.IsTsig() {
|
||||
secret := m.Extra[len(m.Extra)-1].(*RR_TSIG).Hdr.Name
|
||||
if _, ok := w.Client().TsigSecret[secret]; !ok {
|
||||
|
@ -386,7 +387,7 @@ func (w *reply) Send(m *Msg) error {
|
|||
if !ok {
|
||||
return ErrSecret
|
||||
}
|
||||
// Compressie maakt dit stuk
|
||||
// TODO(mg): compression makes this fail
|
||||
if err := TsigGenerate(m, w.Client().TsigSecret[secret], w.tsigRequestMAC, w.tsigTimersOnly); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -396,6 +397,7 @@ func (w *reply) Send(m *Msg) error {
|
|||
if !ok {
|
||||
return ErrPack
|
||||
}
|
||||
// Tsig calculation should happen here
|
||||
_, err := w.writeClient(out)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
23
server.go
23
server.go
|
@ -12,12 +12,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
TsigNone = iota // No Tsig attached to the message
|
||||
TsigVerified // Tisg seen and verified
|
||||
TsigBad // Tisg seen but failed to verify
|
||||
)
|
||||
|
||||
type Handler interface {
|
||||
ServeDNS(w ResponseWriter, r *Msg)
|
||||
// IP based ACL mapping. The contains the string representation
|
||||
|
@ -30,7 +24,7 @@ type ResponseWriter interface {
|
|||
// RemoteAddr returns the net.Addr of the client that sent the current request.
|
||||
RemoteAddr() net.Addr
|
||||
// Return the status of the Tsig (TsigNone, TsigVerified or TsigBad)
|
||||
TsigStatus() int
|
||||
TsigStatus() error
|
||||
// Write writes a reply back to the client.
|
||||
Write([]byte) (int, error)
|
||||
}
|
||||
|
@ -48,7 +42,7 @@ type conn struct {
|
|||
type response struct {
|
||||
conn *conn
|
||||
req *Msg
|
||||
tsigStatus int
|
||||
tsigStatus error
|
||||
}
|
||||
|
||||
// ServeMux is an DNS request multiplexer. It matches the
|
||||
|
@ -320,10 +314,17 @@ func (c *conn) serve() {
|
|||
w.Write(buf)
|
||||
break
|
||||
}
|
||||
// Check the tsig here TODO
|
||||
|
||||
w.tsigStatus = nil
|
||||
if req.IsTsig() {
|
||||
secret := req.Extra[len(req.Extra)-1].(*RR_TSIG).Hdr.Name
|
||||
if _, ok := w.conn.tsigSecret[secret]; !ok {
|
||||
w.tsigStatus = ErrKeyAlg
|
||||
}
|
||||
w.tsigStatus = TsigVerify(c.request, w.conn.tsigSecret[secret], "", false)
|
||||
}
|
||||
w.req = req
|
||||
c.handler.ServeDNS(w, w.req) // this does the writing back to the client
|
||||
w.tsigStatus = TsigNone
|
||||
if c.hijacked {
|
||||
return
|
||||
}
|
||||
|
@ -375,6 +376,6 @@ func (w *response) Write(data []byte) (n int, err error) {
|
|||
func (w *response) RemoteAddr() net.Addr { return w.conn.remoteAddr }
|
||||
|
||||
// TsigStatus implements the ResponseWriter.TsigStatus method
|
||||
func (w *response) TsigStatus() int {
|
||||
func (w *response) TsigStatus() error {
|
||||
return w.tsigStatus
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue