Skip to content

Commit 655dbae

Browse files
committed
Validate cached options on load
1 parent 885eef2 commit 655dbae

File tree

4 files changed

+35
-22
lines changed

4 files changed

+35
-22
lines changed

src/Servers/Kestrel/Core/src/Internal/ConfigurationReader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private Dictionary<string, SniConfig> ReadSni(IConfigurationSection sniConfig)
124124
// },
125125
// "ClientCertificateMode" : "NoCertificate"
126126
// },
127-
// "b.example.org": {
127+
// "*.example.org": {
128128
// "Certificate": {
129129
// "Path": "testCert2.pfx",
130130
// "Password": "testPassword"
@@ -219,7 +219,7 @@ internal class EndpointDefaults
219219
// },
220220
// "ClientCertificateMode" : "NoCertificate"
221221
// },
222-
// "b.example.org": {
222+
// "*.example.org": {
223223
// "Certificate": {
224224
// "Path": "testCert2.pfx",
225225
// "Password": "testPassword"

src/Servers/Kestrel/Core/src/Internal/SniOptionsSelector.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Security.Authentication;
88
using Microsoft.AspNetCore.Server.Kestrel.Https;
99
using Microsoft.AspNetCore.Server.Kestrel.Https.Internal;
10+
using Microsoft.Extensions.Logging;
1011

1112
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
1213
{
@@ -24,7 +25,8 @@ public SniOptionsSelector(
2425
KestrelConfigurationLoader configLoader,
2526
EndpointConfig endpointConfig,
2627
HttpsConnectionAdapterOptions fallbackOptions,
27-
HttpProtocols fallbackHttpProtocols)
28+
HttpProtocols fallbackHttpProtocols,
29+
ILogger logger)
2830
{
2931
_endpointName = endpointConfig.Name;
3032

@@ -41,7 +43,10 @@ public SniOptionsSelector(
4143
}
4244

4345
sslServerOptions.EnabledSslProtocols = sniConfig.SslProtocols ?? fallbackOptions.SslProtocols;
44-
HttpsConnectionMiddleware.ConfigureAlpn(sslServerOptions, sniConfig.Protocols ?? fallbackHttpProtocols);
46+
47+
var httpProtocols = sniConfig.Protocols ?? fallbackHttpProtocols;
48+
httpProtocols = HttpsConnectionMiddleware.ValidateAndNormalizeHttpProtocols(httpProtocols, logger);
49+
HttpsConnectionMiddleware.ConfigureAlpn(sslServerOptions, httpProtocols);
4550

4651
var clientCertificateMode = sniConfig.ClientCertificateMode ?? fallbackOptions.ClientCertificateMode;
4752

src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ public void Load()
318318
}
319319
else
320320
{
321-
sniOptionsSelector = new SniOptionsSelector(this, endpoint, httpsOptions, listenOptions.Protocols);
321+
var logger = Options.ApplicationServices.GetRequiredService<ILogger<KestrelConfigurationLoader>>();
322+
sniOptionsSelector = new SniOptionsSelector(this, endpoint, httpsOptions, listenOptions.Protocols, logger);
322323
}
323324
}
324325

src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,7 @@ public HttpsConnectionMiddleware(ConnectionDelegate next, HttpsConnectionAdapter
5858
_options = options;
5959
_logger = loggerFactory.CreateLogger<HttpsConnectionMiddleware>();
6060

61-
// This configuration will always fail per-request, preemptively fail it here. See HttpConnection.SelectProtocol().
62-
if (options.HttpProtocols == HttpProtocols.Http2)
63-
{
64-
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
65-
{
66-
throw new NotSupportedException(CoreStrings.Http2NoTlsOsx);
67-
}
68-
else if (IsWindowsVersionIncompatible())
69-
{
70-
throw new NotSupportedException(CoreStrings.Http2NoTlsWin81);
71-
}
72-
}
73-
else if (options.HttpProtocols == HttpProtocols.Http1AndHttp2 && IsWindowsVersionIncompatible())
74-
{
75-
_logger.Http2DefaultCiphersInsufficient();
76-
options.HttpProtocols = HttpProtocols.Http1;
77-
}
61+
_options.HttpProtocols = ValidateAndNormalizeHttpProtocols(_options.HttpProtocols, _logger);
7862

7963
_next = next;
8064
// capture the certificate now so it can't be switched after validation
@@ -369,6 +353,29 @@ private static X509Certificate2 ConvertToX509Certificate2(X509Certificate certif
369353
return new X509Certificate2(certificate);
370354
}
371355

356+
internal static HttpProtocols ValidateAndNormalizeHttpProtocols(HttpProtocols httpProtocols, ILogger logger)
357+
{
358+
// This configuration will always fail per-request, preemptively fail it here. See HttpConnection.SelectProtocol().
359+
if (httpProtocols == HttpProtocols.Http2)
360+
{
361+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
362+
{
363+
throw new NotSupportedException(CoreStrings.Http2NoTlsOsx);
364+
}
365+
else if (IsWindowsVersionIncompatible())
366+
{
367+
throw new NotSupportedException(CoreStrings.Http2NoTlsWin81);
368+
}
369+
}
370+
else if (httpProtocols == HttpProtocols.Http1AndHttp2 && IsWindowsVersionIncompatible())
371+
{
372+
logger.Http2DefaultCiphersInsufficient();
373+
return HttpProtocols.Http1;
374+
}
375+
376+
return httpProtocols;
377+
}
378+
372379
private static bool IsWindowsVersionIncompatible()
373380
{
374381
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))

0 commit comments

Comments
 (0)