From 4ddfc47448499debc868f7d119b7eb3df88e63df Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Wed, 15 Oct 2014 21:03:15 +0100 Subject: [PATCH] don't trip over truncated udp packets and log such events, plus any other errors during decoding, nicely, including the connection on which this occured. Closes #123. --- router/crypto.go | 13 ++++++++++--- router/router.go | 7 ++++++- router/types.go | 4 ++++ router/utils.go | 4 ++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/router/crypto.go b/router/crypto.go index 100ae454..2eb2aeb0 100644 --- a/router/crypto.go +++ b/router/crypto.go @@ -224,13 +224,20 @@ func (nd *NonDecryptor) IterateFrames(fun FrameConsumer, packet *UDPPacket) erro dstNameByte := buf[:NameSize] buf = buf[NameSize:] length := binary.BigEndian.Uint16(buf[:2]) - frame := buf[2 : 2+length] - buf = buf[2+length:] + buf = buf[2:] + if len(buf) < int(length) { + return PacketDecodingError{Desc: fmt.Sprintf("too short; expected frame of length %d, got %d", length, len(buf))} + } + frame := buf[:length] + buf = buf[length:] err := fun(nd.conn, packet.Sender, srcNameByte, dstNameByte, length, frame) if err != nil { return err } } + if len(buf) > 0 { + return PacketDecodingError{Desc: fmt.Sprintf("%d octets of trailing garbage", len(buf))} + } return nil } @@ -279,7 +286,7 @@ func (nd *NaClDecryptor) ReceiveNonce(msg []byte) { func (nd *NaClDecryptor) IterateFrames(fun FrameConsumer, packet *UDPPacket) error { buf, err := nd.decrypt(packet.Packet) if err != nil { - return err + return PacketDecodingError{Desc: fmt.Sprint("decryption failed; ", err)} } packet.Packet = buf return nd.NonDecryptor.IterateFrames(fun, packet) diff --git a/router/router.go b/router/router.go index 28d10abc..34541035 100644 --- a/router/router.go +++ b/router/router.go @@ -204,7 +204,12 @@ func (router *Router) udpReader(conn *net.UDPConn, po PacketSink) { if !ok { continue } - checkWarn(relayConn.Decryptor.IterateFrames(handleUDPPacket, udpPacket)) + err = relayConn.Decryptor.IterateFrames(handleUDPPacket, udpPacket) + if pde, ok := err.(PacketDecodingError); ok { + relayConn.log(pde.Error()) + } else { + checkWarn(err) + } } } diff --git a/router/types.go b/router/types.go index 41a09cf0..5cfd51e0 100644 --- a/router/types.go +++ b/router/types.go @@ -129,6 +129,10 @@ type NameCollisionError struct { Name PeerName } +type PacketDecodingError struct { + Desc string +} + type LocalAddress struct { ip net.IP network *net.IPNet diff --git a/router/utils.go b/router/utils.go index babd837b..7774f242 100644 --- a/router/utils.go +++ b/router/utils.go @@ -46,6 +46,10 @@ func (nce NameCollisionError) Error() string { return fmt.Sprint("Multiple peers found with same name: ", nce.Name) } +func (pde PacketDecodingError) Error() string { + return fmt.Sprint("Failed to decode packet: ", pde.Desc) +} + func (packet UDPPacket) String() string { return fmt.Sprintf("UDP Packet\n name: %s\n sender: %v\n payload: % X", packet.Name, packet.Sender, packet.Packet) }