From 08441efeaeb9c951e99421d743114d64422c542f Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Thu, 23 Oct 2014 09:38:10 -0700 Subject: [PATCH] #18 - Validate close status codes. --- .../CommonWebSocket.cs | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNet.WebSockets.Protocol/CommonWebSocket.cs b/src/Microsoft.AspNet.WebSockets.Protocol/CommonWebSocket.cs index a045609012..481e5a9393 100644 --- a/src/Microsoft.AspNet.WebSockets.Protocol/CommonWebSocket.cs +++ b/src/Microsoft.AspNet.WebSockets.Protocol/CommonWebSocket.cs @@ -414,6 +414,10 @@ namespace Microsoft.AspNet.WebSockets.Protocol Utilities.MaskInPlace(_frameInProgress.MaskKey, new ArraySegment(_receiveBuffer, _receiveBufferOffset, (int)_frameBytesRemaining)); } _closeStatus = (WebSocketCloseStatus)((_receiveBuffer[_receiveBufferOffset] << 8) | _receiveBuffer[_receiveBufferOffset + 1]); + if (!ValidateCloseStatus(_closeStatus.Value)) + { + await SendErrorAbortAndThrow(WebSocketCloseStatus.ProtocolError, "Invalid close status code.", cancellationToken); + } try { var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); @@ -451,6 +455,29 @@ namespace Microsoft.AspNet.WebSockets.Protocol return result; } + private static bool ValidateCloseStatus(WebSocketCloseStatus closeStatus) + { + if (closeStatus < (WebSocketCloseStatus)1000 || closeStatus >= (WebSocketCloseStatus)5000) + { + return false; + } + else if (closeStatus >= (WebSocketCloseStatus)3000) + { + // 3000-3999 - Reserved for frameworks + // 4000-4999 - Reserved for private usage + return true; + } + int[] validCodes = new[] { 1000, 1001, 1002, 1003, 1007, 1008, 1009, 1010, 1011 }; + foreach (var validCode in validCodes) + { + if (closeStatus == (WebSocketCloseStatus)validCode) + { + return true; + } + } + return false; + } + public async override Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken) { ThrowIfDisposed(); @@ -592,7 +619,7 @@ namespace Microsoft.AspNet.WebSockets.Protocol private async Task SendErrorAbortAndThrow(WebSocketCloseStatus error, string message, CancellationToken cancellationToken) { - if (State == WebSocketState.Open) + if (State == WebSocketState.Open || State == WebSocketState.CloseReceived) { await CloseOutputAsync(error, message, cancellationToken); }