How to access user certificate stored in active directory (AD)?

September 17th, 2008 by ganton | Print

Last week I ran into a problem how to access user certificates stored in AD. First of all I’ve checked what X509Store class offers to developers. Unfortunately, it allows access only to current user store and local machine store of the machine where developed application is ran. I’ve searched the Internet and I didn’t found any information how do use it in order to achieve my current aim. I’ve even found that it is not possible using it.

After some googling I’ve tried to use Capicom and I was happy to get what I’ve looked for. First of all I needed to interop capicom.dll. It can be down using tlbimp.exe (.Net Type Library importer tool). Below is an example:

tlbimp capicom.dll /namespace:Interop.Capicom /out:Interop.Capicom.dll

After this operation I was able to add Interop.Capicom.dll in my test application and to use it. Below I’ll provide the code from that application which retrieves all certificates and displays their number into console output.

[sourcecode language="csharp"]

Capicom.Certificate cert = new Capicom.CertificateClass();
cert.Load(@”D:\_work\Tests\Matrix Authority Test.cer”, null, Capicom.CAPICOM_KEY_STORAGE_FLAG.CAPICOM_KEY_STORAGE_USER_PROTECTED,
Capicom.CAPICOM_KEY_LOCATION.CAPICOM_CURRENT_USER_KEY);
Console.WriteLine(cert.SerialNumber);
Capicom.StoreClass store = new Capicom.StoreClass();
store.Open(Capicom.CAPICOM_STORE_LOCATION.CAPICOM_ACTIVE_DIRECTORY_USER_STORE, “CN=Gochev*”, Capicom.CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_READ_WRITE);
foreach (Capicom.Certificate item in store.Certificates)
{
Console.WriteLine(item.SerialNumber);
}
Console.Read();
store.Close();

[/sourcecode]

Note that your domain user should have permissions to read AD.

Further, I’ve decided to experiment with direct access to AD using DirectoryEntry, DirectorySearcher and SearchResult classes. I’d like to provide a sample code which is well documented and understandable I hope. Note that in lines 45, 46 I access a user certificate directly from user object property and after retrieving it I was able to create an instance of X509Certificate2 class

[sourcecode language="csharp"]

using System;
using System.Text;
using System.DirectoryServices;
using System.Collections;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;

namespace CapicomTest
{
class Program
{
static void Main(string[] args)
{

string adRootFileName = @”d:\ad_root.txt”; // path of the file where to store all objects found in AD root
string aGochevPropsFileName = @”d:\user_props.txt”; // path of the file where to store all properties found in a AD user root
using (DirectoryEntry directory = new DirectoryEntry())
{
directory.Path = @”LDAP://“;
directory.Username = ““;
directory.Password = ““;
directory.AuthenticationType = AuthenticationTypes.Secure;
using (TextWriter writer = File.CreateText(adRootFileName))
{
WriteChildrens(directory.Children, 0, writer);
}
Process.Start(adRootFileName); // open ad_root.txt in a new process of a default txt files editor
Byte[] certificateBytes;
if (directory.NativeObject != null)
{
DirectorySearcher searcher = new DirectorySearcher(directory); // create direcotry searcher to search into AD root
searcher.Filter = “(SAMAccountName=)”; // add a filter to search the AD root for a specific user
SearchResult result = searcher.FindOne();
using (DirectoryEntry de = new DirectoryEntry(result.Path, ““, ““, AuthenticationTypes.Secure))
{
using (TextWriter writer = File.CreateText(aGochevPropsFileName))
{
foreach (string propertyName in de.Properties.PropertyNames) // loop all properties of the object and write information about them into a file
{
writer.WriteLine(string.Format(”{0}={1}”, propertyName, de.Properties[propertyName].Value));
}
}
Process.Start(aGochevPropsFileName); // open user_props.txt in a new process of a default txt files editor
certificateBytes = de.Properties["userCertificate"].Value as byte[]; // retrieve a certificate
X509Certificate2 cert = new X509Certificate2(certificateBytes); // upload the certificate
}
}
}
}

///


/// Goes through all DirectoryEntry (ies) recursively and writes them to the writer.
///

/// Directory entries of the AD root. /// Integer variable used to calculate intend tabs. /// TextWriter object associated with a file where information is stored private static void WriteChildrens(DirectoryEntries entries, int tabs,
TextWriter writer)
{
foreach (DirectoryEntry item in entries)
{
string t = new string(’\t’, tabs);
writer.WriteLine(t + item.Name);
WriteChildrens(item.Children, tabs + 1, writer);
}
}
}
}

[/sourcecode]

Useful links:

One Response to “How to access user certificate stored in active directory (AD)?”

  1. Irina Says:

    Thanks a million! This article helped me a lot.

Leave a Reply