Skip to content

SslStream delayed client certificate negotiation #49346

Closed

Description

Background and Motivation

Related:
dotnet/aspnetcore#23948
#26210

Http servers like IIS, Http.Sys, HttpListener, etc. can conditionally request a client certificate after receiving the http request. Kestrel does not due to a lack of support in SslStream. Customers ask for this because they only want to require a client certificate for some pages/paths in their application.

Alternative strategies have proven too breaking for applications to adopt when moving from IIS to Kestrel.

Proposed API

namespace  System.Net.Security
{
    public class SslStream {

+   public Task<X509Certificate2?> GetClientCertificateAsync(CancellationToken cancellationToken)

No reads or writes would be allowed in parallel with this operation in order to avoid corrupting internal state.

Should successes and failures be cached? E.g. what happens if you call this API more than once per connection? What if a client cert was provided during the initial handshake?

What validation should happen on this certificate?

Risks

  • POST Deadlocks: It's common for Http.Sys users of this feature to deadlock for POST request scenarios if the TCP window fills up with body data before the certificate is requested.
    • The app can mitigate this by draining the expected data before requesting the certificate.
    • 100-continue mechanics can also be used to delay the request body, but that is timing sensitive.
    • SslStream should fail the connection if any application data is received while the client certificate request is outstanding. That avoids all questions about buffering or parallelism.
    • What about HTTP pipelining? An app processing one request at a time wouldn't know about pipelined requests.
  • In TLS 1.2 and lower the client certificate is requested by renegotiating the TLS context. This is called out as a security risk in the spec. Explore why.
  • TLS 1.3 has removed the renegotiation feature and replaced it with a dedicated extension for requesting the client certificate. The same public API should work across protocols.
  • HTTP/2 has explicitly banned renegotiation and the new TLS 1.3 extension due to head of line blocking. Kestrel will need to prevent this API from being called for HTTP/2 connections.
  • HTTP/3: Edit: Quic requires TLS 1.3 and explicitly prohibits the new extension.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions