Fix handling of non fully qualified domain names

When PackDomain sees such a name it calls panic.
All panic now use the prefix 'dns:'
This commit is contained in:
Miek Gieben 2012-08-28 18:21:23 +02:00
parent 8bc979fe1e
commit e4fb00c34d
8 changed files with 43 additions and 17 deletions

View File

@ -111,8 +111,24 @@ func TestPack(t *testing.T) {
t.Fail() t.Fail()
} }
} }
ns := NewRR("pool.ntp.org. 390 IN NS a.ntpns.org") x := new(Msg)
t.Log("ns", ns.String()) ns, _ := NewRR("pool.ntp.org. 390 IN NS a.ntpns.org")
ns.(*RR_NS).Ns = "a.ntpns.org."
x.Ns = append(m.Ns, ns)
x.Ns = append(m.Ns, ns)
x.Ns = append(m.Ns, ns)
// This crashes due to the fact the a.ntpns.org isn't a FQDN
// How to recover() from a remove panic()?
if _, ok := x.Pack(); !ok {
t.Log("Packing failed")
t.Fail()
}
x.Answer = make([]RR, 1)
x.Answer[0], err = NewRR(rr[0])
if _, ok := x.Pack(); !ok {
t.Log("Packing failed")
t.Fail()
}
} }
func TestCompressLenght(t *testing.T) { func TestCompressLenght(t *testing.T) {

18
msg.go
View File

@ -205,8 +205,7 @@ func PackDomainName(s string, msg []byte, off int, compression map[string]int, c
// Add trailing dot to canonicalize name. // Add trailing dot to canonicalize name.
lenmsg := len(msg) lenmsg := len(msg)
if n := len(s); n == 0 || s[n-1] != '.' { if n := len(s); n == 0 || s[n-1] != '.' {
// Make it fully qualified panic("dns: name not fully qualified")
s += "."
} }
// Each dot ends a segment of the name. // Each dot ends a segment of the name.
// We trade each dot byte for a length byte. // We trade each dot byte for a length byte.
@ -235,13 +234,23 @@ func PackDomainName(s string, msg []byte, off int, compression map[string]int, c
if i-begin >= 1<<6 { // top two bits of length must be clear if i-begin >= 1<<6 { // top two bits of length must be clear
return lenmsg, false return lenmsg, false
} }
// off can already (we're in a loop) be bigger than len(msg)
// this happens when a name isn't fully qualified
if off+1 > len(msg) {
return lenmsg, false
}
msg[off] = byte(i - begin) msg[off] = byte(i - begin)
offset := off offset := off
off++ off++
// TODO(mg): because of the new check above, this can go. But
// just leave it as is for the moment.
if off > lenmsg { if off > lenmsg {
return lenmsg, false return lenmsg, false
} }
for j := begin; j < i; j++ { for j := begin; j < i; j++ {
if off+1 > len(msg) {
return lenmsg, false
}
msg[off] = bs[j] msg[off] = bs[j]
off++ off++
if off > lenmsg { if off > lenmsg {
@ -1210,7 +1219,7 @@ func (dns *Msg) Pack() (msg []byte, ok bool) {
dh.Arcount = uint16(len(extra)) dh.Arcount = uint16(len(extra))
// TODO(mg): still a little too much, but better than 64K... // TODO(mg): still a little too much, but better than 64K...
msg = make([]byte, dns.Len()+1) msg = make([]byte, dns.Len()+10)
// Pack it in: header and then the pieces. // Pack it in: header and then the pieces.
off := 0 off := 0
@ -1328,7 +1337,8 @@ func (dns *Msg) String() string {
// Len return the message length when in (un)compressed wire format. // Len return the message length when in (un)compressed wire format.
// If dns.Compress is true compression is taken into account, currently // If dns.Compress is true compression is taken into account, currently
// this only counts owner name compression. // this only counts owner name compression. There is no check for
// nil valued sections (allocated, but contains no RRs).
func (dns *Msg) Len() int { func (dns *Msg) Len() int {
// Message header is always 12 bytes // Message header is always 12 bytes
l := 12 l := 12

View File

@ -256,7 +256,7 @@ forever:
} }
go d.serve() go d.serve()
} }
panic("not reached") panic("dns: not reached")
} }
// ServeUDP starts a UDP listener for the server. // ServeUDP starts a UDP listener for the server.
@ -290,7 +290,7 @@ func (srv *Server) ServeUDP(l *net.UDPConn) error {
} }
go d.serve() go d.serve()
} }
panic("not reached") panic("dns: not reached")
} }
func newConn(t *net.TCPConn, u *net.UDPConn, a net.Addr, buf []byte, handler Handler, tsig map[string]string) (*conn, error) { func newConn(t *net.TCPConn, u *net.UDPConn, a net.Addr, buf []byte, handler Handler, tsig map[string]string) (*conn, error) {

View File

@ -155,7 +155,7 @@ type timerWireFmt struct {
// If something goes wrong an error is returned, otherwise it is nil. // If something goes wrong an error is returned, otherwise it is nil.
func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) { func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) {
if m.IsTsig() == nil { if m.IsTsig() == nil {
panic("TSIG not last RR in additional") panic("dns: TSIG not last RR in additional")
} }
// If we barf here, the caller is to blame // If we barf here, the caller is to blame
rawsecret, err := packBase64([]byte(secret)) rawsecret, err := packBase64([]byte(secret))

View File

@ -883,7 +883,7 @@ func (rr *RR_NSEC) String() string {
func (rr *RR_NSEC) Len() int { func (rr *RR_NSEC) Len() int {
l := len(rr.NextDomain) + 1 l := len(rr.NextDomain) + 1
return rr.Hdr.Len() + l + 32 return rr.Hdr.Len() + l + 32 + 1
// TODO: +32 is max type bitmap // TODO: +32 is max type bitmap
} }
@ -1420,7 +1420,7 @@ func cmToString(mantissa, exponent uint8) string {
} }
return s return s
} }
panic("not reached") panic("dns: not reached")
} }
// Map of constructors for each RR wire type. // Map of constructors for each RR wire type.

View File

@ -57,7 +57,7 @@ func (u *Msg) NameNotUsed(rr []RR) {
// "RRset exists (value dependent -- with rdata)" RRs. RFC 2136 section 2.4.2. // "RRset exists (value dependent -- with rdata)" RRs. RFC 2136 section 2.4.2.
func (u *Msg) RRsetUsedRdata(rr []RR) { func (u *Msg) RRsetUsedRdata(rr []RR) {
if len(u.Question) == 0 { if len(u.Question) == 0 {
panic("empty question section") panic("dns: empty question section")
} }
u.Answer = make([]RR, len(rr)) u.Answer = make([]RR, len(rr))
for i, r := range rr { for i, r := range rr {
@ -104,7 +104,7 @@ func (u *Msg) RRsetNotUsed(rr []RR) {
// RRsetAddRdata creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1 // RRsetAddRdata creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1
func (u *Msg) RRsetAddRdata(rr []RR) { func (u *Msg) RRsetAddRdata(rr []RR) {
if len(u.Question) == 0 { if len(u.Question) == 0 {
panic("empty question section") panic("dns: empty question section")
} }
u.Ns = make([]RR, len(rr)) u.Ns = make([]RR, len(rr))
for i, r := range rr { for i, r := range rr {

6
xfr.go
View File

@ -50,7 +50,7 @@ func (c *Client) XfrReceive(q *Msg, a string) (chan *XfrMsg, error) {
default: default:
return nil, ErrXfrType return nil, ErrXfrType
} }
panic("not reached") panic("dns: not reached")
} }
func (w *reply) axfrReceive(c chan *XfrMsg) { func (w *reply) axfrReceive(c chan *XfrMsg) {
@ -84,7 +84,7 @@ func (w *reply) axfrReceive(c chan *XfrMsg) {
c <- &XfrMsg{Request: w.req, Reply: in, Rtt: w.rtt, RemoteAddr: w.conn.RemoteAddr(), Error: nil} c <- &XfrMsg{Request: w.req, Reply: in, Rtt: w.rtt, RemoteAddr: w.conn.RemoteAddr(), Error: nil}
} }
} }
panic("not reached") panic("dns: not reached")
} }
func (w *reply) ixfrReceive(c chan *XfrMsg) { func (w *reply) ixfrReceive(c chan *XfrMsg) {
@ -132,7 +132,7 @@ func (w *reply) ixfrReceive(c chan *XfrMsg) {
c <- &XfrMsg{Request: w.req, Reply: in, Rtt: w.rtt, RemoteAddr: w.conn.RemoteAddr()} c <- &XfrMsg{Request: w.req, Reply: in, Rtt: w.rtt, RemoteAddr: w.conn.RemoteAddr()}
} }
} }
panic("not reached") panic("dns: not reached")
} }
// XfrSend performs an outgoing Ixfr or Axfr. The function is [AI]xfr agnostic, it is // XfrSend performs an outgoing Ixfr or Axfr. The function is [AI]xfr agnostic, it is

View File

@ -155,5 +155,5 @@ func modToPrintf(s string) (string, int, string) {
default: default:
return "%0" + xs[1] + xs[2], offset, "" return "%0" + xs[1] + xs[2], offset, ""
} }
panic("not reached") panic("dns: not reached")
} }