From 1f512fc3f05332ba7117626cdfb4e07474e58e60 Mon Sep 17 00:00:00 2001 From: Gary Burd Date: Thu, 28 Apr 2016 09:34:18 -0700 Subject: [PATCH] Handle invalid close frames Send protocol error if close code or payload are invalid. Fixes Autobahn tests 7.5.1, 7.9.*. --- conn.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/conn.go b/conn.go index e7180c8..ed7736c 100644 --- a/conn.go +++ b/conn.go @@ -14,6 +14,7 @@ import ( "net" "strconv" "time" + "unicode/utf8" ) const ( @@ -43,6 +44,8 @@ const ( CloseMessageTooBig = 1009 CloseMandatoryExtension = 1010 CloseInternalServerErr = 1011 + CloseServiceRestart = 1012 + CloseTryAgainLater = 1013 CloseTLSHandshake = 1015 ) @@ -184,6 +187,29 @@ func isData(frameType int) bool { return frameType == TextMessage || frameType == BinaryMessage } +var validReceivedCloseCodes = map[int]bool{ + // see http://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number + + CloseNormalClosure: true, + CloseGoingAway: true, + CloseProtocolError: true, + CloseUnsupportedData: true, + CloseNoStatusReceived: false, + CloseAbnormalClosure: false, + CloseInvalidFramePayloadData: true, + ClosePolicyViolation: true, + CloseMessageTooBig: true, + CloseMandatoryExtension: true, + CloseInternalServerErr: true, + CloseServiceRestart: true, + CloseTryAgainLater: true, + CloseTLSHandshake: false, +} + +func isValidReceivedCloseCode(code int) bool { + return validReceivedCloseCodes[code] || (code >= 3000 && code <= 4999) +} + func maskBytes(key [4]byte, pos int, b []byte) int { for i := range b { b[i] ^= key[pos&3] @@ -747,7 +773,13 @@ func (c *Conn) advanceFrame() (int, error) { if len(payload) >= 2 { echoMessage = payload[:2] closeCode = int(binary.BigEndian.Uint16(payload)) + if !isValidReceivedCloseCode(closeCode) { + return noFrame, c.handleProtocolError("invalid close code") + } closeText = string(payload[2:]) + if !utf8.ValidString(closeText) { + return noFrame, c.handleProtocolError("invalid utf8 payload in close frame") + } } c.WriteControl(CloseMessage, echoMessage, time.Now().Add(writeWait)) return noFrame, &CloseError{Code: closeCode, Text: closeText}