diff --git a/src/Kestrel.Core/Internal/HttpsConnectionAdapter.cs b/src/Kestrel.Core/Internal/HttpsConnectionAdapter.cs index 301c9c7a23..95ee435b43 100644 --- a/src/Kestrel.Core/Internal/HttpsConnectionAdapter.cs +++ b/src/Kestrel.Core/Internal/HttpsConnectionAdapter.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Net.Security; +using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; @@ -186,7 +187,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Https.Internal sslStream.Dispose(); return _closedAdaptedConnection; } - catch (IOException ex) + catch (Exception ex) when (ex is IOException || ex is AuthenticationException) { _logger?.LogDebug(1, ex, CoreStrings.AuthenticationFailed); sslStream.Dispose(); diff --git a/test/Kestrel.FunctionalTests/HttpConnectionManagerTests.cs b/test/Kestrel.FunctionalTests/HttpConnectionManagerTests.cs index 7f5296763c..ef8ac428b1 100644 --- a/test/Kestrel.FunctionalTests/HttpConnectionManagerTests.cs +++ b/test/Kestrel.FunctionalTests/HttpConnectionManagerTests.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests using (var server = new TestServer(context => { appStartedWh.Release(); - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); return tcs.Task; }, new TestServiceContext(new LoggerFactory(), mockTrace.Object))) diff --git a/test/Kestrel.FunctionalTests/HttpsTests.cs b/test/Kestrel.FunctionalTests/HttpsTests.cs index 8ca3718481..ef79d815ff 100644 --- a/test/Kestrel.FunctionalTests/HttpsTests.cs +++ b/test/Kestrel.FunctionalTests/HttpsTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Net; using System.Net.Security; using System.Net.Sockets; @@ -235,15 +236,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests var request = Encoding.ASCII.GetBytes("GET / HTTP/1.1\r\nHost:\r\n\r\n"); await sslStream.WriteAsync(request, 0, request.Length); - // Temporary workaround for a deadlock when reading from an aborted client SslStream on Mac and Linux. - if (TestPlatformHelper.IsWindows) - { - await sslStream.ReadAsync(new byte[32], 0, 32); - } - else - { - await stream.ReadAsync(new byte[32], 0, 32); - } + await sslStream.ReadAsync(new byte[32], 0, 32); } } @@ -295,15 +288,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests var request = Encoding.ASCII.GetBytes("GET / HTTP/1.1\r\nHost:\r\n\r\n"); await sslStream.WriteAsync(request, 0, request.Length); - // Temporary workaround for a deadlock when reading from an aborted client SslStream on Mac and Linux. - if (TestPlatformHelper.IsWindows) - { - await sslStream.ReadAsync(new byte[32], 0, 32); - } - else - { - await stream.ReadAsync(new byte[32], 0, 32); - } + await sslStream.ReadAsync(new byte[32], 0, 32); } } @@ -415,6 +400,43 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests Assert.Equal(LogLevel.Debug, loggerProvider.FilterLogger.LastLogLevel); } + [Fact] + public async Task ClientAttemptingToUseUnsupportedProtocolIsLoggedAsDebug() + { + var loggerProvider = new HandshakeErrorLoggerProvider(); + LoggerFactory.AddProvider(loggerProvider); + var hostBuilder = TransportSelector.GetWebHostBuilder() + .UseKestrel(options => + { + options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions => + { + listenOptions.UseHttps(TestResources.TestCertificatePath, "testPassword"); + }); + }) + .ConfigureServices(AddTestLogging) + .Configure(app => app.Run(httpContext => Task.CompletedTask)); + + using (var host = hostBuilder.Build()) + { + host.Start(); + + using (var socket = await HttpClientSlim.GetSocket(new Uri($"https://127.0.0.1:{host.GetPort()}/"))) + using (var stream = new NetworkStream(socket, ownsSocket: false)) + using (var sslStream = new SslStream(stream, true, (sender, certificate, chain, errors) => true)) + { + // SslProtocols.Tls is TLS 1.0 which isn't supported by Kestrel by default. + await Assert.ThrowsAsync(() => + sslStream.AuthenticateAsClientAsync("127.0.0.1", clientCertificates: null, + enabledSslProtocols: SslProtocols.Tls, + checkCertificateRevocation: false)); + } + } + + await loggerProvider.FilterLogger.LogTcs.Task.DefaultTimeout(); + Assert.Equal(1, loggerProvider.FilterLogger.LastEventId); + Assert.Equal(LogLevel.Debug, loggerProvider.FilterLogger.LastLogLevel); + } + private class HandshakeErrorLoggerProvider : ILoggerProvider { public HttpsConnectionFilterLogger FilterLogger { get; } = new HttpsConnectionFilterLogger(); diff --git a/test/Kestrel.FunctionalTests/ResponseTests.cs b/test/Kestrel.FunctionalTests/ResponseTests.cs index 99e2113b6c..6df4f10abf 100644 --- a/test/Kestrel.FunctionalTests/ResponseTests.cs +++ b/test/Kestrel.FunctionalTests/ResponseTests.cs @@ -3122,7 +3122,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests var chunkData = new byte[chunkSize]; var requestAborted = false; - var appFuncCompleted = new TaskCompletionSource(); + var appFuncCompleted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var mockKestrelTrace = new Mock(); var testContext = new TestServiceContext diff --git a/version.props b/version.props index 44985cedb3..bebad1de91 100644 --- a/version.props +++ b/version.props @@ -1,4 +1,4 @@ - + 2.2.0 preview1