I\'m trying to bypass https certificate validation only to our own testing environment (multiple machines), while trying to keep certificate validation for all the other connect
Seems like in .NET 4.5 you can do the following:
var request = (HttpWebRequest)WebRequest.Create(url);
request.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => true
I did not realize it initially, as you actually have to cast result of Create
method to HttpWebRequest
, as abstract WebRequest
does not contain this delegate.
You actually can disable SSL cert validation per client/channel with this code:
var noCertValidationAuth = new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None
};
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = noCertValidationAuth;
It is actually a variation of answer in this thread, so kudos there.
Something like this:
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidateCert);
public static bool ValidateCert(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
string requestHost;
if(sender is string)
{
requestHost = sender.ToString();
}
else
{
HttpWebRequest request = sender as HttpWebRequest;
if(request != null)
{
requestHost = request.Host;
}
}
if(!string.IsNullOrEmpty(requestHost) && requestHost == "my_test_machine")
return true;
return sslPolicyErrors == SslPolicyErrors.None;
}
Note the documentation on the sender
parameter:
sender parameter passed to the RemoteCertificateValidationCallback can be a host string name or an object derived from WebRequest (HttpWebRequest, for example) depending on the CertificatePolicy property
Disclaimer - I didn't test this, I wrote it based on the documentation. YMMV.
What you could do is place a setting in Your web.config file.
Then in Your code check the value in the web.config file. Then set the certificate validation depending on that value.
Edit
One option is:
String url = "https://www.stackoverflow.com";
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };
Another is: http://weblog.west-wind.com/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors
Edit 2
Try something like this:
ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation;
private static bool customXertificateValidation(object sender, X509Certificate cert,
X509Chain chain, SslPolicyErrors error)
{
if (check something here)
{
return true;
}
return false;
}
I was finally able to found a real solution when using .net 4.5.
This code allows you to use a custom validator only for a specific WCF client.
It has been tested against BasicHttpBinding with BasicHttpSecurityMode.Transport
.
There is a new property named SslCertificateAuthentication in ClientBase.ClientCredentials.ServiceCertificate
.
You can initialize this property with a X509ServiceCertificateAuthentication where you can provide a custom X509CertificateValidator
.
For example:
// initialize the ssl certificate authentication
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.Custom,
CustomCertificateValidator = new CustomValidator(serverCert)
};
// simple custom validator, only valid against a specific thumbprint
class CustomValidator : X509CertificateValidator
{
private readonly X509Certificate2 knownCertificate;
public CustomValidator(X509Certificate2 knownCertificate)
{
this.knownCertificate = knownCertificate;
}
public override void Validate(X509Certificate2 certificate)
{
if (this.knownCertificate.Thumbprint != certificate.Thumbprint)
{
throw new SecurityTokenValidationException("Unknown certificate");
}
}
}
I used a flag in the Web.config file to indicate when a certificate is self-signed and we also know that we are in a development environment:
<add key="isSelfSignedCertificate" value="true"/>
In the code we must check this flag to apply the certificate validation exception:
using System.Net;
bool isSelfSignedCertificate = Convert.ToBoolean(ConfigurationManager.AppSettings["isSelfSignedCertificate"]);
if (isSelfSignedCertificate)
{
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
}