ProblemYou have been asked to configure sendmail to read the genericstable from an LDAP server. SolutionOn the LDAP server, add support for the sendmail.schema file to the LDAP configuration as described in Recipe 1.3. On the LDAP server, add the genericstable data to the LDAP database by first creating an LDIF file and then running ldapadd . Use the sendmailMTAMap object class defined in the sendmail.schema file to format the genericstable data in the LDIF file. On the LDAP server, you can also create an LDIF file containing the generics domain data for class $=G . The data should be formatted using the sendmailMTAClass object class defined in the sendmail.schema file. Use ldapadd to add the data from the LDIF file to the LDAP database. On the sendmail system, check that sendmail includes LDAP support. If the command sendmail -bt -d0.1 does not display the string LDAPMAP in the "Compiled with:" list, recompile and reinstall sendmail as described in Recipe 1.3. On the sendmail system, add a genericstable FEATURE macro that loads the genericstable from the LDAP server to the sendmail configuration. Use the GENERICS_DOMAIN_FILE macro to load class $=G from the LDAP server. Set the confLDAP_CLUSTER define to match the sendmailMTACluster attribute used in the genericstable entries added to the LDAP database. Here are sample lines you might add to a sendmail configuration to read the genericstable from an LDAP server: dnl Define the sendmailMTACluster value define(`confLDAP_CLUSTER', `wrotethebook.com') dnl Load the genericstable from the LDAP server FEATURE(`genericstable', `LDAP') dnl Load class $=G from the LDAP server GENERICS_DOMAIN_FILE(`@LDAP') Follow the example in Recipe 1.8 to build and install the sendmail.cf file and then restart sendmail. DiscussionThis recipe uses an LDAP server to duplicate the configuration used in Recipe 4.11. Why and how the genericstable is used is covered in Recipe 4.11. This recipe focuses on how the genericstable data is stored in and retrieved from an LDAP server. The data is first entered into an LDIF file. Each data entry is formatted in a manner compatible with the sendmail schema. The LDAP record format used for the genericstable can be used for any sendmail database by simply placing the database's map name in the sendmailMTAMapName attribute, the correct key data in the sendmailMTAKey attribute, and the correct return value in the sendmailMTAMapValue attribute. Here is an example using the dave , becky, and alana entries from the genericstable described in Recipe 4.11. # cat > ldap-generics dn: sendmailMTAMapName=generics, dc=wrotethebook, dc=com objectClass: sendmailMTA objectClass: sendmailMTAMap sendmailMTACluster: wrotethebook.com sendmailMTAMapName: generics dn: sendmailMTAKey=dave, sendmailMTAMapName=generics, dc=wrotethebook, dc=com objectClass: sendmailMTA objectClass: sendmailMTAMap objectClass: sendmailMTAMapObject sendmailMTAMapName: generics sendmailMTACluster: wrotethebook.com sendmailMTAKey: dave sendmailMTAMapValue: david.craig@wrotethebook.com dn: sendmailMTAKey=becky, sendmailMTAMapName=generics, dc=wrotethebook, dc=com objectClass: sendmailMTA objectClass: sendmailMTAMap objectClass: sendmailMTAMapObject sendmailMTAMapName: generics sendmailMTACluster: wrotethebook.com sendmailMTAKey: becky sendmailMTAMapValue: rebecca.fro@wrotethebook.com dn: sendmailMTAKey=alana, sendmailMTAMapName=generics, dc=wrotethebook, dc=com objectClass: sendmailMTA objectClass: sendmailMTAMap objectClass: sendmailMTAMapObject sendmailMTAMapName: generics sendmailMTACluster: wrotethebook.com sendmailMTAKey: alana sendmailMTAMapValue: alana.smiley@wrotethebook.com Ctrl-D # ldapadd -x -D "cn=Manager,dc=wrotethebook,dc=com" \ > -W -f ldap-generics Enter LDAP Password: SecretLDAPpassword adding new entry "sendmailMTAMapName=generics, dc=wrotethebook, dc=com" adding new entry "sendmailMTAKey=dave, sendmailMTAMapName=generics, dc=wrotethebook, dc=com" adding new entry "sendmailMTAKey=becky, sendmailMTAMapName=generics, dc=wrotethebook, dc=com" adding new entry "sendmailMTAKey=alana, sendmailMTAMapName=generics, dc=wrotethebook, dc=com" Notice that four entries are used to enter the first three genericstable values in the LDAP database. The first entry defines the genericstable map name, which is generics . Once the map name is known to LDAP, data can be associated with that map name. The next three entries contain the actual genericstable data. The sendmail configuration in this recipe also uses LDAP to load class $=G . The following example adds a class $=G entry to the LDAP database containing a sendmailMTAClassValue attribute that matches the GENERICS_DOMAIN value used in Recipe 4.11: # cat > ldap-generics-domain dn: sendmailMTAClassName=G, dc=wrotethebook, dc=com objectClass: sendmailMTA objectClass: sendmailMTAClass sendmailMTAHost: chef.wrotethebook.com sendmailMTAClassName: G sendmailMTAClassValue: chef.wrotethebook.com Ctrl-D # ldapadd -x -D "cn=Manager,dc=wrotethebook,dc=com" \ > -W -f ldap-generics-domain Enter LDAP Password: SecretLDAPpassword adding new entry "sendmailMTAClassName=G, dc=wrotethebook, dc=com" Again, the data is first entered into an LDIF file and then stored in the LDAP database using the ldapadd command. The sendmailMTAClassName attribute identifies the class to which the data belongs. The individual values bound for class $=G are defined by the sendmailMTAClassValue attributes in the LDAP record. Only one sendmailMTAClassValue is used in the example, but a single sendmailMTAClassName record can hold multiple values. The ldapsearch command can be used to examine the results: # ldapsearch -LLL -x '(sendmailMTAMapName=generics)' sendmailMTAMapValue dn: sendmailMTAMapName=generics, dc=wrotethebook, dc=com dn: sendmailMTAKey=dave, sendmailMTAMapName=generics, dc=wrotethebook, dc=com sendmailMTAMapValue: david.craig@wrotethebook.com dn: sendmailMTAKey=becky, sendmailMTAMapName=generics, dc=wrotethebook, dc=com sendmailMTAMapValue: rebecca.fro@wrotethebook.com dn: sendmailMTAKey=alana, sendmailMTAMapName=generics, dc=wrotethebook, dc=com sendmailMTAMapValue: alana.smiley@wrotethebook.com # ldapsearch -LLL -x '(sendmailMTAClassName=G)' sendmailMTAClassValue dn: sendmailMTAClassName=G, dc=wrotethebook, dc=com sendmailMTAClassValue: chef.wrotethebook.com Three modifications were made to the sendmail configuration from Recipe 4.11 to create a configuration that reads genericstable data from LDAP:
Adding the LDAP string to the genericstable FEATURE command changes the format of the sendmail.cf K command that defines the generics database. A grep shows the effect of the LDAP string: # grep 'Kgenerics' recipe4-10.cf Kgenerics hash /etc/mail/genericstable # grep '^Kgenerics' sendmail.cf Kgenerics ldap -1 -v sendmailMTAMapValue -k (&(objectClass=sendmailMTAMapObject)((sendmailMTACluster=${sendmailMTACluster}) (sendmailMTAHost=$j))(sendmailMTAMapName=generics)(sendmailMTAKey=%0)) The first grep shows the default format of the K command used to declare the generics database when no arguments are used with the genericstable FEATURE command. By default, sendmail looks for a hash type database in the local file /etc/mail/genericstable . Adding the LDAP argument to the genericstable FEATURE command changes the database type to ldap and adds some LDAP-specific options to the K command. The -v option specifies the LDAP attribute used as the return value. The -k option defines the LDAP search criteria used as a database key. All of the attribute names used in the K command shown above are attributes defined in the sendmail schema. If you define your own schema, you cannot simply use the LDAP string in the genericstable FEATURE command. You must instead manually define -v and -k options that use your custom schema. For example: FEATURE(`genericstable', `ldap: -1 -k (&(objectClass=LocalUserObject) (LocalUserKey=%0)) -v LocalUserEmailAddress') Of course, the attribute names used in this example are imaginary and would need to be replaced with the attributes you defined when you designed your custom schema. However, the format of the genericstable FEATURE command is similar to the command you would use in your sendmail configuration. Notice that the K command created by adding the LDAP argument to the genericstable feature does not include the LDAP server name or the LDAP default base distinguished name. The server and the base can be added to the K command using the same -h and -b arguments that you would use with the ldapsearch command. In the sendmail configuration, the -h and -b arguments are defined using confLDAP_DEFAULT_SPEC ; see Recipe 5.9 for an example. However, it is not necessary to use confLDAP_DEFAULT_SPEC if the HOST and BASE values in the ldap.conf file are correct for sendmail. After this recipe is installed, genericstable data can be read from LDAP exactly as if it were being read from a local database, as the following test illustrates: # rm -f /etc/mail/genericstable* # sendmail -bt ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > /map generics alana map_lookup: generics (alana) returns alana.smiley@wrotethebook.com (0) > /quit The rm command proves that the test cannot be reading genericstable data from a local file. The /map command passes the key alana to the generics database and gets the return value alana.smiley@wrotethebook.com . The /map command in this example is formatted exactly as it was in Recipe 4.11, when data was read from a local database. The only difference is that, here, data is being read from an LDAP server. The test that was used in Recipe 4.11 to evaluate the effect of the $=G class can be rerun after this recipe is installed. Again, it works exactly as expected despite the fact that the data comes from an LDAP server: # sendmail -bt ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > $=G chef.wrotethebook.com > /tryflags HS > /try esmtp alana@[127.0.0.1] Trying header sender address alana@[127.0.0.1] for mailer esmtp canonify input: alana @ [ 127 . 0 . 0 . 1 ] Canonify2 input: alana < @ [ 127 . 0 . 0 . 1 ] > Canonify2 returns: alana < @ rodent . wrotethebook . com . > canonify returns: alana < @ rodent . wrotethebook . com . > 1 input: alana < @ rodent . wrotethebook . com . > 1 returns: alana < @ rodent . wrotethebook . com . > HdrFromSMTP input: alana < @ rodent . wrotethebook . com . > PseudoToReal input: alana < @ rodent . wrotethebook . com . > PseudoToReal returns: alana < @ rodent . wrotethebook . com . > MasqSMTP input: alana < @ rodent . wrotethebook . com . > MasqSMTP returns: alana < @ rodent . wrotethebook . com . > MasqHdr input: alana < @ rodent . wrotethebook . com . > canonify input: alana . smiley @ wrotethebook . com Canonify2 input: alana . smiley < @ wrotethebook . com > Canonify2 returns: alana . smiley < @ wrotethebook . com . > canonify returns: alana . smiley < @ wrotethebook . com . > MasqHdr returns: alana . smiley < @ wrotethebook . com . > HdrFromSMTP returns: alana . smiley < @ wrotethebook . com . > final input: alana . smiley < @ wrotethebook . com . > final returns: alana . smiley @ wrotethebook . com Rcode = 0, addr = alana.smiley@wrotethebook.com > /quit The data for any sendmail database and for any sendmail class can be defined centrally through an LDAP server. sendmail treats the data the same, regardless of the source. See AlsoRecipe 4.11 explains how the genericstable is used and it explains the importance of class $=G . Chapter 5 provides additional examples of using LDAP for sendmail databases. The sendmail book covers the GENERICS_DOMAIN_FILE macro in Section 4.8.16.2, the genericstable in Section 4.8.16, and the confLDAP_CLUSTER define in Section 21.9.82. The cf/README file covers LDAP in the section Using LDAP for Aliases, Maps, and Classes . |