10.10 STARTTLS
Encryption can improve the security of
sendmail. Ordinarily, mail is sent between two
machines in the clear. That is, if you were to watch the transmission
of bytes over the network you would see what is actually
being sent or received. This includes passwords, which are also sent
in the clear.
To reduce the likelihood that someone watching the network will find
something that can harm you, you can encrypt the stream of data.
Three forms of encryption are available as of this writing:
- SSL
-
SSL is a method for encrypting a single connection over which network
traffic can flow. One implementation of SSL is available from
http://www.openssl.org/.
- TLS
-
Transport Layer Security, defined by RFC2246, is the successor to SSL
that provides further means of connection encryption. It, too, is
available from http://www.openssl.org.
- SMTP AUTH=
-
The DIGEST-MD5 and GSSAPI mechanisms, among others, for the AUTH=
extension to SMTP, also provides stream encryption.
In this section we show you:
How to install the OpenSSL library
What digital certificates and their acronyms are
How to include support for STARTTLS in sendmail
How to set up the configuration file for use with STARTTLS
Which sendmail macros are relevant to STARTTLS
10.10.1 The SSL Library
An SSL library might already exist on your machine. If so, and if it
is a secure version, you can skip this section.
The SSL library is available from the OpenSSL organization at the
following sites:
- http://www.OpenSSL.org/source/ web download
- ftp://ftp.openssl.org/source/ anonymous ftp
Be sure you download V0.9.6g or higher (earlier versions had security
problems).
After you have downloaded and unpacked the source, look in the file
called INSTALL. That file contains all the information you need to
build and install the package. Throughout the rest of this section we
will assume you have successfully installed this package in its
default location /usr/local/ssl.
10.10.1.1 A proper random number source
If your system lacks the device /dev/urandom you
will need to perform additional steps before you can use TLS. If your
system supports /dev/urandom you can skip this
section.
For TLS (and thus STARTTLS) to work in a reliable and secure manner,
you need to set up a way for sendmail to acquire
high-quality pseudorandom numbers. There are a few alternatives to
/dev/urandom that you can use, some more
suitable than others. They are, in order of preference:
SUNWski, which is a package from Sun Microsystems that emulates
/dev/urandom, and which only works with SunOS
5.5.
EGD, which stands for Entropy Gathering Daemon.
PRNGD, which stands for PseudoRandom Number Generator Daemon.
You can also roll your own random number source in a file.
10.10.1.2 SUNWski
Sun Microsystems provides an equivalent to
/dev/urandom, called
/dev/random, as part of its SUNWski package for
Solaris. If it is not already installed on your system you can
install it from a variety of sources. First, look on your Solaris
Server Intranet Extension CD (if you have one). Lacking that, look at
the web site http://freeware4sun.wroc.pl/.
Look under Solaris 2.6 for patch number 106754, 106755, or 106756,
which contain the SUNWski package.
10.10.1.3 EGD
EGD is a persistent daemon that provides excellent pseudorandom
numbers via a Unix domain socket. It is available as
perl(1) source from http://egd.sourceforge.net/.
If you choose to download and install this daemon, you can advise
sendmail of that fact by defining the
RandFile option (RandFile) in
your mc configuration file:
define(`confRAND_FILE', `egd:/etc/entropy')
Here, a decision was made to run the EGD daemon at the system level,
and to have it create its socket as
/etc/entropy. If you place that socket in a different location, you
should replace /etc/entropy in the
confRAND_FILE line (as discussed earlier) with the
new location. The egd: prefix is required and
constant.
Note that, to include support inside sendmail
for use with this daemon, you must build
sendmail with the EGD compile-time macro defined
(EGD):
APPENDDEF(`confENVDEF', `-DEGD') in your Build m4 file
10.10.1.4 PRNGD
PRNGD is an EGD-compatible daemon available from http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html.
You download and install it, then use it in the same manner described
for EGD.
10.10.1.5 Roll your own
It is possible to use a file created by you that contains random
numbers. To do this, first define the location of that file with
sendmail's
RandFile option (RandFile).
Such a declaration might look like this:
define(`confRAND_FILE', `file:/var/run/randfile')
Note that the file: prefix is literal and must be
present. The file, here named /var/run/randfile,
contains at least 128 bytes of random data.
For such a file to work, you need to update its contents more often
than once every 10 minutes. If you update it less often,
sendmail might refuse to use it upon startup (as
a daemon or simply to send an email message). That is, the
modification time of the file must always be within 10 minutes of any
envocation of sendmail.
10.10.2 Digital Certificates
Digital certificates—and especially the acronyms and
abbreviated terms used by sendmail to describe
digital certificates—are central to the understanding and
operation of TLS.
A digital certificate is simply a block of
bytes issued to a machine or a business by an authority. The block of
bytes is unique to the person, machine, or business that acquired it,
and can serve to identify that machine or business. Buried within
that block of bytes is the identity of the authority that issued the
block. When a machine or business offers the block of bytes as its
identification, the receiver can connect to the authority to verify
that the block of bytes is in fact authentic.
In actual practice, such blocks of bytes or digital certificates can
be more complex. For example, a master authority can issue a
certificate to a regional authority. That regional authority can then
issue individual certificates to individual machines. Each
machine's certificate will contain embedded
information about both authorities: the regional and the master
authority.
Digital certificates are supplied in two parts: a public part and a
private part. The private part is kept private on the local machine
and never given out. The public part is given to others to establish
an identity.
To ensure that digital certificates are valid, a hash is also stored
inside each certificate. When a certificate is offered as
identification, the receiver fetches the public part to ascertain the
issuing authority, then uses that public part as a key to decrypt the
authority's signature inside the certificate. A hash
is computed on the decrypted signature, and if that hash matches the
hash stored inside the certificate, the certificate is considered
good.
Each digital certificate is embedded with a time that allows an
authority to expire the certificate. This feature is used by
commercial sites that issue top-level certificates, as a way to force
the annual renewal (and payment for) those certificates.
The sendmail program uses a number of acronyms
and abbreviations to refer to the various components of digital
certificates. They are listed in Table 10-3.
Table 10-3. Acronyms, abbreviations, and terms for digital certificates
CA
|
Certificate Authority (authority that issues a digital certificate)
|
Cert
|
A digital certificate, but often means just the public part of the
whole certificate
|
Cipher
|
The type of encryption used for a connection
|
Client Certificate
|
Identifies connecting client to the mail server
|
CN
|
Common Name (the username or site name)
|
Key
|
The private key, but often means just the private part of the whole
certificate
|
Private Key
|
The private key part of a certificate
|
Public Key
|
The public key part of a certificate
|
Server Certificate
|
Identifies mail server to connecting client
|
For example, you might see a reference to "install a
CA cert" in this book or in the
sendmail documentation. This phrase means to
install a digital certificate issued by a certificate authority. When
you install the Certs of the issuing CA, you are generally installing
only the public parts.
You are encouraged to refer to Table 10-3 while
reading the next few sections, where these acronyms, abbreviations,
and terms are frequently used.
10.10.3 Enable TLS with Build
To enable TLS in sendmail you need to add two
new lines to your Build m4
file:
APPENDDEF(`conf_sendmail_ENVDEF', `-DSTARTTLS')
APPENDDEF(`conf_sendmail_LIBS', `-lssl -lcrypto')
With these two lines in place, build a new
sendmail. If you get an error such as the
following:
tls.c:16: openssl/err.h: No such file or directory
you will need to let Build know where you
installed the ssl components:
APPENDDEF(`conf_sendmail_INCDIRS', `-I/opt/packages/openssl/include')
APPENDDEF(`conf_sendmail_LIBDIRS', `-L/opt/packages/openssl/lib')
Here, we installed OpenSSL in the nonstandard path
/opt/packages/openssl.
10.10.4 Set Up Your Certificates
There are two ways to set up your site's
certificates: create your own and sign them yourself; or create your
own and have a commercial site sign them. Commercial signatures
generally require the payment of an annual fee.
Table 10-4 shows a few of the commercial sites that
sign certificates. There are many more than we show here. Use your
favorite search engine to find more.
We don't cover the creation of certificates here,
nor how to sign them. Instead we refer you to:
- http://www.sendmail.org/~gshapiro/security.pdf
-
A brief tutorial that describes sendmail
security in general, and provides examples of certificate creation.
- Network Security with OpenSSL
-
By John Viega, Matt Messier, and Pravir Chandra,
O'Reilly & Associates, 2002. Provides a full
description of OpenSSL, including how to create certificates and how
to sign them.
- SSL and TLS: Designing and Building Secure Systems
-
By Eric Rescorla, Addison Wesley Professional Publisher, 2001, is a
higher-level book that covers the protocols of SSL and TLS Internet
security protocols.
10.10.5 Add STARTTLS Support to Your mc File
After you have built sendmail with STARTTLS
support (Section 10.10.3), and after you have created a
certificate for use with sendmail, you must set
up your configuration file to use STARTTLS. There are seven
mc configuration file macros that you can use to
do this. Based on what we have shown in the previous sections, one
way to define them might look like this:
define(`CERT_DIR', `/etc/mail/certs')
define(`confCACERT_PATH', `CERT_DIR')
define(`confCACERT', `CERT_DIR`'/cacert.pem')
define(`confSERVER_CERT', `CERT_DIR`'/client.cert.pem')
define(`confSERVER_KEY', `CERT_DIR`'/client.key.pem')
define(`confCLIENT_CERT', `CERT_DIR`'/client.cert.pem')
define(`confCLIENT_KEY', `CERT_DIR`'/client.key.pem')
Here, we have set the settings for the server and client certificate
and key files to be the same. At your site, you might want to have
separate certificates and keys for the two roles of server (accept
connections) and client (make connections). You might also prefer to
keep the key outside the certificate file, as was done with the
cacert.pem.
10.10.6 Test STARTTLS
Once you have built sendmail with STARTTLS
support, and before you install it, you should test to see if
STARTTLS is working. One way to perform such a test is like this:
# obj.*/sendmail/sendmail -bs -Am
Here, we run the newly built sendmail relative
to the source directory. The -bs tells
sendmail to speak SMTP on its standard input.
The -Am tells sendmail to use
its server configuration file (not submit.cf),
even though it is running in mail-submission mode. Such a test
session might look like this:
220 your.host.domain ESMTP Sendmail 8.12.7/8.12.7; Mon, 14 Jan 2002 11:43:02 -0700 (PST)
ehlo your.host.domain
250-your.host.domain Hello root@localhost, pleased to meet you
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-8BITMIME
250-SIZE
250-DSN
250-ETRN
250-STARTTLS note this line
250-DELIVERBY
250 HELP
quit
221 2.0.0 your.host.domain closing connection
Here, the STARTTLS SMTP keyword appears, revealing that this site
supports SSL encryptions of connections.
If STARTTLS doesn't appear, rerun the command with
extra debugging, like this:
# obj.*/sendmail/sendmail -O LogLevel=14 -bs -Am
Look in your syslog log files for
sendmail messages. Look for messages such as
warnings about unsafe files, or warnings about the validity of X.509
certificates. If this fails, and you need additional help, you can
connect to http://www.sendmail.org/tips/.
If STARTTLS does appear, run sendmail as usual.
Then examine Received: header lines for mail you
received from other sites that support STARTTLS, and look for
indications that TLS encryption worked:
Received: from other.host.domain (other.host.domain [123.45.67.89])
by your.host.domain (8.12.5/8.12.3) with ESMTP id g75FlHR4038187
(version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=NO) note
for <you@your.host.domain>; Fri, 13 Dec 2002 08:47:36 -0700 (PDT)
Note that, even though the Received: header shows
verify=NO, the message was still encrypted because
the cipher= and bits= are
present with values.
10.10.7 Macros for Use with STARTTLS
If you decide to use STARTTLS with sendmail, be
aware that a number of related sendmail macros
are useful in rule sets and database maps. These are shown in Table 10-5, and described in detail in Chapter 21.
Table 10-5. Macros for use with STARTTLS
${cert_issuer}
|
${cert_issuer}
|
Distinguished name of CA that signed the presented cert
|
${cert_md5}
|
${cert_md5}
|
MD5 of certificate
|
${cert_subject}
|
${cert_subject}
|
Distinguished name of certificate
|
${cipher}
|
${cipher}
|
Cipher suite used for connection
|
${cipher_bits}
|
${cipher_bits}
|
TLS encryption key length
|
${tls_version}
|
${tls_version}
|
TLS/SSL version
|
${verify}
|
${verify}
|
Result of cert verification
|
10.10.8 STARTTLS and the access Database
Beginning with V8.11, four new prefixes in the
access database are available for use with
STARTTLS connection encryption (Section 10.10).
CERTISSUER: and CERTSUBJECT:
are for use with the Local_Relay_Auth rule set.
TLS_Srv: and TLS_Clt: are for
use with the tls_server and
tls_client rule sets.
10.10.8.1 The access database and Local_Relay_Auth
In the rule set Local_Relay_Auth, the
STARTTLS-related sendmail macro
${verify} (which contains the result of connection
verification) is compared to the literal value OK. If it is not OK,
the other relaying checks are performed.
If ${verify} is OK, the value in the
sendmail macro ${cert_issuer}
(${cert_issuer}) is prefixed with
CERTISSUER:, and the result looked up in the
access database. That macro contains as its
value the distinguished name of the authority that signed the
presented certificate. The value undergoes special translation before
the lookup. Specifically, all nonprinting characters, the space and
tab characters, and the special characters:
< > ( ) " +
are replaced with the hexadecimal value of the character prefixed
with a plus. For example, Sendmail CA becomes
Sendmail+20CA.
Therefore, if the issuer has the following distinguished name:
/C=US/ST=California/L=Berkeley/O=Sendmail.org/CN=Sendmail CA/
that value undergoes special translation, and is prefixed with the
special prefix CERTISSUER: just before the lookup.
So the following is looked up:
CERTISSUER:/C=US/ST=California/L=Berkeley/O=Sendmail.org/CN=Sendmail+20CA/
If that prefix and distinguished name are found in the database, and
if the value returned is the keyword RELAY, relaying is allowed. If
the value returned is the keyword SUBJECT instead of RELAY, the value
of the sendmail macro
${cert_subject} (${cert_subject}) is
looked up in the access database. That macro
contains as its value the distinguished name of the connecting site.
That value also undergoes translation, and is prefixed with the
special prefix CERTSUBJECT: just before the
lookup. For example, if the distinguished name of the certificate for
the connecting site is:
/C=US/ST=California/L=Berkeley/O=Sendmail.org/CN=Eric Allman/
the following is looked up:
CERTSUBJECT:/C=US/ST=California/L=Berkeley/O=Sendmail.org/CN=Eric+20Allman/
If the prefixed macro's value is found, and if the
value returned is the keyword RELAY, relaying is allowed.
10.10.8.2 The access database with tls_server and tls_client
The
tls_server rule set is called after the local
sendmail issued (or should have issued) the
STARTTLS SMTP command. This rule set handles outbound connections.
The tls_client rule set
is called at two possible points: just after the connecting
host's STARTTLS SMTP command is offered; and from
the check_mail rule set (which is called just
after the connecting host issues the MAIL FROM: command). This
tls_client rule set handles inbound connections.
Both rule sets are given the value of the
${verify} sendmail macro in
their workspaces. The tls_client rule set is given
that value, followed by a $| operator, and a
literal string that is MAIL when tls_client is
called from the check_mail rule set, or STARTTLS
otherwise.
If the access database is not used, the
connection is allowed in all cases, both inbound and outbound, unless
the value in ${verify} is SOFTWARE, in which
instance the connection is not allowed.
If the access database is used, the
tls_server rule set looks up the hostname of the
destination host in the access database using
the TLS_Srv: prefix. For example, if the local
sendmail connected to the server
insecure.host.domain, and if the negotiation for
the TLS connection was good, the following lookup is performed:
TLS_Srv:insecure.host.domain
The tls_client rule set looks up the hostname of
the inbound connecting host in the access
database using the TLS_Clt: prefix. For example,
if the local sendmail accepts a connection from
ssl.host.domain, and if the negotiation for TLS
connection was good, the following lookup is performed:
TLS_Clt:ssl.host.domain
For both rule sets, if the host or domain is not found, the
host.domain, then the
domain, are looked up, and if neither is found,
a bare prefix is looked up to determine the default behavior:
TLS_Clt: VERIFY
TLS_Srv: VERIFY
Here, the default for inbound and outbound connections is to require
that they all be verified.
The access database righthand-side string VERIFY
means that the value in the ${verify} macro must
be OK.
In addition to the VERIFY value keyword, a number of bits (key
length) can also be specified as:
VERIFY:bits
In addition to requiring that the certificate be verified, the number
of bits in the ${cipher_bits}
sendmail macro must be at least as wide as the
number of bits specified in bits.
If the number of bits is the only item of concern, and if certificate
verification is not of concern, the VERIFY in
VERIFY:bits can be
changed into ENCR:
ENCR:bits
Here, no certificate verification is required, but the number of bits
in the ${cipher_bits}
sendmail macro must be at least as wide as the
number of bits specified in bits.
If the certificate is verified, and/or the number of bits is
sufficient, the connection is allowed. Otherwise, it is rejected.
When rejected, the rejection is temporary by default. You can prefix
the VERIFY or ENCR with a
TEMP+ to make a particular failure temporary, or
with a PERM+ to make it permanent:
TEMP+VERIFY temporary failure
PERM+ENCR:bits permanent failure
You can also define the TLS_PERM_ERR macro in your
mc configuration file to redefine the default to
be a permanent failure:
define(`TLS_PERM_ERR')
If you wish to add your own rule to the tls_client
or tls_server rule sets, you can do so with an
appropriate mc configuration command:
LOCAL_TLS_CLIENT
additional rules for tls_client here
LOCAL_TLS_SERVER
additional rules for tls_server here
Your rules, if any, will be called first. That is, for example, if
you add rules to tls_client, those rules will be
called before those that were already in the
tls_client rule set. You do not need to restore
the workspace at the end of your rules, however, because that
restoration is taken care of for you.
10.10.8.3 The tls_rcpt rule set
In the
previous section you learned that the tls_server
rule set could be used to require that all mail to a particular site
always be encrypted. For example, an access
database entry such as the following does just that for the
hostA.domain site:
TLS_Srv:hostA.domain ENCR:128
However, because of MX records, mail might not always be sent to the
hostA.domain's mail server.
Consider these two MX records:
hostA.domain. IN MX 10 mail.hostA.domain.
hostA.domain. IN MX 50 mail.someother.domain.
When the server mail.hostA.domain is down or
heavily loaded, your local sendmail will likely
connect to the backup MX site
mail.someother.domain. When this happens, the
requirement that all mail be encrypted (as set in the
access database) will not be honored. Because
you have no way of knowing ahead of time what host will serve as an
MX backup, you probably won't have that backup host
listed in you access database:
TLS_Srv:hostA.domain ENCR:128 mail.someother.domain not listed
When sendmail connects to
mail.someother.domain (and when
mail.someother.domain does not support STARTTLS)
the message will be transmitted in plain text (unencrypted).
The tls_rcpt rule set was created specifically to
deal with this problem. It is called just before a RCPT TO: command
is sent to the other site.
The workspace supplied to tls_rcpt is the current
recipient (the one that will be given in the RCPT TO: command when it
is issued). This rule set is allowed to require encryption or
verification of the recipient's MTA, even if the
message was redirected with MX records to another site.
The tls_rcpt rule set looks up the
recipient in four different ways, where the
format of the recipient address is
user@host.domain. Each lookup is prefixed with a
literal TLS_Rcpt:. The lookups are:
TLS_Rcpt:user@host.domain
TLS_Rcpt:user@
TLS_Rcpt:host.domain
TLS_Rcpt:domain
TLS_Rcpt:
The tls_rcpt rule set accepts the righthand-side
value from the first matched lookup. If there is no match, the
recipient address is considered good and the RCPT TO: command is
allowed to be issued.
The allowable righthand-side values are the same as those described
for the tls_server rule set in the previous
section. The requirements in the righthand side are compared to the
${verify} and ${cipher_bits}
macros, as appropriate, and the connection is either allowed to
continue, or not, based on the result.
To illustrate, consider the MX example given earlier. If the
access database contains the following entry:
TLS_Rcpt:hostA.domain ENCR:128
encryption is required for any recipient at
hostA.domain, even if delivery is redirected
with an MX record to another site, such as
mail.someother.domain.
In addition to the righthand-side values described earlier, the
tls_rcpt rule set allows four righthand-side
suffixes. Each starts with a plus, and when two or more are listed,
each is separated from the others with two plus signs:
TLS_Rcpt:hostA.domain ENCR:128+CN:smtp.hostA.domain++CI:hostB.domain
The suffixes allow further checks to be applied to the connection in
addition to those required by the existing righthand-side value. The
suffixes and their meanings are:
- CN: name
-
The name specified. It must match the
value in the ${cn_subject} macro (${cn_subject}).
- CN
-
The value in the ${cn_subject} macro (${cn_subject}). It must match the value in the
${server_name} macro (${server_name}).
- CS: name
-
The name specified. It must match the
value in the ${cert_subject} macro (${cert_subject}).
- CI: name
-
The name specified. It must match the
value in the ${cert_issuer} macro (${cert_issuer}).
If you wish to add your own rules to the tls_rcpt
rule set, you can do so with the following mc
configuration command:
LOCAL_TLS_RCPT
additional rules for tls_rcpt here
If your rules return a #error or
#discard delivery agent, the connection is
rejected. If they return a $#OK, the connection is
accepted and subsequent tls_rcpt rule set rules
are skipped (the access database lookups are not
performed):
R $* $# OK skip subsequent tls_rcpt rule set rules
But if they return a $@OK, further
tls_rcpt rule set rules are allowed, and the
access database lookups are performed, which
might subsequently reject the connection:
R $* $@ OK allow subsequent tls_rcpt rule set rules
Your rules, if any, will be called first. That is, for example, if
you add rules to tls_rcpt, those rules will be
called before those that were already in the
tls_rcpt rule set. You need not restore the
workspace at the end of your rules, however, because that restoration
is taken care of for you.
10.10.8.4 Disable STARTTLS with the try_tls rule set
By default
STARTTLS is used whenever possible. Unfortunately, some hosts on the
Internet do not properly implement STARTTLS, so even though they
offer STARTTLS, they don't use it properly and the
connection fails. If you know ahead of time which hosts have this
problem you can list them in the access database
and cause STARTTLS to be skipped for them.
The try_tls rule set allows you to exempt specific
connecting hosts and domains from STARTTLS support. This rule set
simply looks up the connecting host's hostname and
address in the access database. Each lookup is
prefixed with a literal Try_TLS:. If the lookup
finds the host or address (if either is in the
access database) the use of STARTTLS is
suppressed:
Try_TLS:broken.server NO a domain
Try_TLS:host.broken.server NO a host
Try_TLS:123.45.67.89 NO an IPv4 address
Try_TLS:IPv6:2002:c0a8:51d2::23f4 NO an IPv6 address
The righthand-side value for this lookup can be anything. All the
try_tls rule set cares about is whether the lookup
succeeds.
If you wish to add your own rule to the try_tls
rule set, you can do so with the following mc
configuration command:
LOCAL_TRY_TLS
additional rules for try_tls here
If your rules return a #error or
#discard delivery agent, STARTTLS is suppressed.
If they return a $#OK, STARTTLS is offered
and subsequent try_tls rule set rules are skipped
(the access database lookups are not performed):
R $* $# OK skip subsequent try_tls rule set rules
But if they return a $@OK, STARTTLS might be
offered. We say might because further try_tls rule
set rules are allowed, and access database
lookups are performed, which, in turn, can subsequently disallow
STARTTLS:
R $* $@ OK allow subsequent try_tls rule set rules
Your rules, if any, will be called first. That is, for example, if
you add rules to try_tls, those rules will be
called before those that were already in the
try_tls rule set. You need not restore the
workspace at the end of your rules, however, because that restoration
is taken care of for you.
|