Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
When you configure Kestler to use certificate authentication and a client sends certificate including an intermediate certificate to a server then server will fail the chain validation if it has the root CA in certificate store but doesn't have the intermediate certificate in the certificate store on Windows.
Expected Behavior
The chain validation should succeed, it should read the intermediate certificates from the TLS connection to build the chain.
Today the implementation is against RFC 5246, the RFC states about client certificate message: "This message conveys the client's certificate chain to the server; the server will use it when verifying the CertificateVerify message..." also it describes the structure "This is a sequence (chain) of certificates. The sender's certificate MUST come first in the list. Each following certificate MUST directly certify the one preceding it. Because certificate validation requires that root keys be distributed independently, the self-signed certificate that specifies the root certificate authority MAY be omitted from the chain, under the assumption that the remote end must already possess it in order to validate it in any case." I feel it clearly expects the server to do the validation using the chain that is sent (with the exception of root).
Steps To Reproduce
Create CA, intermediate and child certificates (e.g. like described https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-6.0#create-certificates-in-powershell)
You can use a simple web server with certificate authentication, e.g.:
using Microsoft.AspNetCore.Authentication.Certificate;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.ConfigureHttpsDefaults(options =>
options.ClientCertificateMode = ClientCertificateMode.AllowCertificate);
});
var app = builder.Build();
app.UseAuthentication();
app.UseHttpsRedirection();
app.MapGet("/", () => "Hello World!");
app.Run();
Put the CA into windows store where you have the server.
Then put on a different computer all 3 certificates into certificate stores and call the service from that computer. The service will ask you for a certificate, choose the child certificate.
Exceptions (if any)
No response
.NET Version
6.0.400
Anything else?
This was first risen as a ticket #42010 but the ticket was closed based on improvement to my other request "how to work around the issue" which was made more possible using making a connection context available (#33953). Nevertheless, the asp .net default code is still not following the TLS specification for client authentication (and it is hard to customize it to follow it).