Thursday, August 17, 2006

Fast Concurrent Binding Overview

One of the things I alluded to in my post that highlighted the differences in capabilities between the ADSI-based System.DirectoryServices (SDS) namespace and the raw LDAP-based System.DirectoryServices.Protocols (SDS.P) was the ability to access a feature called Fast Concurrent Binding (FCB).

FCB is a feature available in Active Directory 2003 (and later) and in ADAM.  To explain it, first let’s cover what happens with a “regular” bind operation in LDAP against AD or ADAM.  With a normal bind, the user’s credentials are presented to the LDAP server, either in plaintext format or via the Windows security model if using a secure binding protocol.  The server then attempts to authenticate these credentials.  If the credentials are accepted, then the server builds a Windows token for the user which will be used to for performing security checks on future operations and changes the state of the current LDAP connection to an authenticated state so that future requests will continue to use the newly established security context and this operation is not repeated.  This is the main reason why LDAP connections are stateful.

FCB eliminates two parts of this equation.  It authenticates the user’s credentials, but it does not build a Windows token for the user and the connection state stays anonymous.  As such, the bind operation will give you an “up/down” result based on whether the user’s name and password were valid, but it won’t let you do anything else with that connection such as perform searches, except as an anonymous user (which is pretty limited by default in AD 2003 and ADAM).

The big upside of FCB is that the bind operation is MUCH faster than a normal bind because the really expensive operation, expanding the user’s group membership to build the token, is eliminated.  Hence the name fast concurrent binding.*

The concurrent part comes from the fact that multiple users can be authenticated on the same LDAP connection simultaneously without worrying about changing the authenticated state of the connection, so the expense of setting up and tearing down the associated socket can also be eliminated.  This makes it potentially even faster.

The big downside with FCB is that it only supports LDAP simple bind, not SASL, and simple bind does not have a built in mechanism for protecting the credentials on the wire like the various SASL mechanisms do.  As such, it is never safe to use FCB unless some form of transport security is used such as SSL or IPSEC!

When to Use Fast Concurrent Binding

Do use FCB when your application is doing pure authentication of credentials via LDAP.  An example of this might be in a web-based application that uses AD or ADAM as a user store and does LDAP authentication.  If you just need a “yes/no” vote as to whether a username/password combo is good, FCB will give you the best performance and may add a significant scalability increase to your application as a result. 

Do not use FCB if you need to authenticate and then perform operations against the directory on the user’s behalf (a delegation scenario from the architectural perspective, although not necessarily using Windows Kerberos delegation features to implement it).  Since the connection state does not change to “authenticated”, the user’s credentials will not be used to perform subsequent operations and you won’t get what you want.

An obvious place where you might want to use FCB would be in something like the ActiveDirectoryMembershipProvider in ASP.NET 2.0.  My understanding is that the development already thought about this and tried to add this support already.  Thus, you may already have this and not even know it!

Another obvious place for this to be used would be in ADFS for authenticating users in the ADAM store and potentially with users in the AD store as well when used with the Federation Service Proxy (which accepts credentials via a forms or basic auth interface in plaintext form).  As of this writing, I do not believe that ADFS is taking advantage of this feature (or and SDS.P capabilities for that matter).  Note to product team…

A Note on ADSI/SDS and Fast Concurrent Binding

Hey Joe, I see that ADSI and SDS have an AuthenticationTypes flag called FastBind.  Can’t I just use that to get FCB?  Why are you telling me this requires SDS.P?

The answer here is “no”, they are not the same thing, despite their unfortunately similar names!  FastBind in ADSI/SDS actually has nothing to do with the bind operation per say, but has to do with what ADSI does after the bind when you go to access an object.  With FastBind NOT set (the default), ADSI does a base-level search to the object you tried to access to read its objectClass attribute before it executes any other searches to load the property cache and such.  ADSI uses this information to determine which ADSI interfaces to make available.  By default, you get the core interfaces like IADs, but you don’t necessarily get one of the “persistent object” interfaces like IADsUser or IADsGroup unless ADSI knows that it is a user or group.  Without those interfaces, you loose access to members like SetPassword and Add (for group membership additions). 

The reason FastBind is called “Fast” is that this initial search is done in addition to any searches to load the property cache, which generally means that at least two base-level searches to the directory will be required to load any given ADSI object (as you normally use the property cache for something!).  All these extra searches add up to lots of network chatter and can slow certain types of operations to a crawl. 

Note that FastBind is an ADSI/SDS thing though and has no bearing on how things work at the lower level LDAP level, as this notion of the persistent object interfaces and property caches is an ADSI abstraction layer.

How to Implement Fast Concurrent Binding in SDS.P

There really isn’t too much too this.  All you really need to do is turn this option on BEFORE your LdapConnection actually connects to the directory for the first time and you are all set.  Briefly, the code looks something like:

_authConnect.SessionOptions.FastConcurrentBind();

In order to get a more thorough look, I’ll simply point you to the LdapAuth.cs class from our book’s website in ch 12 of the Full Samples to see this in real usage. 

Important Warning
There is a bug in the actual implementation printed in the book (first printing at least; assuming there will be more than one and we actually fix it ?).  A small last minute blunder caused the defect.  Please use the version in the full samples from the website.

There are some important caveats as well:

  • Both the server and client must support FCB.  In the book sample, we actually check the server first via its supportedCapabilities RootDSE attribute to find the specific OID.  On the client requirements, be aware the SDS.P requires the client code to be run on Windows 2003 server or higher.  XP and below does not support this!  Our code tries to handle this gracefully, but you should plan ahead anyway.
  • You are using simple bind, so you need plaintext usernames and passwords and must use a user name syntax supported by simple bind.  For AD, this is NT Account Name (domain\user), UPN or DN.  For ADAM, this is generally UPN or DN, but actually could be a lot of things like displayName as well.  Ch 3 of our book goes into more detail.
  • This is simple bind.  You MUST encrypt the network traffic with SSL or something!

Conclusion

We already covered most of this information in our book, but I don’t think we hit all of these things in as much detail as I have covered here.  Additionally, not all of you will buy the book and this isn’t in the free chapter, and we want you to be successful with this somewhat mysterious feature, regardless.  Happy fast(er) binding!

* Of course, with all performance optimizations, always measure and never assume.  Premature optimization is one of the seven deadly sins of software engineering, yada-yada-yada.

Thursday, August 17, 2006 5:05:52 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
Wednesday, August 09, 2006

In a newsgroup thread today, William Stacey taught me some stuff about salted password hashes stored in a traditional relational database.  Apparently, this is not the way the cool kids do it anymore (although MS still has plenty of guidance suggesting to use this approach).  Apparently, the those in the know use an implementation like Secure Remote Password (SRP-6a).

William couldn't find a .NET implementation, so he built one!  You can find his implementation here.

Thursday, August 10, 2006 1:52:50 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 
Sunday, July 30, 2006

I've been telling myself I was going to finally get into the blogging racket for almost 2 years now, but even though I've had the hosting all put together for that entire time, it took me forever to actually get it together.  I just had to do it myself instead of using another site...

Anyway, this blog will probably resemble the blogs I already read, in that it will be mostly technical with a focus on building software using Microsoft's .NET platform.  It will probably lean heavily on my specialties, .NET LDAP programming and application security, but will likely also feature other stuff I'm into like application architecture, agile development, identity federation, cryptography, and setup development in MSI using WiX

Speaking of .NET and LDAP, if you've ever heard of me before, it is most likely because you might have stumbled across one of the myriad usenet posts I've made over the last 4-5 years on the Microsoft newsgroups, or perhaps I answered your question directly.  Micrsosoft has actually designated me an MVP in this area, and I've even written a book about this with my intrepid co-author, Ryan Dunn, to further our aim of providing resources for the .NET community in this obscure, but stranglely difficult and increasingly important aspect of software development.

That's all for now.  Maybe some real content next time, eh?

Sunday, July 30, 2006 2:25:14 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]  | 

Theme design by Jelle Druyts