Skip to content

Commit ebc3c51

Browse files
wtgodbeJamesNKTratcher
authored
Throw when unsupported HTTPS options are set for HTTP/3 (dotnet#35532)
* Throw when using OnAuthenticate in HTTP3 * Add exceptions * Add tests * Update src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs Co-authored-by: James Newton-King <james@newtonking.com> * Update src/Servers/Kestrel/Core/src/ListenOptionsHttpsExtensions.cs Co-authored-by: James Newton-King <james@newtonking.com> * Update src/Servers/Kestrel/Core/src/ListenOptionsHttpsExtensions.cs Co-authored-by: James Newton-King <james@newtonking.com> * Update src/Servers/Kestrel/Core/src/ListenOptionsHttpsExtensions.cs Co-authored-by: Chris Ross <chrross@microsoft.com> * Fixup Co-authored-by: James Newton-King <james@newtonking.com> Co-authored-by: Chris Ross <chrross@microsoft.com>
1 parent d2421ad commit ebc3c51

File tree

4 files changed

+71
-30
lines changed

4 files changed

+71
-30
lines changed

src/Servers/Kestrel/Core/src/ListenOptionsHttpsExtensions.cs

+9
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ public static ListenOptions UseHttps(this ListenOptions listenOptions, ServerOpt
256256
/// <returns>The <see cref="ListenOptions"/>.</returns>
257257
public static ListenOptions UseHttps(this ListenOptions listenOptions, ServerOptionsSelectionCallback serverOptionsSelectionCallback, object state, TimeSpan handshakeTimeout)
258258
{
259+
if (listenOptions.Protocols.HasFlag(HttpProtocols.Http3))
260+
{
261+
throw new NotSupportedException($"{nameof(UseHttps)} with {nameof(ServerOptionsSelectionCallback)} is not supported with HTTP/3.");
262+
}
259263
return listenOptions.UseHttps(new TlsHandshakeCallbackOptions()
260264
{
261265
OnConnection = context => serverOptionsSelectionCallback(context.SslStream, context.ClientHelloInfo, context.State, context.CancellationToken),
@@ -283,6 +287,11 @@ public static ListenOptions UseHttps(this ListenOptions listenOptions, TlsHandsh
283287
throw new ArgumentException($"{nameof(TlsHandshakeCallbackOptions.OnConnection)} must not be null.");
284288
}
285289

290+
if (listenOptions.Protocols.HasFlag(HttpProtocols.Http3))
291+
{
292+
throw new NotSupportedException($"{nameof(UseHttps)} with {nameof(TlsHandshakeCallbackOptions)} is not supported with HTTP/3.");
293+
}
294+
286295
var loggerFactory = listenOptions.KestrelServerOptions?.ApplicationServices.GetRequiredService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
287296

288297
listenOptions.IsTls = true;

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

+5
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,11 @@ private static bool IsWindowsVersionIncompatibleWithHttp2()
510510

511511
internal static SslServerAuthenticationOptions CreateHttp3Options(HttpsConnectionAdapterOptions httpsOptions)
512512
{
513+
if (httpsOptions.OnAuthenticate != null)
514+
{
515+
throw new NotSupportedException($"The {nameof(HttpsConnectionAdapterOptions.OnAuthenticate)} callback is not supported with HTTP/3.");
516+
}
517+
513518
// TODO Set other relevant values on options
514519
var sslServerAuthenticationOptions = new SslServerAuthenticationOptions
515520
{

src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs

+30-30
Original file line numberDiff line numberDiff line change
@@ -593,44 +593,44 @@ public async Task Http3_NoUseHttps_Throws()
593593
}
594594

595595
[Fact]
596-
public async Task Http3_UseHttp3Callback_NoSslServerOptions()
596+
public void Http3_ServerOptionsSelectionCallback_Throws()
597597
{
598598
var serverOptions = CreateServerOptions();
599599
serverOptions.DefaultCertificate = _x509Certificate2;
600600

601-
IFeatureCollection bindFeatures = null;
602-
var multiplexedConnectionListenerFactory = new MockMultiplexedConnectionListenerFactory();
603-
multiplexedConnectionListenerFactory.OnBindAsync = (ep, features) =>
601+
serverOptions.ListenLocalhost(5001, options =>
604602
{
605-
bindFeatures = features;
606-
};
607-
608-
var testContext = new TestServiceContext(LoggerFactory);
609-
testContext.ServerOptions = serverOptions;
610-
await using (var server = new TestServer(context => Task.CompletedTask,
611-
testContext,
612-
serverOptions =>
613-
{
614-
serverOptions.ListenLocalhost(5001, listenOptions =>
603+
options.Protocols = HttpProtocols.Http3;
604+
var exception = Assert.Throws<NotSupportedException>(() =>
605+
options.UseHttps((SslStream stream, SslClientHelloInfo clientHelloInfo, object state, CancellationToken cancellationToken) =>
615606
{
616-
listenOptions.Protocols = HttpProtocols.Http3;
617-
listenOptions.UseHttps((SslStream stream, SslClientHelloInfo clientHelloInfo, object state, CancellationToken cancellationToken) =>
618-
{
619-
return ValueTask.FromResult((new SslServerAuthenticationOptions()));
620-
}, state: null);
621-
});
622-
},
623-
services =>
624-
{
625-
services.AddSingleton<IMultiplexedConnectionListenerFactory>(multiplexedConnectionListenerFactory);
626-
}))
627-
{
628-
}
607+
return ValueTask.FromResult((new SslServerAuthenticationOptions()));
608+
}, state: null)
609+
);
610+
Assert.Equal("UseHttps with ServerOptionsSelectionCallback is not supported with HTTP/3.", exception.Message);
611+
});
612+
}
629613

630-
Assert.NotNull(bindFeatures);
614+
[Fact]
615+
public void Http3_TlsHandshakeCallbackOptions_Throws()
616+
{
617+
var serverOptions = CreateServerOptions();
618+
serverOptions.DefaultCertificate = _x509Certificate2;
631619

632-
var sslOptions = bindFeatures.Get<SslServerAuthenticationOptions>();
633-
Assert.Null(sslOptions);
620+
serverOptions.ListenLocalhost(5001, options =>
621+
{
622+
options.Protocols = HttpProtocols.Http3;
623+
var exception = Assert.Throws<NotSupportedException>(() =>
624+
options.UseHttps(new TlsHandshakeCallbackOptions()
625+
{
626+
OnConnection = context =>
627+
{
628+
return ValueTask.FromResult(new SslServerAuthenticationOptions());
629+
}
630+
})
631+
);
632+
Assert.Equal("UseHttps with TlsHandshakeCallbackOptions is not supported with HTTP/3.", exception.Message);
633+
});
634634
}
635635

636636
[Fact]

src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3TlsTests.cs

+27
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,33 @@ public async Task ClientCertificate_Allow_NotAvailable_Optional()
227227
await host.StopAsync().DefaultTimeout();
228228
}
229229

230+
[ConditionalFact]
231+
[MsQuicSupported]
232+
public async Task OnAuthentice_Available_Throws()
233+
{
234+
var builder = CreateHostBuilder(async context =>
235+
{
236+
await context.Response.WriteAsync("Hello World");
237+
}, configureKestrel: kestrelOptions =>
238+
{
239+
kestrelOptions.ListenAnyIP(0, listenOptions =>
240+
{
241+
listenOptions.Protocols = HttpProtocols.Http3;
242+
listenOptions.UseHttps(httpsOptions =>
243+
{
244+
httpsOptions.OnAuthenticate = (_, _) => { };
245+
});
246+
});
247+
});
248+
249+
using var host = builder.Build();
250+
using var client = Http3Helpers.CreateClient();
251+
252+
var exception = await Assert.ThrowsAsync<NotSupportedException>(() =>
253+
host.StartAsync().DefaultTimeout());
254+
Assert.Equal("The OnAuthenticate callback is not supported with HTTP/3.", exception.Message);
255+
}
256+
230257
private IHostBuilder CreateHostBuilder(RequestDelegate requestDelegate, HttpProtocols? protocol = null, Action<KestrelServerOptions> configureKestrel = null)
231258
{
232259
return Http3Helpers.CreateHostBuilder(AddTestLogging, requestDelegate, protocol, configureKestrel);

0 commit comments

Comments
 (0)