.Net Directory Services Programming – C# - Part 2
Topics Covered
Binding – How to connect to directory services and the flexibility of the bind process.
Properties – Review of the most commonly used AD properties, and a look at a few others.
Binding
You will remember in Part 1 that we provided a very simple code example of binding to AD and retrieving the object reference for the user object CN=Mike Hamilton. Here I want to review a little more in detail the binding process.
Binding The Default Server
Often called serverless binding, or binding to your root context, the following shows the simplest of binding calls:
DirectoryEntry newEntry = new DirectoryEntry();
There is one major assumption here: You must be logged into the directory service (or the application you are executing must be) – otherwise the call will fail. This call will return the default server, or default root context – the server that validated your logging onto this network. I will review this in more detail shortly.
Passing The Directory (or ADsPath – we’ll review this in a later Part).
Here we pass the specific server and context that we want to bind to. Borrowing from Part 1 – you’ll remember how we bound to the specific user object.
DirectoryEntry userEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/CN=Mike Hamilton,DC=developer,DC=Hamilton,DC=com”);
Here we specify the context of the bind. Note, this can be any server within our domain or even another domain within our directory forest.
Passing The Path and Credentials to Bind
Here we want to bind to a specific path, and provide credentials that validate we have the permission to do so. This is important as you delve into security in later Parts.
DirectoryEntry userEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/CN=Mike Hamilton,DC=developer,DC=Hamilton,DC=com”, “<adminAccountName>”,”<adminPassword”);
Here you would replace adminAccountName and adminPassword with the actual credentials you want to user. Those can be the administrator account or any account that actually has permissions to perform the binding.
Passing The Path, Credentials, and Authentication Type
Not only can we bind with specific credentials, but we can also specify the authentication type we wish the directory service to use. For example:
DirectoryEntry userEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/CN=Mike Hamilton,DC=developer,DC=Hamilton,DC=com”, “<adminAccountName>”,”<adminPassword”, AuthenticationTypes.Secure);
We will review the AuthenticationTypes when we review AuthenticationTypeEnum in our security review.
Passing a Native ADSI Object Reference
You will get more into this type of binding when you get into security. For now, I am presenting this for an example/reference for future reviews.
DirectoryEntry iAdsEntry = new DirectoryEntry(IADSObject);
As we move through the different presentations on this topic, we will touch on each of the bindings methods presented, offering examples / benefits of that method.
Properties in AD
I clarify here – AD (Active Directory). I should note that LDAP is LDAP across most directory providers. I emphasize AD here because some of the examples I will use are specific to AD insofar as the default behavior of a property or binding context. I will explain those when applicable, and will make a notation in the example conveying that it is an AD specific property or context.
As mentioned previously, AD (and most directory providers) has a hoard of properties that are available to the developer. Here I want to present some of the most common. What is important to note is the syntax to use when referencing a specific property. (You will remember from Part 1 that property names are spelled out using Camel-Case and single names are in lower-case only.)
When a user is initially created, that First Name, Last Name, Account Login Name – ever wondered what these were in AD? There are some givens when interacting with these properties – and I want to point those out first.
The Account Login Name is written to a few AD properties that cannot be modified via code. There are some things you can do with an AD user object, but one of the most frustrating is renaming or copying to another directory. You can move an object, and of course, delete one – but let’s move forward.
When the account is first created, the following properties are assigned the names you provide when creating the account (and this is assuming you created the account with a management tool / snap-in that facilitates user management – like AD Users & Computers (dsa.msc)):
- First Name = givenName
- Last Name = sn
- Login Account Name = sAMAccountName, name, dn
If you wanted to retrieve these values using LDAP, and following our example in Part 1, we would do something like the following:
using System;
using System.DirectoryServices;
namespace DirectoryUtility
public class Main()
{
DirectoryEntry userEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/CN=Mike Hamilton,OU=Developers,OU=Accounts,DC=developer,DC=hamilton,DC=com”);
string loginID = userEntry.Properties[“sAMAccountName”].Value.ToString();
string firstName = userEntry.Properties[“givenName”].Value.ToString();
string lastName = userEntry.Properties[“sn”].Value.ToString();
MessageBox.Show(“Login ID: “+loginID.ToString()+”\r\n Full Name: “+firstName.ToString()+” “+lastName.ToString(),”Results”);
}
Yes, this is a rough example, and it does not allow for exception handling. The objective was to show you how to reference just these fields.
Here I’ll list a few (I say a few lightly – there are dozens) properties that you will commonly use or need to use:
- sAMAccountName – user ID of the account created (Note, when programmatically creating/adding users – you have control over this field – but not after the object has been added).
- name – same value as the sAMAccountName property.
- givenName – First Name of the user.
- sn – or Sur Name – Last Name of the User
- displayName – typically, the same as the name, and sAMAccountName
- userPrincipalName – the same as name, sAMAccountName
- co – Country
- mail – single email address value (I’ll demonstrate how we can maintain multiple emails in another Part).
- telephoneNumber – User’s phone number
- description – A description of this account
- userAccountControl – The enumerated property that we’ll use to manage the user’s account – access, password change, locked, and others.
- wWWHomePage – User’s default homepage –optional.
- parent – Parent owner object. For example, the name of the OU the user account is in.
- cn – Cononical – or Common Name – usually the combination of givenName + sn (NOTE: If you have migrated from another system, like NT4 to AD 2000 – this value is the same as the name, sAMAccountName, and displayName – by default, and it cannot be changed)
How to list and view all properties available with LDAP?
The following code snippet shows how to step through the properties associated with a DirectoryEntry object. (NOTE: This code assumes there is a listbox named propertiesListBox on a form that we can add the properties to.)
private void PopulateProperties(DirectoryEntry userEntry)
{
if (userEntry!=null)
{
propertiesListBox.Clear();
foreach (string propertyName in userEntry.Properties.PropertyNames)
propertiesListBox.Items.Add(propertyName);
}}
SUMMARY
I realize that a lot of this is not meat and potatoes yet, but those Parts are coming. I wanted to take the time to introduce some fundamentals because I realize there are a lot of developers out there that have not been introduced to DirectoryServices, and there is a lot to learn!
In our next couple of Parts we are going to look at the DirectorySearcher, the other major class in the DirectoryServices namespace, and then we’re going to look at a few basic examples of user / object management. We will start our own solution that will end up in a complete application that will allow you to connect to a directory service, list accounts and objects in that service, add accounts, add groups, and add other specific objects.