rewrite NSEC bitmap [un]packing to account for out-of-order

This commit is contained in:
Filippo Valsorda 2015-08-05 00:18:02 +01:00
parent 2b564cd047
commit 40484667f4
1 changed files with 36 additions and 42 deletions

78
msg.go
View File

@ -765,41 +765,31 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
// Do absolutely nothing // Do absolutely nothing
break break
} }
var lastwindow, lastlength uint16
lastwindow := uint16(0)
length := uint16(0)
if off+2 > lenmsg {
return lenmsg, &Error{err: "overflow packing nsecx"}
}
for j := 0; j < val.Field(i).Len(); j++ { for j := 0; j < val.Field(i).Len(); j++ {
t := uint16((fv.Index(j).Uint())) t := uint16(fv.Index(j).Uint())
window := uint16(t / 256) window := t / 256
if lastwindow != window { length := (t-window*256)/8 + 1
if window > lastwindow && lastlength != 0 {
// New window, jump to the new offset // New window, jump to the new offset
off += int(length) + 3 off += int(lastlength) + 2
if off > lenmsg { lastlength = 0
return lenmsg, &Error{err: "overflow packing nsecx bitmap"}
}
} }
length = (t - window*256) / 8 if window < lastwindow || length < lastlength {
bit := t - (window * 256) - (length * 8) return len(msg), &Error{err: "nsec bits out of order"}
if off+2+int(length)+1 > lenmsg { }
return lenmsg, &Error{err: "overflow packing nsecx bitmap"} if off+2+int(length) > len(msg) {
return len(msg), &Error{err: "overflow packing nsec"}
} }
// Setting the window # // Setting the window #
msg[off] = byte(window) msg[off] = byte(window)
// Setting the octets length // Setting the octets length
msg[off+1] = byte(length + 1) msg[off+1] = byte(length)
// Setting the bit value for the type in the right octet // Setting the bit value for the type in the right octet
msg[off+2+int(length)] |= byte(1 << (7 - bit)) msg[off+1+int(length)] |= byte(1 << (7 - (t % 8)))
lastwindow = window lastwindow, lastlength = window, length
}
off += 2 + int(length)
off++
if off > lenmsg {
return lenmsg, &Error{err: "overflow packing nsecx bitmap"}
} }
off += int(lastlength) + 2
} }
case reflect.Struct: case reflect.Struct:
off, err = packStructValue(fv, msg, off, compression, compress) off, err = packStructValue(fv, msg, off, compression, compress)
@ -1161,36 +1151,39 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
} }
fv.Set(reflect.ValueOf(serv)) fv.Set(reflect.ValueOf(serv))
case `dns:"nsec"`: // NSEC/NSEC3 case `dns:"nsec"`: // NSEC/NSEC3
if off == lenmsg { if off == len(msg) {
break break
} }
// Rest of the record is the type bitmap // Rest of the record is the type bitmap
if off+2 > lenmsg {
return lenmsg, &Error{err: "overflow unpacking nsecx"}
}
var nsec []uint16 var nsec []uint16
length := 0 length := 0
window := 0 window := 0
for off+2 < lenmsg { lastwindow := -1
for off < len(msg) {
if off+2 > len(msg) {
return len(msg), &Error{err: "overflow unpacking nsecx"}
}
window = int(msg[off]) window = int(msg[off])
length = int(msg[off+1]) length = int(msg[off+1])
//println("off, windows, length, end", off, window, length, endrr) off += 2
if window <= lastwindow {
// RFC 4034: Blocks are present in the NSEC RR RDATA in
// increasing numerical order.
return len(msg), &Error{err: "out of order NSEC block"}
}
if length == 0 { if length == 0 {
// A length window of zero is strange. If there // RFC 4034: Blocks with no types present MUST NOT be included.
// the window should not have been specified. Bail out return len(msg), &Error{err: "empty NSEC block"}
// println("dns: length == 0 when unpacking NSEC")
return lenmsg, &Error{err: "overflow unpacking nsecx"}
} }
if length > 32 { if length > 32 {
return lenmsg, &Error{err: "overflow unpacking nsecx"} return len(msg), &Error{err: "NSEC block too long"}
}
if off+length > len(msg) {
return len(msg), &Error{err: "overflowing NSEC block"}
} }
// Walk the bytes in the window - and check the bit settings... // Walk the bytes in the window and extract the type bits
off += 2
for j := 0; j < length; j++ { for j := 0; j < length; j++ {
if off+j+1 > lenmsg {
return lenmsg, &Error{err: "overflow unpacking nsecx"}
}
b := msg[off+j] b := msg[off+j]
// Check the bits one by one, and set the type // Check the bits one by one, and set the type
if b&0x80 == 0x80 { if b&0x80 == 0x80 {
@ -1219,6 +1212,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
} }
} }
off += length off += length
lastwindow = window
} }
fv.Set(reflect.ValueOf(nsec)) fv.Set(reflect.ValueOf(nsec))
} }