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()
}
}
ns := NewRR("pool.ntp.org. 390 IN NS a.ntpns.org")
t.Log("ns", ns.String())
x := new(Msg)
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) {

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.
lenmsg := len(msg)
if n := len(s); n == 0 || s[n-1] != '.' {
// Make it fully qualified
s += "."
panic("dns: name not fully qualified")
}
// Each dot ends a segment of the name.
// 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
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)
offset := 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 {
return lenmsg, false
}
for j := begin; j < i; j++ {
if off+1 > len(msg) {
return lenmsg, false
}
msg[off] = bs[j]
off++
if off > lenmsg {
@ -1210,7 +1219,7 @@ func (dns *Msg) Pack() (msg []byte, ok bool) {
dh.Arcount = uint16(len(extra))
// 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.
off := 0
@ -1328,7 +1337,8 @@ func (dns *Msg) String() string {
// Len return the message length when in (un)compressed wire format.
// 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 {
// Message header is always 12 bytes
l := 12

View File

@ -256,7 +256,7 @@ forever:
}
go d.serve()
}
panic("not reached")
panic("dns: not reached")
}
// ServeUDP starts a UDP listener for the server.
@ -290,7 +290,7 @@ func (srv *Server) ServeUDP(l *net.UDPConn) error {
}
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) {

View File

@ -155,7 +155,7 @@ type timerWireFmt struct {
// If something goes wrong an error is returned, otherwise it is nil.
func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) {
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
rawsecret, err := packBase64([]byte(secret))

View File

@ -883,7 +883,7 @@ func (rr *RR_NSEC) String() string {
func (rr *RR_NSEC) Len() int {
l := len(rr.NextDomain) + 1
return rr.Hdr.Len() + l + 32
return rr.Hdr.Len() + l + 32 + 1
// TODO: +32 is max type bitmap
}
@ -1420,7 +1420,7 @@ func cmToString(mantissa, exponent uint8) string {
}
return s
}
panic("not reached")
panic("dns: not reached")
}
// 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.
func (u *Msg) RRsetUsedRdata(rr []RR) {
if len(u.Question) == 0 {
panic("empty question section")
panic("dns: empty question section")
}
u.Answer = make([]RR, len(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
func (u *Msg) RRsetAddRdata(rr []RR) {
if len(u.Question) == 0 {
panic("empty question section")
panic("dns: empty question section")
}
u.Ns = make([]RR, len(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:
return nil, ErrXfrType
}
panic("not reached")
panic("dns: not reached")
}
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}
}
}
panic("not reached")
panic("dns: not reached")
}
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()}
}
}
panic("not reached")
panic("dns: not reached")
}
// 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:
return "%0" + xs[1] + xs[2], offset, ""
}
panic("not reached")
panic("dns: not reached")
}