From 65cd41dbf542a5ad5a2fbc2c9e2bb96f2f5aa2bf Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 23 Sep 2017 17:49:19 -0700 Subject: [PATCH] Block POST requests for websocket connections (#934) --- .../HttpConnectionDispatcher.cs | 9 +++++ .../Internal/SocketHttpLoggerExtensions.cs | 11 ++++++ .../HttpConnectionDispatcherTests.cs | 34 +++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionDispatcher.cs b/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionDispatcher.cs index fbd6cf468a..1bcca138ef 100644 --- a/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionDispatcher.cs +++ b/src/Microsoft.AspNetCore.Sockets.Http/HttpConnectionDispatcher.cs @@ -388,6 +388,15 @@ namespace Microsoft.AspNetCore.Sockets return; } + var transport = (TransportType?)connection.Metadata[ConnectionMetadataNames.Transport]; + if (transport == TransportType.WebSockets) + { + _logger.PostNotAllowedForWebSockets(connection.ConnectionId); + context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; + await context.Response.WriteAsync("POST requests are not allowed for WebSocket connections."); + return; + } + // TODO: Use a pool here byte[] buffer; diff --git a/src/Microsoft.AspNetCore.Sockets.Http/Internal/SocketHttpLoggerExtensions.cs b/src/Microsoft.AspNetCore.Sockets.Http/Internal/SocketHttpLoggerExtensions.cs index 06c1bb6c34..ab7154de66 100644 --- a/src/Microsoft.AspNetCore.Sockets.Http/Internal/SocketHttpLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Sockets.Http/Internal/SocketHttpLoggerExtensions.cs @@ -50,6 +50,9 @@ namespace Microsoft.AspNetCore.Sockets.Internal private static readonly Action _cannotChangeTransport = LoggerMessage.Define(LogLevel.Debug, new EventId(7, nameof(CannotChangeTransport)), "{time}: Connection Id {connectionId}: Cannot change transports mid-connection; currently using {transportType}, requesting {requestedTransport}."); + private static readonly Action _postNotallowedForWebsockets = + LoggerMessage.Define(LogLevel.Debug, new EventId(8, nameof(PostNotAllowedForWebSockets)), "{time}: Connection Id {connectionId}: POST requests are not allowed for websocket connections."); + private static readonly Action _negotiationRequest = LoggerMessage.Define(LogLevel.Debug, new EventId(8, nameof(NegotiationRequest)), "{time}: Connection Id {connectionId}: Sending negotiation response."); @@ -201,6 +204,14 @@ namespace Microsoft.AspNetCore.Sockets.Internal } } + public static void PostNotAllowedForWebSockets(this ILogger logger, string connectionId) + { + if (logger.IsEnabled(LogLevel.Debug)) + { + _postNotallowedForWebsockets(logger, DateTime.Now, connectionId, null); + } + } + public static void NegotiationRequest(this ILogger logger, string connectionId) { if (logger.IsEnabled(LogLevel.Debug)) diff --git a/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs b/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs index b6bb73d717..b71067b857 100644 --- a/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs +++ b/test/Microsoft.AspNetCore.Sockets.Tests/HttpConnectionDispatcherTests.cs @@ -150,6 +150,40 @@ namespace Microsoft.AspNetCore.Sockets.Tests } } + [Fact] + public async Task PostNotAllowedForWebSocketConnections() + { + var manager = CreateConnectionManager(); + var dispatcher = new HttpConnectionDispatcher(manager, new LoggerFactory()); + var connection = manager.CreateConnection(); + connection.Metadata[ConnectionMetadataNames.Transport] = TransportType.WebSockets; + + using (var strm = new MemoryStream()) + { + var context = new DefaultHttpContext(); + context.Response.Body = strm; + + var services = new ServiceCollection(); + services.AddEndPoint(); + services.AddOptions(); + context.Request.Path = "/foo"; + context.Request.Method = "POST"; + var values = new Dictionary(); + values["id"] = connection.ConnectionId; + var qs = new QueryCollection(values); + context.Request.Query = qs; + + var builder = new SocketBuilder(services.BuildServiceProvider()); + builder.UseEndPoint(); + var app = builder.Build(); + await dispatcher.ExecuteAsync(context, new HttpSocketOptions(), app); + + Assert.Equal(StatusCodes.Status405MethodNotAllowed, context.Response.StatusCode); + await strm.FlushAsync(); + Assert.Equal("POST requests are not allowed for WebSocket connections.", Encoding.UTF8.GetString(strm.ToArray())); + } + } + [Theory] [InlineData(TransportType.ServerSentEvents)] [InlineData(TransportType.LongPolling)]