I am using a HttpClientHandler
with a custom ServerCertificateCustomValidationCallback
.
I need, or at least would like to have, access to the certificate chain and the server certificate after the request is done. At the moment I just put both of them in class variables for access later.
Is this possible?
The behavior I'm seeing now is such that both objects cant be accessed after the validation.
I currently get a System.Security.Cryptography.CryptographicException
when I try to inspect the server certificate in my debugger. The chain appears to be empty.
The problem you face is caused because objects are disposed after leaving callback. You can copy certificate to local variable as follows:
class MyClass {
static X509Certificate2 localCert; // must be static
void MyMethod() {
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) =>
{
localCert = new X509Certificate2(cert.RawData);
// continue validation and return value
...
};
// do TLS connection
...
}
}
chain copy is a bit more complex, because you cannot serialize it. However, you can try to use p/invoke and duplicate chain handle by calling CertDuplicateCertificateChain function and passing existing chain handle as a parameter. That is, create another static field of type of X509Chain
and assign it this way inside callback function:
localChain = new X509Chain(Win32.CertDuplicateCertificateChain(chain.ChainContext));
function definition may be like this:
static class Win32 {
[DllImport("crypt32.dll", SetLastError = true)]
public static extern IntPtr CertDuplicateCertificateChain(IntPtr pChainContext);
[DllImport("crypt32.dll", SetLastError = true)]
public static extern void CertFreeCertificateChain(IntPtr pChainContext);
}
do not forget to manually dispose your local chain instance to avoid memory leak. I haven't tested this approach to copy chain, but this is what I would try first.