ServerCertificateValidationCallback Recommendations

I am working on a project that uses some HTTP communication between two server servers. Servers use X509 certificates for authentication. Needless to say, when server A (client) establishes a connection with server B (server), there is an SSL / TLS check error, because the certificates used do not belong to trusted third parties.

Usually the way to handle it is ServicePointManager.ServerCertificateValidationCallback , for example:

 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => { return cert.GetCertHashString() == "xxxxxxxxxxxxxxxx"; }; 

This approach works, except that it is not perfect. In essence, this is a validation override procedure for EVERY HTTP request that an application executes. Thus, if another class tries to start an HTTP request, it will fail. Also, if another class overrides ServicePointManager.ServerCertificateValidationCallback for its own purposes, then my message starts to fail suddenly.

The only solution that comes to mind is creating a separate AppDomain to execute client HTTP requests. This will work, but it’s really stupid to do this just to make HTTP requests possible. The overhead will be overwhelming.

With this in mind, did anyone investigate whether there is a better practice in .NET that would allow access to web services when processing SSL / TLS client checks without affecting other web clients?

+14
c # ssl web-services webclient
Jan 03 '14 at 23:04
source share
3 answers

A valid (safe) methodology working in .NET 4.5+ is the use of HttpWebRequest . ServerCertificateValidationCallback HttpWebRequest . ServerCertificateValidationCallback . Assigning this callback to a specific request instance changes the validation logic for the request only, without affecting other requests.

 var request = (HttpWebRequest)WebRequest.Create("https://..."); request.ServerCertificateValidationCallback += (sender, cert, chain, error) => { return cert.GetCertHashString() == "xxxxxxxxxxxxxxxx"; }; 
+15
Jun 15 '14 at 1:16
source share

A direct approach for this scenario would be to install two self-generated certificates in trusted root stores on client machines. When you do this, you will receive a security warning because certificates cannot be authenticated using Thawte or similar, but after this normal secure connection should work. IIRC, you need to install the full version (for both open and private) in a trusted root for this to work.

+5
Jan 03 '14 at 23:28
source share

Alternative for code that does not use HttpWebRequest, and for environments where you cannot install trusted certificates in the certificate store: Check the callback error parameter, which will contain any error detected before the callback. This way, you can ignore errors for specific hash strings, but accept other certificates that pass verification.

 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => { if (cert.GetCertHashString() == "xxxxxxxxxxxxxxxx") { return true; } else { return error == SslPolicyErrors.None; } }; 

Link: https://msdn.microsoft.com/en-us/library/system.net.security.remotecertificatevalidationcallback(v=vs.110).aspx

Please note that this will still affect other instances of the web client in the same appdomain (they will all accept the specified hash string), but at least it won’t block other certificates.

+4
Jun 23 '16 at 17:34
source share



All Articles