Skip to content

Throw when unsupported HTTPS options are set for HTTP/3 #35532

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ public static ListenOptions UseHttps(this ListenOptions listenOptions, ServerOpt
/// <returns>The <see cref="ListenOptions"/>.</returns>
public static ListenOptions UseHttps(this ListenOptions listenOptions, ServerOptionsSelectionCallback serverOptionsSelectionCallback, object state, TimeSpan handshakeTimeout)
{
if (listenOptions.Protocols.HasFlag(HttpProtocols.Http3))
{
throw new NotSupportedException($"{nameof(UseHttps)} with {nameof(ServerOptionsSelectionCallback)} is not supported with HTTP/3.");
}
return listenOptions.UseHttps(new TlsHandshakeCallbackOptions()
{
OnConnection = context => serverOptionsSelectionCallback(context.SslStream, context.ClientHelloInfo, context.State, context.CancellationToken),
Expand Down Expand Up @@ -283,6 +287,11 @@ public static ListenOptions UseHttps(this ListenOptions listenOptions, TlsHandsh
throw new ArgumentException($"{nameof(TlsHandshakeCallbackOptions.OnConnection)} must not be null.");
}

if (listenOptions.Protocols.HasFlag(HttpProtocols.Http3))
{
throw new NotSupportedException($"{nameof(UseHttps)} with {nameof(TlsHandshakeCallbackOptions)} is not supported with HTTP/3.");
}

var loggerFactory = listenOptions.KestrelServerOptions?.ApplicationServices.GetRequiredService<ILoggerFactory>() ?? NullLoggerFactory.Instance;

listenOptions.IsTls = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ private static bool IsWindowsVersionIncompatibleWithHttp2()

internal static SslServerAuthenticationOptions CreateHttp3Options(HttpsConnectionAdapterOptions httpsOptions)
{
if (httpsOptions.OnAuthenticate != null)
{
throw new NotSupportedException($"The {nameof(HttpsConnectionAdapterOptions.OnAuthenticate)} callback is not supported with HTTP/3.");
}

// TODO Set other relevant values on options
var sslServerAuthenticationOptions = new SslServerAuthenticationOptions
{
Expand Down
60 changes: 30 additions & 30 deletions src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -593,44 +593,44 @@ public async Task Http3_NoUseHttps_Throws()
}

[Fact]
public async Task Http3_UseHttp3Callback_NoSslServerOptions()
public void Http3_ServerOptionsSelectionCallback_Throws()
{
var serverOptions = CreateServerOptions();
serverOptions.DefaultCertificate = _x509Certificate2;

IFeatureCollection bindFeatures = null;
var multiplexedConnectionListenerFactory = new MockMultiplexedConnectionListenerFactory();
multiplexedConnectionListenerFactory.OnBindAsync = (ep, features) =>
serverOptions.ListenLocalhost(5001, options =>
{
bindFeatures = features;
};

var testContext = new TestServiceContext(LoggerFactory);
testContext.ServerOptions = serverOptions;
await using (var server = new TestServer(context => Task.CompletedTask,
testContext,
serverOptions =>
{
serverOptions.ListenLocalhost(5001, listenOptions =>
options.Protocols = HttpProtocols.Http3;
var exception = Assert.Throws<NotSupportedException>(() =>
options.UseHttps((SslStream stream, SslClientHelloInfo clientHelloInfo, object state, CancellationToken cancellationToken) =>
{
listenOptions.Protocols = HttpProtocols.Http3;
listenOptions.UseHttps((SslStream stream, SslClientHelloInfo clientHelloInfo, object state, CancellationToken cancellationToken) =>
{
return ValueTask.FromResult((new SslServerAuthenticationOptions()));
}, state: null);
});
},
services =>
{
services.AddSingleton<IMultiplexedConnectionListenerFactory>(multiplexedConnectionListenerFactory);
}))
{
}
return ValueTask.FromResult((new SslServerAuthenticationOptions()));
}, state: null)
);
Assert.Equal("UseHttps with ServerOptionsSelectionCallback is not supported with HTTP/3.", exception.Message);
});
}

Assert.NotNull(bindFeatures);
[Fact]
public void Http3_TlsHandshakeCallbackOptions_Throws()
{
var serverOptions = CreateServerOptions();
serverOptions.DefaultCertificate = _x509Certificate2;

var sslOptions = bindFeatures.Get<SslServerAuthenticationOptions>();
Assert.Null(sslOptions);
serverOptions.ListenLocalhost(5001, options =>
{
options.Protocols = HttpProtocols.Http3;
var exception = Assert.Throws<NotSupportedException>(() =>
options.UseHttps(new TlsHandshakeCallbackOptions()
{
OnConnection = context =>
{
return ValueTask.FromResult(new SslServerAuthenticationOptions());
}
})
);
Assert.Equal("UseHttps with TlsHandshakeCallbackOptions is not supported with HTTP/3.", exception.Message);
});
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,33 @@ public async Task ClientCertificate_Allow_NotAvailable_Optional()
await host.StopAsync().DefaultTimeout();
}

[ConditionalFact]
[MsQuicSupported]
public async Task OnAuthentice_Available_Throws()
{
var builder = CreateHostBuilder(async context =>
{
await context.Response.WriteAsync("Hello World");
}, configureKestrel: kestrelOptions =>
{
kestrelOptions.ListenAnyIP(0, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http3;
listenOptions.UseHttps(httpsOptions =>
{
httpsOptions.OnAuthenticate = (_, _) => { };
});
});
});

using var host = builder.Build();
using var client = Http3Helpers.CreateClient();

var exception = await Assert.ThrowsAsync<NotSupportedException>(() =>
host.StartAsync().DefaultTimeout());
Assert.Equal("The OnAuthenticate callback is not supported with HTTP/3.", exception.Message);
}

private IHostBuilder CreateHostBuilder(RequestDelegate requestDelegate, HttpProtocols? protocol = null, Action<KestrelServerOptions> configureKestrel = null)
{
return Http3Helpers.CreateHostBuilder(AddTestLogging, requestDelegate, protocol, configureKestrel);
Expand Down