Friday, March 8, 2013
Thursday, March 7, 2013
It is relatively straightforward to write .Net applications against Active Directory (AD) and Active Directory Lightweight Directory Services (ADLDS), but a number of challenges arise from writing applications against non-Microsoft directories.
More often than you would think, I am confronted with the use case of connecting to a non-Microsoft directory (ex. OpenLDAP, Oracle Internet Directory, IBM Directory Server, and Novell eDirectory). In a few cases, you can use the same classes that you would with AD or ADLDS that exist in the System.DirectoryServices namespace (ex. DirectoryEntry, DirectorySearcher, SearchResult, DirectoryEntries, etc), but in many cases you will run into an assortment of issues that usually ends in failure.
Digging into the namespace a little further, Microsoft has developed the System.DirectoryServices.Protocols namespace that gives you the ability to interact with LDAP directories at a lower level than the classes provided by the System.DirectoryServices namespace, but at a higher level than having to write your own LDAPv3 library from scratch.
Below is sample code for a sample C# .Net application and a sample Powershell script that allows interaction with non-Microsoft LDAP directories:
//Application Connects to and Searches OpenLDAP directory
static void Main(string args)
// Connects to myopenldap.mikesblog.lan using SSL on a non-standard port
LdapConnection c = new LdapConnection("directory.mikesblog.lan:637");
//Set session options
c.SessionOptions.SecureSocketLayer = true;
// Pick Authentication type:
// Anonymous, Basic, Digest, DPA (Distributed Password Authentication),
// External, Kerberos, Msn, Negotiate, Ntlm, Sicily
c.AuthType = AuthType.Basic;
// Gets username and password. There are better ways to do this more securely...
// but that's not the topic of this post.
Console.Write("Enter Username: ");
string username = Console.ReadLine();
Console.Write("Enter Password: ");
string password = Console.ReadLine();
// Bind with the network credentials. Depending on the type of server,
// the username will take different forms. Authentication type is controlled
// above with the AuthType
c.Bind(new System.Net.NetworkCredential(username, password));
SearchRequest r = new SearchRequest(
//params string  of attributes... in this case all
SearchResponse re = (SearchResponse)c.SendRequest(r);
//How many results do we have?
foreach (SearchResultEntry i in re.Entries)
//Do something with each entry here, such as read attributes
The example Powershell port follows:
#Script Connects to and Searches OpenLDAP directory
#Load the assemblies
#Connects to myopenldap.mikesblog.lan using SSL on a non-standard port
$c = New-Object System.DirectoryServices.Protocols.LdapConnection "myopenldap.mikesblog.lan:637"
#Set session options
$c.SessionOptions.SecureSocketLayer = $true;
# Pick Authentication type:
# Anonymous, Basic, Digest, DPA (Distributed Password Authentication),
# External, Kerberos, Msn, Negotiate, Ntlm, Sicily
$c.AuthType = [System.DirectoryServices.Protocols.AuthType]::Basic
# Gets username and password.
$user = Read-Host -Prompt "Username"
$pass = Read-Host -AsSecureString "Password"
$credentials = new-object "System.Net.NetworkCredential" -ArgumentList $user,$pass
# Bind with the network credentials. Depending on the type of server,
# the username will take different forms. Authentication type is controlled
# above with the AuthType
$basedn = "ou=users,dc=mikesblog,dc=lan"
$filter = "(uid=burrm)"
$scope = [System.DirectoryServices.Protocols.SearchScope]::Subtree
$attrlist = ,"*"
$r = New-Object System.DirectoryServices.Protocols.SearchRequest -ArgumentList `
#$re is a System.DirectoryServices.Protocols.SearchResponse
$re = $c.SendRequest($r);
#How many results do we have?
foreach ($i in $re.Entries)
#Do something with each entry here, such as read attributes