Certificate Validation Callbacks in Indigo

A while back I hinted that there was another way to get solve the certificate problem when using the Https security mode in Indigo. It turns out that it's possible to register a System.Net.Security.RemoteCertificateValidationCallback event handler on the client to do custom validation of the certificate provided by the service. This gave me the hook I needed to check whether the provided certificate contained the correct DNS name even though the URL for the service specified localhost as the address.
 
The signature for the event handler is a little daunting;
 
public delegate bool RemoteCertificateValidationCallback ( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors  errors );
 
but it turns out to be fairly easy to implement what I'm looking for. Here's the event handler implementation I used;
 
staticbool ValidateServerCert(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
  bool bRet = false;
  if (cert.Subject.StartsWith("CN=")) {
    if (cert.Subject.Substring(cert.Subject.IndexOf('=') + 1).StartsWith(Dns.GetHostName()))
      bRet = true;
  }
 
  return bRet;
}
 
The code above just pulls out the Subject field of the X509 certificate and checks to make sure that the name begins with the hostname of the machine I'm actually running on. Given that I know my URL is localhost, then provided the machine name is actually my machine name, I know I'm good to go.
 
The rest of the client code looks like this;
 
staticvoid Main(string[] args)
{
  ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCert);
  ChannelFactory<ISimpleChannel> cf = newChannelFactory<ISimpleChannel>("SecurityBasicEndpointConfig");
  ISimpleChannel sc = cf.CreateChannel();
  Console.WriteLine("{0}", sc.Ping("Hello, World!"));
}
 
Note the registration of the event handler with the ServicePointManager. The config file for the client looks like this;
 
<configurationxmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" >
 <system.serviceModel>
  <bindings>
   <basicProfileBinding>
    <bindingconfigurationName="SecurityBasicClientBinding"securityMode ="Https" />
   </basicProfileBinding>
  </bindings>
  <client>
   <endpointconfigurationName="SecurityBasicEndpointConfig"
                 address="https://localhost:8088/securitybasic"
                 bindingSectionName="basicProfileBinding"
                 bindingConfiguration="SecurityBasicClientBinding"
                 contractType="Gudge.Samples.ISimple, Client" />
  </client>
 </system.serviceModel>
</configuration>
 
The server side code looks just like that shown earlier while the the config looks like this;
 
<configurationxmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" >
 <system.serviceModel>
  <bindings>
   <basicProfileBinding>
    <bindingconfigurationName="SecurityBasicServiceBinding" 
             securityMode
="Https" />
   </basicProfileBinding>
  </bindings>
  <services>
   <serviceserviceType="Gudge.Samples.Service" >
    <endpointaddress="https://localhost:8088/securitybasic"
              bindingSectionName="basicProfileBinding"
              bindingConfiguration="SecurityBasicServiceBinding"
              contractType="Gudge.Samples.ISimple, Service" />
   </service>
  </services>
 </system.serviceModel>
</configuration>
 
That's it. The above allows me to use localhost in my config files for client and service while still having the client code work correctly. And I get to check that the subject of the certificate matches my machine name. Much more sophisticated certificate validation can be performed, but this approach did what I needed it to do in this specific case. You probably wouldn't want to run my validation handler in any cases where the URLs in play were NOT specifying localhost for the machine name.

Posted Jul 13 2005, 09:50 PM by martin-gudgin

Comments

Damir Dobric Posts wrote Securing WCF (Windows Communication Foundation) transport wit SSL
on 06-28-2006 5:18 PM
Securing WCF (Windows Communication Foundation) transport
&nbsp;
WCF provides mechanism of securing...

Add a Comment

(required)  
(optional)
(required)  
Remember Me?