Skip to content
July 27, 2011 / Terry Gardner

LDAP: Using ldapsearch

ldapsearch is a command-line tool distributed with most directory server software used to search for entries in a directory information tree (DIT) and possibly return specified attributes from the entry. ldapsearch can also return just the distinguished name (DN) of the entry with no attributes, or the names of attributes with no values.

ldapsearch prints out information in LDIF format, which is a textual representation of the data in the directory information tree. In this textual representation, characters that are not safe UTF-8 characters are base-64 encoded (look for double semi-colons (::) in the LDIF output following an attribute type or name).

Understanding how to construct filters to find objects in a directory to some extent involves understanding matching rules. Matches rules are discussed in “LDAP: Search Best Practices” and “LDAP: Matching Rules”.

naming

The distinguished name (DN) is the string that identifies an entry in the directory server database, and can be thought of as the “primary key” of an entry. An example of a distinguished name is "uid=user.0,ou=people,dc=example,dc=com" which serves to identity the entry of "user.0". The entry "uid=user.0,ou=people,dc=example,dc=com" has attributes associated with it that we will discover using ldapsearch.

The directory information model is tree-like, that is, it can be considered to be like a file-system in nature, where objects “above” another object are notated as being to the right of the object in LDIF. In a file system, the DN of user.0 might be notated as /com/example/people/user.0 where people is “above” user.0, whereas in LDIF, ou=people is “above” user.0 in the DN "uid=user.0,ou=people,dc=example,dc=com".

the environment

Where possible, examples are given using the old OpenLDAP ldapsearch syntax and also using a more modern ldapsearch syntax.

A directory server has been installed at localhost, listening on ports 1389 and 1636. The directory server supports unsecured connections on port 1389, connections using the StartTLS extended operation on port 1389, and connections using SSL on port 1636. The examples are given for completeness, and for compatibility with older installations: new code, configuration, and scripts should use TLS, not SSL. In some cases, the root DN "cn=directory manager" is used to authenticate the connection.

The naming contexts for this directory server are dc=example,dc=com and o=example, as given by querying the root DSE as shown below:

Using the old OpenLDAP ldapsearch tool:

/usr/bin/ldapsearch -LLL -x -h localhost -p 1389 \
 -b '' -s base \
 '(objectClass=*)' namingContexts
dn:
namingContexts: dc=example,dc=com
namingContexts: o=example.com

Using the modern ldapsearch tool and StartTLS:

ldapsearch --hostname localhost --port 1389 \
 --useStartTls --trustAll \
 --baseDn '' --searchScope base \
 '(objectClass=*)' namingContexts
dn:
namingContexts: dc=example,dc=com
namingContexts: o=example.com

Using the modern ldapsearch tool and SSL:

#
# modern ldapsearch tool
# using SSL
#
ldapsearch --hostname localhost --port 1636 \
 --useSSL --trustAll \
 --baseDn '' --searchScope base \
 '(objectClass=*)' namingContexts
dn:
namingContexts: dc=example,dc=com
namingContexts: o=example.com

The examples will use the naming context (or prefix, if you prefer)
dc=example,dc=com.

components of a search

To search for an entry or entries in a directory, the following
components must be provided:

  • base object, or base DN
  • scope
  • filter
  • list of attributes – may have a default in your API
  • whether aliases are dereferenced – may have a default in your API
  • size limit – may have a default in your API
  • time limit – may have a default in your API
  • types only – may have a default in your API

base object

The base object or base DN, possibly referred to as the search base in some documentation, is the distinguished name (DN) “relative to where the search is to be performed” (RFC 4511). In other words, the search starts at the base object. Objects above the base object will not be returned in the search. If the base object is the zero-length string, the object is called the root DSE. The root DSE contains information about the directory server and the objects it hosts, known request controls, vendor information, and other data. See The Root DSE for more information.

scope

The scope of a search has one of three values: base, one, or sub, corresponding to the object itself, one level immediately subordinate to the object, and all subtrees subordinate to the object.

filter

A filter is used to limit objects returned to the conditions of the filter. As with all search filters, be aware of and understand the matching rules the directory server will use to do matching of attribute values. Some examples of filters are:

  • (objectClass=*) – a presence filter, used to limit the objects returned to those entries that have an objectClass attribute, which in the directory information model is all entries.
  • (uid=user.0) – an equality filter, used to limit the objects returned to those objects where the uid attribute has the value user.0. Note that this might be multiple entries. Some directory servers support the notion of attribute uniqueness which might restrict the number of entries where the attribute uid has the value user.0 to one entry.
  • (uid=user.*) – a substring filter, used to find the entries that begin with the string user. and are followed by some characters. This is not a wildcard in the sense of regular expressions as exemplified by the UNIX commands grep, fgrep and egrep. Directory servers vary in their support of substring searches.
  • (employeeNumber>=1) – a greater than filter, used to limit objects returned to those which have an employeeNumber attribute with an integer value greater than or equal to 1..
  • (employeeNumber<=1) – a less than filter, used to limit objects returned to those which have an employeeNumber attribute with an integer value less than or equal to 1.
  • (employeeNumber~=1) – an approx filter, used to limit objects returned to those who employee number is approximately 1.
  • (uid:caseExactMatch:=user.0)- an example of an extensible match filter that limits the objects returned to the uid whose value is exactly user.0 (that is, case-sensitive).

    Use the old OpenLDAP ldapsearch to retrieve the entries which have a uid attribute that matches user.0, where case is significant:

    /usr/bin/ldapsearch -LLL -x -h localhost -p 1389 \
     -D 'cn=directory manager' -w password \
     -b ou=people,dc=example,dc=com -s one \
     '(uid:caseExactMatch:=user.0)' uid
    dn: uid=user.0,ou=People,dc=example,dc=com
    uid: user.0
    

    Use the old OpenLDAP ldapsearch to retrieve the entries which have a uid attribute that matches usEr.0, where case is significant:

    /usr/bin/ldapsearch -LLL -x -h localhost -p 1389 \
     -D 'cn=directory manager' -w password ]
     -b ou=people,dc=example,dc=com -s one \
     '(uid:caseExactMatch:=usEr.0)' uid
    

    Use the modern ldapsearch to retrieve the entries which have a uid attribute that matches user.0, where case is significant:

    ldapsearch --hostname localhost --port 1389 \
     --useStartTLS --trustAll \
     --bindDn 'cn=directory manager' --bindPassword password \
     --baseDn ou=people,dc=example,dc=com --searchScope one \
     '(uid:caseExactMatch:=user.0)' uid
    dn: uid=user.0,ou=People,dc=example,dc=com
    uid: user.0
    

    Use the modern ldapsearch to retrieve the entries which have a uid attribute that matches usEr.0, where case is significant:

    ldapsearch --hostname localhost --port 1389 \
     --useStartTLS --trustAll \
     --bindDn 'cn=directory manager' --bindPassword password \
     --baseDn ou=people,dc=example,dc=com --searchScope one \
     '(uid:caseExactMatch:=usEr.0)' uid
    

    Components of the DN can be included in an extensible match. For example, to list all the uid attributes in the subtree underneath the ou=people,dc=example,dc=com branch use the dn attributes flag dn after the attribute:

    #
    # OpenLDAP ldapsearch tool
    #
    /usr/bin/ldapsearch -LLL -x -h localhost -p 1389 \
     -D 'cn=directory manager' -w password \
     -b dc=example,dc=com -s sub  -z 3 \
     '(ou:dn:caseIgnoreMatch:=people)' uid
    dn: ou=People,dc=example,dc=com
    
    dn: uid=user.0,ou=People,dc=example,dc=com
    uid: user.0
    
    dn: uid=user.1,ou=People,dc=example,dc=com
    uid: user.1
    
    Size limit exceeded (4)
    Additional information: This search operation
    has sent the maximum of 3 entries to the client
    #
    # modern syntax
    #
    ldapsearch --hostname localhost --port 1389 \
     --bindDn "cn=directory manager" --bindPassword password \
     --baseDn dc=example,dc=com --searchScope sub \
     --sizeLimit 3 '(ou:dn:caseIgnoreMatch:=people)' \
      uid
    dn: ou=People,dc=example,dc=com
    
    dn: uid=user.0,ou=People,dc=example,dc=com
    uid: user.0
    
    dn: uid=user.1,ou=People,dc=example,dc=com
    uid: user.1
    
    This search operation has sent the maximum of 3 entries to the client
    Result Code:  4 (Size Limit Exceeded)
    Diagnostic Message:  This search operation has
     sent the maximum of 3 entries to the client
    

    This example limited the number of entries to return (-z 3 in the older syntax, --sizeLimit 3 in the more modern syntax). caseIgnoreMatch is used for comparisons because the ou=People entry has an uppercase P in People.

Filters can also be combined with and (&), or (|), and not (!):

  • (|(uid=user.0)(objectClass=inetOrgPerson)) - limits the objects returned to those whose uid has the value user.0 or an objectClass whose value is inetOrgPerson
  • (&(uid=user.0)(objectClass=inetOrgPerson)) - limits the objects returned to those whose uid has the value user.0 and an objectClass whose value is inetOrgPerson
  • (!(objectClass=inetOrgPerson)) - limits the objects returned to those that do not have an objectClass attribute with value inetOrgPerson. Negation filters can only have one filter component, i.e., (!(objectClass=inetOrgPerson)(uid=user.0)) is not a legal negation filter and will be rejected by LDAP compliant directory servers, however, there are some directory servers in wide use that will accept this illegal value for a negation filter. These directory servers should not be used in non-trivial or mission-critical environments.


Hint icon NOTE: depending on your directory server software, you may need to inform your friendly neighborhood directory server administrator of which attributes you intend to use in search filters and what kind of filters you intend to use because those attributes may need to be indexed.

types only

If typesOnly is false, attributes and value safe returned, otherwise only attribute descriptions are returned.

requested attribute list

The list of attributes to return from the entries that match the search parameters.

  • If no attribute list is specified, all attributes are returned
  • If an asterisk (*) is specified, all attributes are returned except operational attributes - escape the asterisk from the shell if necessary
  • If the attribute 1.1 is specified, then no attributes are returned (1.1 is the OID that cannot match to any other attribute). If 1.1 and other attribute names are specified, then the 1.1 is ignored
  • The plus sign + indicates the operator's desire to get all operational attributes
  • If the list of attribute names contains @objectClassName then all attributes that are required or allowed by that objectClass and that are present in matched entries are returned to the client ("LDAP: Retrieving attributes of an object class")

Return no attributes:

/usr/bin/ldapsearch -LLL -x -h localhost -p 1389 \
 -D 'cn=directory manager' -w password \
 -b ou=people,dc=example,dc=com -s one \
 '(uid:caseExactMatch:=user.0)' 1.1
dn: uid=user.0,ou=People,dc=example,dc=com

Return the value of the uid attribute (the 1.1 is ignored:

ldapsearch --hostname localhost --port 1389 \
 --useStartTLS --trustAll \
 --bindDn 'cn=directory manager' --bindPassword password \
 --baseDn ou=people,dc=example,dc=com --searchScope one \
 '(uid:caseExactMatch:=user.0)' uid 1.1
dn: uid=user.0,ou=People,dc=example,dc=com
uid: user.0

Return all attributes except operational attributes:

/usr/bin/ldapsearch -LLL -x -h localhost -p 1389 \
 -D 'cn=directory manager' -w password \
 -b ou=people,dc=example,dc=com -s one \
 '(uid:caseExactMatch:=user.0)'
dn: uid=user.0,ou=People,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
postalAddress: Aaren Atp$91327 Broadway Street$Las Vegas, UT  08103
postalCode: 08103
description: This is the description for Aaren Atp.
uid: user.0
userPassword:: e1NTSEF9Y1Y1RStDUUxEOU12R2hZd05tYnUxU1N0Ly9NR2pMOElyL2hVUHc9PQ=
 =
employeeNumber: 0
initials: AWA
givenName: Aaren
pager: +1 214 214 4195
mobile: +1 947 007 3231
cn: Aaren Atp
sn: Atp
telephoneNumber: +1 089 907 9947
street: 91327 Broadway Street
homePhone: +1 457 787 9183
l: Las Vegas
mail: user.0@example.com
st: UT

Return the value of all the operational attributes using '+' as one of the requested attribute names:

/usr/bin/ldapsearch -LLL -x -h localhost -p 1389 \
 -D 'cn=directory manager' -w password \
 -b ou=people,dc=example,dc=com -s one \
 '(uid:caseExactMatch:=user.0)' +
dn: uid=user.0,ou=People,dc=example,dc=com
ds-entry-unique-id:: rVWjSnY/NY+T+dqG+ezZ5A==
entryUUID: ad55a34a-763f-358f-93f9-da86f9ecd9e4
ds-entry-checksum: 3185925438
subschemaSubentry: cn=schema

Return the value of all attributes that are allowed or required by the person object class from the entry uid=user.0,ou=people,dc=example,dc=com and no authentication state:

ldapsearch -h localhost -p 1389 \
  -b uid=user.0,ou=people,dc=example,dc=com \
  -s base '(&)' @person
dn: uid=user.0, ou=People, dc=example, dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
description: This is the description for Aaren Atp.
description: test value.
cn: Aaren Atp
sn: Atp
telephoneNumber: +1 089 907 9947
userPassword: {SSHA}DScFdUF4NLfLRj2Xm9x9nRDOHqlyt+bbkjTrKg==

size limit

Limits the number of entries returned. A value of 0 (zero) indicates that no client-requested limit is in effect.

This value, known as the client-requested value, cannot override any restrictions the server may have placed on the number of entries to return. For example, modern professional-quality directory servers can enforce restrictions on the number of entries returned in very granular ways, such as restricting the number of entries that will be returned in response to a search request for a particular authentication identity. The client-requested size limit cannot override this restriction - the client-requested limit can only be lower than the administrator limits.

The default in most ldapsearch implementations is 0. All but the most trivial searches should include a client-requested size limit and time limit greater than 0.

time limit

Limits the amount of time (in seconds) spent on a search. A value of 0 indicates an unlimited amount of time. As with the size limit, client-request valued cannot override server restrictions. The default in most clients is 0. All but the most trivial searches should include a client-requested size limit and time limit greater than 0.

references

Updates

  • Added reference to '@' objectClassname in attribute lists
  • Added reference to LDAP: Programming Practices
  • Clarified the use of the old OpenLDAP tool vs. the modern tool
  • Added references to matching rules in a more prominent place