From e0413903e5721c048125aa779fa7967f4adb573e Mon Sep 17 00:00:00 2001 From: David Fowler Date: Mon, 17 Aug 2020 12:20:10 -0700 Subject: [PATCH] Minimal changes to support certificate chain-preloading at startup (#24934) --- .../Kestrel/Core/src/Internal/SniOptionsSelector.cs | 7 +++++++ .../Core/src/Middleware/HttpsConnectionMiddleware.cs | 6 ++++++ src/Servers/Kestrel/Core/test/SniOptionsSelectorTests.cs | 5 ++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/SniOptionsSelector.cs b/src/Servers/Kestrel/Core/src/Internal/SniOptionsSelector.cs index 279ca5c65c..c5801c46be 100644 --- a/src/Servers/Kestrel/Core/src/Internal/SniOptionsSelector.cs +++ b/src/Servers/Kestrel/Core/src/Internal/SniOptionsSelector.cs @@ -68,6 +68,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal } } + if (sslOptions.ServerCertificate != null) + { + // This might be do blocking IO but it'll resolve the certificate chain up front before any connections are + // made to the server + sslOptions.ServerCertificateContext = SslStreamCertificateContext.Create((X509Certificate2)sslOptions.ServerCertificate, additionalCertificates: null); + } + if (!certifcateConfigLoader.IsTestMock && sslOptions.ServerCertificate is X509Certificate2 cert2) { HttpsConnectionMiddleware.EnsureCertificateIsAllowedForServerAuth(cert2); diff --git a/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs b/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs index eb8ab43591..b131323693 100644 --- a/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs +++ b/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs @@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Https.Internal // The following fields are only set by HttpsConnectionAdapterOptions ctor. private readonly HttpsConnectionAdapterOptions _options; + private readonly SslStreamCertificateContext _serverCertificateContext; private readonly X509Certificate2 _serverCertificate; private readonly Func _serverCertificateSelector; @@ -89,6 +90,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Https.Internal else { EnsureCertificateIsAllowedForServerAuth(_serverCertificate); + + // This might be do blocking IO but it'll resolve the certificate chain up front before any connections are + // made to the server + _serverCertificateContext = SslStreamCertificateContext.Create(_serverCertificate, additionalCertificates: null); } var remoteCertificateValidationCallback = _options.ClientCertificateMode == ClientCertificateMode.NoCertificate ? @@ -232,6 +237,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Https.Internal var sslOptions = new SslServerAuthenticationOptions { ServerCertificate = _serverCertificate, + ServerCertificateContext = _serverCertificateContext, ServerCertificateSelectionCallback = selector, ClientCertificateRequired = _options.ClientCertificateMode != ClientCertificateMode.NoCertificate, EnabledSslProtocols = _options.SslProtocols, diff --git a/src/Servers/Kestrel/Core/test/SniOptionsSelectorTests.cs b/src/Servers/Kestrel/Core/test/SniOptionsSelectorTests.cs index a2c2be973b..adbe314802 100644 --- a/src/Servers/Kestrel/Core/test/SniOptionsSelectorTests.cs +++ b/src/Servers/Kestrel/Core/test/SniOptionsSelectorTests.cs @@ -385,10 +385,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests { { "www.example.org", new SniConfig() } }; - var fallbackOptions = new HttpsConnectionAdapterOptions { - ServerCertificate = new X509Certificate2() + ServerCertificate = new X509Certificate2(TestResources.GetCertPath("aspnetdevcert.pfx"), "testPassword") }; var sniOptionsSelector = new SniOptionsSelector( @@ -761,7 +760,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests return null; } - var cert = new X509Certificate2(); + var cert = TestResources.GetTestCertificate(); CertToPathDictionary.Add(cert, certInfo.Path); return cert; }