mirror of https://github.com/gorilla/websocket.git
Handle invalid close frames
Send protocol error if close code or payload are invalid. Fixes Autobahn tests 7.5.1, 7.9.*.
This commit is contained in:
parent
a724ba4528
commit
1f512fc3f0
32
conn.go
32
conn.go
|
@ -14,6 +14,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -43,6 +44,8 @@ const (
|
||||||
CloseMessageTooBig = 1009
|
CloseMessageTooBig = 1009
|
||||||
CloseMandatoryExtension = 1010
|
CloseMandatoryExtension = 1010
|
||||||
CloseInternalServerErr = 1011
|
CloseInternalServerErr = 1011
|
||||||
|
CloseServiceRestart = 1012
|
||||||
|
CloseTryAgainLater = 1013
|
||||||
CloseTLSHandshake = 1015
|
CloseTLSHandshake = 1015
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -184,6 +187,29 @@ func isData(frameType int) bool {
|
||||||
return frameType == TextMessage || frameType == BinaryMessage
|
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 {
|
func maskBytes(key [4]byte, pos int, b []byte) int {
|
||||||
for i := range b {
|
for i := range b {
|
||||||
b[i] ^= key[pos&3]
|
b[i] ^= key[pos&3]
|
||||||
|
@ -747,7 +773,13 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||||
if len(payload) >= 2 {
|
if len(payload) >= 2 {
|
||||||
echoMessage = payload[:2]
|
echoMessage = payload[:2]
|
||||||
closeCode = int(binary.BigEndian.Uint16(payload))
|
closeCode = int(binary.BigEndian.Uint16(payload))
|
||||||
|
if !isValidReceivedCloseCode(closeCode) {
|
||||||
|
return noFrame, c.handleProtocolError("invalid close code")
|
||||||
|
}
|
||||||
closeText = string(payload[2:])
|
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))
|
c.WriteControl(CloseMessage, echoMessage, time.Now().Add(writeWait))
|
||||||
return noFrame, &CloseError{Code: closeCode, Text: closeText}
|
return noFrame, &CloseError{Code: closeCode, Text: closeText}
|
||||||
|
|
Loading…
Reference in New Issue