WCF per connection server certificate validation

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.


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.


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");
        }
    }
}

Tags:

C#

Wcf

Ssl