cache
no
Determines whether to enable client-side caching of LDAP search results, as described in the ldap_enable_cache(3) manpage.
cache_expiry
30 seconds
Defines the cache expiration timeout when cache=yes.
cache_size
32 KB
Specifies the size of the LDAP cache when cache=yes.
dereference
0
Controls whether Postfix should dereference aliases when searching the directory. Possible values are 0 (never), 1 (when searching), 2 (when locating the base object for the search), and 3 (always).
domain
none
A list (possibly a table lookup) of domain names that restricts when a query is made. This means that a local "user" (with the @ . . . ) will not be queried, nor will any email address that does not match one of the domains listed. For example:
ltable_domain = plainjoe.
org, hash:/etc/postfix/moredomains
query_filter
(mailacceptinggeneralid=%s)
The RFC 2254-style LDAP search filter.
result_attribute
maildrop
The attribute value that should be read as a result of the query_filter.
scope
sub
The scope of the directory search; must be one of sub, base, or one.
search_base
none
The DN that acts as the base search suffix for the query.
server_host
localhost
The hostname of the LDAP server to which queries should be submitted. The value is of the form hostname [:port ][,hostname [:port ], . . . ].
server_port
389
The port on which the server_host is listening (unless overridden by the hostname:port syntax).
special_result_attribute
none
Allows administrators to define an attribute that returns DNs from an LDAP search. If this value is present in the entry returned by a successful search, another query is issued using the returned DN as the search_base.
timeout
10 seconds
The maximum amount of time, in seconds, that can elapse before the search is abandoned.
Exim
The Exim MTA is another Sendmail alternative. It was first developed in 1995 by Dr. Philip Hazel while at Cambridge University. For the full details on configuring Exim, Philip Hazel's book, Exim: The Mail Transfer Agent (O'Reilly), provides an excellent tutorial on the various configuration details.[1] If you are not familiar with Exim, it is a good idea to visit http://www.exim.org/ to obtain an overview of Exim's mail architecture. We will be looking at Exim 4.10.
Like Sendmail and Postfix, Exim supports various types of file and database lookups, such as mySQL, Berkeley DBM, and LDAP. In its default form, the Exim Makefile supports only linear searches in files (lsearch) and database lookups (dbm). To enable LDAP lookups, a handful of Makefile variables must be set. These variables are presented in Table 7-8.
Table 7-8. Exim LDAP-related Makefile variables
Variable
Description
LOOKUP_LDAP
This variable must be set to yes to include LDAP lookup support in the exim binary.
LOOKUP_INCLUDE
LOOKUP_LIBS
These variables provide a means of supplementing the existing CFLAGS and LDFLAGS variables when building Exim. To support LDAP lookups, they must specify the locations of include files and LDAP libraries. For example:
LOOKUP_INCLUDE=-I/opt/ldap/include
LOOKUP_LIBS=-L/opt/ldap/lib -llldap -llber
LDAP_LIB_TYPE
This variable defines which LDAP client libraries will be used. Possible values are UMICHIGAN, OPENLDAP1, OPENLDAP2, NETSCAPE, and SOLARIS.
Build the mail server with the following LDAP settings in Exim's Local/Makefile:
## Included in Exim's Local/Makefile to enable LDAP lookup support
LOOKUP_LDAP=yes
LOOKUP_INCLUDE=-I /usr/local/include
LOOKUP_LIBS=-L/usr/local/lib -lldap -llber
LDAP_LIB_TYPE=OPENLDAP2
It is a good idea to verify that the OpenLDAP libraries have been linked to the exim binary using some type of tool, such as ldd(1) , to view linking dependencies:
$ ldd /usr/exim/bin/exim
libresolv.so.2 => /lib/libresolv.so.2 (0x40026000)
libnsl.so.1 => /lib/libnsl.so.1 (0x40037000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x4004b000)
libdb-4.0.so => /lib/libdb-4.0.so (0x40078000)
libldap.so.2 => /usr/local/lib/libldap.so.2 (0x4010f000)
liblber.so.2 => /usr/local/lib/liblber.so.2 (0x40146000)
libc.so.6 => /lib/libc.so.6 (0x40153000)
libdl.so.2 => /lib/libdl.so.2 (0x4027b000)
libsasl2.so.2 => /usr/lib/libsasl2.so.2 (0x4027e000)
libssl.so.2 => /lib/libssl.so.2 (0x40290000)
libcrypto.so.2 => /lib/libcrypto.so.2 (0x402bd000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Once the Exim binaries have been built and installed (we'll assume that the default location of /usr/exim/ is the installation directory), the next step is decide what data should be retrieved from the directory. Our discussion of Postfix defined a useful schema for retrieving mail aliases for local users; let's see how this same schema applies to Exim. The schema makes use of the uid attribute type (posixAccount) as the key and the mail attribute type (inetOrgPerson) as the resulting value. For completeness's sake, here's the LDIF entry for a user account with a mail alias; it's the same entry you used for the Postfix server. All mail that would be delivered to the local user named guest1 should be forwarded to the address [email protected].
## User account including a mail alias
dn: uid=guest1,ou=People,dc=plainjoe,dc=org
uid: guest1
cn: Guest Account
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword: {CRYPT}Fd8nE1RtCh5G6
loginShell: /bin/bash
uidNumber: 783
gidNumber: 1000
homeDirectory: /home/guest1
gecos: Guest Account
sn: Account
mail: [email protected]
Exim searches are defined using the data keyword. The general syntax for a table lookup is:
data = ${lookup db_type {db_search_parameters}}
LDAP queries can use a db_type of:
ldap
Indicates that the search will return a single value and that Exim should interpret multiple values as a failure
ldapdn
Specifies that the search will match one entry in the directory and that the returned value is the DN of that entry
ldapm
Defines searches that may return multiple values
To inform Exim that local alias data should be retrieved from an LDAP directory, you must configure an appropriate redirect router. To do so, you create an ldap_aliases entry in /usr/exim/configure :
## Alias Director, which retrieves data from an LDAP director. The name
## "ldap_aliases" has been arbitrarily chosen.
ldap_aliases:
driver = redirect
data = ${lookup ldap
{ ldap://ldap.plainjoe.org/
ou=people,dc=plainjoe,dc=org
?mail?sub?(uid=${local_part})} }
The driver keyword is used to define the type of router being implemented. In contrast to both Sendmail and Postfix, Exim uses an LDAP URL to define the LDAP host, port, search base, retrieved attribute values, scope, and filter. The line continuation character () has been used to make the line more readable. The variable ${local_part} is the username extracted from the local recipient's mail address (for example, the ${local_part} of [email protected] would be jdoe). So you can read the query specification as: "Using the LDAP server at ldap.plainjoe.org (on the def
ault port of tcp/389), perform a substring search of the uid attribute, searching for the local part of the email address, and returning the value of the mail attribute. Perform the search with a search base of ou=people,dc=plainjoe,dc=org."
* * *
Note
It is possible to define multiple servers for LDAP queries with the ldap_default_servers parameter in Exim's configure file. This option accepts a colon-separated list of servers and ports that are tried one by one until a server is successfully contacted. This setting would utilize two directory servers, ldap1 and ldap2, for fault tolerance purposes:
ldap_default_servers = ldap1::389:ldap2::389
* * *
Using Exim's address-testing mode, you can verify that mail sent to guest1@garion will indeed be forwarded to [email protected]:
root# exim -v -bt guest1@garion
[email protected]
<-- [email protected]
deliver to [email protected]
router = dnslookup, transport = remote_smtp
host plainjoe.org [xxx.xxx.xxx.xxx]
The log file for slapd (loglevel 256) shows that the lookup for (uid=guest1) was performed as expected:
Aug 16 17:05:09 ldap slapd[3574]: conn=36 op=1 SRCH
base="ou=people,dc=plainjoe,dc=org" scope=2 filter="(uid=guest1)"
The LDAP URL format does not allow any space for defining credentials to be used when binding to the server. The default behavior is to perform an anonymous bind and not request any limits on search results. Exim can request a simple bind using credentials specified by the user and pass options. Table 7-9 lists several parameters that can be included in the LDAP query as option = value to specify authentication information as well as search limits.
Table 7-9. Additional Exim LDAP query parameters
Parameter
Description
user
The DN used when binding to the directory server
pass
The clear-text password used when binding to the directory server with a non-empty user
size
The upper limit on the number of entries returned from the lookup
time
The upper limit, in seconds, on the time to wait for a response to a lookup
To use these additional parameters when performing an LDAP lookup, they must preceed the URL in the data string. For example, to bind to the LDAP server as the user cn=Mail Admin,dc=plainjoe,dc=org using the password secret, you would define the following query:
data = ${lookup ldap
{ user="cn=Mail Admin,dc=plainjoe,dc=org"
pass=secret
ldaps://ldap.plainjoe.org/
ou=people,dc=plainjoe,dc=org
?mail?sub?(uid=${local_part})} }
Because Exim uses LDAPv2 binds, it cannot take advantage of SASL authentication or the StartTLS LDAv3 extension. However, it can understand URLs that use ldaps://. This is important when sending a DN and password to the directory server in clear text.
It should also be mentioned that because the pass value is stored in clear text, it is preferable to preface the data line with the hide keyword (i.e., hide data = . . . ) directive so that the line cannot be displayed by ordinary users using the exim -bP command.
* * *
[1] At the time of this writing, Hazel's book covers Exim 3. The current release discussed in this chapter is Exim 4. There have been some substantial changes between the two versions.
Chapter 8. Standard Unix Services and LDAP
In Chapter 6, we examined the possibilities of integrating an LDAP directory into basic authentication services by using the PAM and NSS modules. In Chapter 7, we integrated LDAP into the network mail infrastructure in both clients and servers. This chapter takes LDAP integration a step further by exploring how other standard Unix services can make use of our directory. The applications we will explore are Apache, FTP (ProFTPD), Samba, RADIUS (FreeRadius), DNS (BIND 9), and printing (LPRng and LPD). It is impossible to cover all the services a network may provide, but by showing a few concise, real-world solutions to common problems, I hope to give you tools and ideas that you can apply to any network applications you encounter in the future.
The applications discussed in this chapter will communicate directly with the LDAP directory. Servers that do not possess native LDAP support can use the PAM and NSS solutions presented in Chapter 6.
The Directory Namespace
Although we will eventually need to modify it, we will start by using the namespace developed in Chapter 6 and Chapter 7. Our directory root is dc=plainjoe,dc=org, and user-related information is stored beneath the people organizational unit directly below the root, as shown in Figure 8-1. The group organizational unit contains any posixGroup entries as well as any administrative group (groupOfNames) objects used in access control rules for the directory.[1] We will need to add additional organizational units, which we will do later in this chapter.
Figure 8-1. Initial namespace for the directory used in this chapter
* * *
[1] Examples of using administrative groups in ACLs and the groupofNames object can be found in Appendix E.
An FTP/HTTP Combination
The first set of services that we will explore is the combination of the ProFTPD server (http://www.proftpd.org/) and Apache (http://www.apache.org/). In this scenario, we would like to build a new web server and allow users to publish web content using an FTP client. All user and group accounts already exist in the LDAP directory, but just to make things interesting, assume that your theoretical web server platform cannot make use of either PAM or NSS to access any of this information.
The solution we would like to deploy is illustrated in Figure 8-2. Users should be able to put files into ~
Figure 8-2. Interaction between ProFTPD, Apache, and the LDAP directory on www.plainjoe.org
Two add-ins, both developed by John Morrissey (http://www.horde.net/~jwm), will help you implement your new web server. We will begin by looking at ProFTPD's LDAP features.
ProFTPD
Morrissey's LDAP authentication module (mod_ldap) is included with current releases of the ProFTPD server.[2]
Our focus will be on the ProFTPD Release v1.2.7. Building mod_ldap is controlled by an option to the configure script (—with-modules=mod_ldap). After extracting the source code, the following commands build the binaries and tools to include support for mod_ldap:
$ ./configure --with-modules=mod_ldap
$ make
$ /bin/su -c "make install"
You can specify multiple modules as arguments to the —with-modules option by separating each module name in the list with a colon (e.g., —with-modules=mod_ldap:mod_linuxprivs). For more information on the various modules supported by the ProFTPD package, refer to the documentation included with the software or the online versions at http://www.proftpd.org/docs/.
ProFTPD's -l command-line option can be used to verify that the mod_ldap module was included in the final binary. The actual list of modules may vary depending on the OS used during compilation, but at a minimum, you must see mod_ldap listed:
$ proftpd -l
Compiled-in modules:
mod_core.c
mod_auth.c
mod_xfer.c
mod_site.c
mod_ls.c
mod_unixpw.c
mod_log.c
mod_ldap.c
The sample-configurations/ subdirectory included in the source distribution contains settings for several common scenarios. We'll use the following proftpd.conf file as starting point. The parameters are fairly self-explanatory, but you can review the configuration documentation included i
n the docs/ directory of the proftpd source distribution if you need more information.
## ###################################################
## ProFTPD configuration file
## (/usr/local/etc/proftpd.conf)
## Global directives
## ###################################################
ServerType standalone
DefaultServer on
Port 21
Umask 022
User nobody
Group nobody
## <- LDAP parameters will go here. ->
# Normally, files should be overwritable.
AllowOverwrite on
Your first step is to restrict a user to her individual ~/public_html subdirectory when connecting. We will assume that this directory already exists. The DefaultRoot option defines the path that will be passed to the chroot( ) call by the proftpd server.
## Limit users to their web directory.
DefaultRoot ~/public_html
The next step is to instruct the proftpd daemon to use the mod_ldap module for authentication. The LDAPDoAuth keyword accepts up to three arguments. The first either turns the module on or off. The second argument is the base suffix to use when searching the directory. The final argument allows an administrator to define a customized search filter. In the absence of an explicit filter string, the default of (&(uid=%u)(objectclass=posixAccount)) is used.
## Limit users to their web directory. Use the default search filter.
LDAPDoAuth on "ou=people,dc=plainjoe,dc=org"
Of course, you also must define the hostname of the directory server:
## Define the LDAP server to contact.
LDAPServer ldap.plainjoe.org
By default, the ProFTPD daemon uses an anonymous bind when searching an LDAP directory. However, if you include the LDAPDNInfo directive in the configuration file, the daemon uses a DN and password to bind to the LDAP server. We'll stick with anonymous binds since Chapter 6 allowed nss_ldap clients to enumerate account information this way.
LDAP System Administration Page 20