Our application currently validates server certificates in unmanaged code using openssl (http://www.openssl.org/docs/crypto/X509_verify_cert.html). We are moving that into managed code. I have the X509 certificate being marshalled over into the managed side, but how to validate that certificate in C#?
a) Is there a simple way to validate that certificate against the currently installed trusted roots?
b) If not, what is the manual process to validate? Is it documented somewhere?
I've explored the classes in Mono.Security.X509, which gives me tools to work with certificates and stores, but I'm having trouble connecting the dots.
EDIT I added my ultimate solution below. I would welcome further feedback on the approach.
Based on the information here and here, I determine the following:
For a simple example, we can use Mono X509Chain to build a certificate chain and validate it against the user trusted roots:
var x509 = new Mono.Security.X509.X509Certificate(certificateBytes);
var chain = new Mono.Security.X509.X509Chain();
bool certificateStatus = chain.Build(x509);
From examining the Mono source, I can see that this checks the trust on the certificate chain and also the dates on the certificate. Certificate revocation is not implemented, however.
We also check that the name on the cert matches the name of the host the user is connecting to. The .NET framework gives us an easy way to get that info:
var x5092 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificateBytes);
string hostName = x5092.GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType.DnsName, false);
bool hostNameMatch = string.Compare(hostName, this.Server, true) == 0;
Certificates can also have alternative names that should be checked, but using X509NameType.DnsAlternativeName
doesn't seem to be implemented on Mono (it's hard-coded to return string.Empty
).
As far as I can see this is a good, basic solution.