LDAP Queries on SID or GUID in PowerShell or .NET

Performing LDAP queries to find objects in your directory by SID or GUID aren’t always straightforward.  It’s not as easy in Active Directory, for example, to perform a query like:

“objectSID={theSID},CN=Users,DC=domain,DC=com” since Active Directory stores values in hex.

A Lot of Solutions Exist

There are some nice write-ups out there that give an example using PowerShell for a GUID (but not an SID).  The same write-up explains that you can do queries of the form:  [ADSI]“LDAP://<SID=$theSID>” to make it work.  When I tried this technique with system.directoryservices.protocols (S.DS.P), however, I wasn’t able to get it going since you don’t write queries of the form “LDAP://” or “GC://” but instead work with port numbers to specify your protocol.  It might be possible (I didn’t spend a lot of time), but the application that I’m writing builds LDAP query strings dynamically and this technique would make SIDs or GUIDs special cases in my code.  Avoiding these kinds of special cases is important to me for easier code maintenance.

I also didn’t want to use PowerShell’s Active Directory commandlets because they aren’t generic to LDAP but are instead specific to Active Directory.  I wanted to stick with S.DS.P.  S.DS.P is also faster than abstractions that have been written on top of LDAP to simplify it.

There are a lot of old algorithms to convert the SID or GUID into a string representation of a byte array.  I have my own C# algorithm that does it, and there are plenty out there in VBScript.  It’s not that clean to me.  What came to my rescue (in either PowerShell or .NET) was System.Security.Principal.SecurityIdentifier and the method GetBinaryForm.

System.Security.Principal.SecurityIdentifier and GetBinaryForm Helped

The following in PowerShell (easily adaptable to C#) is what I used:

$ot = New-Object System.Security.Principal.SecurityIdentifier($theSID)
$c = New-Object 'byte[]' $ot.BinaryLength
$ot.GetBinaryForm($c,0)
$c | %{ $out += $("\{0:x2}" -f $_) }

“$out” gets the converted result.  This was much more preferable to me then including yet another conversion function in my script and I was happy to find it.