In a previous posting, I mentioned that even though System.DirectoryServices (SDS) and System.DirectoryServices.Protocols (SDS.P) share a lot of overlap in functionality, there are some important things that can only be done in SDS.P. One that I mentioned is handling server and client certificates that are using when doing SSL/LDAP.
Both SDS and SDS.P support SSL/LDAP. Basically, if your server is configured to support SSL (and both AD and ADAM can support this, although neither have the required certificates provisioned "out of the box"), you can just turn on SSL LDAP with the appropriate setting and it will just work. However, SDS doesn't give you much control over the process. It doesn't expose any information about the certificate the server supplied, nor does it let you choose which client certificate to use (if a choice is possible). Additionally, if there is a problem with the server's certificate such a certificate trust issue or expiration, with SDS, that is automatically counted as an error.
In SDS.P, we get more control. Not only can I inspect the certificate to find out information about it, but i can select my own client certificate and I have control over whether or not to trust the server's certificate if I want. I can thus choose to ignore potential problems (at my peril, of course) and connect anyway.
SDS.P implements the client and server certificate verification stuff via callbacks implemented as delegates, specifically the QueryClientCertificateCallback and VerifyServerCertificateCallback delegates. In order to use them, you create a method with the matching signature of the delegate and then set the LdapSessionOptions.QueryClientCertificate or LdapSessionOptions.VerifyServerCertificate properties for options set up on your LdapConnection. Do this before you bind. BTW, the LdapSessionOptions class is where a lot of the cool advanced features are in SDS.P that allow you access to features not exposed by SDS. It is worth spending some time staring at it. :)
Here is a brief code snippet example of doing this in C#:
LdapConnection con = new LdapConnection(new LdapDirectoryIdentifier(dc + ":636", true, false));con.SessionOptions.SecureSocketLayer = true;con.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(ServerCallback);con.SessionOptions.QueryClientCertificate = new QueryClientCertificateCallback(ClientCallback);
Here, the method ServerCallback looks something like this:
public static bool ServerCallback(LdapConnection connection, X509Certificate certificate){//do some stuff here}
The Sample App
Now, let's put this together into a useful example. In my scenario here, I have an AD domain with third-party issued certificates that I'm responsible for maintaining by hand. If these certificates expire, my apps that use SSL/LDAP may break and cause me embarassment and scorn amongst my colleagues (or worse). As such, I'd like to have a list of the certificates on my DCs in order of expiration, so that I can plan my renewal/replacement work in advance.
The sample code shows how we can use the VerifyServerCertificateCallback to simply grab the server's current certificate and find its expiration date. It shoves that into an in memory data structure and eventually dumps out the results to the console. The sample shows the power of the new System.DirectoryServices.ActiveDirectory (SDS.AD) namespace to quickly and easily enumerate the DCs in my domain with no hassle. This also shows how these two different LDAP stacks can be integrated to do the things that each is best at.
For good measure, I tried to make the sample fast. We might have a lot of DCs, so instead of querying them one at a time and waiting for all that network stuff to happen, why not use the .NET thread pool and let it hit them "simultaneously" (more or less)? Try that with that goofy script stuff. :)
I wrote this sample using Jeff Key's fantastic Snippet Compiler 2, which is a nice tool for rattling off quicky .NET stuff. It doesn't make you bust out VS.NET and create a whole project for throwaway stuff. It also doesn't make you buy VS.NET, although Microsoft has made that easier with the express editions. Sure, you can always use the free SDK, but this is quite a bit easier to use than notepad and a hand-written MSBuild file. You'll need assembly references to mscorlib,system,system.directoryservices and system.directoryservices.protocols. You'll obviously need the .NET 2.0 runtime installed to use the binary.
Enjoy! All feedback is appreciated.
Remember Me
Theme design by Jelle Druyts
Powered by: newtelligence dasBlog 1.9.6264.0
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2008, Joseph E. Kaplan
E-mail