Problem
I have a simple web service call for a web service developed in C# that was generated by a.NET (C#) 2.0 Windows app via the web service proxy generated by Visual Studio (2.0). This has worked for several years and continues to operate in the dozen or so locations where it is now implemented.
A problem has arisen during the installation of a new system at a new location. When trying to use the web service, it fails with the following message:
The web service’s URL employs SSL (https://), although this has worked (and continues to operate) from many other locations for a long time.
What should I look for? Is there a security concern with Windows and.NET that is specific to this installation? If that’s the case, how do I establish trust relationships? I’m completely lost!
Asked by Rob Schripsema
Solution #1
The excerpts below will repair an issue with the SSL certificate on the server you’re calling. It could be self-signed, or the certificate and the server’s host names could be different.
This is risky if you’re calling a server that isn’t under your direct control, because you can’t be sure you’re talking to the server you believe you’re talking to. If you’re dealing with internal servers and getting a “proper” certificate isn’t an option, use the following command to inform the web service to ignore the certificate issues and boldly continue.
The first two are written as lambda expressions, while the third is written in ordinary code. Any certificate is accepted by the first. The latter two at the very least verify that the host name in the certificate matches what you anticipate.
//Trust all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
// trust sender
System.Net.ServicePointManager.ServerCertificateValidationCallback
= ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));
// validate cert by calling a function
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);
// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
bool result = cert.Subject.Contains("YourServerName");
return result;
}
Answered by Sebastian Castaldi
Solution #2
This is the very simple “catch-all” solution:
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Sebastian-solution castaldi’s is a little more detailed.
Answered by Remy
Solution #3
Thoughts (based on prior suffering):
Answered by Marc Gravell
Solution #4
The following solution appeals to me the most:
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
…then perform the following before submitting the request for the error.
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
After consulting Luke’s Solution, I discovered this.
Answered by cusman
Solution #5
If you don’t want to blindly trust everyone and instead want to set a trust exception for specific hosts, the following technique is better.
public static class Ssl
{
private static readonly string[] TrustedHosts = new[] {
"host1.domain.com",
"host2.domain.com"
};
public static void EnableTrustedHosts()
{
ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, errors) =>
{
if (errors == SslPolicyErrors.None)
{
return true;
}
var request = sender as HttpWebRequest;
if (request != null)
{
return TrustedHosts.Contains(request.RequestUri.Host);
}
return false;
};
}
}
Then simply dial Ssl. When your app starts, enableTrustedHosts.
Answered by Gregor Slavec
Post is based on https://stackoverflow.com/questions/703272/could-not-establish-trust-relationship-for-ssl-tls-secure-channel-soap