简体   繁体   中英

How do I use SSL certificates with HttpWebRequest in C#?

Currently I'm writing a utility application that will connect to a given IP and port and check the information in the SSL certificate using HttpWebRequest. When I try to extract the certificate I get an error that an exception was thrown. The exception seems to be because the act of coping the SSL certificate seems to trigger yet another validation check.

Here is the code, and maybe someone can either show me a better way to do this or if I am missing something. I don't care if the SSL Certificate is expired or doesn't match the URL. None of that is relevant for what I'm doing.

When I assign the X509Certificate in the delegate to a new variable, and look at the variable in the debugger, all the properties show SSLCert.Issuer threw an exception of type 'System.Security.Cryptography.CyrptographicException'

When I try to access a property of SSLCert, I get the following Exception thrown: m_safeCertContext is an invalid handle

I'be searched for that exception, but everything points to an invalid certificate, which might be true if the certificate is expired, and might be true for the IP and port combination I am connecting to. But since I am connecting to the IP using the IP and not anything that would match the common name, I expect that and could care less as I still need the information.

The code is below, I put some comments in as well for what doesn't work and what does work.

 // To get around the SSL validation in the HttpWebRequest
        System.Net.ServicePointManager.ServerCertificateValidationCallback =
            delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                        System.Security.Cryptography.X509Certificates.X509Chain chain,
                        System.Net.Security.SslPolicyErrors sslPolicyErrors)
            {
                // The below works but isn't what I want. CertName and ExpireDate are both Strings
                this.CertName = ProcessSubject(certificate.Subject);
                this.ExpireDate = certificate.GetExpirationDateString();
                // The below works but the X509Certificate SSLCert shows exceptions in the debugger for most of the properties.
                this.SSLCert = certificate;

                return true; // **** Always accept
            };
        HttpWebRequest myRequest = (HttpWebRequest)System.Net.WebRequest.Create("https://" + this.IP + ":" + this.Port + "/SSLCheck.html");
        myRequest.KeepAlive = false;
        myRequest.Method = "GET";

        try
        {
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
        }
        catch (Exception e)
        {
            if (e.Message != "The remote server returned an error: (404) Not Found.")
            {
                throw Exception("Error");
            }

        }

        // THE BELOW FAILS
        this.CertName = this.SSLCert.Subject;

This is just a guess on my part. WHat I think is happening is that the certificate info coming through in the SSL handshake is used by .NET to create a cert object that is passed to you in the delegate. The delegate is only to be used for the purpose of validation. After the call completes, .NET closes the safe handle of the certificate. THat is why the call fails when trying to access the certificate outside the callback.

TO get around this, you can serialize the certificate inside the delegate, and deserialize it outside the delegate.

(Edit from our comments below)

I suppose what you need to do is create a custom class and store the data you need in it inside the delegate code, rather than pass around the actual certificate reference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM