Executive Summary:

OpenLDAP’s proxy service can allow LDAP operations to cross the boundaries between AD and OpenLDAP deployments. To demonstrate this proxy service, we walk through the steps to make AD’s cn=Users container, which by default contains all user objects, part of an OpenLDAP directory. To produce the examples in this article, I used CentOS 4.3, OpenLDAP 2.2.13, and AD running on Windows Server 2003 R2. Later in the article, I’ll show you a limitation in the commonly deployed OpenLDAP 2.2, which you can solve by installing OpenLDAP 2.3 on CentOS 4.3.

Solutions Snapshot

You can’t access Active Directory (AD) Schema via OpenLDAP.

Use OpenLDAP’s proxy service to connect to AD.

What You Need:
CentOS; OpenLDAP; AD running on Windows Server 2003 R2


1. Start slapd.
2. Configure slapd-ldap; restart
slapd and run ldapsearch.
3. Install OpenLDAP 2.3.
4. Modify pidfile and argsfile.
5. Restart slapd and run ldapsearch

Both Active Directory (AD) and Open- LDAP play important roles in the enterprise. In fact, within the same company you’ll find the UNIX group using OpenLDAP and the LAN and Windows administrators using AD. However, most people are unable to fully access the AD schema via OpenLDAP.

OpenLDAP and AD can peacefully coexist— the key is finding the best way to allow LDAP operations to cross the boundaries between AD and OpenLDAP deployments. One way to make that happen is to use Open- LDAP’s proxy service. To demonstrate this proxy service, I’ll walk you through the steps to make AD’s cn=Users container, which by default contains all user objects, part of an OpenLDAP directory.

Terms and Versions

Before moving on, let’s define terminology. First, an LDAP server is actually what is known as a Directory Service Agent (DSA). Second, a DSA manages either part or all of a Directory Information Tree (DIT). Several DSAs may be deployed to manage an entire DIT as well as to allow for replication and high availability. The portion of the DIT that a DSA manages is known either as a partition or database. I use the term database.

To produce the examples in this article, I used CentOS 4.3, OpenLDAP 2.2.13, and AD running on Windows Server 2003 R2. Later in the article, I’ll show you a limitation in the commonly deployed OpenLDAP 2.2, which you can solve by installing OpenLDAP 2.3 on CentOS 4.3.(For CentOS 4.3, I use the RPMS found at i386/RPMS/.) See the sidebar “Upgrading OpenLDAP on CentOS,” for installation instructions.

Starting the OpenLDAP Server Process

The OpenLDAP server process is named slapd, which stands for “stand-alone LDAP daemon.” It provides almost all of the Open- LDAP server functionality, including the ability to accept connections from LDAP clients, process queries and updates, and implement the ACLs that restrict access to confidential information within the directory. Notably, in OpenLDAP, replication is handled by another process entirely and is beyond the scope of this article.

Let’s start off with a sample slapd configuration that brings up a basic DIT with no ACLs or any other special capabilities. On the OpenLDAP server, configuration starts with the slapd.conf file shown in Listing 1. In this configuration, slapd manages a database for the directory tree dc=testcorp,dc=com.

To start slapd, type the following:

# service ldap start

and load the initial entries into the database.

To load the entries, first enter the information from Listing 2 into a file named dir. ldif. These entries will define a very simple tree which has a suffix (aka root) of dc=testcorp, dc=com and two branches that are ou=People and ou=Groups. Now, load the entries using ldapadd:

 # ldapadd -x -h localhost -D cn=manager,dc=testcorp,
dc=com -W -f dir.ldif
Enter LDAP Password: <value-of-rootpw>
adding new entry “dc=testcorp,dc=com”
adding new entry “ou=People,
adding new entry “ou=Groups,

The –x option specifies that ldapadd should use simple authentication instead of Simple Authentication and Security Layer (SASL). With simple authentication, the LDAP client (in this case, ldapadd) sends the credentials in plaintext. Even if you use LDAP over SSL (LDAPS) or LDAP StartTLS, you’re still using simple authentication, but the tunnel being used for communication is encrypted (and far more secure).

We can test that our entries loaded properly by using ldapsearch

# ldapsearch -LLL -x -h localhost -b ‘dc=testcorp,dc=com’

which performs a query to find all entries below the root of the tree. Figure 1, page 48, shows the results. As expected, ldapsearch returns the three entries that we originally imported via ldapadd. We are now ready to begin working with referrals.

A Caveat to Using Referrals

You saw how easy it is to view entries that OpenLDAP manages by using a simple ldapsearch command on our client—but what about viewing entries that AD manages? For that to happen, you need to direct either the LDAP client or the LDAP server (i.e., OpenLDAP) to AD.

An obvious choice is to use referrals, which is a way for a DSA to forward—or refer—an LDAP request to another DSA. However, while referrals are both powerful and flexible (both for managers and application developers), keep in mind an important caveat: How a client handles a referral is entirely dependent on implementation. For example, OpenLDAP’s ldapsearch can chase referrals when used with the -C option, but only anonymously—ldapsearch doesn’t try to authenticate against the second DSA.

If you did create a referral in OpenLDAP to AD, ldapsearch (as well as other OpenLDAP binaries such as ldapadd) would return output containing the following: “In order to perform this operation a successful bind must be completed on the connection.” This statement simply means that ldapsearch chased the referral to a domain controller (DC) and the operation was rejected because ldapsearch didn’t try to authenticate.

To solve this problem, you could write your own LDAP clients (e.g., using Perl’s Net::LDAP), use another vendor’s toolset, or bypass this issue entirely and use Open- LDAP’s proxy service. I’ll show you the third option.

Using OpenLDAP as a Proxy

OpenLDAP can provide a proxy for connections to AD on behalf of a client. Simply put, OpenLDAP will work with AD for you whenever necessary. The benefit of this approach is that you don’t have to rely on the behavior of the LDAP client—the server, OpenLDAP, will be configured to chase referrals for you so that you don’t have to depend on client behavior, which may or may not work as you want.

With an OpenLDAP proxy, all operations are routed through slapd, even though some need to be performed within AD. For routing through slapd to work, you configure slapd-ldap, the proxy back end for the slapd daemon. You could use other back ends such as slapd-meta, which provides even more features such as naming context rewriting, but slapd-ldap is the simplest to configure during initial testing.

Let’s add a slapd-ldap configuration to slapd.conf. Listing 3 shows the code. In it, you can see several changes:

database ldap. We have defined a new back end by using slapd-ldap, which will be our proxy service.

subordinate. Without this keyword, slapd searches only the database specified by the search base (e.g., if dc=testcorp,dc=com were the specified search base, then cn=users,dc=testcorp,dc=com would never be examined because it’s a different slapd database).

rebind-as-user. This option tells slapd to bind to the remote DSA with the credentials supplied by the client; the credentials must be valid in AD.

Uri. This specifies the remote LDAP server, which in this case is the AD DC. Notice that we aren’t using SSL here—in the real world, you would configure SSL for security.

chase-referrals. This option specifies that slapd will chase any referrals automatically.

What’s interesting is that AD is using the same suffix of dc=testcorp, dc=com as Open- LDAP. Often both UNIX and AD administrators bring up a directory service with the same standard suffix (i.e., naming context), and only later do they find that they need to provide for better integration.

Now, restart slapd and run ldapsearch again:

# ldapsearch -x -h localhost
 -LLL -b dc=testcorp,dc=com -D cn=dpuryear,cn=users,
 dc=testcorp,dc=com -W ‘(cn=dpuryear)’ cn
Enter LDAP Password:

In this example, the ldapsearch command searches against cn = users, dc = testcorp, dc=com, which slapd should map to CN=Users in AD. And slapd does map it, as you can see by the output below:

dn: CN=dpuryear,CN=Users,DC=t
cn: dpuryear

which shows the entry CN=dpuryear, CN=Users, DC=testcorp, DC=com— the account for dpuryear in the AD CN=Users container. slapd now knows that any operation against cn=users,dc=testcorp,dc=com (which is our superior in the directory tree), actually requires these steps:

  1. Open an LDAP connection to ldap://
  2. Bind with the credentials supplied by the client.
  3. Perform the operation.
  4. Return the results to the client.

But there’s a problem: We don’t have access to all of the data in AD. To see what I mean, try to return the attribute sAMAccountName, which is specific to the AD schema. When I type

# ldapsearch -x -h localhost -LLL -b
 dc=testcorp,dc=com -D cn=dpuryear,cn=users,dc=testcorp,
 dc=com -W ‘(cn=dpuryear)’ cn sAMAccountName
Enter LDAP Password:

slapd returns only attributes defined in the schema known to OpenLDAP and nothing more:

dn: CN=dpuryear,CN=Users,DC=testcorp,D
cn: dpuryear

Notice that sAMAccountName is not shown, even though it exists in AD and was requested in our ldapsearch command. To access all of the data in AD, you need to install the most recent version of OpenLDAP, OpenLDAP 2.3, which can transparently pass unknown schema, albeit with some minor syntax rules applied so that it can perform filtering.

Using OpenLDAP 2.3 to Pass Unknown Schema

You can install OpenLDAP 2.3 either by compiling the source, or, far easier, by installing it from RPM Package Manager (RPM). After installation, the only configuration change required is to modify pidfile and argsfile because the newer OpenLDAP RPM assumes a different location for those files. Listing 4 shows the code for this.

Now, restart slapd and try ldapsearch again—first using the “cn” in your filter

# ldapsearch -x -h localhost -LLL -b
 dc=testcorp,dc=com -D cn=dpuryear,cn=users,dc=testcorp,
 dc=com -W ‘(cn=dpuryear)’ cn sAMAccountName
Enter LDAP Password:

and then the AD-only sAMAccountName:

# ldapsearch -x -h localhost -LLL -b
 dc=testcorp,dc=com -D cn=dpuryear,cn=users,dc=testcorp,
 dc=com -W ‘(sAMAccountName=dpuryear)’ cn
Enter LDAP Password:

Success! As you can see from the following output, ldapsearch queried slapd, which in turn queried AD for us:

dn: cn=dpuryear,cn=Users,dc=testcorp,
cn: dpuryear

The key difference here is that we now have access to the complete AD schema, including sAMAccountName.

Seamless Access to AD

You should now be able to attach AD to any part of your OpenLDAP directory. You can authenticate your AD users in LDAP applications that use OpenLDAP or even provide access to multiple ADs in your network if they aren’t all part of a larger forest already.