How LDAP Works: Directory Services, DIT Structure, and Active Directory
Lightweight Directory Access Protocol (LDAP) is a protocol for accessing and managing distributed directory information services over a network. If you have ever logged into a corporate laptop, had your email address auto-completed from a company directory, or been assigned to a security group that controls your application access, LDAP was almost certainly the underlying technology. Originally defined in RFC 1777 (1995) as a simpler alternative to the X.500 Directory Access Protocol, LDAP v3 (RFC 4511, 2006) has become the standard way to store and query identity information in enterprises. Active Directory, the backbone of most corporate IT environments, is fundamentally an LDAP directory with Microsoft-specific extensions.
What Is a Directory Service?
A directory service is a specialized database optimized for read-heavy, write-infrequent workloads. Unlike a general-purpose relational database, a directory is designed around a hierarchical data model, attribute-based queries, and distributed replication. Think of it as a phone book for an organization — you look up information far more often than you update it.
Directory services store identity information: user accounts, group memberships, email addresses, phone numbers, office locations, certificates, and anything else that describes people, devices, or resources in an organization. They provide a single source of truth that other systems query: email servers look up mailbox locations, RADIUS servers verify credentials, SAML Identity Providers retrieve user attributes, and applications check group memberships for authorization.
The Directory Information Tree (DIT)
LDAP organizes data in a hierarchical tree structure called the Directory Information Tree (DIT). Every entry in the directory has a unique position in this tree, identified by its Distinguished Name (DN).
Naming: DN, RDN, and Common Attributes
Every LDAP entry is identified by its Distinguished Name (DN), which is the full path from the entry to the root of the tree, written with the most specific component first:
uid=jdoe,ou=People,dc=example,dc=com
Key naming components:
- DN (Distinguished Name) — The fully qualified, globally unique name of an entry. Think of it as an absolute filesystem path.
- RDN (Relative Distinguished Name) — The leftmost component of the DN that distinguishes this entry from its siblings. In
uid=jdoe,ou=People,dc=example,dc=com, the RDN isuid=jdoe. - dc (Domain Component) — Represents a part of the DNS domain.
example.combecomesdc=example,dc=com. - ou (Organizational Unit) — A container for organizing entries, similar to folders:
ou=People,ou=Groups,ou=Servers. - cn (Common Name) — A human-readable name, often used as the RDN for groups and services:
cn=engineering. - uid (User ID) — Login username, commonly used as the RDN for user entries.
- sn (Surname) — Last name.
- givenName — First name.
- mail — Email address.
- userPassword — Stored password hash (or delegated to another authentication system).
- memberOf — Groups the user belongs to (virtual attribute in Active Directory, computed from group
memberattributes).
Schema and Object Classes
LDAP enforces data structure through a schema — a set of rules defining what attributes an entry can or must have. The schema is built from two components:
- Attribute Types — Define individual attributes with a name, OID (Object Identifier), syntax (string, integer, DN, etc.), matching rules (case-sensitive, case-insensitive), and whether it is single-valued or multi-valued.
- Object Classes — Define sets of required and optional attributes. Every entry has one or more object classes that determine its shape.
Object classes come in three types:
- Structural — Defines the primary nature of an entry. Every entry must have exactly one structural object class. Examples:
inetOrgPerson,organizationalUnit,groupOfNames. - Auxiliary — Adds optional attributes to an entry without changing its structural class. Examples:
posixAccount(adds UID, GID, home directory),ldapPublicKey(adds SSH public keys). - Abstract — A base class that other classes inherit from.
topis the root abstract class that all entries inherit from.
A typical user entry might use these object classes:
dn: uid=jdoe,ou=People,dc=example,dc=com objectClass: top objectClass: inetOrgPerson # structural: cn, sn, mail, etc. objectClass: posixAccount # auxiliary: uidNumber, gidNumber, homeDirectory objectClass: ldapPublicKey # auxiliary: sshPublicKey cn: Jane Doe sn: Doe givenName: Jane uid: jdoe mail: [email protected] uidNumber: 1001 gidNumber: 1001 homeDirectory: /home/jdoe loginShell: /bin/bash userPassword: {SSHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g= sshPublicKey: ssh-ed25519 AAAA... jane@laptop
LDAP Operations
LDAP defines a set of operations that clients can perform:
Bind (Authentication)
The Bind operation authenticates the client to the directory. There are two types:
- Simple Bind — The client sends a DN and password in plaintext. This must always be used over an encrypted connection (LDAPS or StartTLS) to prevent credential interception.
- SASL Bind — The client authenticates using a SASL mechanism such as GSSAPI (Kerberos), EXTERNAL (TLS client certificate), DIGEST-MD5, or PLAIN. GSSAPI/Kerberos is the standard bind method in Active Directory environments.
A common pattern is the bind-and-search authentication flow: an application binds as a service account, searches for the user by username, then attempts to bind as the found user's DN with the provided password. If the second bind succeeds, the password is correct.
# Step 1: Service account binds BIND DN="cn=app-svc,ou=Services,dc=example,dc=com" Password="svc-secret" # Step 2: Search for the user by username SEARCH Base="ou=People,dc=example,dc=com" Filter="(uid=jdoe)" # Result: DN="uid=jdoe,ou=People,dc=example,dc=com" # Step 3: Attempt to bind as the user BIND DN="uid=jdoe,ou=People,dc=example,dc=com" Password="user-provided-password" # Success = correct password; Failure = wrong password
Search
The Search operation queries the directory. It takes several parameters:
- Base DN — The starting point in the DIT for the search. Example:
ou=People,dc=example,dc=com. - Scope — How deep to search:
base— Only the base entry itself.one(one-level) — Direct children of the base entry only.sub(subtree) — The base entry and all descendants.
- Filter — An expression defining which entries to return. LDAP filter syntax uses prefix notation with specific operators:
- Equality:
(uid=jdoe) - Substring:
(cn=Jane*) - Presence:
(mail=*)— any entry with a mail attribute. - AND:
(&(objectClass=inetOrgPerson)(department=Engineering)) - OR:
(|(uid=jdoe)(uid=bsmith)) - NOT:
(!(accountDisabled=TRUE))
- Equality:
- Attributes — Which attributes to return. By default, all user attributes are returned; you can request specific ones for efficiency:
cn mail memberOf. - Size Limit — Maximum number of entries to return.
- Time Limit — Maximum time the server should spend on the search.
Add, Modify, Delete, Modify DN
- Add — Creates a new entry in the directory. The request includes the full DN and all required attributes.
- Modify — Changes attributes of an existing entry. Supports three modification types:
add(add a value),delete(remove a value), andreplace(replace all values). - Delete — Removes an entry from the directory. The entry must be a leaf (no children) unless the server supports the subtree delete control.
- Modify DN — Renames an entry or moves it to a different location in the DIT.
Compare and Extended Operations
- Compare — Tests whether an entry has a specific attribute value without returning the entry. Useful for password verification without exposing the password hash.
- Extended — A generic operation type for protocol extensions. The most important extended operation is StartTLS (OID 1.3.6.1.4.1.1466.20037), which upgrades a plaintext LDAP connection to TLS.
LDAPS vs. StartTLS
LDAP supports two methods for TLS encryption:
- LDAPS (LDAP over SSL/TLS, port 636) — The connection starts as TLS from the beginning, similar to HTTPS. The client connects to port 636 and performs a TLS handshake before any LDAP traffic.
- StartTLS (port 389) — The client connects on the standard LDAP port (389) in plaintext, then sends a StartTLS extended operation to upgrade the connection to TLS. After the TLS handshake completes, all subsequent LDAP operations are encrypted.
Both provide the same level of encryption once established. LDAPS is simpler (no upgrade step) and is generally preferred in new deployments. StartTLS has a known downgrade vulnerability: if an attacker can strip the StartTLS command from the client's connection (a man-in-the-middle attack), the client may fall back to plaintext. To prevent this, clients should be configured to require StartTLS and fail if it is not available.
Active Directory: Microsoft's LDAP Implementation
Microsoft Active Directory (AD) is the world's most deployed LDAP-based directory. It serves as the authentication and authorization backbone for most enterprise Windows environments. AD uses LDAP as its primary access protocol, with several extensions:
- Global Catalog (GC) — A read-only, partial replica containing a subset of attributes from all domains in an AD forest. Accessible on port 3268 (LDAP) or 3269 (LDAPS). Used for cross-domain searches and Universal Group membership resolution.
- AD-specific attributes —
sAMAccountName(pre-Windows 2000 login name),userPrincipalName(UPN, the modern login format:[email protected]),userAccountControl(bitmask controlling account state: disabled, locked, password expired, etc.),whenCreated,whenChanged. - Integrated Kerberos — AD uses Kerberos for authentication by default. LDAP bind operations in AD environments typically use GSSAPI (Kerberos) or NTLM rather than simple bind.
- Group Policy — AD stores Group Policy Objects (GPOs) that are applied to computers and users based on their OU placement in the DIT.
- LDAP referrals — In a multi-domain forest, AD returns referrals directing the client to the appropriate domain controller for cross-domain queries.
- rootDSE — The root of the directory (empty DN) exposes server capabilities, naming contexts, supported controls, and the default domain DN.
AD also supports LDAP controls — extensions to standard LDAP operations. Important AD controls include paged results (for searches returning more than 1000 entries), server-side sorting, and the SD control (for retrieving security descriptors).
LDAP Replication
Production LDAP deployments use replication for high availability and geographic distribution. Two replication models exist:
- Single-master (master-replica) — One server accepts writes; changes are replicated to read-only replicas. Used by OpenLDAP (with syncrepl). Simple but the master is a single point of failure for writes.
- Multi-master — Multiple servers accept writes; changes are replicated to all peers. Used by Active Directory, 389 Directory Server, and OpenLDAP (with mirror mode). More resilient but introduces conflict resolution complexity — what happens when the same entry is modified simultaneously on two masters?
Active Directory uses a multi-master replication model where all domain controllers accept writes. Replication is based on a change notification mechanism with configurable replication intervals (15 seconds within a site, 15 minutes or more between sites). AD uses Update Sequence Numbers (USNs) and a high-watermark vector to track which changes each replica has already received, preventing infinite replication loops.
LDAP Injection
Similar to SQL injection, LDAP injection occurs when user input is incorporated into LDAP search filters without proper sanitization. Consider an application that searches for a user like this:
filter = "(&(uid=" + username + ")(userPassword=" + password + "))"
An attacker who enters *)(uid=*))(|(uid=* as the username can manipulate the filter to bypass authentication. The resulting filter becomes:
(&(uid=*)(uid=*))(|(uid=*)(userPassword=anything))
Defenses include:
- Input sanitization — Escape special characters in LDAP filters:
*,(,),\,NUL. RFC 4515 defines the escaping rules. - Parameterized queries — Use LDAP libraries that support parameterized filter construction rather than string concatenation.
- Bind-based authentication — Instead of searching for a matching username+password combination, search for the user by username only, then attempt a bind as that user with the provided password. This avoids putting the password in a filter entirely.
LDAP in Authentication Flows
LDAP rarely faces end users directly. Instead, it serves as the backend for other authentication protocols:
- RADIUS — RADIUS servers (FreeRADIUS, NPS) authenticate users by performing LDAP binds against the directory. The RADIUS server receives the user's credentials, looks up the user in LDAP, and attempts a bind to verify the password.
- SAML — SAML Identity Providers (ADFS, Shibboleth, Keycloak) query LDAP for user attributes and verify credentials via LDAP bind before issuing SAML assertions.
- Kerberos — Active Directory stores Kerberos principal information (keys, ticket policies) in LDAP. The KDC (Key Distribution Center) queries LDAP to look up principal records and retrieve encryption keys for ticket generation.
- PAM/NSS — On Linux systems, PAM (Pluggable Authentication Modules) and NSS (Name Service Switch) can query LDAP for user authentication and account information, allowing centralized management of Linux user accounts via the same directory used for Windows.
- OIDC — OpenID Connect providers like Keycloak and Dex use LDAP as their user store, querying the directory for authentication and attribute retrieval.
LDAP Performance and Indexing
LDAP servers must handle high query rates efficiently. Performance depends heavily on proper indexing:
- Equality index — Speeds up exact match searches like
(uid=jdoe). Essential for attributes used in bind-and-search authentication. - Substring index — Speeds up wildcard searches like
(cn=*doe*). Consumes more disk space than equality indexes. - Presence index — Speeds up searches for entries that have a specific attribute:
(mail=*). - Approximate index — Supports "sounds like" searches using phonetic algorithms.
Without proper indexes, LDAP searches degrade to full directory scans. On a directory with millions of entries, an unindexed search can take seconds instead of milliseconds — and the LDAP server may refuse the query entirely if it exceeds the configured time or size limits.
Security Best Practices
- Always use TLS — Use LDAPS (port 636) or require StartTLS on port 389. Never allow plaintext LDAP in production. Credentials sent via simple bind are in cleartext without TLS.
- Use service accounts wisely — Service accounts used for LDAP queries should have minimal permissions: read-only access to the specific OUs and attributes they need. Never use a domain admin account as an application's LDAP bind DN.
- Implement account lockout — Configure account lockout after a number of failed bind attempts to prevent brute-force attacks against the directory.
- Hash passwords properly — Store passwords using strong hashing algorithms (SSHA-512, bcrypt, PBKDF2). Avoid legacy schemes like MD5 or SHA-1.
- Protect the rootDSE — The rootDSE exposes server configuration information. In sensitive environments, restrict anonymous access to the rootDSE.
- Monitor search performance — Log slow queries and unindexed searches. They can indicate misconfigured applications or denial-of-service attacks.
- Sanitize inputs — Escape special characters in LDAP filter construction to prevent LDAP injection attacks.
LDAP and Network Infrastructure
LDAP directories are critical infrastructure whose availability directly impacts authentication across the entire organization:
- DNS — Active Directory is tightly integrated with DNS. Domain controllers register SRV records (
_ldap._tcp.example.com) that clients use to discover LDAP servers. DNS failures can prevent LDAP discovery entirely. - TLS — LDAPS and StartTLS depend on properly configured certificates. Certificate expiration or CA trust issues cause authentication outages that affect every service using the directory.
- Kerberos — AD domain controllers serve as both LDAP servers and Kerberos KDCs. The two protocols share the same infrastructure and user store.
- BGP — In multi-site deployments, LDAP replication traffic and client queries traverse WAN links routed by BGP. Routing disruptions can partition the directory, causing authentication failures at remote sites.
Relevant RFCs
- RFC 4511 — Lightweight Directory Access Protocol (LDAP): The Protocol. Defines LDAP v3 operations.
- RFC 4512 — LDAP: Directory Information Models. Defines the DIT, entries, attributes, and schema.
- RFC 4513 — LDAP: Authentication Methods and Security Mechanisms.
- RFC 4515 — LDAP: String Representation of Search Filters.
- RFC 4516 — LDAP: Uniform Resource Locator.
- RFC 4519 — LDAP: Schema for User Applications. Defines standard attribute types and object classes.
- RFC 4532 — LDAP "Who am I?" Extended Operation.
- RFC 2307 — An Approach for Using LDAP as a Network Information Service (POSIX attributes).
See It in Action
Major LDAP and directory service providers operate on networks routed via BGP. Explore them using the god.ad BGP Looking Glass:
- AS8075 — Microsoft (Active Directory / Azure AD / Entra ID)
- AS15169 — Google (Google Workspace / Cloud Identity LDAP)
- AS16509 — Amazon (AWS Directory Service / Managed Microsoft AD)
- AS36459 — GitHub (LDAP authentication for GitHub Enterprise)
- AS14618 — Amazon (AWS IAM Identity Center with AD integration)