Purpose and Audience
The same filter grammar applies across standards-compliant servers, but available attributes and matching rules depend on the target schema. Build against that schema and escape every untrusted assertion value.
What Is an LDAP Search Filter?
An LDAP search filter is a string representing one or more Boolean conditions used to select which directory entries are returned by an LDAP search operation. The filter itself does not specify where to search (the search DN), the scope (base, one, subtree), or which attributes are returned—those are distinct parameters in LDAP queries. Instead, the filter specifies only the selection logic: which entries match the criteria expressed in the filter string. Syntax precision is critical, as LDAP servers interpret filter strings strictly according to standards, and mistakes often result in no results or subtle misbehavior.
LDAP Filter Syntax (RFC 4515 Essentials)
LDAP filter strings must be constructed according to the rules specified in RFC 4515. The syntax models filters as fully parenthesized, nested Boolean expressions, using ASCII/UTF-8 characters and a specific set of operators:
- Each filter is enclosed in parentheses:
(filter) - Operators are encoded as single leading characters:
&(AND),|(OR),!(NOT) - Comparisons use attribute=value syntax inside parentheses: e.g.,
(cn=John Doe) - Special characters (
*,(,),\, and NUL) within values must be escaped with a backslash followed by their hex code
Examples of valid filter structures:
- Simple equality:
(uid=bob) - Boolean AND:
(&(objectClass=person)(department=Engineering)) - Negation:
(!(mail=*))
Any deviation from this form, missing parentheses, or failure to escape reserved characters will render the filter invalid, or worse, silently modify its logic.
Basic Filter Types and Their Use
LDAP provides several core filter types:
Equality:
(attr=value)
Matches entries whereattrequalsvalue. Example:(uid=jdoe)Presence:
(attr=*)
Matches entries whereattris present with any value. Example:(mail=*)Substring:
(attr=pre*mid*suf)
Finds entries where the value ofattrstarts withpre, containsmid, and ends withsuf. Wildcards can be used at any position except for a completely empty value. Example:(cn=Jo*)finds "John", "Joanna", etc.Ordering:
(attr>=value)or(attr<=value)
Matches attributes greater than or equal to (or less than or equal to) the given value, as defined by the attribute's schema matching rule.Approximate:
(attr~=value)
Matches attributes that are approximately equal to the value, according to the directory's schema and implementation.Extensible Match:
(attr:matchingRule:=value)
Uses a matching rule OID to apply custom or advanced comparisons (such as group membership inheritance in Active Directory).
Example (AD-specific):(member:1.2.840.113556.1.4.1941:=dn)
Combining Filters: AND, OR, NOT, and Nesting
LDAP implements Boolean logic using prefix operators:
AND:
(&(...)(...))
Both (or all) enclosed filters must be true.
Example:(&(objectClass=person)(mail=*))OR:
(|(...)(...))
At least one enclosed filter must be true.
Example:(|(department=Engineering)(department=Sales))NOT:
(!(filter))
Inverts the result of the enclosed filter.
Example:(!(telephoneNumber=*))
Filters can be nested without practical depth limits (as per specification), though excessively deep nesting can harm maintainability and, occasionally, compatibility.
Example of a complex filter:(&(|(department=Engineering)(department=Sales))(!(cn=Test User)))
Each subfilter must itself be a valid LDAP filter.
Escaping Special Characters in LDAP Filters
Certain characters have special meaning in LDAP filter strings and must be escaped if they occur in attribute values:
*(asterisk): Used for wildcards in substring filters(and)(parentheses): Denote filter boundaries\(backslash): Escape character itself- NUL (ASCII 0x00): Not allowed unescaped
Escape sequences use a backslash and two hex digits representing the character code:
*→\2a(→\28)→\29\→\5c- NUL →
\00
Example:
To filter for a literal asterisk value * in the displayName attribute:(displayName=\2a)
Failure to escape these characters will either cause a syntax error or result in incorrect (and potentially insecure) filter behavior.
Attribute Matching, Case Sensitivity, and Schema Impact
Attribute names in filters are case-insensitive: (CN=alice) is the same as (cn=alice). However, attribute value comparisons depend on the attribute's matching rule, which is defined in the directory schema—not by the filter syntax itself:
- For most string attributes (like
cn,sn,mail), the matching rule is usually case-insensitive. - For some attributes (e.g., password, binary data), comparisons may be case-sensitive or require exact matching.
Thus, always consult your directory's schema documentation to confirm how values are matched, especially for custom attributes.
Active Directory and Vendor-Specific Filter Considerations
Active Directory often optimizes queries on the objectCategory attribute better than on the multi-valued objectClass attribute. This is because:
objectCategoryis single-valued and indexed; it enables faster queries for entry type filtering.- Many standard AD queries for users, groups, or computers are written as:
(&(objectCategory=person)(objectClass=user))
Additionally, AD and some LDAP servers support matching rule OIDs for advanced cases:
- The
1.2.840.113556.1.4.1941OID enables recursive (transitive) group membership searches (theinChainrule).
Caution: Not all LDAP servers support OID-based matching rules or proprietary extensions. Porting such filters between products may require changes.
Common LDAP Filter Mistakes (and How to Avoid Them)
Major sources of filter failures include:
- Unescaped special characters: The most common culprit for failed queries. Always escape reserved characters in values—at every occurrence, not just at the beginning or end.
- Parenthesis mismatches: Missing or extra parentheses lead to invalid filters.
- Unsupported features: Using wildcards in filter positions or with attribute types not supported by your server, or using OID-based matches on servers that do not support them.
- Incorrect logic grouping: Misplaced
&,|, or!may invert or miscombine subfilters. Double-check all nested logic. - Schema misunderstandings: Assuming case-sensitivity or insensitivity without confirming attribute matching rules.
To debug, validate filter strings against RFC 4515's rules and, if available, test with your directory's CLI tools or a reputable LDAP GUI browser.
Best Practices for Building Reliable LDAP Search Filters
- Readability: Format and comment complex filters in your application configuration or code; avoid unnecessary nesting.
- Escape values: Consistently call escape logic in any filter-builder functions.
- Schema awareness: Understand your target directory’s schema—check attribute types, matching rules, and what is indexed for best performance.
- Performance: Prefer indexed, single-valued attributes (like
objectCategoryin AD) for type and membership queries. - Cross-vendor compatibility: Avoid vendor-specific features (notably matching rule OIDs and proprietary attributes) unless they are strictly required and portable is not a goal.
- Validation: Always test filters with representative data and, if possible, with multiple LDAP implementations your code may encounter.
Authoritative References and Further Reading
- RFC 4515: Lightweight Directory Access Protocol (LDAP): String Representation of Search Filters
- RFC 2254: The String Representation of LDAP Search Filters (historic)
- The LDAP Filter Definition (Oracle copy of RFC 2254)