I need help to understand how to configure and how certificate revocations really work in Windows.
I'm testing a scenario where I have a self-signed certificate that will be the one for the root CA, another certificate for Intermediate CA signed by the root CA and then the Server certificate signed by the Intermediate CA.
I built a simple POC application (C#) that will create a TCP Server and a TCP Client, I added all the certificates to the correct stores, root to the trusted, intermediate to the intermediate and then the Server one to the personal.
The certificates look fine, if I select the one in the personal folder, the named Server certificate, I can see that the chain is correctly built up to the root.
The TCP server will use the Server certificate in the AuthenticateAsServer
method, then in the client I have a callback method to validate the server certificate and that's where I start to have problems...
I already tested 3 scenarios, all with "different" but similar outcomes:
As is, the method that validates the certificate returns only one status in the chain status property, "Revocation Status Unknown".
If I create a revocation list and added it to the store intermediate\certificate revocation list, the chain status returns 3 status, one saying that the certificate is revoked (so it uses the list installed in the store), another one with the "Revocation Status Unknown" and the third one something related to CRL Offline
If I use a simple endpoint (http://localhost/something.crl) that returns the revocation list (CRL file), and added this information to x509 extensions of the intermediate certificate, it returns 2 status, one with the "Revocation Status Unknown" and other with offline status (the endpoint it's working and I removed the list from the store).
To sum up, I don't know how to configure all of this, so the validate server certificate callback doesn't fail, with (installed or available in one endpoint) and without revocation list.
Thanks
I need help to understand how to configure and how certificate revocations really work in Windows.
I'm testing a scenario where I have a self-signed certificate that will be the one for the root CA, another certificate for Intermediate CA signed by the root CA and then the Server certificate signed by the Intermediate CA.
I built a simple POC application (C#) that will create a TCP Server and a TCP Client, I added all the certificates to the correct stores, root to the trusted, intermediate to the intermediate and then the Server one to the personal.
The certificates look fine, if I select the one in the personal folder, the named Server certificate, I can see that the chain is correctly built up to the root.
The TCP server will use the Server certificate in the AuthenticateAsServer
method, then in the client I have a callback method to validate the server certificate and that's where I start to have problems...
I already tested 3 scenarios, all with "different" but similar outcomes:
As is, the method that validates the certificate returns only one status in the chain status property, "Revocation Status Unknown".
If I create a revocation list and added it to the store intermediate\certificate revocation list, the chain status returns 3 status, one saying that the certificate is revoked (so it uses the list installed in the store), another one with the "Revocation Status Unknown" and the third one something related to CRL Offline
If I use a simple endpoint (http://localhost/something.crl) that returns the revocation list (CRL file), and added this information to x509 extensions of the intermediate certificate, it returns 2 status, one with the "Revocation Status Unknown" and other with offline status (the endpoint it's working and I removed the list from the store).
To sum up, I don't know how to configure all of this, so the validate server certificate callback doesn't fail, with (installed or available in one endpoint) and without revocation list.
Thanks
Share Improve this question edited Nov 18, 2024 at 7:50 MckPT asked Nov 16, 2024 at 19:27 MckPTMckPT 352 silver badges8 bronze badges 4 |1 Answer
Reset to default 1This sounds like a CRL availability issue at some point in the chain. I suggest looking closely at the results of the X509Chain
object provided to the RemoteCertificateValidationCallback
delegate in either the SslClientAuthenticationOptions()
or the SslStream
ctor.
The following code will help track down which certificate is causing the issue:
static bool ValidateRemoteCertificateAsClient(object sender,
X509Certificate? serverCertificate,
X509Chain? serverCertificateChain,
SslPolicyErrors sslPolicyErrors)
{
if(sslPolicyErrors == SslPolicyErrors.None)
{
Console.WriteLine("No errors found during validation");
return true;
}
if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != 0)
Console.WriteLine("Validation Error: Remote certificate not available");
if((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) != 0)
Console.WriteLine("Validation Error: Remote certificate name mis-match");
if((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
ArgumentNullException.ThrowIfNull(serverCertificateChain, nameof(serverCertificateChain));
ArgumentOutOfRangeException.ThrowIfZero(serverCertificateChain.ChainElements.Count,nameof(serverCertificateChain.ChainElements));
Console.WriteLine("Validation Error: One or more chain errors found.");
foreach (var chainElement in serverCertificateChain.ChainElements)
{
Console.WriteLine("Chain certificate: " + chainElement.Certificate.Subject);
if (chainElement.ChainElementStatus.Length == 0)
Console.WriteLine($" No validation errors found.");
else
{
foreach (var chainStatus in chainElement.ChainElementStatus)
{
Console.WriteLine(" Error: " + chainStatus.StatusInformation);
foreach (X509ChainStatusFlags flag in Enum.GetValues(typeof(X509ChainStatusFlags)))
{
if (flag != X509ChainStatusFlags.NoError && (chainStatus.Status & flag) != 0)
{
Console.WriteLine($" Flag: {flag} ({((int)flag)})");
}
}
}
}
}
}
return false;
}
https
instead ofhttp
(CRLs can't be fetched over HTTPS or the cert validation system would need to call itself) or b) you only provided CRLs for the bottom layer, but the X509Chain doing the work is set to do EntireChainExcludeRoot, so you're missing revocation data for the middle layer, or c) you issued both layers to the same file, and it's guaranteed wrong for at least one of them. – bartonjs Commented Nov 18, 2024 at 18:36