* * *
Outlook Express is a little more friendly than Mozilla when it comes to using LDAPS to connect to a directory server. On Windows 98, simply indicating that the directory server should be accessed using SSL on port 636 is enough. It is not necessary to tell Internet Explorer or Outlook to trust the self-signed certificate used by an OpenLDAP server. I'll let you decide whether this is a good thing; Mozilla was less trusting, requiring you to tell it to trust the LDAP server's certificate.
Mail Transfer Agents (MTAs)
The remainder of this chapter discusses LDAP support within several popular MTAs. You can skim this material if you want an overview of various mail servers, or you can focus on the details regarding your specific MTA and skip the others. In either case, I assume that you have some familiarity with the Simple Mail Transport Protocol (SMTP) and mail servers in general.
Before we begin, Table 7-2 provides a summary of the LDAP versions used by the mail servers presented in this section. The same rule for enabling LDAPv2 binds described in the beginning of this chapter still holds true for two out of the three mail servers listed.
Table 7-2. LDAP versions used by various mail servers
Mail transfer agent
LDAPv2 bind
LDAPv3 bind
Sendmail
✓
Postfix
✓
Exim
✓
Sendmail
Sendmail is the default MTA on most current versions of Unix. A number of alternatives have appeared in the past few years (such as Postfix, Qmail, and Exim), but if you work with Unix or Linux systems, chances are you'll deal with Sendmail. Sendmail introduced support for retrieving information from an LDAP directory in Version 8.9. However, this support didn't really stabilize until later versions (this discussion focuses on Version 8.12). It by no means attempts to give comprehensive coverage of Sendmail. For information on the details of configuring and running a Sendmail server, refer to Sendmail, by Bryan Costales and Eric Allman (O'Reilly).
Sendmail's LDAP integration falls into four categories: support for retrieving mail aliases from a directory, support for accessing generic Sendmail maps using LDAP queries, expansion of Sendmail classes at startup using information obtained from a directory, and support for retrieving specific mail-routing information from an LDAP directory. We will return to the specifics of these features in later sections.
In order to support any of these functions, Sendmail must be compiled with the LDAPMAP option enabled. Here's how to modify site.config.m4 to compile LDAP against the client libraries installed by OpenLDAP 2:
dnl . . . /devtools/Site/site.config.m4
dnl Enable LDAP features in Sendmail during compilation
dnl
APPENDDEF (`confMAPDEF´, `-DLDAPMAP´)dnl
APPENDDEF(`confLIBS´, `-lldap -llber´)dnl
dnl
dnl The following two entries are needed so
dnl that make can find the the ldap header files
dnl and libraries
APPENDDEF(`confINCDIRS´, `-I/opt/ldap/include´)dnl
APPENDDEF(`confLIBDIRS´, `-L/opt/ldap/lib´)dnl
Refer to the sendmail/README file for any relevant details about your server's operating system, particularly if you're using LDAP libraries other than OpenLDAP. The previous example was used to build Sendmail 8.12.6 linked against OpenLDAP client libraries on a Linux system. The resulting sendmail binary should be checked to ensure that the LDAPMAP option was properly enabled. Here we have a Linux host named garion that includes several compile-time options that were enabled by default. The only one to be concerned with is the LDAPMAP flag that you specified in site.config.m4:
$ cd sendmail-8.12.6/obj.Linux.2.4.19.i686/sendmail
$ echo | ./sendmail -bt -d0
Version 8.12.6
Compiled with: DNSMAP LDAPMAP LOG MATCHGECOS MIME7TO8
MIME8TO7 NAMED_BIND NETINET NETUnix NEWDB
PIPELINING SCANF USERDB USE_LDAP_INIT XDEBUG
= == == == SYSTEM IDENTITY (after readcf) == == == =
(short domain name) $w = garion
(canonical domain name) $j = garion.plainjoe.org
(subdomain name) $m = plainjoe.org
(node name) $k = garion
Sendmail 8.12 includes what developers have described as an experimental schema file for OpenLDAP 2. The attributes and object classes are not defined in any Internet-Draft or RFC and may change in future releases. Because we are mainly concerned with exploring the specifics of sendmail, this is of little risk to us. However, if other applications made use of it, changes to the directory schema would require tight control so no dependencies are broken. Figure 7-9 displays the six object classes defined Sendmail's schema file. All of the attributes are defined as strings (either as a Directory String or an IA5String).
* * *
Warning
There is a syntax error in the sendmail.schema file included with Sendmail 8.12.6. The sendmailMTAAliasGrouping attribute uses an invalid combination with String matching rules. This can be fixed by changing the SYNTAX for this attribute to use the Directory String OID (1.3.6.1.4.1.1466.115.121.1.15).
* * *
Figure 7-9. Object classes defined in sendmail.schema
To install the Sendmail objects and attributes, simply copy sendmail.schema to the schema/ directory:
root# cp cf/sendmail.schema /usr/local/etc/openldap/schema
and then include it in the global section of slapd.conf:
## Add support for Sendmail 8.12 objects and atrributes.
include /usr/local/etc/openldap/schema/sendmail.schema
As usual, slapd will need to be restarted to recognize the new items.
Maps
To access information quickly, Sendmail uses a number of maps in which it retrieves dates by searching for a unique key value. These maps can take various forms; some of the more common ones are the Berkeley DBM or YP/NIS maps. Within the sendmail.cf file, an LDAP map is designated by the ldap keyword. If you're hacking the Sendmail configuration directly, you can use LDAP for any of the maps, but that's beyond the scope of this book. We will work only with Sendmail's m4 configuration generator.
Sendmail provides support for several frequently used maps as FEATURE( ) s. Any of these features that accept an optional argument to refine the search can also accept the keyword LDAP to specify that the lookup should be performed using directory calls. The most basic definition of an access_db table using LDAP would look like:
FEATURE(`access_db´, `LDAP´)
The default sendmail.cf entry generated for this m4 macro is:
Kaccess ldap -k (&(objectClass=sendmailMTAMapObject)
(sendmailMTAMapName=access)
(|(sendmailMTACluster=${sendmailMTACluster})
(sendmailMTAHost=$j))
(sendmailMTAKey=%0))
-1 -v sendmailMTAMapValue
The -k option defines the search, and the -v parameter specifies the name of the attribute's value to return. -1 indicates that the search must return only one value or else it will be considered a failure. Table 7-3 contains a complete list of LDAP-specific options. It is best to refer to the Sendmail documentation (doc/op/op.ps) for a complete list of all lookup parameters.
Table 7-3. Configuration options for use with LDAP maps
Switch
Description
-1
The search must return a single value or else it is considered to be a failed lookup.
-b suffix
The DN to use as the base search suffix.
-d binddn
Defines a DN to use when binding to the directory.
-h hostname
The LDAP server hostname.
-k filter
Defines the search filter.
- l time-Z size
Define the time and size limits for a given search. The time limit is given in seconds.
-M method
The method of authentication to use when binding t
o the LDAP server: LDAP_AUTH_NONE, LDAP_AUTH_SIMPLE, or LDAP_AUTH_KRBV4.
-n
Retrieves attribute names only, not values. This is the same as the attrsOnly Boolean flag used during ldap_search( ).
-P pwfile
The file containing the credentials for -d binddn.
-p port
The port to use when connecting to the LDAP server.
-R
Does not automatically chase referrals.
-r deref
Controls how Sendmail should dereference aliases when searching: never, always, search, or find.
-s
The search scope (base, one, or sub).
-V sep
Retrieves both the attribute name and value separated by the sep character.
-v
Defines the attribute type that contains the value of the search result.
It is possible to define your own defaults for LDAP searches using the confLDAP_DEFAULT_SPEC variable in your m4 source file. This is a common place to set the hostname of the LDAP server and the base suffix used in searches. We will see an example of this later when we discuss aliases.
Table 7-4 lists all of the the Sendmail m4 features that support LDAP queries.
Table 7-4. Sendmail features that can be defined to use LDAP searches
Feature
sendmailMTAMapName
Description
access_db
access
List of hosts or networks that should be allowed to relay mail
authinfo
authinfo
Provides a separate map for storing client authentication information
bitdomain
bitdomain
A table for mapping bitnet hosts to Internet addresses
domaintable
domain
Makes use of a table that maps domain names to new domain names
genericstable
generics
Utilizes a table that contains rules for rewriting sender addresses in outgoing mail
mailertable
mailer
Includes support for a mailer table that contains rules for routing mail to specific domains
uucpdomain
uucpdomain
A table for mapping UUCP hosts to Internet addresses
virtusertable
virtuser
Includes support for a domain-specific version of aliasing
Aliases
Before implementing mail alias lookups via LDAP, let's begin with a simple sendmail.mc configuration file for a central mail hub for the plainjoe.org domain. Figure 7-10 illustrates how this host fits into the plainjoe.org network. Clients on the network spool messages to the mail hub, which ensures that all outgoing messages have a send in the form of [email protected]:
divert(-1)
#######################################################
Sendmail m4 file for plainjoe.org mail hub on local
network.
#######################################################
divert(0)
OSTYPE(`linux´)dnl
FEATURE(`use_cw_file´)dnl
dnl
dnl Masquerading settings
dnl
EXPOSED_USER(`root´)dnl
MASQUERADE_AS(`plainjoe.org´)dnl
MASQUERADE_DOMAIN(`plainjoe.org´)dnl
FEATURE(`masquerade_envelope´)dnl
FEATURE(`masquerade_entire_domain´)dnl
dnl
FEATURE(`relay_entire_domain´)dnl
FEATURE(`local_procmail´)dnl
define(`PROCMAIL_MAILER_PATH´, `/usr/bin/procmail´)dnl
define(`STATUS_FILE´, `/var/log/mail.stats´)dnl
dnl
dnl Mailer settings
dnl
MAILER(`smtp´)dnl
MAILER(`procmail´)dnl
Figure 7-10. Utilizing a simple mail hub for the plainjoe.org domain
The ALIAS_FILE m4 option (AliasFile in sendmail.cf) allows an administrator to define the location of the aliases file (even within an LDAP directory). A very basic /etc/mail/aliases might appear as:
postmaster: root, [email protected]
nobody: /dev/null
Here, the postmaster alias maps to the root account and the address [email protected]. Any mail addressed to [email protected] is sent to the bit bucket (/dev/null).
To use Sendmail's default LDAP search parameters for aliases, simply add:
define(`ALIAS_FILE´, `ldap:´)dnl
to the source m4 configuration file. This will generate a search similar to the one shown for the access_db lookup. However, this default search does not restrict the returned results to a single value (i.e., there is no -1 option specified).
ldap -k (&(objectClass=sendmailMTAAliasObject)
(sendmailMTAAliasGrouping=aliases)
(|(sendmailMTACluster=${sendmailMTACluster})
(sendmailMTAHost=$j))
(sendmailMTAKey=%0))
-v sendmailMTAAliasValue
You could integrate the mail aliases into the existing ou=people organizational unit within your directory. There is one main problem with this, however: all of the object classes defined in sendmail.schema are defined as structural. The user accounts with ou=people cannot have a second structural class. You should therefore create a new ou to store aliases for Sendmail. Other applications may arise in the future that also require a portion of the directory for storing data. In preparation, the naming scheme ou= servicename ,ou=services,dc=plainjoe,dc=org has been chosen to organize subtrees. Figure 7-11 shows your new directory namespace.
Figure 7-11. New ou=aliases for use by Sendmail
The LDIF needed to create these three new ous should be very familiar by now:
dn: ou=services,dc=plainjoe,dc=org
objectClass: organizationalUnit
ou: services
dn: ou=sendmail,ou=services,dc=plainjoe,dc=org
ou: sendmail
objectClass: organizationalUnit
dn: ou=aliases,ou=sendmail,ou=services,dc=plainjoe,dc=org
objectClass: organizationalUnit
ou: aliases
Next, you will create the directory entries corresponding to the /etc/mail/aliases entries for postmaster and nobody:
dn: sendmailMTAKey=postmaster,ou=aliases,ou=sendmail,
ou=services,dc=plainjoe,dc=org
objectClass: sendmailMTAAliasObject
sendmailMTAAliasValue: root
sendmailMTAAliasValue: [email protected]
sendmailMTAKey: postmaster
dn: sendmailMTAKey=postmaster,ou=aliases,ou=sendmail,
ou=services,dc=plainjoe,dc=org
objectClass: sendmailMTAAliasObject
sendmailMTAAliasValue: /dev/null
sendmailMTAKey: nobody
The final step is to configure the actual lookup in sendmail.mc . Because you expect to use additional LDAP searches in Sendmail, it is best to define any global defaults using confLDAP_DEFAULT_SPEC . Specify that all LDAP requests should be sent to the host ldap.plainjoe.org:
define(confLDAP_DEFAULT_SPEC, `-h ldap.plainjoe.org´)dnl
The ALIAS_FILE definition will contain the base suffix, search filter, and requested attribute values. By default, Sendmail uses a subtree scope, which is fine for the alias searches:
define(`ALIAS_FILE´, `ldap:-k
(&(objectClass=sendmailMTAAliasObject)(sendmailMTAKey=%0))
-v sendmailMTAAliasValue
-b "ou=aliases,ou=sendmail,ou=services,dc=plainjoe,dc=org"´)dnl
After generating and installing the new sendmail.cf file:
$ cd sendmail-8.12.6/cf/cf
$ sh Build sendmail.cf
$ /bin/su -c "cp sendmail.cf /etc/mail/sendmail.cf"
you can test aliases using Sendmail's verify mode (sendmail -bv):
$ sendmail -bv [email protected]
root . . . deliverable: mailer local, user root
[email protected] . . . deliverable:
mailer local, user mailadmin
Before continuing on to Sendmail's ldap_routing feature, you may be wondering what advantage was achieved by storing Sendmail's aliases in LDAP. After all, you did create a new subtree within the directory, and it certainly does seem that some information, such as usernames, will end up being duplicated from the organizational unit. How did you reduce the duplication of data?
By shifting your focus from account management to service management, you can see that your directory provides a means of sharing basic Sendmail configuration data among multiple servers. This means that you no longer have to manage duplicate /etc/mail/aliases files on each of your Sendmail hosts. Remember that the default Sendmail LDAP queries include:
(|(sendmailMTACluster=${sendmailMTACluster})(sendmailMTAHost=$j))
as part of the search filter. A Sendmail installation can be defined as a member of a cluster using the confLDAP_CLUSTER variable:
define(`confLDAP_CLUSTER´, `MailCluster´)
This provides a means of associating directory entries with individual hosts ($j) or groups of servers (${sendmailMTACluster}).
Mail routing using LDAP
Sendmail's LDAP mail-routing functionality can be described as an LDAP virtusertable. This is a domain-specific form of aliasing that supports the handling of virtual domains. It provides rules for rewriting recipient addresses or rerouting a message to the appropriate host. The following virtual user table entry would route messages that are addressed to [email protected] to the host somehost.foo.com:
[email protected] somehost.foo.com
Under its default configuration, Sendmail's ldap_routing uses the inetLocalMailRecipient auxiliary object class defined in the expired Internet-Draft draft-lachman-laser-ldap-mail-routing-xx.txt. A version of this draft is included with the OpenLDAP source distribution. There are no required attributes in this object class, as you can see in Figure 7-12.
LDAP System Administration Page 18