Multiple LDAP search bases support
==================================

Purpose
-------

Some deployments use search bases to limit or extend the set of users
and groups visible to a system.

One common example is for applications granting access only to users in
a hard-coded group name. In this case, the group search base would
generally be set differently for each machine running this application.
Other machines running the same application providing access to other
users would receive a different "view" of LDAP through the use of search
bases.

Expected Behaviour
------------------

Individual Lookups
~~~~~~~~~~~~~~~~~~

For targeted lookups (e.g. ``getpwuid()``, ``getgrnam()``) we should try
each of the search bases in order until one of them returns the entry we
are looking for, or we have exhausted all of the search bases. Each
search will be performed with the search scope provided.

Enumeration
~~~~~~~~~~~

For enumeration, we will need to iterate through ALL search bases to
retrieve users, groups, etc. For each search base, we need to examine
each entry retrieved and compare it against the entries received from
earlier search bases. If there are conflicts, we will discard the
conflicting value from the later search base. (Therefore the entry in
the earlier search bases will always win.

Implementation
--------------

We will extend the ``ldap_*_search_base`` options to support behavior
similar to that of ``nss_base_passwd`` and ``nss_base_group`` from
nss-ldapd.

The standard search base (``ldap_search_base`` will be left alone as a
single value with scope "subtree".

The new ``ldap_*_search_base`` options will include a new delimiter,
'``?``'. If this is present, we will divide the string up into triples
as follows: ::

    search_base?scope?filter[?search_base?scope?filter...]

Parsing
~~~~~~~

We will split the input string on the '?' delimiter. If the resulting
array is exactly one, or is a multiple of three, we will continue.
Otherwise it will fail validation.

The scope must be one of 'subtree', 'onelevel' or 'base'
(case-insensitive).

The filter will be optional and may be a zero-length string. The filter
must be pre-sanitized and must pass filter validation with
``ldb_parse_tree()``