宇宙仮面の
C# Programming

 
Image

LDAP client using ADSI and C# (English)

開発環境: Visual Studio 2003 

1.Index

  1. Index
  2. Introduction
  3. References
  4. Setup OpenLDAP
  5. LDAP Access from .NET C#
  6. Source Code

2.Introduction

Directory Service is very similar to the Phone Book. It's mainly focusing on searching personal data, such as name, address, phone number, mail address, organization, etc. In the network world, ISO X.500 series defines so called DAP (Directory Access Protocol). LDAP has been define as a subset of X.500 for "Light Weight" Directory Service by the IETF.

As you know, there are some famous LDAP service software as follows.

  • Microsoft Active Directory
  • OpenLDAP
  • Sun ONE Directory Server
  • Novell eDirectory
  • IBM Directory Server

Active Directory Service Interfaces (ADSI) is a set of COM interfaces used to access the features of directory services from different network providers. By default, Active Directory supports following four providers.

  • IIS (Internet Information Services)
  • LDAP (Lightweight Directory Access Protocol)
  • NDS (Novell NetWare Directory Service)
  • WinNT

.NET Framework provide  System.DirectoryServices name space for easy access to the Active Directory. It has two components, DirectoryEntry and DirectorySearcher. In this article, I'll describe how to create LDAP client using ADSI and C#.

3.References

  1. OpenLDAP
  2. MSDN System.DirectoryServices Name Space

4.Setup OpenLDAP

First of all, we need a LDAP server to test C# LDAP client can access the LDAP server. The most famous free LDAP server would be the OpenLDAP. As OpenLDAP has been bundled with Fedora Core 3, most easy way to setup LDAP is to install Fedora Core 3 and run OpenLDAP. I installed Fedora Core 3 on my Virtual PC, because I don't want to dedicate my PC to linux. When I first met linux, I loved linux. But, now I don't. Because it takes too much time to maintain linux. This is my personal opinion, but the TCO of linux could be two or three times higher than the Windows. Anyway, if you have much time and money and IT skills, linux can be good choice to dance with!

Ok, let's get back to setup OpenLDAP on Fedora Core 3.

  1. Install Fedora Core on VPC.
  2. Configure /etc/openldap/slapd.conf
    Note: slapd.conf is a configuration file for the slapd daemon.
  3. Configure /etc/openldap/ldap.conf
    ldap.conf is a configuration file for the OpenLDAP clients, such as ldapsearch.
  4. Start LDAP Service.
    /etc/rc.d/init.d/ldap start
  5. Add LDAP entries as follows.
Fedore Core 3
// Check out LDAP daemon(slapd) is running.

[root@uchukamen init.d]# ps ax | grep slapd
24693 ? Ssl 0:00 /usr/sbin/slapd -u ldap -h ldap:///
24734 pts/1 S+ 0:00 grep slapd

// Add LDAP entries by ldapadd command.
[root@uchukamen ldap]# ldapadd -x -D 'cn=Manager,dc=uchukamen,dc=com' -W -f /root/Desktop/uchukamen.ldif
Enter LDAP Password: secret
adding new entry "dc=uchukamen,dc=com"

adding new entry "cn=Manager,dc=uchukamen,dc=com"

// Search LDAP entries by ldapearch command.
[root@uchukamen ldap]# ldapsearch -x -b 'dc=uchukamen,dc=com' -s sub '(cn=*)'
# extended LDIF
#
# LDAPv3
# base <dc=uchukamen,dc=com> with scope sub
# filter: (cn=*)
# requesting: ALL
#

# Manager, uchukamen.com
dn: cn=Manager,dc=uchukamen,dc=com
objectClass: organizationalRole
cn: Manager

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1
[root@uchukamen ldap]#

// Now OpenLDAP is up and running!

 

Example of uchukamen.ldif
dn: dc=uchukamen,dc=com
objectClass: dcObject
objectClass: organization
dc: uchukamen
o: uchukamen

dn: cn=Manager,dc=uchukamen,dc=com
objectClass: organizationalRole
cn: Manager

 

Note: How to clean up LDAP entries.
When I misstyped LDIF file and used ldapadd command, following ldap commands hung up.

To recover from this, try following steps.

  1. /etc/rc.d/init.d/ldap stop
  2. rm all files under /var/lib/ldap/*
  3. Restart slapd.

 

Important NOTE: slapd.conf
By default, slapd.conf has plain text password "secret". Please make sure to change the password! Please check out OpenLDAP or Linux man pages for detail.

5.LDAP Access from .NET C#

Now it's time to make the LDAP client access program.

  1. Create a new C# Windows Forms project.
  2. Drag and Drop ComboBox for LDAP Path, TextBox for Entry Name, Button for search and TreeView to display search results as follows.LDAP path should be "LDAP://IP address for Fedora Core 3/dc=uchukamen,dc=com" in this example. You can specify hostname instead of the IP address, if you can resolve name.
    Image
  3. From the toolbox->Componet, Drag and Drop "DirectoryEntry" and "DirectorySearcher".

    Image
  4. Change AuthenticationType of the directoryEntry1 property to "Anonymous".
  5. Double click the search button, and add click event handler.
    On search button click event
    private void button1_Click(object sender, System.EventArgs e)
    {
        this.treeView1.Nodes.Clear();
        search();
    }

     

  6. Now, implement search() method. It's quite simple code, you could understand easily. Please note you have to specify Username and Password with null string "".
    search() method
    private void search()
    {			
    	try
    	{
    		directoryEntry1.Path = comboBox1.Text;
    		directoryEntry1.Username = "";
    		directoryEntry1.Password = "";
    		directorySearcher1.SearchRoot = directoryEntry1;
    
    		// Get the first entry of the search.
    		SearchResult searchResult = directorySearcher1.FindOne();
    		if ( searchResult == null )
    		{
    			MessageBox.Show("Could not find entries: " + 
    				directoryEntry1.Path, "LDAP Search", 
    				MessageBoxButtons.OK);
    			return;
    		}
    
    		DirectoryEntry directoryEntry = searchResult.GetDirectoryEntry();
    
    		textBoxEntryName.Text = directoryEntry.Name;		
    
    		ResultPropertyCollection resultPropColl = searchResult.Properties;
    		foreach( string propName in resultPropColl.PropertyNames)
    		{						
    			TreeNode node = this.treeView1.Nodes.Add(propName);
    			foreach( Object collection in resultPropColl[propName])
    			{
    				node.Nodes.Add(collection.ToString());
    			}
    		}
    	}
    	catch(Exception exc)
    	{
    		MessageBox.Show( "Exception : " + exc.Message, 
    			"LDAP Search", MessageBoxButtons.OK);
    	}
    }

    That's it!

  7. Now build the solution and run! You will see following result set.
    Image

6.Source Code

 

History
2005/6/23   V1.0 for .NET Framework V1.1

Form1.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.DirectoryServices;

namespace uchukamen.LDAP
{
public class Form1 : System.Windows.Forms.Form

	private System.Windows.Forms.Label label1;
	private System.Windows.Forms.TreeView treeView1;
	private System.Windows.Forms.ComboBox comboBox1;
	private System.Windows.Forms.Button button1;
	private System.DirectoryServices.DirectoryEntry directoryEntry1;
	private System.DirectoryServices.DirectorySearcher directorySearcher1;
	private System.Windows.Forms.Label label2;
	private System.Windows.Forms.TextBox textBoxEntryName;
	/// 
	/// 
	private System.ComponentModel.Container components = null;

	public Form1()
	{
		//
		//
		InitializeComponent();
		//
		//
	}
	/// 
	/// 
	protected override void Dispose( bool disposing )
	{
		if( disposing )
		{
			if (components != null) 
			{
				components.Dispose();
			}
		}
		base.Dispose( disposing );
	}

	#region Windows 
	/// 
	private void InitializeComponent()
	{
		this.label1 = new System.Windows.Forms.Label();
		this.treeView1 = new System.Windows.Forms.TreeView();
		this.comboBox1 = new System.Windows.Forms.ComboBox();
		this.button1 = new System.Windows.Forms.Button();
		this.directoryEntry1 = new System.DirectoryServices.DirectoryEntry();
		this.directorySearcher1 = new System.DirectoryServices.DirectorySearcher();
		this.textBoxEntryName = new System.Windows.Forms.TextBox();
		this.label2 = new System.Windows.Forms.Label();
		this.SuspendLayout();
		// 
		// label1
		// 
		this.label1.Location = new System.Drawing.Point(16, 16);
		this.label1.Name = "label1";
		this.label1.Size = new System.Drawing.Size(64, 16);
		this.label1.TabIndex = 2;
		this.label1.Text = "LDAP Path";
		// 
		// treeView1
		// 
		this.treeView1.ImageIndex = -1;
		this.treeView1.Location = new System.Drawing.Point(16, 80);
		this.treeView1.Name = "treeView1";
		this.treeView1.SelectedImageIndex = -1;
		this.treeView1.Size = new System.Drawing.Size(480, 200);
		this.treeView1.TabIndex = 3;
		// 
		// comboBox1
		// 
		this.comboBox1.Items.AddRange(new object[] {
		   "LDAP://192.168.1.11/dc=uchukamen,dc=com"});
		this.comboBox1.Location = new System.Drawing.Point(104, 16);
		this.comboBox1.Name = "comboBox1";
		this.comboBox1.Size = new System.Drawing.Size(288, 20);
		this.comboBox1.TabIndex = 4;
		this.comboBox1.Text = "LDAP://192.168.1.11/dc=uchukamen,dc=com";
		// 
		// button1
		// 
		this.button1.Location = new System.Drawing.Point(416, 16);
		this.button1.Name = "button1";
		this.button1.TabIndex = 5;
		this.button1.Text = "Search";
		this.button1.Click += new System.EventHandler(this.button1_Click);
		// 
		// directoryEntry1
		// 
		this.directoryEntry1.AuthenticationType = 
			System.DirectoryServices.AuthenticationTypes.Anonymous;
		// 
		// textBoxEntryName
		// 
		this.textBoxEntryName.Location = new System.Drawing.Point(104, 48);
		this.textBoxEntryName.Name = "textBoxEntryName";
		this.textBoxEntryName.Size = new System.Drawing.Size(288, 19);
		this.textBoxEntryName.TabIndex = 6;
		this.textBoxEntryName.Text = "";
		// 
		// label2
		// 
		this.label2.Location = new System.Drawing.Point(16, 48);
		this.label2.Name = "label2";
		this.label2.Size = new System.Drawing.Size(72, 16);
		this.label2.TabIndex = 8;
		this.label2.Text = "Entry Name";
		// 
		// Form1
		// 
		this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
		this.ClientSize = new System.Drawing.Size(512, 294);
		this.Controls.Add(this.label2);
		this.Controls.Add(this.textBoxEntryName);
		this.Controls.Add(this.button1);
		this.Controls.Add(this.comboBox1);
		this.Controls.Add(this.treeView1);
		this.Controls.Add(this.label1);
		this.Name = "Form1";
		this.Text = "Form1";
		this.ResumeLayout(false);
		}
	#endregion

	/// 
	/// 
	[STAThread]
	static void Main() 
	{
		Application.Run(new Form1());
	}

	private void button1_Click(object sender, System.EventArgs e)
	{
		this.treeView1.Nodes.Clear();
		search();
	}

	private void search()
	{			
		try
		{
			directoryEntry1.Path = comboBox1.Text;
			directoryEntry1.Username = "";
			directoryEntry1.Password = "";

			directorySearcher1.SearchRoot = directoryEntry1;

			// Get the first entry of the search.
			SearchResult searchResult = directorySearcher1.FindOne();
			if ( searchResult == null )
			{
				MessageBox.Show("Could not find entries: " + 
					directoryEntry1.Path, "LDAP Search", 
					MessageBoxButtons.OK);
				return;
			}

			DirectoryEntry directoryEntry = searchResult.GetDirectoryEntry();

			textBoxEntryName.Text = directoryEntry.Name;		

			ResultPropertyCollection resultPropColl = searchResult.Properties;
			foreach( string propName in resultPropColl.PropertyNames)
			{						
				TreeNode node = this.treeView1.Nodes.Add(propName);
				foreach( Object collection in resultPropColl[propName])
				{
					node.Nodes.Add(collection.ToString());
				}
			}
		}
		catch(Exception exc)
		{
			MessageBox.Show( "Exception : " + exc.Message, 
				"LDAP Search", MessageBoxButtons.OK);
		}
	}
}
}