Chapter 7 contains recipes that use the AUTH SMTP extension to provide strong authentication of the end points in a mail exchange. In this chapter, the recipes use the SMTP STARTTLS extension for both strong authentication and encryption.
While encryption is one of the primary benefits of the SMTP STARTTLS extension, it is important to remember that this is not end-to-end encryption. Mail can take multiple hops before it is delivered. Some intervening hops may not use STARTTLS. Additionally, the mail message is still stored as clear text by both the sender and the recipient. STARTTLS only provides encryption for mail passing over a single hop between two sendmail systems configured for STARTTLS.
Chapter 7 explained how sendmail relied on the Simple Authentication and Security Layer (SASL) to provide the security tools necessary for AUTH authentication. STARTTLS relies on the Transport Layer Security (TLS) protocol for both authentication and encryption.
TLS is an Internet standard
protocol, defined in RFC
2246, The TLS Protocol Version 1.0. TLS is based
on the Secure Sockets Layer (SSL) protocol that was originally
developed by Netscape for web security. The manner in which TLS is
used to secure mail transport is defined in RFC 2487, SMTP
Service Extension for Secure SMTP over TLS. The SMTP
extension that supports TLS is called STARTTLS.
The receiving system advertises support for STARTTLS in its response
to the client’s EHLO
command. The
connecting system requests TLS security by issuing the
STARTTLS
command in response to the advertisement.
TLS uses public key encryption, which is also called asymmetric encryption. It is asymmetric because it uses two different keys. A public key that is made available to the world and a private key that is kept secret. Anything encrypted with the public key can only be decrypted with the private key, and anything encrypted with the private key can only be decrypted with the public key. Four keys are needed to authenticate both the TLS client and the TLS server: the client’s public and private keys and the server’s public and private keys.[1]
A TLS public key is distributed in a file called a certificate. It is called a certificate because it is certified to contain a valid public key by a digital signature. There are a few different techniques used to sign the certificates used by sendmail.
First, there are commercial certificate authorities (CAs). For a fee, a commercial CA will sign your certificate request creating a signed certificate. A CA is trusted to provide reasonable assurance that the certificate is correct and represents the organization it claims to represent. Commercial CAs are well established because they have been signing certificates for web sites for a number of years. Using a commercial CA to sign sendmail certificates is easy, and it has the added benefit of supporting a global customer base—certificates signed by a commercial CA are accepted around the world. Because many web sites want access to a global customer base, they use commercial CAs. In fact, a list of trusted commercial CAs can be obtained from any web browser. Figure 8-1 shows the list of CAs displayed by Netscape.
An alternative to using a commercial CA is to create a private CA. Creating a private CA is more complex than using a commercial CA, and it limits the customer base to those sites that are willing to accept certificates from the private CA. While a private CA is inadequate for a web site that must support a global customer base, it is a viable solution for sendmail security because mail security is often used between a limited number of partners. Recipe 8.1 shows you how to build a private CA, and Recipe 8.3 uses that CA to create the certificates used in the other recipes.
Finally, it is possible to create a self-signed certificate, which is not signed by any type of CA. sendmail does not accept self-signed certificates for authentication because, without the certification of a recognized CA, there is no way to verify the certificate’s information. sendmail does, however, accept self-signed certificates for encryption. In fact, if you only want encryption, the TLS client doesn’t need a certificate at all. However, using a CA increases the utility of the STARTTLS protocol because it adds strong authentication to basic encryption.
If the sendmail system is also a web server, it may already have a commercially signed certificate that can be used for sendmail. If not, use openssl to create certificates. To have a sendmail certificate signed by a commercial CA, create a certificate signing request (CSR)—also called a certificate request—and send it to the commercial CA for signing. (See the web site of the CA you select for the exact details.) If you run a private CA, create the CSR and use the private CA to sign it. Recipe 8.2 and Recipe 8.3 show examples of creating a CSR and of signing it to produce a signed certificate.
Certificates contain much more than just a public key. Use openssl to examine the contents of a certificate, as in this example:
# openssl x509 -noout -text -in rodent.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2 (0x2)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=US, ST=Maryland, L=Gaithersburg, O=WroteTheBook,
CN=chef.wrotethebook.com/Email=craig@chef.wrotethebook.com
Validity
Not Before: Jan 28 16:25:58 2003 GMT
Not After : Jan 28 16:25:58 2004 GMT
Subject: C=US, ST=Maryland, L=Gaithersburg, O=WroteTheBook,
CN=rodent.wrotethebook.com/Email=alana@rodent.wrotethebook.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:b0:91:de:51:14:19:91:61:39:ed:23:61:ef:9d:
e4:44:9f:ff:6a:fd:5c:cc:e8:bd:79:1f:2d:bc:eb:
ca:66:da:86:fb:99:17:79:07:94:dd:94:90:aa:6a:
44:55:ff:ec:65:e9:4e:41:b1:e9:e9:c4:09:89:81:
47:2b:a1:bd:a0:0b:bf:9c:c5:5e:39:de:c5:49:a3:
e6:5c:af:9e:32:eb:ae:63:80:7f:c6:ad:12:d0:87:
01:db:06:a3:93:bf:41:9f:51:81:4f:09:fa:da:e3:
ca:69:dc:35:4f:cd:43:fd:ab:6c:51:3d:24:97:60:
bd:bf:e8:91:9c:5a:f4:b2:df
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
76:6E:60:D0:EE:B4:62:49:84:46:04:7C:44:E6:F8:9E:CF:84:B6:DC
X509v3 Authority Key Identifier:
keyid:3C:D9:71:02:66:8A:D4:AD:3C:07:FD:57:2A:C5:03:C2:B8:7D:FF:D5
DirName:/C=US/ST=Maryland/L=Gaithersburg/O=WroteTheBook/
CN=chef.wrotethebook.com/Email=craig@chef.wrotethebook.com
serial:00
Signature Algorithm: md5WithRSAEncryption
c4:45:4a:e4:01:eb:0b:83:c4:26:c5:de:9e:06:8f:7a:b6:2d:
f0:f3:63:dd:ba:1c:22:2d:f9:ac:3d:92:04:c4:4f:a8:9c:d1:
7c:de:a7:6d:94:10:62:cb:69:c6:ba:8f:09:e7:a9:49:18:97:
4b:aa:50:b9:0a:c9:49:59:0d:65:b6:44:1a:d6:88:6c:bd:d9:
3e:89:e6:1c:76:c8:54:69:7f:b4:9d:7a:a7:de:92:12:cc:f5:
43:e5:e5:da:b0:34:9d:cf:ee:b9:65:a1:a8:d7:cc:aa:96:12:
10:7f:2b:99:94:79:f3:b4:bf:0a:58:54:65:7f:98:36:be:a5:
22:de
Several important pieces of information can be seen in this display. Foremost, of course, is the public key. It is the 1024-bit RSA public key that appears about halfway through the display. This is the key used to encrypt the session information sent to the system holding the private key—the session information includes the session key that will be used to encrypt the mail.
The system that owns this certificate is identified by the Subject
field. The Subject field contains
the distinguished
name (DN) of the remote host. The DN is a formal name that
can contain several fields. In this example, the DN contains a
country code (C), a state code (ST), a locality (L), an
organizational name (O), and a common name (CN). Inside the sendmail
configuration, the DN of the subject is found in the
${cert_subject}
macro, and the CN of the subject
is found in the ${cn_subject}
macro. In the
example, the certificate belongs to the host
rodent.wrotethebook.com.
The CA that signed the certificate is identified by the Issuer field,
which contains the DN of the CA. Inside the sendmail configuration,
the DN of the CA is found in the ${cert_issuer}
macro, and the CN of the CA is found in the
${cn_issuer}
macro. In the example,
chef.wrotethebook.com is the private CA that is
created in Recipe 8.1.
At the bottom of the display is the digital signature of the
certificate created by the CA. It is an MD5 digest of the
certificate, which is stored in the sendmail configuration in the
macro ${cert_md5}
. The digest is encrypted by the
CA’s private key. sendmail uses the
CA’s public key to decrypt the digest. If sendmail
successfully decrypts and verifies the digest, it stores
OK
in the macro ${verify}
and
considers the certificate valid for authentication.
The ${verify}
macro
can contain any one of several different
values depending on the result of the verification process. The
possible values for the ${verify}
macro are:
FAIL
The certificate failed the verification process.
NONE
STARTTLS is not being used. Thus no verification was performed.
NOT
A certificate was not requested from the remote host. If the local system does not request a certificate from the remote system, verification is not performed.
NO
No certificate was provided by the remote host. Therefore, there was no certificate to verify.
OK
The certificate was successfully verified.
PROTOCOL
A protocol error occurred.
SOFTWARE
The STARTTLS handshake failed.
TEMP
A temporary error occurred.
Once again, refer back to the certificate displayed by the
openssl
x509
command. Near the
top of the output, the TLS version number is identified in the
Version field of the certificate. Inside the sendmail configuration,
the TLS version number is stored in the
${tls_version}
macro.
As we have seen, several sendmail macros can be traced directly back
to the TLS certificate. Two other important TLS related macros get
their values from the session encryption used for the email
connection. ${cipher}
identifies the type of
encryption used for the connection, and
${cipher_bits}
contains the number of bits of
encryption used for the connection. All of the important TLS
encryption and authentication data is available for use inside the
sendmail configuration.
The best way to control how TLS security information is applied on your system is through the access database. These are the access database records that provide control over a TLS connection:
CERTISSUER
:Authorizes relaying based on the DN of the CA that signed the
certificate. Recipe 8.5 and Recipe 8.6 provide example of using the
CERTISSUER
: record.
CERTSUBJECT
:Authorizes relaying based on the DN of the host that presented the certificate. Recipe 8.6 covers the use of this record.
TLS_Srv
:Defines the minimum security required for an outbound TLS connection.
Recipe 8.7 and Recipe 8.9
show how to use the TLS_SRV
: record.
TLS_Clt
:Defines the minimum security required for an inbound TLS connection.
Recipe 8.8 and Recipe 8.9
contain examples of the TLS_Clt
: record.
TLS_Rcpt
:Defines the minimum security required for mail sent to the specified recipient. Recipe 8.10 uses this record.
Try_TLS
:Controls whether the STARTTLS
command is issued to
the specified remote TLS server. See Recipe 8.11 for an example of how this record is used.
Srv_Features
:Controls whether STARTTLS is advertised to the specified remote TLS client, and whether the specified remote TLS client is required to present a certificate. See Recipe 8.12 and Recipe 8.13 for examples of this record.
sendmail provides hooks into the rulesets that process the access database entries related to STARTTLS:
LOCAL_TLS_CLIENT
is a hook into the
tls_clt
ruleset that processes
TLS_Clt
: database records.
LOCAL_TLS_SERVER
is a hook into the
tls_srv
ruleset that processes
TLS_Srv
: access database
records.
LOCAL_TLS_RCPT
is a hook into the
tls_rcpt
ruleset that processes
TLS_Rcpt
: records.
LOCAL_TRY_TLS
is a hook into the
try_tls
ruleset that processes
Try_TLS
: records.
These hooks provide access to the full range of sendmail’s capabilities, including all of the information that sendmail has at the time that the access database records are being processed. Anything that cannot be done within the confines of the standard database record formats can probably be done through a custom ruleset. The power and simplicity of using the access database to control delivery over a TLS connection make custom TLS rulesets largely unnecessary. However, if you have an application for a custom ruleset, sendmail provides all of the tools you need to roll your own.
The sendmail implementation of STARTTLS depends on OpenSSL for authentication, encryption, and support tools. Before any of the recipes in this chapter can be used, OpenSSL must be installed.
Modern systems often include OpenSSL in order to provide web security. Our sample Red Hat Linux system includes an OpenSSL RPM file, as this simple command shows:
$ rpm -q openssl
openssl-0.9.6b-18
If your system includes OpenSSL, you can proceed. If it is not
installed, install the version provided by your Unix vendor using the
vendor’s package management tools. If your Unix
vendor does not provide OpenSSL, download the source from
http://www.openssl.org/source/or
ftp://ftp.openssl.org/source/. The source comes
as a gzipped tarball. Unzip and restore the
tarball. Go to the newly created directory and run
config and then make to
compile the source code. Then run make
test
and make
install
to install OpenSSL. If you have any
problems compiling the source, see the INSTALL
file delivered with the source code.
Additionally, sendmail must be specially compiled to support STARTTLS. If your sendmail binary was not compiled with STARTTLS support, recompile sendmail as described in Recipe 1.6 and Recipe 1.7.
Your organization has decided not to use a commercial CA and has asked you to create a private CA to sign and manage certificates for sendmail.
Select a directory in which to place the CA directory structure
(/etc/mail/certs is a common choice). Change to
that directory and run the CA script provided
with the OpenSSL distribution. Use the -newca
command-line option of the CA script.[2] The
script allows you to enter a certificate filename to work with an
existing CA certificate. In this case, we are not working with an
existing CA certificate, so just press the Return key to create a new
CA. When
prompted for a PEM passphrase, enter
the password that will be required whenever the certificate authority
is used to sign a certificate request. Finally, enter the
distinguished name of the system that is acting as the CA. Here is an
example:
#cd /etc/mail
#mkdir certs
#cd certs
#/usr/share/ssl/misc/CA -newca
CA certificate filename (or enter to create) Making CA certificate ... Using configuration from /usr/share/ssl/openssl.cnf Generating a 1024 bit RSA private key ...............++++++ .............++++++ writing new private key to './demoCA/private/./cakey.pem' Enter PEM pass phrase:SaytheSECRETword
! Verifying password - Enter PEM pass phrase:SaytheSECRETword
! ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [GB]:US
State or Province Name (full name) [Berkshire]:Maryland
Locality Name (eg, city) [Newbury]:Gaithersburg
Organization Name (eg, company) [My Company Ltd]:WroteTheBook
Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:chef.wrotethebook.com
Email Address []:craig@chef.wrotethebook.com
The CA script creates a directory structure it calls demoCA, which contains the files needed for a private CA. Change the name demoCA to something that sounds less temporary, for example, to the directory name CA:
# mv demoCA CA
Change to the new directory structure. Tighten the security on the private directory, which holds the certificate authority’s private key:
#cd CA
#chmod 0700 private
Copy the openssl.cnf file to the CA directory. The copy will be used by the private CA when signing sendmail certificates. To distinguish it from the original openssl.cnf file, the copy is renamed sendmailssl.cnf when it is copied to the CA directory:
# cp /usr/share/ssl/openssl.cnf sendmailssl.cnf
Finally, edit the sendmailssl.cnf file to point to the newly created CA directory structure. Change the line:
dir = ./demoCA # Where everything is kept
to read:
dir = /etc/mail/certs/CA # Where everything is kept
The private CA can now be used to sign certificates as described in Recipe 8.3.
It is not absolutely necessary to build a private CA just to create the certificates needed by STARTTLS. Introduction to this chapter describes alternative ways to obtain signed certificates. This recipe should not be taken as a recommendation for creating a private CA. It is incorporated as a recipe in this chapter because building a private CA is the most complex method of signing certificates, and thus it is the method most in need of a recipe to explain how it is done. Before you decide to build a private CA, evaluate the alternatives to make sure you choose the approach that is most suitable for your situation.
The complexity of creating a private CA is substantially reduced by
the CA script provided with the OpenSSL
distribution. The CA script accepts several
different command-line arguments, but the one that is most useful for
a sendmail system is the -newca
option.
-newca
causes the script to create the directory
structure and files needed by a CA. It also causes the script to
build the private key and the certificate that will be used by the
CA. An ls of the directory created by the
CA script shows the following:
#ls
cacert.pem certs crl index.txt newcerts private serial #ls private
cakey.pem
The directory created by the CA
script contains
three files:
This file contains the serial number that will be used for the next certificate signed by the CA. The CA script stores the serial number 01 in the initial serial file. The serial number is incremented every time a certificate is signed.
This file maps the serial number assigned to a certificate to the subject of the certificate. The serial number is identified by its numeric value, and the certificate subject is identified by its distinguished name. Initially, this file is empty. Data is added to the file each time a certificate is signed.
This file is the certificate created for the certificate authority by
the CA script. (See Introduction for
information on the format of certificates.) This public key will be
distributed to the sendmail systems that recognize this CA, and it
will be referenced in their configurations. When you create a private
CA to sign certificates for sendmail, it is common to make this the
root CA in the sendmail configuration. See the
confCACERT
define in Recipe 8.4 for an example.
The private key associated with the CA certificate is stored in the
private subdirectory and is named
cakey.pem, as the second ls
command in the example shows. The private key is kept safe on the CA.
It is never distributed to, or used on, any other system. The
cakey.pem file is encrypted and can only be used
by someone who knows the PEM passphrase provided to the
CA script when the
cakey.pem file was created. In the example in
the Solution section, the PEM passphrase is
SaytheSECRETword!
. The passphrase is required in
Recipe 8.3 when the CA is used to sign
certificates.
In addition to the files just described, the directory created by the CA script contains four subdirectories:
This directory is used to hold private keys. The CA script places the certificate authority’s private key here. In the Solution section, the permissions on this directory are changed to 0700.
This directory holds copies of all the certificates signed by this CA. The certificates in this directory are identified by serial numbers. This directory is empty when created by the CA script. Files are added to the directory by the signature process.
This directory holds certificate revocation lists. The CA script creates this directory to be empty. See Network Security with OpenSSL, by Viega, Messier, and Chandra (O’Reilly), for information on CRLs.
This directory can be used to hold certificates. However, the CA script does not place the CA’s certificate in this directory.
This recipe recommends adding a copy of
openssl.cnf to the files and directories created
by the CA
script. The
openssl.cnf configuration file is read by
openssl every time it is executed.
openssl is used to create and sign certificates,
and it will be used in subsequent recipes in this chapter. To
simplify customizing the OpenSSL configuration for sendmail
certificate management, and to avoid any possibility of interfering
with the OpenSSL configuration used by the web site administrator, we
copy openssl.cnf to
sendmailssl.cnf. The new name is intended to
make it clear that this configuration is used only by the sendmail
CA. We then edit the sendmailssl.cnf file to
point to /etc/mail/certs/CA as the directory
used by the default CA. This recipe assumes that the private CA is
being used exclusively for sendmail certificate management. Because
this CA is used exclusively for sendmail, it makes sense to create a
sendmail-specific OpenSSL configuration. Recipe 8.3 uses the newly created
sendmailssl.cnf file.
Recipe 8.2 and Recipe 8.3 are both directly related to this recipe. Introduction to this chapter contains important information about certificates and certificate authorities. The sendmail book discusses certificates in Section 10.10.2. The config manpage provides information on the openssl.cnf file. Network Security with OpenSSL, by Viega, Messier, and Chandra (O’Reilly), provides information about certificates, certificate authorities, and certificate revocation lists.
You must create a certificate request before the CA can sign it, and thus provide you with a signed certificate.
On the sendmail host, create a directory to hold the certificate and private key. Here is an example:
#cd /etc/mail
#mkdir certs
Change to the new directory. Use the openssl
req
command to create an unsigned X.509
certificate and a private key. When prompted for the distinguished
name, enter the DN of the sendmail host for which the certificate is
being created. In this example we create a certificate for
crab.wrotethebook.com:
#cd /etc/mail/certs
#umask 0066
#openssl req -nodes -new -x509 -keyout key.pem -out newcert.pem
Using configuration from /usr/share/ssl/openssl.cnf Generating a 1024 bit RSA private key .++++++ ...................++++++ writing new private key to 'key.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [GB]:US
State or Province Name (full name) [Berkshire]:Maryland
Locality Name (eg, city) [Newbury]:Gaithersburg
Organization Name (eg, company) [My Company Ltd]:WroteTheBook
Organizational Unit Name (eg, section) []: Common Name (eg, your name or the server's name) []:crab.wrotethebook.com
Email Address []:admin@wrotethebook.com
Next, use openssl
x509
to
generate a certificate signing request from the certificate and key
pair created above. The newcert.pem file created
above is a temporary file that can be removed after the CSR is
created:
#openssl x509 -x509toreq -in newcert.pem -signkey key.pem -out csr.pem
Getting request Private Key Generating certificate request #rm -f newcert.pem
Send the CSR, csr.pem in this example, to the CA. The CA signs the sendmail host’s certificate request. Recipe 8.3 shows how this is done using the private CA created in Recipe 8.1.
The CA returns a signed certificate to the sendmail host, along with a copy of the CA’s certificate. On the sendmail host, place the sendmail host’s signed certificate and the CA’s certificate in the certificate directory created in the first step. Create a symbolic link to a hash of the CA’s certificate using the following command:
ln -sca_filename
`openssl x509 -noout -hash <ca_filename
`.0
In the command above, replace ca_filename
with the filename of the CA’s certificate. sendmail
uses the hash created by this command for certificate verification.
Run this command, replacing ca_filename
with the name of the new CA certificate file, every time a CA
certificate is added to the directory identified by the
confCACERT_PATH
define. Recipe 8.4 discusses the
confCACERT_PATH
define.
Most of the work in this recipe is done on the sendmail host. However, it doesn’t have to be. All of the files necessary to request a signed certificate for crab.wrotethebook.com can be generated on any system that has OpenSSL installed. The advantage of creating the CSR on the sendmail host is that the private key is created there and never has to leave the system, making it easier to maintain private key security. The disadvantage is that the administrator of crab.wrotethebook.com needs to use the complex openssl commands to build the CSR. Many sites prefer to have one CA administrator who creates the certificate and key for each sendmail host on the CA server and then distributes the signed files to the sendmail systems. The approach you use is mostly a matter of organizational style.
The only thing that must be created on the sendmail host is the directory that will hold the certificate and the private key. The name of this directory, the name of the certificate file, the name of the key file, and the name of the CA certificate file, are all important values used to configure sendmail for STARTTLS, as can be seen in Recipe 8.4.
The openssl
req
command in the
Solution section
creates
a new, self-signed X.509 certificate (-new
-x509
). The certificate is written to a file named
newcert.pem (-out
newcert.pem
). The private key associated with the
certificate is stored in a file named key.pem
(-keyout
key.pem
). The
key.pem file is not encrypted with DES
(-nodes
). This is important. If the private key is
accidentally placed in an encrypted file, the sendmail administrator
is prompted for the password to decrypt the file every time sendmail
needs to access the private key. This could cause the sendmail system
to hang during the boot process until the password is entered.
The openssl
x509
command
processes an X.509 certificate. In this case, the command converts an
X.509 certificate to a certificate request
(-x509toreq
). The certificate that is being
converted is the newcert.pem file created in the
first step (-in
newcert.pem
-signkey key.pem
). The CSR is
written to a file named
csr.pem (-out
csr.pem
).
The CSR file is sent to the CA. The CA uses that file as input to the signature process and returns another file, which is the signed certificate. Often, one file is sent to the CA and one is returned. The Solution section, however, also mentions a second file—the CA’s certificate. This certificate may not be sent from the CA as part of the signature process. There may be some other means for obtaining that file. Regardless of how the CA certificate is obtained, a hash should be made from the CA certificate as shown in the last step of the Solution. sendmail uses the hash during certificate verification.
Recipe 8.3 covers signing the certificate request created in this recipe.
When you operate a private CA for sendmail, you are responsible for signing the certificate requests of the sendmail hosts.
On the CA, use the openssl
ca
command to sign the certificate signing request provided by the
sendmail host. When prompted for the PEM passphrase, enter the
password created for the private CA. Answer
“yes” to the two questions, and the
certificate is signed. Here is an example in which the CSR created in
Recipe 8.2 is signed on the CA created in
Recipe 8.1:
#openssl ca -config ./sendmailssl.cnf -policy policy_anything -out cert.pem -infiles csr.pem
Using configuration from ./sendmailssl.cnf Enter PEM pass phrase:SaytheSECRETword
! Check that the request matches the signature Signature ok The Subjects Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'Maryland' localityName :PRINTABLE:'Gaithersburg' organizationName :PRINTABLE:'WroteTheBook' commonName :PRINTABLE:'crab.wrotethebook.com' emailAddress :IA5STRING:'admin@wrotethebook.com' Certificate is to be certified until Jan 27 19:50:16 2004 GMT (365 days) Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries Data Base Updated
The CSR sent from the sendmail system is an intermediate file that is no longer needed. Delete the unneeded file:
# rm -f csr.pem
Send the signed certificate to the sendmail host. In this example, we send the file cert.pem to the sendmail host. We named the certificate file cert.pem because it is a neutral name well suited to textbook examples. However, the certificate filename is whatever you choose to make it, and it should be something descriptive. For example, the certificate was signed for the host crab.wrotethebook.com so we could have given it the name crab.wrotethebook.com.cert.pem.
Also, send the sendmail host a copy of the CA’s certificate. Assuming that this is the CA created in Recipe 8.1, the CA certificate file sent to the sendmail host would be cacert.pem.
The openssl
ca
command is used
to sign certificates. In the Solution
section, the openssl command signs the
csr.pem file from Recipe 8.2 (-infiles
csr.pem
), producing a signed certificate in a file
named cert.pem (-out
cert.pem
).
This openssl command references the special
OpenSSL configuration file (-config
./sendmailssl.cnf
) that was created in Recipe 8.1 for the private sendmail CA. If the
configuration file is not identified on the command line using the
-config
option, the openssl
command uses the openssl.cnf file. The OpenSSL
file provides default values used when creating and signing
certificates; it defines the pathnames of the files and directories
required by a CA, and it defines the certificate signing policies. By
default, the openssl.cnf file, and the
sendmailssl.cnf file that Recipe 8.1 created from it, contain two signature
policies:
Signature policies define
what
information must be provided by the DN of the subject before a
certificate will be accepted for signing.
policy_match requires that a common name be
provided. Additionally, it requires that country, state, and
organization names be provided, and that these names match the
country, state, and organization names used in the certificate of the
CA. It makes the organizational unit name and the email address
optional. policy_match is the default if no
-policy
argument is provided on the
openssl
ca
command line.
This policy requires that a common name be provided. It makes all other DN fields optional.
This recipe uses -policy
policy_anything
, which is commonly used when
signing sendmail certificates. After all, the administrator is shown
the DN and asked whether or not the certificate should be signed. If
the administrator deems that the DN does not contain enough
information for email security, the administrator can refuse to sign
the certificate. However, in this specific example,
policy_match could have been used and it would
have worked. Remember, this is a private CA. We know that the
country, state, and organization names used in the DN of the CA match
the values in the DN of the server. Yet,
policy_anything makes a better example because
it is more flexible and deals with a larger variety of
configurations. Most sendmail administrators use
policy_anything and that is why it is included
in this recipe.
After signing the certificate request, the CSR (csr.pem) is deleted. The certificate cert.pem is sent to crab.wrotethebook.com along with the CA’s certificate cacert.pem. The sendmail host will reference both of these certificates in the STARTTLS configuration.
Recipe 8.1 covers creating the private CA
used to sign the certificate in this recipe. Recipe 8.2 creates the certificate request signed in this
example. Introduction to this chapter contains important
information about certificates and certificate authorities. The
sendmail book discusses certificates in Section
10.10.2. The config manpage provides information
on the openssl.cnf file. The
req manpage documents the
openssl
req
command. The
x509 manpage documents the
openssl
x509
command, and the
ca manpage covers the openssl
ca
command. TCP/IP Network
Administration, Third Edition, by Craig Hunt
(O’Reilly), provides examples of using
openssl commands in Chapter 11.
Network Security with OpenSSL, by Viega,
Messier, and Chandra
(O’Reilly), provides information about certificates,
certificate authorities, openssl.cnf, and the
openssl command.
You have been asked to configure sendmail to offer STARTTLS service for transport layer security.
STARTTLS requires that OpenSSL is properly installed and configured. See Introduction for information on installing OpenSSL. It also requires a copy of sendmail compiled with STARTTLS support, as described in Recipe 1.6 and Recipe 1.7. Additionally, the sendmail host needs a certificate if it will be accepting inbound STARTTLS connections. Use OpenSSL to create the certificate, as described in Recipe 8.2 and Recipe 8.3.
Create a sendmail configuration with defines pointing to the files that contain the host’s certificate, the host’s private key, the root CA certificate file, and the directory where CA certificates are stored. Here are examples of the defines:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem')
Build the sendmail.cf file, copy it to /etc/mail/sendmail.cf, and then restart sendmail, as described in Recipe 1.8.
This recipe provides a full STARTTLS configuration. A system configured with all of these defines can act as a TLS server or client and can perform both encryption and authentication. The six defines point sendmail to the files necessary for this full range of service:
confCACERT_PATH
Sets the value for the CACERTPath
option in the
sendmail.cf file. The
CACERTPath
option points to the directory in which
certificate authority certificates are stored. It is very common for
this directory to be the same one that holds the server and client
certificates.
confCACERT
Sets the value for the CACERTFile
option, which
points to the certificate of the root certificate authority. The
value provided to this define is the full pathname of the file that
holds the CA certificate.
confSERVER_CERT
Sets the value for the sendmail.cf
ServerCertFile
option, which holds the full pathname of the file
containing the server certificate used for inbound connections.
confSERVER_KEY
Sets the value for the ServerKeyFile
option. The
ServerKeyFile
option points to the file that holds
the server’s private key.
confCLIENT_CERT
Sets the value for the sendmail.cf
ClientCertFile
option, which holds the full
pathname of the file containing the client certificate used for
inbound connections.
confCLIENT_KEY
Sets the value for the ClientKeyFile
option. The
ClientKeyFile
option points to the file that holds
the client’s private key.
If OpenSSL is installed, sendmail is compiled with STARTTLS support,
and these defines point to valid certificates, sendmail will
advertise STARTTLS in response to the SMTP EHLO
command. A simple telnet test shows that
STARTTLS is ready for use:
#telnet localhost smtp
Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 chef.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 22 Aug 2003 12:01:37 - 0400ehlo localhost
250-chef.wrotethebook.com Hello IDENT:6l4ZhaGP3Qczqknqm/KdTFGsrBe2SCYC@localhost [127.0.0.1], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH DIGEST-MD5 CRAM-MD5 250-STARTTLS 250-DELIVERBY 250 HELPQUIT
221 2.0.0 chef.wrotethebook.com closing connection Connection closed by foreign host.
If your system doesn’t advertise
STARTTLS
in response to the
EHLO
command, check the logfile to make sure that
all file permissions are correct. If they are, try increasing the
LogLevel
to 14 to log additional STARTTLS
debugging information. See Recipe 1.10 for
information on setting the LogLevel
.
This recipe shows a system configured with both client and server certificates and keys. Many systems are configured as both clients and servers for STARTTLS because mail is often forwarded by one system to another. When the system receives inbound mail, it acts as a STARTTLS server. When it forwards that mail on to another system, it acts as a STARTTLS client. Therefore, the system needs to act as both a STARTTLS server and a STARTTLS client. Normally such a system uses the same certificate and key for both its client and server roles.
A STARTTLS client will attempt to use STARTTLS
whenever the server offers it. Running the
sendmail command with the -v
option shows the STARTTLS client side of this sample configuration.
An example of this is seen in the following code:
#sendmail -Am -v -t
To: craig@chef.wrotethebook.com From: craig@rodent.wrotethebook.com Subject: First STARTTLS testCtrl-D
craig@chef.wrotethebook.com... Connecting to chef.wrotethebook.com. via esmtp... 220 chef.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 22 Aug 2003 12:01:37 - 0400 >>> EHLO rodent.wrotethebook.com 250-chef.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH DIGEST-MD5 CRAM-MD5 250-STARTTLS 250-DELIVERBY 250 HELP >>> STARTTLS 220 2.0.0 Ready to start TLS >>> EHLO rodent.wrotethebook.com 250-chef.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH EXTERNAL DIGEST-MD5 CRAM-MD5 250-DELIVERBY 250 HELP >>> MAIL From:<craig@rodent.wrotethebook.com> SIZE=97 AUTH=craig@rodent.wrotethebook. com 250 2.1.0 <craig@rodent.wrotethebook.com>... Sender ok >>> RCPT To:<craig@chef.wrotethebook.com> >>> DATA 250 2.1.5 <craig@chef.wrotethebook.com>... Recipient ok 354 Enter mail, end with "." on a line by itself >>> . 250 2.0.0 h0UGn9P7001230 Message accepted for delivery craig@chef.wrotethebook.com... Sent (h0UGn9P7001230 Message accepted for delivery) Closing connection to chef.wrotethebook.com. >>> QUIT 221 2.0.0 chef.wrotethebook.com closing connection
The client (rodent) connects to the server
(chef) and issues an EHLO
command. In response to that command, the server advertises that
STARTTLS is available. The client then issues a
STARTTLS
command to open the TLS connection. The
server responds with the message:
220 2.0.0 Ready to start TLS
Immediately after the response, the test shows another
EHLO
message. Many system administrators are
confused by this. Don’t be. The STARTTLS negotiation
takes place “outside” of the email
exchange. STARTTLS creates the encrypted tunnel through which the
mail travels. The first EHLO
, the
server’s STARTTLS
advertisement,
the client’s STARTTLS
command,
and the server’s TLS ready response are all used to
create the tunnel. The second EHLO
command and all
that follows it are part of the standard SMTP protocol exchange,
which is sent inside the encrypted tunnel. Note that this SMTP
protocol exchange is displayed by the sendmail
-v
command as clear text. The mail stream is only
encrypted on the network. Within the end systems, the mail stream is
clear text.
The effect of the STARTTLS protocol can be indirectly observed in the
headers of the mail message that passed through the encrypted tunnel.
The following headers are from the test message sent by the
sendmail
-Am
-v
-t
command used above:
Return-Path: <craig@rodent.wrotethebook.com> Received: from rodent.wrotethebook.com (rodent.wrotethebook.com [192.168.0.3]) by chef.wrotethebook.com (8.12.9/8.12.9) with ESMTP id h0UGn9P7001230 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=OK) for <craig@chef.wrotethebook.com>; Thu, 30 Jan 2003 11:49:10 -0500 Received: (from root@localhost) by rodent.wrotethebook.com (8.12.9/8.12.9) id h0UGvpSD010157; Thu, 30 Jan 2003 11:57:51 -0500 Date: Thu, 30 Jan 2003 11:57:51 -0500 Message-Id: <200301301657.h0UGvpSD010157@rodent.wrotethebook.com> To: craig@chef.wrotethebook.com From: craig@rodent.wrotethebook.com Subject: First STARTTLS test
The Received
: header generated by
chef.wrotethebook.com, which is the STARTTLS
server in this exchange, shows the TLS characteristics of the link
over which the mail was received. The header displays the version of
the TLS protocol that was used for the connection, the type of
encryption used for the connection, the number of bits used for the
encryption, and whether the client’s certificate was
verified. Because this information is only placed in the header when
TLS is used for the connection, it tells us that the client is
properly configured to use TLS when communicating with this server.
Recipe 8.2 and Recipe 8.3 cover how certificates and keys are created. Chapter 1 provides additional information on compiling sendmail. The sendmail book covers STARTTLS in Section 10.10.
You have been asked to configure sendmail to grant relaying privileges to STARTTLS clients that present a certificate signed by a trusted certificate authority.
Make sure that OpenSSL is installed as described in Introduction and that sendmail is compiled with STARTTLS support as shown in Recipe 1.6 and Recipe 1.7.
Identify each trusted certificate authority
in the access
database using CERTISSUER
: entries. The key field
of each entry begins with the CERTISSUER
: tag
followed by the distinguished name of the CA. The return value of the
entry is the keyword RELAY
, indicating that any
host presenting a certificate signed by the trusted CA is granted
relaying privileges.
Create a STARTTLS sendmail configuration and add the
access_db feature. Here are samples of the
defines that configure STARTTLS and the FEATURE
macro that enables the access database:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Rebuild the sendmail.cf file, copy the new sendmail.cf file to /etc/mail, and restart sendmail. Recipe 1.8 provides an example of these steps.
TLS can provide strong authentication of the end points and encryption of the data stream. Despite these important security features, establishing a STARTTLS connection is not, by itself, enough to grant relaying privileges. A test shows this:
#sendmail -Am -v -t
To: craig@crab.wrotethebook.com From: craig@rodent.wrotethebook.com Subject: Attempt to relay after successful TLS connectionCtrl-D
craig@crab.wrotethebook.com... Connecting to chef.wrotethebook.com. via relay... 220 chef.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 22 Aug 2003 12:01:37 - 0400 >>> EHLO rodent.wrotethebook.com 250-chef.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH DIGEST-MD5 CRAM-MD5 250-STARTTLS 250-DELIVERBY 250 HELP >>> STARTTLS 220 2.0.0 Ready to start TLS >>> EHLO rodent.wrotethebook.com 250-chef.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH EXTERNAL DIGEST-MD5 CRAM-MD5 250-DELIVERBY 250 HELP >>> MAIL From:<craig@rodent.wrotethebook.com> SIZE=102 AUTH=craig@rodent. wrotethebook.com 250 2.1.0 <craig@rodent.wrotethebook.com>... Sender ok >>> RCPT To:<craig@crab.wrotethebook.com> >>> DATA 550 5.7.1 <craig@crab.wrotethebook.com>... Relaying denied 503 5.0.0 Need RCPT (recipient) >>> RSET 250 2.0.0 Reset state craig... Connecting to local... craig... Sent Closing connection to chef.wrotethebook.com. >>> QUIT 221 2.0.0 chef.wrotethebook.com closing connection
In response to the first EHLO
command, the server
advertises STARTTLS
. The client then issues a
STARTTLS
command, and the server responds that it
is ready. This indicates that an encrypted session will start. The
second EHLO
command is the first SMTP command in
the encrypted session. It is followed by a MAIL
From
: and a RCPT
To
: command. Notice the response to the
RCPT
To
: command.[3] The message is rejected with a
“Relaying denied” error, even
though it comes in the midst of an encrypted session. Clearly, TLS
does not, by itself, authorize relaying. It is up to the sendmail
administrator to decide when and how TLS authentication data should
be used. One way to use TLS data is through the
access database.
The ${verify}
and
${cert_issuer}
macros are used in the
Local_Relay_Auth
ruleset to authorize relaying.
${verify}
contains OK
when
sendmail is able to verify the CA signature on the certificate
received from a remote site. sendmail takes the distinguished name of
the CA that signed the certificate from the Issuer field of the
certificate and stores it in the macro
${cert_issuer}
. If ${verify}
equals OK
, sendmail searches the
access database for a
CERTISSUER
: entry that matches the
${cert_issuer}
value. If a match is found, the
action specified by the CERTISSUER
: entry is
taken. If no match is found, processing continues normally. Here is
an example of adding a CERTISSUER
: entry to the
access database:
#cd /etc/mail
#cat >> access CERTISSUER:/C=US/ST=Maryland/L=Gaithersburg/O=WroteTheBook/CN=chef.wrotethebook.com/ Email=craig@chef.wrotethebook.com RELAY
Ctrl-D
#makemap hash access < access
Given the access database entry just shown, a site that presents a certificate signed by /C=US/ST=Maryland/L=Gaithersburg/O=WroteTheBook/CN=chef.wrotethebook.com/Email=craig@chef.wrotethebook.com is granted relaying privileges. /C=US/ST=Maryland/L=Gaithersburg/O=WroteTheBook/CN=chef.wrotethebook.com/Email= craig@chef.wrotethebook.com is the complete DN of the private CA created in Recipe 8.1. Therefore, any host with a certificate signed by our private CA is allowed to relay mail.
A DN can contain almost any character. Several characters, however, have special meaning to sendmail and others are difficult to enter into the access database. For these reasons, the DN stored in the access database uses a special format for storing nonprintable characters, the space, the tab, <, >, (, ), “, and +. These characters are stored as their hexadecimal values preceded by a plus. For example, a space becomes +20, a ( becomes +25.
After adding the CERTISSUER
: entry to the
access database, rerun the test shown earlier in
this section. The RCPT To
: command now produces
the following result:
>>> RCPT To:<craig@crab.wrotethebook.com> 250 2.1.5 <craig@crab.wrotethebook.com>... Recipient ok
The client is now granted relaying privileges because a CA that is trusted to authorize relaying signed the client’s certificate.
Recipe 8.4 covers the STARTTLS sendmail configuration used as the basis for this recipe. The private CA mentioned in the discussion of this recipe is covered in Recipe 8.1. Chapter 3 discusses the traditional techniques used to grant relaying privileges, including the access database. The content of a certificate, including the Issuer field, is covered in this chapter’s Introduction. The sendmail book discusses using the access database for STARTTLS in Section 10.10.8.
You want to grant relaying privileges to STARTTLS clients based on the client’s identity, as specified by the client’s certificate.
sendmail must be compiled with STARTTLS support, and OpenSSL must be installed. See Recipe 1.6 and Recipe 1.7 and Introduction to this chapter for more information.
Create an access database entry using a
CERTISSUER
: tag followed by the DN of the trusted
certificate authority to identify the CA that signed the
client’s certificate. The return value of the
CERTISSUER
: entry must be the keyword
SUBJECT
. Next, define each client that is to be
granted relaying privileges using a CERTSUBJECT
:
entry in the access database. The key field of
these entries begins with the CERTSUBJECT
: tag
followed by the DN of the client. The return value is the keyword
RELAY
.
Add the access_db feature to the STARTTLS sendmail configuration. Here are sample configuration lines:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Following the example from Recipe 1.8, rebuild the sendmail.cf file. Install the new configuration, and restart sendmail.
Successfully establishing a STARTTLS session does not, by itself, authorize relaying. (See Recipe 8.5 for a test that illustrates this.) However, the authentication data provided by STARTTLS can be used to control relaying via the access database. Here are access database entries that authorize relaying based on the value in the subject field of the client’s certificate:
CERTISSUER:/C=US/ST=Maryland/L=Gaithersburg/O=WroteTheBook/CN=chef.wrotethebook.com/ SUBJECT CERTSUBJECT:/C=US/ST=Maryland/L=Gaithersburg/O=WroteTheBook/CN=rodent.wrotethebook. com/ RELAY CERTSUBJECT:/C=US/ST=Maryland/L=Gaithersburg/O=WroteTheBook/CN=crab.wrotethebook.com/ RELAY
This example checks both the Issuer field and the Subject field from
the certificate presented by the client. These values are matched
against the access database by the
Local_Relay_Auth
ruleset, but only if the
${verify}
macro contains the string
OK
, which indicates that the certificate was
successfully verified by sendmail. Both fields are looked up because,
before the subject of a certificate can be trusted, the CA that signs
and verifies the certificate must be trusted.
If ${verify}
returns OK
, the
Local_Relay_Auth
ruleset looks for a
CERTISSUER
: entry containing the distinguished
name from the Issuer field of the certificate. If a match is found
and the action is RELAY
, relaying is authorized
for any system with a certificate signed by the specified CA, as
described in Recipe 8.5. If a match is found
and the action is SUBJECT
, a second
access database lookup is performed. This time,
the ruleset looks for a CERTSUBJECT
: entry
containing the DN from the Subject field of the certificate. If it is
found, and it contains the action RELAY
, relaying
is permitted for the specified client. If it is not found, normal
processing continues. Relaying can still be granted to the client
through any of the basic methods described in Chapter 3. STARTTLS provides an additional method of
granting relaying privileges; it does not invalidate the other
traditional methods.
A distinguished name may contain characters that require special formatting before the DN is entered in the access database. See the Discussion of Recipe Recipe 8.5 for information on this topic.
The m4 configuration lines in this recipe are identical to those used in Recipe 8.5. Both use the access database and both are full STARTTLS configurations. See Recipe 8.5 for additional information. Chapter 3 discusses the traditional techniques used to grant relaying privileges, including the access database. The content of a certificate, including the Issuer and Subject fields, is covered in this chapter’s Introduction. The sendmail book discusses using the access database for STARTTLS in Section 10.10.8.
To prevent mail bound for particular hosts from being sent in the clear, you have been asked to configure sendmail to only send mail to the specified hosts when the connection is satisfactorily encrypted.
OpenSSL and STARTTLS support are prerequisites. See Introduction and Recipe 8.4 for additional details on these basic components.
Specify the level of encryption
required for outbound
connections using a TLS_Srv
: entry in the
access database. The key field of each entry is
the tag TLS_Srv
: followed by the domain name or IP
address of the remote TLS server to which the local host will
connect. The return value should contain the keyword
ENCR
: followed by the number of bits of encryption
required when connecting to the specified remote host.
Create a sendmail configuration that supports STARTTLS and the
access database. Here are sample STARTTLS
defines and an access_db
FEATURE
macro:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Rebuild and install the sendmail.cf file, then restart sendmail. See Recipe 1.8 as an example.
Most mail is sent as clear text because the vast majority of systems do not use TLS. Even when STARTTLS is configured, a host sends outbound mail without regard to the level of encryption used. If you require encryption for mail sent to a specific site, you must tell sendmail about that requirement. The access database provides the means for informing sendmail of this requirement.
The TLS_Srv
: entry defines the STARTTLS
requirements for outbound connections. The
format of the entry is:
TLS_Srv:name requirement
TLS_Srv
: is the required tag.
name
is the name of the remote TLS server,
which can be defined by domain name or IP address. If the
name
field is blank, the entry applies to
all outbound mail connections. Because most sendmail systems send
mail to a wide variety of remote systems, some of which have STARTTLS
and some of which do not, the name field is almost never blank.
requirement
is the keyword that tells
sendmail what is required of this TLS connection.
The ENCR
: keyword
in
the requirement
field tells sendmail that
encryption is required. The keyword is followed by the minimum number
of encryption bits that must be used. Here is a sample
access database entry:
TLS_Srv:chef.wrotethebook.com ENCR:168
This entry tells sendmail that when a connection is made to chef.wrotethebook.com, the connection must be encrypted with at least 168-bit encryption.
168-bits is the default level of encryption used on our sample
STARTTLS connection. You can check the level of encryption used on
your link by sending a test message and looking at the
Received
: header in the message. For example:
Received: from rodent.wrotethebook.com (rodent.wrotethebook.com [192.168.0.3]) by chef.wrotethebook.com (8.12.9/8.12.9) with ESMTP id h13GqDl5001443 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=OK) for <craig@chef.wrotethebook.com>; Mon, 3 Feb 2003 11:52:14 -0500
This header tells you that 168-bits encryption is used
(bits=168
). If the TLS_Srv
:
entry shown above was installed on rodent, mail
would flow to chef because the link between the
two systems has a sufficient level of encryption. However, if the
link between the two systems did not meet the minimum standard of
encryption, the client would abort the connection before sending the
mail, as this test demonstrates:
#sendmail -Am -v -t
To: craig@chef.wrotethebook.com From: craig@rodent.wrotethebook.com Subject: Test ENCR:168 with no TLS linkCtrl-D
craig@chef.wrotethebook.com... Connecting to chef.wrotethebook.com. via esmtp... 220 chef.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 22 Aug 2003 12:01:37 - 0400 >>> EHLO rodent.wrotethebook.com 250-chef.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH DIGEST-MD5 CRAM-MD5 250-DELIVERBY 250 HELP >>> QUIT 221 2.0.0 chef.wrotethebook.com closing connection craig@chef.wrotethebook.com... Deferred: 403 4.7.0 encryption too weak 0 less than 168 Closing connection to chef.wrotethebook.com.
In this case, the server fails to offer STARTTLS, while the client’s access database requires 168-bit encryption on this link. The client terminates the connection with an “encryption too weak” error message. The message displays the number of encryption bits used by the server (0 in this case because TLS did not start) and the number required by the client (168 in this example). The SMTP response code of this error message is 403, and the DSN code is 4.7.0. Each code starts with a 4, which indicates that this is a temporary failure. The keyword “Deferred” in the message indicates that sendmail will attempt to deliver this message again during the next queue run.
Treating a STARTTLS failure as
a
temporary failure, which is the default, is generally correct.
Normally, a server is identified in a TLS_Srv
:
entry only when the server actually offers STARTTLS. If the server
fails to successfully create a TLS connection with the client, the
failure is probably temporary. However, it is up to you to decide
whether the failure should be considered temporary. The requirement
field in a TLS_Srv
: entry can be preceded by the
string TEMP+
to select a temporary failure, which
is the default, or by the string PERM+
to select a
permanent error. For example, assume the access
database on rodent contained the following
TLS_Srv
: entry:
TLS_Srv:chef.wrotethebook.com PERM+ENCR:168
If chef.wrotethebook.com does not offer at least 168-bit encryption, the client terminates the session and returns the mail to the sender. No more attempts are made to deliver the mail. The sender sees the following error in the returned message:
----- The following addresses had permanent fatal errors ----- craig@chef.wrotethebook.com (reason: 503 5.7.0 encryption too weak 0 less than 168)
Use the define
TLS_PERM_ERR
as an alternative to adding
PERM+
to the requirement field. The following line
added to the sendmail configuration changes the default from a
temporary failure to a permanent failure:
define(`TLS_PERM_ERR')
With this setting, individual actions must be flagged as temporary
failures using TEMP+
.
The search for TLS_Srv
:
access database entries occurs in the
tls_server
ruleset, which is called by the client
when the client is ready to issue the STARTTLS
command. The tls_server
ruleset is called with the
value returned by ${verify}
in its workspace. The
tls_server
ruleset makes three attempts to find a
TLS_Srv
: match. It first uses ruleset
D
to find a TLS_Srv
: entry that
matches the hostname returned by ${server_name}
.
If no match is found, it then uses ruleset A
to
find a TLS_Srv
: entry that matches the value
returned by ${server_addr}
. If there is still no
match, it looks for a TLS_Srv
: entry with a blank
name field. These searches process all possible matches for a given
domain name and IP address. For example, for a connection to
foo.bar.example.com with IP address
192.168.23.45, the following lookups would happen, in the order
listed, until a match was found:
TLS_Srv:foo.bar.example.com TLS_Srv:bar.example.com TLS_Srv:example.com TLS_Srv:com TLS_Srv:192.168.23.45 TLS_Srv:192.168.23 TLS_Srv:192.168 TLS_Srv:192 TLS_Srv:
The ruleset TLS_connection
is called and passed
anything returned by the access database
lookups. It is TLS_connection
that processes the
ENCR
: requirement field and compares the number of
bits from that field to the number of bits returned by
${cipher_bits}
. If the macro
${cipher_bits}
is less than the value from the
requirement field, an error message is displayed and the connection
ends.
The m4 macro LOCAL_TLS_SERVER
allows you to add custom sendmail.cf rewrite
rules to the beginning of the tls_server
process.
Put the LOCAL_TLS_SERVER
macro at the end of the
master configuration file and list the custom rewrite rules after the
macro.
Recipe 8.8 and Recipe 8.9
cover related access database entries. In
particular, VERIFY
: is an alternative action
keyword that can
be used to implement this recipe.
See Recipe 8.9 for details on the
VERIFY
: keyword. Recipe 8.5 and Recipe 8.6 also describe
how the access database is used with STARTTLS.
The basic STARTTLS recipe upon which this recipe is built is covered
in Recipe 8.4. The
sendmail book covers the use of the
access database with STARTTLS in Section
10.10.8.
You have been asked to configure sendmail to require that the connection is satisfactorily encrypted before accepting mail from specified hosts.
All configurations require OpenSSL, as described in Introduction. If your system does not have a basic setup, begin there.
Specify the level of encryption required for inbound
connections using a
TLS_Clt
: entry in the access
database. The key field of each entry is the tag
TLS_Clt
: followed by the domain name or IP address
of the remote TLS client that will initiate the connection. The
return value should contain the keyword ENCR
:
followed by the number of bits of encryption required before
accepting a connection from the specified remote host.
Add the STARTTLS defines and the access_db feature to the sendmail configuration. Here are sample additions to the configuration:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Follow the example in Recipe 1.8 to build the new sendmail.cf file, install it, and restart sendmail.
The TLS_Clt
: access database
entry uses the same format as the TLS_Srv
: entry
covered in the Discussion of Recipe 8.7. All
of the fields described for the TLS_Srv
:
entry—name
,
requirement
, TEMP+
, and
PERM+
—are used in exactly the same way for
the TLS_CLT
: entry. The difference is that the
TLS_Clt
: entry is used by the server to check for
any special requirements before accepting mail from the client. The
name
field of the
TLS_Clt
: entry defines the domain name or IP
address of the remote TLS client. When the name or address of a
client matches a TLS_Clt
: entry, the
requirement
field of the entry is used to
define the conditions imposed on the client before mail is accepted.
A sample TLS_Clt
: entry is:
TLS_Clt:rodent.wrotethebook.com ENCR:168
This entry tells sendmail that a connection from rodent.wrotethebook.com must be encrypted with at least 168-bit encryption. If it isn’t, mail from the client is rejected, as this test from the client rodent shows:
#sendmail -Am -v -t
To: craig@chef.wrotethebook.com From: craig@rodent.wrotethebook.com Subject: Test the TLS_Clt: entryCtrl-D
craig@chef.wrotethebook.com... Connecting to chef.wrotethebook.com. via esmtp... 220 chef.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 22 Aug 2003 12:01:37 - 0400 >>> EHLO rodent.wrotethebook.com 250-chef.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH DIGEST-MD5 CRAM-MD5 250-STARTTLS 250-DELIVERBY 250 HELP >>> STARTTLS 220 2.0.0 Ready to start TLS >>> EHLO rodent.wrotethebook.com 250-chef.wrotethebook.com Hello rodent.wrotethebook.com [192.168.0.3], pleased to meet you 250 ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH DIGEST-MD5 CRAM-MD5 250-DELIVERBY 250 HELP >>> MAIL From:<craig@rodent.wrotethebook.com> 403 4.7.0 encryption too weak 56 less than 168 craig@chef.wrotethebook.com... Deferred: 403 4.7.0 encryption too weak 56 less than 168 Closing connection to chef.wrotethebook.com. >>> QUIT 221 2.0.0 chef.wrotethebook.com closing connection
In this test, the error message “encryption too
weak” is in response to the
client’s MAIL
From
: command. The server checks the
access database TLS_Clt
:
entries in the tls_client
ruleset. That ruleset is
called at two different points in the SMTP protocol exchange. First,
it is called when the STARTTLS
command is
received, and it is called again when the MAIL
From
command is received. When the
tls_client
ruleset is called, it is passed the
value returned by ${verify}
, the literal
$|
, and either of the keywords
STARTTLS
or MAIL
.
The tls_client
ruleset is very similar to the
tls_server
ruleset described in Recipe 8.7. tls_client
first uses
ruleset D
to look for a
TLS_Clt
: entry that matches the value found in
${client_name}
. If no match is found, it uses
ruleset A
to look for a
TLS_Clt
: entry that matches the address in the
${client_addr}
macro. If still no match is found,
tls_client
looks for a TLS_Clt
:
entry with a blank name field. tls_client
would do
the following lookups for a connection from a client named
foo.bar.example.com that had the IP address
192.168.23.45, until a match was found:
TLS_Clt:foo.bar.example.com TLS_Clt:bar.example.com TLS_Clt:example.com TLS_Clt:com TLS_Clt:192.168.23.45 TLS_Clt:192.168.23 TLS_Clt:192.168 TLS_Clt:192 TLS_Clt:
tls_client
then calls
TLS_connection
and passes that ruleset anything it
has obtained from the access database. The
TLS_connection
ruleset checks to see if the
connection meets the requirements defined by the
TLS_Clt
: record.
The m4 macro LOCAL_TLS_CLIENT
provides a hook into the tls_client
ruleset. Use
the macro to add custom sendmail.cf rewrite
rules to the beginning of the tls_client
process.
Recipe 8.7 and Recipe 8.9
cover
related access
database entries. In particular, VERIFY
: is an
alternative action keyword that can be used to implement this recipe.
See Recipe 8.9 for details on the
VERIFY
: keyword. Recipe 8.5 and Recipe 8.6 also describe
how the access database is used with STARTTLS.
The STARTTLS recipe upon which this recipe is built is covered in
Recipe 8.4. The
sendmail book covers the use of the
access database with STARTTLS in Section
10.10.8.
You have been asked to configure sendmail to exchange mail with a specified host only when the certificate provided by that host is verified.
The system must have OpenSSL installed and sendmail compiled with STARTTLS support before attempting to implement this recipe. See this chapter’s Introduction and Chapter 1 for more information about OpenSSL and about recompiling sendmail.
Create an access database entry for each host
that is required to provide a verified certificate. Use the
TLS_Clt
: tag if the remote host initiates the
connection into the local host, or use the
TLS_Srv
: tag if the local host initiates the
connection to the remote host. Use the VERIFY
keyword in the return field to require a validated certificate from
the remote system. Add a colon and a numeric value after the
VERIFY
keyword to require a level of encryption in
addition to the verified certificate.
Create a STARTTLS sendmail configuration that includes the access_db feature. Here are sample lines that might be added to the sendmail configuration:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Rebuild the sendmail.cf file, copy the new sendmail.cf file to /etc/mail, and restart sendmail, as shown in Recipe 1.8.
When both end points are properly configured to support STARTTLS,
sendmail uses TLS to encrypt the mail transport even if the end
points do not present verified certificates. In this context, a
verified certificate is one signed by a CA that sendmail trusts. If
sendmail can verify the signature on the certificate, sendmail sets
the ${verify}
macro to OK
. When
a certificate is received that cannot be verified,
${verify}
is set to one of several possible
values, all of which are covered in Introduction of this chapter.
For example, NO
is one of the values indicating
that the certificate was not verified. Yet TLS is still used to
encrypt the link even when ${VERIFY}
is set to
NO
, as can be seen in the
Received
: header shown below:
Return-Path: <craig@horseshoe.wrotethebook.com> Received: from horseshoe.wrotethebook.com (horseshoe.wrotethebook.com [192.168.0.2]) by chef.wrotethebook.com (8.12.9/8.12.9) with ESMTP id h14HeQAd001228 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=NO) for <craig@chef.wrotethebook.com>; Tue, 4 Feb 2003 12:40:27 -0500 Received: (from root@localhost) by horseshoe.wrotethebook.com (8.12.9/8.12.9) id h14Hnn91001180; Tue, 4 Feb 2003 12:49:49 -0500 Date: Tue, 4 Feb 2003 12:49:49 -0500 Message-Id: <200302041749.h14Hnn91001180@horseshoe.wrotethebook.com> To: craig@chef.wrotethebook.com From: craig@horseshoe.wrotethebook.com Subject: Test self-signed certificate
The first Received
: header shows that the link was
encrypted with 168-bit encryption, and that no certificate was
verified for horseshoe.wrotethebook.com. The
implications of this are two-fold:
First, it is possible to use STARTTLS without recourse to a certificate authority if the only thing you want to do is encrypt the link.
Second, optional configuration is required to limit STARTTLS connections to those system with verifiable certificates.
The VERIFY
requirement is used with
TLS_Clt
: or TLS_Srv
: to require
a verified certificate. When VERIFY
is specified,
the current value stored in the ${verify}
macro
must be OK
. Otherwise, the connection is rejected.
Here are some example access database entries:
TLS_Clt:crab.wrotethebook.com VERIFY TLS_Srv:smtp.wrotethebook.com VERIFY:168 TLS_Clt:horseshoe.wrotethebook.com VERIFY:168
The first access database entry only accepts
inbound mail from crab.wrotethebook.com if the
certificate crab presents is verified. The
TLS_Clt
: entries are processed by the
tls_client
ruleset. See Recipe 8.8 for a description of that ruleset.
The second access database entry tells sendmail
that an outbound connection made to the server
smtp.wrotethebook.com must use 168-bit
encryption and that the certificate presented by the server must be
verified. If either of these conditions is not met, the connection is
terminated. The TLS_Srv
: entry is processed by the
tls_server
ruleset covered in Recipe 8.7.
The last entry requires 168-bit encryption and a verified certificate
for the TLS client horseshoe.wrotethebook.com.
If chef.wrotethebook.com had been configured
with that entry, the mail that created the
Received
: header shown at the beginning of this
discussion would not have been accepted. As the
Received
: header made clear,
horseshoe used 168-bit encryption, but it did
not present a verifiable certificate. A test run from
horseshoe shows the impact of adding this
TLS_Clt
: entry to the configuration of the
receiving host:
#sendmail -Am -v -t
To: craig@chef.wrotethebook.com From: craig@horseshoe.wrotethebook.com Subject: Test VERIFY:168Ctrl-D
craig@chef.wrotethebook.com... Connecting to chef.wrotethebook.com. via esmtp... 220 chef.wrotethebook.com ESMTP Sendmail 8.12.9/8.12.9; Fri, 22 Aug 2003 12:01:37 - 0400 >>> EHLO horseshoe.wrotethebook.com 250-chef.wrotethebook.com Hello horseshoe.wrotethebook.com [192.168.0.2], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH DIGEST-MD5 CRAM-MD5 250-STARTTLS 250-DELIVERBY 250 HELP >>> STARTTLS 220 2.0.0 Ready to start TLS >>> EHLO horseshoe.wrotethebook.com 250-chef.wrotethebook.com Hello horseshoe.wrotethebook.com [192.168.0.2], pleased to meet you 250 ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH DIGEST-MD5 CRAM-MD5 250-DELIVERBY 250 HELP >>> MAIL From:<craig@horseshoe.wrotethebook.com> 403 4.7.0 not authenticated craig@chef.wrotethebook.com... Deferred: 403 4.7.0 not authenticated Closing connection to chef.wrotethebook.com. >>> QUIT 221 2.0.0 chef.wrotethebook.com closing connection
The STARTTLS
command is issued and accepted. The
second EHLO
command indicates the successful start
of the encrypted session. However, the response to the
MAIL
From
: command is the error
“not authenticated” because a
TLS_Clt
: entry in the access
database on chef required a certificate signed
by a trusted certificate authority.
Notice that the response codes 403 and 4.7.0 are used on the error
message. The 4 at the start of each code indicates that this is a
temporary failure. In response to these temporary failures, the
client will queue the message and attempt to deliver it during
subsequent queue runs. By default, errors generated by a
VERIFY
requirement are temporary errors. Use
PERM+
to make the error a permanent failure in
order to prevent the remote system from resending the message at each
queue run. For example:
TLS_Clt:horseshoe.wrotethebook.com PERM+VERIFY:168
See Recipe 8.7 for more information on
PERM+
, TEMP+
, and the define
TLS_PERM_ERR
, all of which control whether TLS
errors are permanent or temporary.
The test shown above points out the difference between encryption and authentication. Encryption can be used even if the end points have not been authenticated. Therefore, special privileges, such as relaying, cannot be extended on the basis of the level of encryption used. Special privileges require authentication. Happily, TLS can provide both encryption and authentication when they are needed.
Recipe 8.7 and Recipe 8.8
provide additional examples of the
TLS_Clt
: and TLS_Srv
:
access database entries. Recipe 8.5 and Recipe 8.6 describe
other ways the access database is used with
STARTTLS. This recipe contains m4 commands
described in Recipe 8.4. The
sendmail book covers the use of the
access database with STARTTLS in Section
10.10.8.
You have been asked to ensure that encryption and authentication are used for mail addressed to specific recipients.
Install OpenSSL and recompile sendmail with STARTTLS support as described in the Introduction and in Recipe 1.6 and Recipe 1.7.
Use TLS_Rcpt
: access database
entries to define those recipients that require TLS security and to
specify the level of security required. The key field of each entry
contains the tag TLS_Rcpt
: and the full or partial
address of the recipient. The return value defines the level of
security required, and it can be either the keyword
ENCR
:, followed by the number of bits of
encryption required, or the keyword VERIFY
,
optionally followed by a number of bits of encryption.
Add the access_db feature and the STARTTLS defines to the sendmail configuration. Here are sample lines that could be added to the configuration:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Rebuild the sendmail.cf file, copy the new sendmail.cf file to /etc/mail, and restart sendmail. See Recipe Recipe 1.8 for an example.
The TLS_Clt
: and TLS_Srv
:
access database entries used in Recipe 8.7, Recipe 8.8, and Recipe 8.9 enforce minimum TLS security requirements
based on the name or address of the remote host. sendmail checks for
${client_name}
and
${client_addr}
in TLS_CLT
:
entries for inbound connections, and for
${server_name}
and
${server_addr}
in TLS_Srv
:
entries for outbound connections. These entries ensure that
connections between the specified remote hosts and local host are
secured, but these entries do not guarantee that mail addressed to a
specific user will be secure. There is no guarantee because mail can
reach recipients over multiple paths—some of which may be
secured and others may not. Look at some sample MX records:
wrotethebook.com. IN MX 10 chef.wrotethebook.com. wrotethebook.com. IN MX 20 rodent.wrotethebook.com. wrotethebook.com. IN MX 30 mail.example.com.
Given these three MX records, mail bound for
pat@wrotethebook.com could go over a connection
to chef, rodent, or
mail.example.com. Assume that
chef and rodent have
STARTTLS support but that mail.example.com does
not. Mail sent from our system to
pat@wrotethebook.com would be encrypted if the
delivery connection was made to chef or
rodent, but the mail would be sent as clear text
if the connection was made to mail.example.com.
We don’t run mail.example.com,
so we can’t change the way it is
configured—what we can do is ensure that mail sent to
pat@wrotethebook.com only goes via an adequately
encrypted connection. The following TLS_Rcpt
:
entry ensures that mail is only sent to
pat@wrotethebook.com if the remote host has
presented a verified certificate and the link is using 168-bit
encryption:
TLS_Rcpt:pat@wrotethebook.com VERIFY:168
The basic format of the TLS_Rcpt
: entry is:
TLS_Rcpt:recipient
requirements
+suffix
++suffix
The string TLS_Rcpt
: is the required tag for this
database record. recipient
is the full or
partial email address of the recipient. The recipient address can be:
A full address in the format
user
@
host.domain
.
This format matches a specific user on a specific host.
TLS_Rcpt:craig@crab.wrotethebook.com
is an
example.
A hostname in the format host.domain
;
e.g., TLS_Rcpt:crab.wrotethebook.com
. Any user on
the specified host is matched.
A domain name to match every user on every host in the specified
domain. For example, TLS_Rcpt:wrotethebook.com
would match every recipient in the
wrotethebook.com domain.
A username written in the form
user
@
; e.g.,
TLS_Rcpt:craig@
. This format matches any recipient
with the specified username on any host in any domain.
A blank field, which matches every possible recipient address. This format is used to define a default security requirement for all outbound mail.
The requirements
field defines the minimum
security requirements that must be met before mail is sent to the
recipient. The keyword ENCR
or
VERIFY
can be used in the
requirements
field to require a level of
encryption or a verified certificate. For example
ENCR:168
requires a minimum of 168-bit encryption,
although it does not require a verified certificate from the remote
server. The VERIFY
keyword does require a verified
certificate and optionally can be combined with a numeric value to
also require a level of encryption. For example,
VERIFY:168
requires a verified certificate from
the remote server and 168-bit encryption on the link. Recipe 8.7, Recipe 8.8, and Recipe 8.9 provide examples of the
ENCR
and VERIFY
keywords. The
sample TLS_Rcpt
: entry just shown uses
VERIFY:168
to require authentication and
encryption.
The impact of the sample entry is seen when mail addressed to pat@wrotethebook.com is routed to the backup MX server mail.example.com:
#sendmail -Am -v -t
To: pat@wrotethebook.com From: david@wrotethebook.net Subject: Test TLS_Rcpt:Ctrl-D
pat@wrotethebook.com... Connecting to mail.example.com. via esmtp... 220 mail.example.com ESMTP Sendmail 8.12.9/8.12.9; Wed, 5 Feb 2003 15:33:02 -0500 >>> EHLO wrotethebook.net 250-mail.example.com Hello IDENT:24znrK/hAUFBK67n3St2d8DU/5bqb70s@chef [192.168.10. 8], pleased to meet you 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-EXPN 250-VERB 250-8BITMIME 250-SIZE 250-DSN 250-ETRN 250-AUTH GSSAPI DIGEST-MD5 CRAM-MD5 250-DELIVERBY 250 HELP >>> MAIL From:<david@wrotethebook.net> SIZE=92 AUTH=david@wrotethebook.net 250 2.1.0 <david@wrotethebook.net>... Sender ok pat@wrotethebook.com... Deferred >>> RSET 250 2.0.0 Reset state Closing connection to mail.example.com. >>> QUIT 221 2.0.0 mail.example.com closing connection
The backup MX server mail.example.com does not
offer the STARTTLS service in its response to the
EHLO
command. Therefore, the client does not issue
a STARTTLS
command. Instead, the client issues the
MAIL
From
: command. The client
then checks for a TLS_Rcpt
: entry in the
access database, finds it, and terminates the
session with the message:
pat@wrotethebook.com ... Deferred
This message indicates that the mail has been queued and will be sent
again during the next queue run, which means that sendmail is
treating this delivery problem as a temporary error. By default, most
TLS connection problems are treated as temporary failures. You can
change by using the TLS_PERM_ERR
define in the
master configuration file, or you can override the default for a
specific TLS_Rcpt
: entry by adding
PERM+
to the entry. For example, the following
entry would make the failure shown above a permanent failure:
TLS_Rcpt:pat@wrotethebook.com PERM+VERIFY:168
However, it is not a good idea to make this a permanent failure.
Failures caused by TLS_Rcpt
: entries should be
temporary failures. The failure happened because the connection went
to a backup MX server that doesn’t support STARTTLS.
When the mail is resent during the queue run, it will probably go to
the primary MX server, which does have STARTTLS, and therefore, the
mail will be successfully delivered. Making the failure permanent
undermines the error recovery potential inherent in the sendmail
queue process. It is more likely that you would use
TEMP+
to make the failure temporary if, for some
reason, the default for TLS failures had been set to permanent using
the TLS_PERM_ERR
define. Recipe 8.7, Recipe 8.8, and Recipe 8.9 cover TLS_PERM_ERR
,
PERM+
, and TEMP+
.
The other access database entries covered in
this chapter also use the ENCR
:,
VERIFY
:, PERM+
, and
TEMP+
keywords. However, the
TLS_Rcpt
: record has more options than these other
access entries. The
requirements
field of the
TLS_Rcpt
: entry can be followed by one or more
optional values. These options are called
suffixes because they are added to the
TLS_Rcpt
: record after the ENCR
or VERIFY
keyword. The first suffix is added after
a single plus sign (+
), and subsequent suffixes
are added with two plus signs (++
). The possible
suffixes are:
CN
:name
The CN
option checks the common name (CN) of the
subject from the certificate presented by the server. sendmail holds
the CN of the subject in the macro ${cn_subject}
.
If name
is provided, the value of
name
must match the value stored in the
${cn_subject}
macro. If
name
is left blank, the value returned by
${cn_subject}
must match the value returned by
${server_name}
. The macro
${server_name}
holds the hostname of the remote
host to which the client is currently connected, as determined by a
reverse domain lookup of the IP address used by TCP for the current
connection.
CS
:name
The CS
option compares
name
against the value returned by
${cert_subject}
. The macro
${cert_subject}
holds the distinguished name from
the Subject field of the certificate presented by the remote server.
The DN and name
must match.
CI
:name
The CI
option compares
name
against the value returned by
${cert_issuer}
. The macro
${cert_issuer}
holds the distinguished name from
the Issuer field of the certificate presented by the remote server.
The value in ${cert_issuer}
and the value in the
name
field must match.
Here is a sample TLS_Rcpt
: entry with multiple
suffixes:[4]
TLS_Rcpt:pat@wrotethebook.com VERIFY:168+CN++CI:/C=US/ST=Maryland/L=Gaithersburg/ O=WroteTheBook/CN=chef.wrotethebook.com/
This TLS_Rcpt
: entry requires 168-bit encryption
and a verified certificate from the remote host. The common name of
the subject of the certificate must be the hostname of the server at
the other end of the current connection, and the certificate must be
signed by the private CA created on
chef.wrotethebook.com in Recipe 8.1.
The various options available for the TLS_Rcpt
:
entry make it possible to handle most potential situations. Yet, it
is also possible to create a custom ruleset to do your own
TLS_Rcpt
: processing using the
Local_tls_rcpt
ruleset hook.
Recipe 8.7, Recipe 8.8, and Recipe 8.9 show examples of
related access database entries, and Recipe 8.5
and Recipe 8.6 describe other ways the access database is used with STARTTLS. The sendmail
book covers ${cn_subject}
in Section 21.9.24, ${server_name}
in 21.9.84, ${cert_subject}
in 21.9.15, ${cert_issuer}
in 21.9.13,
and TLS_Rcpt
: in 10.10.8.3.
By default, a sendmail system configured to run STARTTLS
issues the STARTTLS
command to any remote host
that advertises STARTTLS
in its response to the
EHLO
command. You have been asked to prevent
sendmail from using the STARTTLS protocol extension when
communicating with selected remote hosts.
Make sure your system meets the basic OpenSSL and STARTTLS configuration requirements described in this chapter’s Introduction and in Chapter 1.
Add Try_TLS
: entries to the
access database to identify the remote sites for
which STARTTLS should be disabled. The format of the
Try_TLS
: record is:
Try_TLS:name
NO
Try_TLS
: is the required tag value.
name
is the hostname, domain name, or IP
address of the remote site. NO
is the required
return value.
Add the access_db feature and the STARTTLS defines to the sendmail configuration:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Using the guidance in Recipe 1.8, rebuild the sendmail.cf file, copy the new sendmail.cf file to /etc/mail, and restart sendmail.
Here are sample Try_TLS
: entries that prevent
STARTTLS from being used with two different remote hosts:
Try_TLS:example.com NO
Try_TLS:server.wrotethebook.org NO
Given these Try_TLS
: entries, TLS is not used when
connecting to the TLS server
server.wrotethebook.org or when connecting to
any STARTTLS server in the example.com domain.
Try_TLS
: records are processed by the
try_tls
ruleset, which is called by the client
just before the client issues the STARTTLS
command. try_tls
first uses ruleset
D
to look for a Try_TLS
: record
that contains the hostname or the domain name returned by
${server_name}
. If no match is found, it uses the
A
ruleset to look for a
Try_TLS
: record that contains the IP address
returned by ${server_addr}
. If still no match is
found, the STARTTLS
command is issued. If a match
is found that returns the value NO
, the connection
is terminated with a permanent failure.
The LOCAL_TRY_TLS
macro provides a hook into the
try_tls
ruleset for your own custom rewrite rules.
Try_TLS
: entries only apply to outbound
connections, which are a client function. See Recipe 8.12 for an example of using the
SRV_Features
: entry to control the TLS server
functions offered on inbound connections.
Recipe 8.4 explains the STARTTLS defines
used
in this configuration. Recipe 8.5 to Recipe 8.10 show examples of using the
access database with STARTTLS. The
sendmail book covers
${server_addr}
in Section 21.9.83,
${server_name}
in 21.9.84, and
Try_TLS
: records in 10.10.8.4.
You have configured STARTTLS but do not want to encrypt the link for every remote host that is also configured for STARTTLS. You want to configure sendmail to only offer STARTTLS to selected hosts.
Make sure the system meets the basic OpenSSL and STARTTLS configuration requirements described in Introduction and in Chapter 1.
Create Srv_Features
: access
database entries for all hosts to which STARTTLS should be
advertised. The key field of each entry begins with the tag
Srv_Features
:, which is followed by the domain
name, hostname, or IP address that identifies the connecting host.
The return value of each entry is the letter s
.
Add the access_db feature to the STARTTLS
sendmail configuration. Here is the required
FEATURE
macro and sample defines:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Following the instructions in Recipe 1.8, rebuild the sendmail.cf file, copy the new sendmail.cf file to /etc/mail, and restart sendmail.
Use the Srv_Features
: access
database entry to control the extended SMTP features offered to
connecting hosts. The return value of a
Srv_Features
: entry is one or more single
character flags, some of which indicate whether an extended service
should be advertised. (When more than one flag is used, the
individual flags are separated by whitespace.) Lowercase flags enable
SMTP extensions and uppercase flags disable extensions. The
s
flag selectively advertises STARTTLS, and the
S
flag selectively blocks advertising STARTTLS.
These are the flags of particular interest for this recipe.[5]
Assume that you want to limit advertising STARTTLS to only those hosts in the wrotethebook.com domain. You could do that by adding the following two entries to the access database:
Srv_Features:wrotethebook.com s Srv_Features: S
In this case, STARTTLS is advertised to the hosts in the
wrotethebook.com domain as directed by the
s
flag. The S
flag in the
second entry prevents STARTTLS from being advertised to any other
host. A blank name field in a Srv_Features
: entry
indicates that the entry applies to every host for which there is not
a more specific Srv_Features
: entry. In effect,
the second entry creates a default policy for advertising STARTTLS.
This second entry is necessary because the normal default is for
sendmail to advertise STARTTLS when STARTTLS is configured. In the
absence of an applicable Srv_Features
: entry, the
default sendmail behavior applies.
Changing the default sendmail behavior with a
DAEMON_OPTIONS
macro is an alternative to using
the second Srv_Features
: entry described above.
You could add a DAEMON_OPTIONS
macro that
specifies the M=S
modifier to the sendmail
configuration. For example, adding the following lines to the
configuration prevents sendmail from advertising STARTTLS to any
connecting host:
dnl Do not advertise STARTTLS DAEMON_OPTIONS(`Name=MTA, M=S')
After changing the default, you could then override the default for
the hosts in the wrotethebook.com using a single
Srv_Features
: entry:
Srv_Features:wrotethebook.com s
This alternative approach works, but I prefer the first approach of putting both policies in the access database. I think that putting both policies in one place makes it easier for others to understand exactly what the configuration is doing.
The examples in this section assume that you want to limit
advertising to selected hosts. The opposite may be true. You may wish
to advertise STARTTLS to most hosts and only block advertising to
specific hosts with which you are having trouble. In that case, the
specific Srv_Features
: entries would use the
S
flag. No default
Srv_Features
: entry would be required because the
normal sendmail default is to advertise STARTTLS.
Recipe 8.4 describes the basic STARTTLS
configuration that needs to be done before this
recipe is implemented. Recipe 7.9 and Recipe
Recipe 8.13 provide other examples of using the
Srv_Features
: record. Recipe 8.5 through Recipe 8.13 show how
the access database is used with STARTTLS. The
sendmail book covers the
Srv_Features
: entry in Section 19.9.4.
By default, STARTTLS does not require a TLS client to present a certificate. You want to configure sendmail to request certificates from selected TLS clients.
Make sure the system meets the basic OpenSSL and STARTTLS configuration requirements described in Introduction and in Chapter 1.
Create Srv_Features
: access
database entries for all clients that will be required to present a
certificate. The key field of each entry is the tag
Srv_Features
: followed by the domain name,
hostname, or IP address of the selected client. The return value of
each entry is the letter v
.
Add the access_db feature to the STARTTLS
sendmail configuration. Here is the required
FEATURE
macro and sample defines:
dnl Point to the CA certificate directory define(`confCACERT_PATH', `/etc/mail/certs') dnl Point to the root CA's certificate define(`confCACERT', `/etc/mail/certs/cacert.pem') dnl Point to the certificate used for inbound connections define(`confSERVER_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for inbound connections define(`confSERVER_KEY', `/etc/mail/certs/key.pem') dnl Point to the certificate used for outbound connections define(`confCLIENT_CERT', `/etc/mail/certs/cert.pem') dnl Point to the private key used for outbound connections define(`confCLIENT_KEY', `/etc/mail/certs/key.pem') dnl Enable the access database FEATURE(`access_db')
Following the instructions in Recipe 1.8, rebuild the sendmail.cf file, copy the new sendmail.cf file to /etc/mail, and restart sendmail.
Srv_Features
: entries control the way in which a
server interacts with its clients. See Recipe 8.12 and Recipe 7.9 for
more general information about the Srv_Features
:
entry.
Use the v
return value on a
Srv_Features
: entry to request the TLS
client’s certificate. Use the V
return value to specifically prevent sendmail from asking for the
client’s certificate.
Adding the following entry to the access database requires a certificate from all hosts connecting to the local host from the dialin.wrotethebook.com domain:
Srv_Features:dialin.wrotethebook.com v
By itself, the Srv_Features
: entry does not do
anything with the client certificate. It merely requests that the
client present a certificate, which can then be used for special
purposes such as authorizing relaying. Using the certificate for a
special purpose requires additional configuration as shown in other
recipes in this chapter.
Recipe 8.4 describes the STARTTLS defines
used in this configuration. Recipe 7.9
provides other examples of using the Srv_Features
:
record. Recipe 8.5, Recipe 8.6, and Recipe 8.9 use client
certificates to grant relaying privileges. The
sendmail book covers the
Srv_Features
: entry in Section 19.9.4.
[1] For the SMTP connection, the TLS client is the system initiating the connection, and the TLS server is the system to which the connection is being made.
[2] The CA script is found in the misc subdirectory of the OpenSSL ssl directory. On our sample Red Hat Linux system, the full directory path is /usr/share/ssl/misc; on some other systems it is /usr/local/ssl/misc.
[3] Because of PIPELINING, which the EHLO
response shows is offered on this system, some SMTP commands are sent
together to save on TCP roundtrip times. For this reason, the
response to the RCPT
To
:
command follows the DATA
command in this example.
[4] This is one long line with no line breaks.
[5] All of the flags are described in Table 7-2, which is shown in the Discussion section of Recipe 7.9.