LDAP Basics: Master Queries and Filters
Last week we explained how LDAP directories work, without really explaining how to use them. This week we'll show how LDAP queries work, after explaining how the protocol works.
The LDAP protocol supports just a few fairly easy to understand operations. Knowing what's available provides administrators with the ability to surmise how various applications are using LDAP, troubleshoot issues, and construct their own search queries and filters more effectively.
A client, be it a PHP script, command-line program like ldapsearch, or LDAP libraries for user authentication in Unix, will connect to a server on port 389 (or 636 with SSL), and send one of roughly a dozen operation requests. The following operations define how the LDAP protocol works:
Binding is the pivotal concept to understand. It is optional, depending on access control restrictions defined in the server. The act of binding is authentication: it sends a user's DN and password. Binding anonymously may not allow access to all directory entries, or it may not be allowed at all, again depending on how the server is configured.
Search or Compare
Search is used to both list entries and search for them. Searching supports a number of parameters, which define how the search is carried out:
- Base: object to start at
- Scope: how much to search; one entry only, a single level below, or the entire subtree below
- Filter: limit (optimize) search based on attribute/value or object filters
- derefAliases: whether or not to follow alias entries
- attributes: which attributes to return (none specified means return all)
- sizeLimit, timeLimit: number of entries to return, and a time limit
- typesOnly: just return the attribute types, not the actual values
Add, Delete, Modify (Update types)
Updating an LDAP entry can take the form of three operations: add, delete, or modify. Actually four, because modify can modify either an entry or a DN. As was explained last week, modifying the DN simply means moving an entry. Add and Delete do the obvious.
Extended operations can be added at will. For example, many servers support the STARTTLS command, tells the server to start a secure connection.
An Abandon operation will abandon any operation, hopefully. There is no guarantee the server will honor an abandon request.
Unbind abandons any outstanding operations and disconnects a client.
As mentioned before, LDAP is pretty simple. You can connect, search or update entries, and then disconnect. Nearly every LDAP communication follows those three steps.
Navigate LDAP With Command Line Utilities
So how does one connect? The majority of connections to an LDAP server are made by LDAP client programs on a Unix machine, in environments that use LDAP for server directory services. Web applications often gather and display directory information, or use LDAP to authenticate people. Aside from those, LDAP connections can also be made by Perl or even shell scripts to manage the information within. When you want to manually search or update information, you will generally use some common tools such as ldapsearch, ldapvi, or ldapmodify.
Searching an LDAP directory can be challenging if you've never done it before. The command-line utilities have a few arguments that aren't optional. Let's take a look at an ldapsearch example:
ldapsearch -h ldapserver.example.com -b ou=People,dc=example,dc=com uid=charlie
The ldapsearch program, in most Unix/Linux environments, take the same arguments. You must specify a server (-h) and a base (-b) to begin searching at. The base can be as broad or as specific as you'd like. We've chose to start searching at the ou (organizational unit) called people, withing the domain components used to designate our portion of the tree. I could have left out the ou=People portion, but if there is anything else at the level below dc=example, then it would search through those too. It faster to specify the subtree as close to the entry as possible, if you know it. Finally, the last argument was a search filter. I stated that I was interested in all entries where the value of the attribute uid was "charlie."
The previous example used an anonymous bind, since a DN wasn't specified. If you need to search information that is restricted to certain people, then specifying -D followed by a user DN will cause ldapsearch to bind as that user, and prompt for a password.
Search filters can be quite complex. When you're searching manually with ldapsearch, you probably won't get very complex. When writing a script that could potentially be run very often, you want as optimal a search as possible. Search filters can specify many thing, including what object classes to look for. It's all about providing as many hints to the server as possible, so that it may make best use of its search indexes.
A search filter has a few basic operators, including "and" and "or" operators. The general syntax is similar to RPN (for math geeks) or functional languages (for programmers). If we want to search for a person whose given name is Bob, and mail attribute is also bob, we could use a search filter of:
If we wanted to return all entries where either bob is the givenName or the mail attribute, we could simply specify:
Notice the | symbol, followed by two or more attribute/value pairs. In reality, we would really want to specify what object class we're looking for, if this was used in a script:
The filter ensures that the objectClass is person, and the other nested statement is true. Again, we're just trying to give as many hints to the server as possible.
An LDAP URL is similar, but it contains all the information necessary to both identify a server and perform a search. URLs similar to this one, or portions of it, may be required to configure some LDAP clients:
The general format is:
LDAP is extremely powerful, and is certainly the best place for server-based directory information and people information. If you already live in an LDAP environment, hopefully you have a better understanding now. If you're pondering an LDAP deployment, go and unleash the power now.