Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set the 'ServerCertificateValidationCallback' property back to its default behavior?

I use the following line of code within a single method to explicitly check and trust an SSL cert from the following host: MyTrustedCompany.com:

ServicePointManager.ServerCertificateValidationCallback = Function(obj As [Object], certificate As X509Certificate, chain As X509Chain, errors As SslPolicyErrors) (certificate.Subject.Contains("CN=MyTrustedCompany.com"))

No problem with the code -> works perfectly 100%.

The problem is, it is too far reaching. I thought its scope would only be within the method I decalred it, but apparently it is a Shared property on the 'ServicePointManager' object, and must then persist for the entire application, which I do not want.

The problem is later I am calling web services of mine, etc and getting the "Could not establish a trust relationship..." exception. This is because in the line of code above I check for the host name of an SSL cert specefic to that method. I quickly tested Returning 'True' from the callback so all certs would be trusted instead of checking for a specefic name (i.e. MyTrustedCompany) and subsiquent requests worked. This is how I know this callback assignment reaches father than that single method. Sure I could extend the callback to include all other certitificate names, but what I would rather do is set the 'ServerCertificateValidationCallback' back to its default behavior. Like the pseudo code below:

ServicePointManager.ServerCertificateValidationCallback = Nothing  'Default checking behavior

How do I remove the custom validation and set it back to its default behavior? Thanks!

like image 520
atconway Avatar asked Nov 11 '10 16:11

atconway


2 Answers

This actually appears to work (as simple as it is) and makes the object behave in its default manner.

ServicePointManager.ServerCertificateValidationCallback = Nothing
like image 104
atconway Avatar answered Oct 07 '22 19:10

atconway


You'll want to only return true for certain URLs, but otherwise, this does what you want, leaving the possibility of using multiple delegates. The logic for each callback could include a check via reflection so that the callback only returns true when called from certain components, thus creating a sort of tunnel between certain URLs and certain applications.

One way to use this code: 1. Define the mIgnoreBadCertificates delegate early in your object's life 2. Set a property containing the 'beSecure' code true 3. Send the Http Request. 4. Set the property false. This is very important, and should be implemented in a way that guarantees it gets called. The IDisposable pattern is one option.

 private System.Net.Security.RemoteCertificateValidationCallback mIgnoreBadCertificates = new
    System.Net.Security.RemoteCertificateValidationCallback(
      delegate { return true; });

if (beSecure)
    {   //require secure communications
        System.Net.ServicePointManager.ServerCertificateValidationCallback -= mIgnoreBadCertificates;
        Iwds.EventLogger.LogVeryFrequentEvent("Requiring Good Certificates from Remote Sites");
    }
    else
    {   /// Allow connections to SSL sites that have unsafe certificates.
        System.Net.ServicePointManager.ServerCertificateValidationCallback += mIgnoreBadCertificates;
        Iwds.EventLogger.LogVeryFrequentEvent("Ignoring Bad Certificates from Remote Sites");
    }
like image 20
Tom Avatar answered Oct 07 '22 18:10

Tom