Resolve conflicts from last import.

This commit is contained in:
tron 2014-07-06 19:45:50 +00:00
parent 16d67a18c4
commit 8fd41761ab
30 changed files with 5926 additions and 2143 deletions

View File

@ -292,23 +292,35 @@ parameter specifies persistent storage for sender or recipient address
verification results. If you specify an empty value, all address verification
results are lost after "postfix reload" or "postfix stop".
# Example 1: Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
/etc/postfix/main.cf:
# Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
address_verify_map = btree:$data_directory/verify_cache
# Shared persistent cache (requires Postfix 2.9 or later).
address_verify_map = proxy:btree:$data_directory/verify_cache
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
# Example 2: Shared persistent lmdb: cache (Postfix 2.11 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/main.cf:
address_verify_map = lmdb:$data_directory/verify_cache
# address_verify_cache_cleanup_interval = 0
# Shared memory cache (requires Postfix 2.9 or later).
# See memcache_table(5) for details.
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/main.cf:
address_verify_map = proxy:btree:$data_directory/verify_cache
# address_verify_cache_cleanup_interval = 0
# Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances.
# See memcache_table(5) for details.
/etc/postfix/main.cf:
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
address_verify_cache_cleanup_interval = 0
# Example 5: Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
/etc/postfix/main.cf:
address_verify_map =
NOTE 1: The database file should be stored under a Postfix-owned directory,

View File

@ -148,18 +148,20 @@ compiler. Here are a few examples:
and so on. In some cases, optimization is turned off automatically.
44..33 -- BBuuiillddiinngg wwiitthh ooppttiioonnaall eexxtteennssiioonnss
44..33 -- BBuuiillddiinngg wwiitthh ooppttiioonnaall ffeeaattuurreess
By default, Postfix builds as a mail system with relatively few bells and
whistles. Support for third-party databases etc. must be configured when
Postfix is compiled. The following documents describe how to build Postfix with
support for extensions:
support for optional features:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|PPoossttffiixx eexxtteennssiioonn |DDooccuummeenntt |AAvvaaiillaabbiilliittyy|
|OOppttiioonnaall ffeeaattuurree |DDooccuummeenntt |AAvvaaiillaabbiilliittyy|
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
|Berkeley DB database |DB_README |Postfix 1.0 |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
|LMDB database |LMDB_README |Postfix 2.11|
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
|LDAP database |LDAP_README |Postfix 1.0 |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
|MySQL database |MYSQL_README |Postfix 1.0 |
@ -192,31 +194,33 @@ IMPORTANT: Be sure to get the quotes right. These details matter a lot.
Parameters whose defaults can be specified in this way are:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|MMaaccrroo nnaammee |ddeeffaauulltt vvaalluuee ffoorr|ttyyppiiccaall ddeeffaauulltt |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_COMMAND_DIR |command_directory|/usr/sbin |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_CONFIG_DIR |config_directory |/etc/postfix |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_DAEMON_DIR |daemon_directory |/usr/libexec/postfix|
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_DATA_DIR |data_directory |/var/db/postfix |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_MAILQ_PATH |mailq_path |/usr/bin/mailq |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_HTML_DIR |html_directory |no |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_MANPAGE_DIR |manpage_directory|/usr/local/man |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_NEWALIAS_PATH|newaliases_path |/usr/bin/newaliases |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_QUEUE_DIR |queue_directory |/var/spool/postfix |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_README_DIR |readme_directory |no |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_SENDMAIL_PATH|sendmail_path |/usr/sbin/sendmail |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|MMaaccrroo nnaammee |ddeeffaauulltt vvaalluuee ffoorr |ttyyppiiccaall ddeeffaauulltt |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_COMMAND_DIR |command_directory |/usr/sbin |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_CONFIG_DIR |config_directory |/etc/postfix |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_DB_TYPE |default_database_type|hash |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_DAEMON_DIR |daemon_directory |/usr/libexec/postfix|
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_DATA_DIR |data_directory |/var/db/postfix |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_MAILQ_PATH |mailq_path |/usr/bin/mailq |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_HTML_DIR |html_directory |no |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_MANPAGE_DIR |manpage_directory |/usr/local/man |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_NEWALIAS_PATH|newaliases_path |/usr/bin/newaliases |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_QUEUE_DIR |queue_directory |/var/spool/postfix |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_README_DIR |readme_directory |no |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|DEF_SENDMAIL_PATH|sendmail_path |/usr/sbin/sendmail |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
Note: the data_directory parameter (for caches and pseudo-random numbers) was
introduced with Postfix version 2.5.
@ -245,9 +249,11 @@ The following is an extensive list of names and values.
| |at compile time: |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|| |Do not build with Berkeley DB support. By |
||-DNO_DB |default, Berkeley DB support is compiled in on|
|| |platforms that are known to support this |
|| |feature. |
|| |default, Berkeley DB support is compiled in on|
||-DNO_DB |platforms that are known to support this |
|| |feature. If you override this, then you |
|| |probably should also override DEF_DB_TYPE as |
|| |described in section 4.4. |
|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|| |Do not build with Solaris /dev/poll support. |
||-DNO_DEVPOLL |By default, /dev/poll support is compiled in |
@ -271,8 +277,12 @@ The following is an extensive list of names and values.
|| |known to support it. |
|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|| |Do not build with NIS or NISPLUS support. NIS |
||-DNO_NIS |is not available on some recent Linux or |
|| |Solaris distributions. |
||-DNO_NIS |is not available on some recent Linux |
|| |distributions. |
|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|| |Do not build with NISPLUS support. NISPLUS is |
||-DNO_NISPLUS |not available on some recent Solaris |
|| |distributions. |
|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|| |Do not build with PCRE support. By default, |
||-DNO_PCRE |PCRE support is compiled in when the pcre- |

View File

@ -86,14 +86,15 @@ a private key. Both must be in "PEM" format. The private key must not be
encrypted, meaning: the key must be accessible without a password. The
certificate and private key may be in the same file, in which case the
certificate file should be owned by "root" and not be readable by any other
user. If the key is stored separately, this applies to the key file only, and
the certificate file may be "world-readable".
user. If the key is stored separately, this access restriction applies to the
key file only, and the certificate file may be "world-readable".
Public Internet MX hosts without certificates signed by a "reputable" CA must
generate, and be prepared to present to most clients, a self-signed or private-
CA signed certificate. The remote SMTP client will generally not be able to
authenticate the self-signed certificate, but unless the client is running
Postfix or similar software, it will still insist on a server certificate.
Public Internet MX hosts without certificates signed by a well-known public CA
must still generate, and be prepared to present to most clients, a self-signed
or private-CA signed certificate. The remote SMTP client will generally not be
able to verify the self-signed certificate, but unless the client is running
Postfix or similar software, it will only negotiate TLS ciphersuites that
require a server certificate.
For servers that are nnoott public Internet MX hosts, Postfix supports
configurations with no certificates. This entails the use of just the anonymous
@ -106,34 +107,73 @@ administrator explicitly sets "smtpd_tls_cert_file = none". This ensures that
new Postfix SMTP server configurations will not accidentally run with no
certificates.
RSA, DSA and ECDSA (Postfix >= 2.6) certificates are supported. Typically you
will only have RSA certificates issued by a commercial CA. In addition, the
tools supplied with OpenSSL will by default issue RSA certificates. You can
configure all three at the same time, in which case the cipher used determines
which certificate is presented. For Netscape and OpenSSL clients without
special cipher choices, the RSA certificate is preferred.
RSA, DSA and ECDSA (Postfix >= 2.6) certificates are supported. Most sites only
have RSA certificates. You can configure all three at the same time, in which
case the ciphersuite negotiated with the remote SMTP client determines which
certificate is used. If your DNS zone is signed, and you want to publish RFC
6698 TLSA records, these must match any of the configured certificates. Since
the best practice is to publish "3 1 1" certificate associations, create a
separate TLSA record for each public-key certificate digest.
To enable a remote SMTP client to verify the Postfix SMTP server certificate,
the issuing CA certificates must be made available to the client. You should
include the required certificates in the server certificate file, the server
certificate first, then the issuing CA(s) (bottom-up order).
CCrreeaattiinngg tthhee sseerrvveerr cceerrttiiffiiccaattee ffiillee
Example: the certificate for "server.example.com" was issued by "intermediate
CA" which itself has a certificate issued by "root CA". Create the server.pem
file with:
% ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> sseerrvveerr..ppeemm
A Postfix SMTP server certificate supplied here must be usable as SSL server
To verify the Postfix SMTP server certificate, the remote SMTP client must
receive the issuing CA certificates via the TLS handshake or via public-key
infrastructure. This means that the Postfix server public-key certificate file
must include the server certificate first, then the issuing CA(s) (bottom-up
order). The Postfix SMTP server certificate must be usable as SSL server
certificate and hence pass the "openssl verify -purpose sslserver ..." test.
A client that trusts the root CA has a local copy of the root CA certificate,
so it is not necessary to include the root CA certificate here. Leaving it out
of the "server.pem" file reduces the overhead of the TLS exchange.
The examples that follow show how to create a server certificate file. We
assume that the certificate for "server.example.com" was issued by
"intermediate CA" which itself has a certificate issued by "root CA".
* With legacy public CA trust verification, you can omit the root certificate
from the "server.pem" certificate file. If the client trusts the root CA,
it will already have a local copy of the root CA certificate. Omitting the
root CA certificate reduces the size of the server TLS handshake.
% ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> sseerrvveerr..ppeemm
* If you publish RFC 6698 TLSA "2 0 1" or "2 1 1" records to specify root CA
certificate digests, you must include the corresponding root CA
certificates in the "server.pem" certificate file. See the documentation of
the tls_dane_trust_anchor_digest_enable main.cf parameter.
% ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm rroooott..ppeemm >> sseerrvveerr..ppeemm
Remote SMTP clients will be able to use the TLSA record you publish (which
only contains the certificate digest) only if they have access to the
corresponding certificate. Failure to verify certificates per the server's
published TLSA records will typically cause the SMTP client to defer mail
delivery. The foregoing also applies to "2 0 2" and "2 1 2" TLSA records or
any other digest of a CA certificate, but it is expected that SHA256 will
be by far the most common digest for TLSA.
As a best practice, publish either "3 0 1" or "3 1 1" TLSA associations
that specify the SHA256 digest of the server certificate public key with
the alias-expanded hostname of each STARTTLS capable SMTP server. These
continue to work when a certificate is renewed with the same public/private
key pair.
For instructions on how to compute the digest of a certificate or its public
key for use in TLSA records, see the documentation of the
smtpd_tls_fingerprint_digest main.cf parameter.
When a new key or certificate is generated, an additional TLSA record with the
new digest must be published in advance of the actual deployment of the new key
or certificate on the server. You must allow sufficient time for any TLSA
RRsets with only the old digest to expire from DNS caches. The safest practice
is to wait until the DNSSEC signature on the previous TLSA RRset expires, and
only then switch the server to use new keys published in the updated TLSA
RRset. Once the new certificate trust chain and private key are in effect, the
DNS should be updated once again to remove the old digest from the TLSA RRset.
If you want the Postfix SMTP server to accept remote SMTP client certificates
issued by these CAs, append the root certificate to $smtpd_tls_CAfile or
install it in the $smtpd_tls_CApath directory.
issued by one or more root CAs, append the root certificate to
$smtpd_tls_CAfile or install it in the $smtpd_tls_CApath directory.
CCoonnffiigguurriinngg tthhee sseerrvveerr cceerrttiiffiiccaattee aanndd kkeeyy ffiilleess
RSA key and certificate examples:
@ -207,27 +247,25 @@ To get additional information about Postfix SMTP server TLS activity you can
increase the log level from 0..4. Each logging level also includes the
information that is logged at a lower logging level.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|LLeevveell|PPoossttffiixx 22..99 aanndd llaatteerr |EEaarrlliieerr rreelleeaasseess.. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|0 |Log only a summary message on TLS |Disable logging of TLS activity.|
| |handshake completion -- no logging| |
| |of client certificate trust-chain | |
| |verification errors if client | |
| |certificate verification is not | |
| |required. | |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|1 |Also log trust-chain verification |Also log TLS handshake and |
| |errors and peer certificate |certificate information. |
| |summary information. | |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|2 |Also log levels during TLS negotiation. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|3 |Also log hexadecimal and ASCII dump of TLS negotiation process. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|4 |Also log hexadecimal and ASCII dump of complete transmission after |
| |STARTTLS. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|LLeevveell|PPoossttffiixx 22..99 aanndd llaatteerr |EEaarrlliieerr rreelleeaasseess.. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|0 |Disable logging of TLS activity. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|1 |Log only a summary message on TLS |Log the summary message, peer |
| |handshake completion -- no logging|certificate summary information|
| |of client certificate trust-chain |and unconditionally log trust- |
| |verification errors if client |chain verification errors. |
| |certificate verification is not | |
| |required. | |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|2 |Also log levels during TLS negotiation. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|3 |Also log hexadecimal and ASCII dump of TLS negotiation process. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|4 |Also log hexadecimal and ASCII dump of complete transmission after|
| |STARTTLS. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
Use log level 3 only in case of problems. Use of log level 4 is strongly
discouraged.
@ -364,16 +402,40 @@ Example:
SSeerrvveerr--ssiiddee TTLLSS sseessssiioonn ccaacchhee
The Postfix SMTP server and the remote SMTP client negotiate a session, which
takes some computer time and network bandwidth. By default, this session
information is cached only in the smtpd(8) process actually using this session
and is lost when the process terminates. To share the session information
between multiple smtpd(8) processes, a persistent session cache can be used.
You can specify any database type that can store objects of several kbytes and
that supports the sequence operator. DBM databases are not suitable because
they can only store small objects. The cache is maintained by the tlsmgr(8)
process, so there is no problem with concurrent access. Session caching is
highly recommended, because the cost of repeatedly negotiating TLS session keys
is high.
takes some computer time and network bandwidth. SSL protocol versions other
than SSLv2 support resumption of cached sessions. Not only is this more CPU and
bandwidth efficient, it also reduces latency as only one network round-trip is
used to resume a session while it takes two round-trips to create a session
from scratch.
Since Postfix uses multiple smtpd(8) service processes, an in-memory cache is
not sufficient for session re-use. Clients store at most one cached session per
server and are very unlikely to repeatedly connect to the same server process.
Thus session caching in the Postfix SMTP server generally requires a shared
cache (an alternative available with Postfix >= 2.11 is described below).
To share the session information between multiple smtpd(8) processes, a session
cache database is used. You can specify any database type that can store
objects of several kbytes and that supports the sequence operator. DBM
databases are not suitable because they can only store small objects. The cache
is maintained by the tlsmgr(8) process, so there is no problem with concurrent
access. Session caching is highly recommended, because the cost of repeatedly
negotiating TLS session keys is high.
Starting with Postfix 2.11, linked with a compatible OpenSSL library (at least
0.9.8h, preferably 1.0.0 or later) the Postfix SMTP server supports RFC 5077
TLS session resumption without server-side state when the remote SMTP client
also supports RFC 5077. The session is encrypted by the server in a session
ticket returned to client for storage. When a client sends a valid session
ticket, the server decrypts it and resumes the session, provided neither the
ticket nor the session have expired. This makes it possible to resume cached
sessions without allocating space for a shared database on the server. This
feature can be disabled by setting the session cache timeout to zero, otherwise
the timeout must be at least 2 minutes and at most 100 days.
Note, session tickets can only be negotiated if the client disables SSLv2 and
does not use the legacy SSLv2 compatible HELLO message. This is true by default
with the Postfix >= 2.6 SMTP client.
Example:
@ -395,11 +457,15 @@ Example:
/etc/postfix/main.cf:
smtpd_tls_session_cache_timeout = 3600s
As of Postfix 2.11 this setting cannot exceed 100 days. If set <= 0, session
caching is disabled. If set to a positive value less than 2 minutes, the
minimum value of 2 minutes is used instead.
When the Postfix SMTP server does not save TLS sessions to an external cache
database, client-side session caching is unlikely to be useful. To prevent such
wastage, the Postfix SMTP server can be configured to not issue TLS session
ids. By default the Postfix SMTP server always issues TLS session ids. This
works around known interoperability issues with some MUAs, and prevents
database, client-side session caching is unlikely to be useful. To reduce waste
of client resources, the Postfix SMTP server can be configured to not issue TLS
session ids. By default the Postfix SMTP server always issues TLS session ids.
This works around known interoperability issues with some MUAs, and prevents
possible interoperability issues with other MTAs.
Example:
@ -540,7 +606,8 @@ configurations with no server certificates that use oonnllyy the anonymous c
This is enabled by explicitly setting "smtpd_tls_cert_file = none" and not
specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file.
Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade ciphers:
Example, MSA that requires TLSv1 or higher, not SSLv2 or SSLv3, with high grade
ciphers:
/etc/postfix/main.cf:
smtpd_tls_cert_file = /etc/postfix/cert.pem
@ -548,55 +615,37 @@ Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade ciphers:
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5
smtpd_tls_security_level = encrypt
# Preferred form with Postfix >= 2.5:
# Preferred syntax with Postfix >= 2.5:
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
# Alternative form.
# Legacy syntax:
smtpd_tls_mandatory_protocols = TLSv1
If you want to take advantage of ciphers with ephemeral Diffie-Hellman (EDH)
key exchange (this offers "forward-secrecy"), DH parameters are needed. Instead
of using the built-in DH parameters for both 1024-bit (non-export ciphers) and
512-bit (export ciphers), it is better to generate your own parameters, since
otherwise it would "pay" for a possible attacker to start a brute force attack
against parameters that are used by everybody. Postfix defaults to compiled-in
parameters that are shared by all Postfix users who don't generate their own
settings.
To generate your own set of DH parameters, use:
% ooppeennssssll ggeennddhh --oouutt //eettcc//ppoossttffiixx//ddhh__551122..ppeemm --22 551122
% ooppeennssssll ggeennddhh --oouutt //eettcc//ppoossttffiixx//ddhh__11002244..ppeemm --22 11002244
Support for elliptic curve cryptography is available with Postfix 2.6 and
OpenSSL 1.0.0 or later. To enable ephemeral elliptic curve Diffie-Hellman
(EECDH) key-exchange, set "smtpd_tls_eecdh_grade = strong" or
"smtpd_tls_eecdh_grade = ultra". The "ultra" setting is substantially more CPU
intensive, and "strong" is sufficiently secure for most situations.
Examples:
/etc/postfix/main.cf:
smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
# Postfix >= 2.6:
smtpd_tls_eecdh_grade = strong
If you want to take maximal advantage of ciphers that offer forward secrecy see
the Getting started section of FORWARD_SECRECY_README. The full document
conveniently presents all information about Postfix "perfect" forward secrecy
support in one place: what forward secrecy is, how to tweak settings, and what
you can expect to see when Postfix uses ciphers with forward secrecy.
Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later allows TLS
servers to preempt the TLS client's cipher preference list. This is possible
only with SSLv3 and later, as in SSLv2 the client chooses the cipher from a
list supplied by the server.
servers to preempt the TLS client's cipher-suite preference list. This is
possible only with SSLv3 and later, as in SSLv2 the client chooses the cipher-
suite from a list supplied by the server.
By default, the OpenSSL server selects the client's most preferred cipher that
the server supports. With SSLv3 and later, the server may choose its own most
preferred cipher that is supported (offered) by the client. Setting
"tls_preempt_cipherlist = yes" enables server cipher preferences. The default
OpenSSL behavior applies with "tls_preempt_cipherlist = no".
By default, the OpenSSL server selects the client's most preferred cipher-suite
that the server supports. With SSLv3 and later, the server may choose its own
most preferred cipher-suite that is supported (offered) by the client. Setting
"tls_preempt_cipherlist = yes" enables server cipher-suite preferences. The
default OpenSSL behavior applies with "tls_preempt_cipherlist = no".
While server cipher selection may in some cases lead to a more secure or
performant cipher choice, there is some risk of interoperability issues. In the
past, some SSL clients have listed lower priority ciphers that they did not
implement correctly. If the server chooses a cipher that the client prefers
less, it may select a cipher whose client implementation is flawed.
While server cipher-suite selection may in some cases lead to a more secure or
performant cipher-suite choice, there is some risk of interoperability issues.
In the past, some SSL clients have listed lower priority ciphers that they did
not implement correctly. If the server chooses a cipher that the client prefers
less, it may select a cipher whose client implementation is flawed. Most
notably Windows 2003 Microsoft Exchange servers have flawed implementations of
DES-CBC3-SHA, which OpenSSL considers stronger than RC4-SHA. Enabling server
cipher-suite selection may create interoperability issues with Windows 2003
Microsoft Exchange clients.
MMiisscceellllaanneeoouuss sseerrvveerr ccoonnttrroollss
@ -619,11 +668,35 @@ Example:
/etc/postfix/main.cf:
tls_disable_workarounds = 0xFFFFFFFF
tls_disable_workarounds = CVE-2010-4180, LEGACY_SERVER_CONNECT
tls_disable_workarounds = CVE-2010-4180
Note: Disabling LEGACY_SERVER_CONNECT is not wise at this time, lots of servers
are still unpatched and Postfix is not significantly vulnerable to the
renegotiation issue in the TLS protocol.
With Postfix >= 2.11, the tls_ssl_options parameter specifies a list or bit-
mask of OpenSSL options to enable. Specify one or more of the named options
below, or a hexadecimal bitmask of options found in the ssl.h file
corresponding to the run-time OpenSSL library. While it may be reasonable to
turn off all bug workarounds (see above), it is not a good idea to attempt to
turn on all features.
LLEEGGAACCYY__SSEERRVVEERR__CCOONNNNEECCTT
See SSL_CTX_set_options(3).
NNOO__TTIICCKKEETT
See SSL_CTX_set_options(3).
NNOO__CCOOMMPPRREESSSSIIOONN
Disable SSL compression even if supported by the OpenSSL library.
Compression is CPU-intensive, and compression before encryption does not
always improve security.
Example:
/etc/postfix/main.cf:
tls_ssl_options = no_ticket, no_compression
You should only enable features via the hexadecimal mask when the need to
control the feature is critical (to deal with a new vulnerability or a serious
interoperability problem). Postfix DOES NOT promise backwards compatible
behavior with respect to the mask bits. A feature enabled via the mask in one
release may be enabled by other means in a later release, and the mask bit will
then be ignored. Therefore, use of the hexadecimal mask is only a temporary
measure until a new Postfix or OpenSSL release provides a better solution.
SSMMTTPP CClliieenntt ssppeecciiffiicc sseettttiinnggss
@ -653,6 +726,10 @@ mmaayy
Opportunistic TLS.
eennccrryypptt
Mandatory TLS encryption.
ddaannee
Opportunistic DANE TLS.
ddaannee--oonnllyy
Mandatory DANE TLS.
ffiinnggeerrpprriinntt
Certificate fingerprint verification.
vveerriiffyy
@ -805,15 +882,191 @@ not specified consistently.
[example.net]:msa encrypt protocols=TLSv1 ciphers=high
[example.net]:submission encrypt protocols=TLSv1 ciphers=high
DDAANNEE TTLLSS aauutthheennttiiccaattiioonn..
The Postfix SMTP client supports two TLS security levels based on RFC6698 DANE
TLSA records. The opportunistic "dane" level and the mandatory "dane-only"
level.
The "dane" level is a stronger form of opportunistic TLS that is resistant to
man in the middle and downgrade attacks when the destination domain uses DNSSEC
to publish DANE TLSA records for its MX hosts. If a remote SMTP server has
"usable" (see RFC 6698) DANE TLSA records, the server connection will be
authenticated. When DANE authentication fails, there is no fallback to
unauthenticated or plaintext delivery.
If TLSA records are published for a given remote SMTP server (implying TLS
support), but are all "unusable" due to unsupported parameters or malformed
data, the Postfix SMTP client will use mandatory unauthenticated TLS.
Otherwise, when no TLSA records are published, the Postfix SMTP client behavior
is the same as with may.
TLSA records must be published in DNSSEC validated DNS zones. Any TLSA records
in DNS zones not protected via DNSSEC are ignored. The Postfix SMTP client will
not look for TLSA records associated with MX hosts whose "A" or "AAAA" records
lie in an "insecure" DNS zone. Such lookups have been observed to cause
interoperability issues with poorly implemented DNS servers, and are in any
case not expected to ever yield "secure" results, since that would require a
very unlikely DLV DNS trust anchor configured between the host record and the
associated "_25._tcp" child TLSA record.
The "dane-only" level is a form of secure-channel TLS based on the DANE PKI. If
"usable" TLSA records are present these are used to authenticate the remote
SMTP server. Otherwise, or when server certificate verification fails, delivery
via the server in question tempfails.
At both security levels, the TLS policy for the destination is obtained via
TLSA records validated with DNSSEC. For TLSA policy to be in effect, the
destination domain's containing DNS zone must be signed and the Postfix SMTP
client's operating system must be configured to send its DNS queries to a
recursive DNS nameserver that is able to validate the signed records. Each MX
host's DNS zone needs to also be signed, and needs to publish DANE TLSA (RFC
6698) records that specify how that MX host's TLS certificate is to be
verified.
TLSA records do not preempt the normal SMTP MX host selection algorithm, if
some MX hosts support TLSA and others do not, TLS security will vary from
delivery to delivery. It is up to the domain owner to configure their MX hosts
and their DNS sensibly. To configure the Postfix SMTP client for DNSSEC lookups
see the documentation for the smtp_dns_support_level main.cf parameter. The
tls_dane_trust_anchor_digest_enable main.cf parameter controls support for
trust-anchor digest TLSA records. The tls_dane_digests and
tls_dane_digest_agility parameters control the list of supported digests and
digest downgrade attack resistance.
DANE for SMTP MTAs deviates in some details from the baseline DANE protocol in
RFC 6698. Most notably, it is not expected that SMTP MTAs can reasonably
include every public CA that a remote SMTP server's administrator may believe
to be well-known. Nor is there an interactive user to "click OK" when
authentication fails.
Therefore, certificate usages "0" and "1" from RFC 6698 which are intended to
"constrain" existing PKI trust, are not supported. TLSA records with usage "0"
are treated as "unusable". TLSA records with usage "1" are instead treated as
"trust assertions" and mapped to usage "3". Specifically, with certificate
usage "1", Postfix will not require the remote SMTP server's certificate to be
trusted with respect to any locally defined public CAs, it is the domain
owner's responsibility to ensure that the certificate associations in their
TLSA records are appropriate to authenticate their SMTP servers.
The Postfix SMTP client supports only certificate usages "2" and "3" (with "1"
treated as though it were "3"). See tls_dane_trust_anchor_digest_enable for
usage "2" usability considerations. Support for certificate usage "1" is an
experiment, it may be withdrawn in the future. Server operators SHOULD NOT
publish TLSA records with usage "1".
When usable TLSA records are obtained for the remote SMTP server the Postfix
SMTP client sends the SNI TLS extension in its SSL client hello message. This
may help the remote SMTP server live up to its promise to provide a certificate
that matches its TLSA records.
For purposes of protocol and cipher selection, the "dane" security level is
treated like a "mandatory" TLS security level, and weak ciphers and protocols
are disabled. Since DANE authenticates server certificates the "aNULL" cipher-
suites are transparently excluded at this level, no need to configure this
manually. RFC 6698 (DANE) TLS authentication is available with Postfix 2.11 and
later.
When a DANE TLSA record specifies a trust-anchor (TA) certificate (that is an
issuing CA), the strategy used to verify the peername of the server certificate
is unconditionally "nexthop, hostname". Both the nexthop domain and the
hostname obtained from the DNSSEC-validated MX lookup are safe from forgery and
the server certificate must contain at least one of these names.
When a DANE TLSA record specifies an end-entity (EE) certificate, (that is the
actual server certificate), as with the fingerprint security level below, no
name checks or certificate expiration checks are applied. The server
certificate (or its public key) either matches the DANE record or not. Server
administrators should publish such EE records in preference to all other types.
The pre-requisites for DANE support in the Postfix SMTP client are:
* A compile-time OpenSSL library that supports the TLS SNI extension and
"SHA-2" message digests.
* A compile-time DNS resolver library that supports DNSSEC. Postfix binaries
built on an older system will not support DNSSEC even if deployed on a
system with an updated resolver library.
* The "smtp_dns_support_level" must be set to "dnssec".
* The "smtp_host_lookup" parameter must include "dns".
* A DNSSEC-validating recursive resolver (see note below).
The above client pre-requisites do not apply to the Postfix SMTP server. It
will support DANE provided it supports TLSv1 and its TLSA records are published
in a DNSSEC signed zone. To receive DANE secured mail for multiple domains, use
the same hostname to add the server to each domain's MX records. There are no
plans to implement SNI in the Postfix SMTP server.
Note: The Postfix SMTP client's internal stub DNS resolver is DNSSEC-aware, but
it does not itself validate DNSSEC records, rather it delegates DNSSEC
validation to the operating system's configured recursive DNS nameserver. The
Postfix DNS client relies on a secure channel to the resolver's cache for
DNSSEC integrity, but does not support TSIG to protect the transmission channel
between itself and the nameserver. Therefore, it is strongly recommended (DANE
security guarantee void otherwise) that each MTA run a local DNSSEC-validating
recursive resolver ("unbound" from nlnetlabs.nl is a reasonable choice)
listening on the loopback interface, and that the system be configured to use
only this local nameserver. The local nameserver may forward queries to an
upstream recursive resolver on another host if desired.
Note: When the operating system's recursive nameserver is not local, enabling
EDNS0 expanded DNS packet sizes and turning on the DNSSEC "DO" bit in the DNS
request and/or the new DNSSEC-specific records returned in the nameserver's
replies may cause problems with older or buggy firewall and DNS server
implementations. Therefore, Postfix does not enable DNSSEC by default. Since MX
lookups happen before the security level is determined, DANE support is
disabled for all destinations unless you set "smtp_dns_support_level = dnssec".
To enable DNSSEC lookups selectively, define a new dedicated transport with a
"-o smtp_dns_support_level=dnssec" override in master.cf and route selected
domains to that transport. If DNSSEC proves to be sufficiently reliable for
these domains, you can enable it for all destinations by changing the global
smtp_dns_support_level in main.cf.
EExxaammppllee: "dane" security for selected destinations, with opportunistic TLS by
default. This is the recommended configuration for early adopters.
* The "example.com" destination uses DANE, but if TLSA records are not
present or are unusable, mail is deferred.
* The "example.org" destination uses DANE if possible, but if no TLSA records
are found opportunistic TLS is used.
main.cf:
indexed = ${default_database_type}:${config_directory}/
#
# default: Opportunistic TLS with no DNSSEC lookups.
#
smtp_tls_security_level = may
smtp_dns_support_level = enabled
#
# Per-destination TLS policy
#
smtp_tls_policy_maps = ${indexed}tls_policy
#
# default_transport = smtp, but some destinations are special:
#
transport_maps = ${indexed}transport
transport:
example.com dane
example.org dane
tls_policy:
example.com dane-only
master.cf:
dane unix - - n - - smtp
-o smtp_dns_support_level=dnssec
-o smtp_tls_security_level=dane
CCeerrttiiffiiccaattee ffiinnggeerrpprriinntt vveerriiffiiccaattiioonn
Certificate fingerprint verification is available with Postfix 2.5 and later.
At this security level ("smtp_tls_security_level = fingerprint"), no trusted
certificate authorities are used or required. The certificate trust chain,
expiration date, ... are not checked. Instead, the
smtp_tls_fingerprint_cert_match parameter or the "match" attribute in the
policy table lists the remote SMTP server certificate fingerprint or public key
fingerprint (Postfix 2.9 and later).
At the fingerprint security level, no trusted certificate authorities are used
or required. The certificate trust chain, expiration date, etc., are not
checked. Instead, the smtp_tls_fingerprint_cert_match parameter or the "match"
attribute in the policy table lists the remote SMTP server certificate
fingerprint or public key fingerprint. Certificate fingerprint verification is
available with Postfix 2.5 and later, public-key fingerprint support is
available with Postfix 2.9 and later.
If certificate fingerprints are exchanged securely, this is the strongest, and
least scalable security level. The administrator needs to securely collect the
@ -858,7 +1111,7 @@ the example above, we show two matching fingerprints:
smtp_tls_fingerprint_digest = md5
/etc/postfix/tls_policy:
example.com fingerprint
example.com fingerprint
match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1
match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35
@ -892,7 +1145,7 @@ use public-key fingerprints, upgrade to Postfix 2.9.6 or later.
MMaannddaattoorryy sseerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn
At the "verify" TLS security level, messages are sent only over TLS encrypted
At the verify TLS security level, messages are sent only over TLS encrypted
sessions if the remote SMTP server certificate is valid (not expired or
revoked, and signed by a trusted certificate authority) and where the server
certificate name matches a known pattern. Mandatory server certificate
@ -908,6 +1161,17 @@ extension are used to verify the remote SMTP server name. If no DNS names are
specified, the certificate CommonName is checked. If you want mandatory
encryption without server certificate verification, see above.
With Postfix >= 2.11 the "smtp_tls_trust_anchor_file" parameter or more
typically the corresponding per-destination "tafile" attribute optionally
modifies trust chain verification. If the parameter is not empty the root CAs
in CAfile and CApath are no longer trusted. Rather, the Postfix SMTP client
will only trust certificate-chains signed by one of the trust-anchors contained
in the chosen files. The specified trust-anchor certificates and public keys
are not subject to expiration, and need not be (self-signed) root CAs. They
may, if desired, be intermediate certificates. Therefore, these certificates
also may be found "in the middle" of the trust chain presented by the remote
SMTP server, and any untrusted issuing parent certificates will be ignored.
Despite the potential for eliminating "man-in-the-middle" and other attacks,
mandatory certificate trust chain and subject name verification is not viable
as a default Internet mail delivery policy. Most MX hosts do not support TLS at
@ -958,6 +1222,17 @@ extension are used to verify the remote SMTP server name. If no DNS names are
specified, the CommonName is checked. If you want mandatory encryption without
server certificate verification, see above.
With Postfix >= 2.11 the "smtp_tls_trust_anchor_file" parameter or more
typically the corresponding per-destination "tafile" attribute optionally
modifies trust chain verification. If the parameter is not empty the root CAs
in CAfile and CApath are no longer trusted. Rather, the Postfix SMTP client
will only trust certificate-chains signed by one of the trust-anchors contained
in the chosen files. The specified trust-anchor certificates and public keys
are not subject to expiration, and need not be (self-signed) root CAs. They
may, if desired, be intermediate certificates. Therefore, these certificates
also may be found "in the middle" of the trust chain presented by the remote
SMTP server, and any untrusted issuing parent certificates will be ignored.
Despite the potential for eliminating "man-in-the-middle" and other attacks,
mandatory secure server certificate verification is not viable as a default
Internet mail delivery policy. Most MX hosts do not support TLS at all, and a
@ -1044,27 +1319,25 @@ To get additional information about Postfix SMTP client TLS activity you can
increase the loglevel from 0..4. Each logging level also includes the
information that is logged at a lower logging level.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|LLeevveell|PPoossttffiixx 22..99 aanndd llaatteerr |EEaarrlliieerr rreelleeaasseess.. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|0 |Log only a summary message on TLS |Disable logging of TLS activity.|
| |handshake completion -- no logging| |
| |of remote SMTP server certificate | |
| |trust-chain verification errors if| |
| |server certificate verification is| |
| |not required. | |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|1 |Also log remote SMTP server trust-|Also log TLS handshake and |
| |chain verification errors and peer|certificate information. |
| |certificate summary information. | |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|2 |Also log levels during TLS negotiation. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|3 |Also log hexadecimal and ASCII dump of TLS negotiation process. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|4 |Also log hexadecimal and ASCII dump of complete transmission after |
| |STARTTLS. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|LLeevveell|PPoossttffiixx 22..99 aanndd llaatteerr |EEaarrlliieerr rreelleeaasseess.. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|0 |Disable logging of TLS activity. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|1 |Log only a summary message on TLS |Log the summary message and |
| |handshake completion -- no logging|unconditionally log trust-chain|
| |of remote SMTP server certificate |verification errors. |
| |trust-chain verification errors if| |
| |server certificate verification is| |
| |not required. | |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|2 |Also log levels during TLS negotiation. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|3 |Also log hexadecimal and ASCII dump of TLS negotiation process. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
|4 |Also log hexadecimal and ASCII dump of complete transmission after|
| |STARTTLS. |
|_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
Example:
@ -1210,6 +1483,10 @@ Example:
/etc/postfix/main.cf:
smtp_tls_session_cache_timeout = 3600s
As of Postfix 2.11 this setting cannot exceed 100 days. If set <= 0, session
caching is disabled. If set to a positive value less than 2 minutes, the
minimum value of 2 minutes is used instead.
CClliieenntt TTLLSS lliimmiittaattiioonnss
The security properties of TLS communication channels are application specific.
@ -1258,9 +1535,15 @@ security policy.
On the SMTP client, there are further complications. When delivering mail to a
given domain, in contrast to HTTPS, one rarely uses the domain name directly as
the target host of the SMTP session. More typically, one uses MX lookups -
these are usually unauthenticated - to obtain the domain's SMTP server hostname
(s). When, as is current practice, the client verifies the insecurely obtained
MX hostname, it is subject to a DNS man-in-the-middle attack.
- these are usually unauthenticated -- to obtain the domain's SMTP server
hostname(s). When, as is current practice, the client verifies the insecurely
obtained MX hostname, it is subject to a DNS man-in-the-middle attack.
Adoption of DNSSEC and RFC6698 (DANE) may gradually (as domains implement
DNSSEC and publish TLSA records for their MX hosts) address the DNS man-in-the-
middle risk and provide scalable key management for SMTP with TLS. Postfix >=
2.11 supports the new dane and dane-only security levels that take advantage of
these standards.
If clients instead attempted to verify the recipient domain name, an SMTP
server for multiple domains would need to list all its email domain names in
@ -1341,6 +1624,23 @@ eennccrryypptt
overrides the main.cf smtp_tls_mandatory_ciphers parameter, and the
optional "exclude" attribute (Postfix >= 2.6) overrides the main.cf
smtp_tls_mandatory_exclude_ciphers parameter.
ddaannee
Opportunistic DANE TLS. The TLS policy for the destination is obtained via
TLSA records in DNSSEC. If no TLSA records are found, the effective
security level used is may. If TLSA records are found, but none are usable,
the effective security level is encrypt. When usable TLSA records are
obtained for the remote SMTP server, SSLv2 is automatically disabled (see
smtp_tls_mandatory_protocols), and the server certificate must match the
TLSA records. RFC 6698 (DANE) TLS authentication and DNSSEC support is
available with Postfix 2.11 and later.
ddaannee--oonnllyy
Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA
records in DNSSEC. If no TLSA records are found, or none are usable, no
connection is made to the server. When usable TLSA records are obtained for
the remote SMTP server, SSLv2 is automatically disabled (see
smtp_tls_mandatory_protocols), and the server certificate must match the
TLSA records. RFC 6698 (DANE) TLS authentication and DNSSEC support is
available with Postfix 2.11 and later.
ffiinnggeerrpprriinntt
Certificate fingerprint verification. Available with Postfix 2.5 and later.
At this security level, there are no trusted certificate authorities. The
@ -1360,14 +1660,21 @@ vveerriiffyy
validated (not expired or revoked, and signed by a trusted certificate
authority), and if the server certificate name matches the optional "match"
attribute (or the main.cf smtp_tls_verify_cert_match parameter value when
no optional "match" attribute is specified).
no optional "match" attribute is specified). With Postfix >= 2.11 the
"tafile" attribute optionally modifies trust chain verification in the same
manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile"
attribute may be specified multiple times to load multiple trust-anchor
files.
sseeccuurree
Secure certificate verification. Mail is delivered only if the TLS
handshake succeeds, if the remote SMTP server certificate can be validated
(not expired or revoked, and signed by a trusted certificate authority),
and if the server certificate name matches the optional "match" attribute
(or the main.cf smtp_tls_secure_cert_match parameter value when no optional
"match" attribute is specified).
"match" attribute is specified). With Postfix >= 2.11 the "tafile"
attribute optionally modifies trust chain verification in the same manner
as the "smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may
be specified multiple times to load multiple trust-anchor files.
Notes:
* The "match" attribute is especially useful to verify TLS certificates for
@ -1404,16 +1711,15 @@ Example:
/etc/postfix/tls_policy:
example.edu none
example.mil may
example.gov encrypt protocols=SSLv3:TLSv1 ciphers=high
example.com verify
match=hostname:dot-nexthop protocols=SSLv3:TLSv1 ciphers=high
example.gov encrypt ciphers=high
example.com verify match=hostname:dot-nexthop ciphers=high
example.net secure
.example.net secure match=.example.net:example.net
[mail.example.org]:587 secure match=nexthop
# Postfix 2.5 and later
[thumb.example.org] fingerprint
match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35
match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1
match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35
match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1
# Postfix 2.6 and later
example.info may protocols=!SSLv2 ciphers=medium
exclude=3DES
@ -1497,7 +1803,7 @@ Example:
smtp_tls_exclude_ciphers = aNULL
# Preferred form with Postfix >= 2.5:
smtp_tls_mandatory_protocols = !SSLv2
# Alternative form.
# Legacy form for Postfix < 2.5:
smtp_tls_mandatory_protocols = SSLv3, TLSv1
# Also available with Postfix >= 2.6:
smtp_tls_ciphers = export
@ -1572,6 +1878,49 @@ Example:
/etc/postfix/main.cf:
smtp_starttls_timeout = 300s
With Postfix 2.8 and later, the tls_disable_workarounds parameter specifies a
list or bit-mask of OpenSSL bug work-arounds to disable. This may be necessary
if one of the work-arounds enabled by default in OpenSSL proves to pose a
security risk, or introduces an unexpected interoperability issue. Some bug
work-arounds known to be problematic are disabled in the default value of the
parameter when linked with an OpenSSL library that could be vulnerable.
Example:
/etc/postfix/main.cf:
tls_disable_workarounds = 0xFFFFFFFF
tls_disable_workarounds = CVE-2010-4180, LEGACY_SERVER_CONNECT
Note: Disabling LEGACY_SERVER_CONNECT is not wise at this time, lots of servers
are still unpatched and Postfix is not significantly vulnerable to the
renegotiation issue in the TLS protocol.
With Postfix >= 2.11, the tls_ssl_options parameter specifies a list or bit-
mask of OpenSSL options to enable. Specify one or more of the named options
below, or a hexadecimal bitmask of options found in the ssl.h file
corresponding to the run-time OpenSSL library. While it may be reasonable to
turn off all bug workarounds (see above), it is not a good idea to attempt to
turn on all features.
A future version of OpenSSL may by default no longer allow connections to
servers that don't support secure renegotiation. Since the exposure for SMTP is
minimal, and some SMTP servers may remain unpatched, you can add
LEGACY_SERVER_CONNECT to the options to restore the more permissive default of
current OpenSSL releases.
Example:
/etc/postfix/main.cf:
tls_ssl_options = NO_TICKET, NO_COMPRESSION, LEGACY_SERVER_CONNECT
You should only enable features via the hexadecimal mask when the need to
control the feature is critical (to deal with a new vulnerability or a serious
interoperability problem). Postfix DOES NOT promise backwards compatible
behavior with respect to the mask bits. A feature enabled via the mask in one
release may be enabled by other means in a later release, and the mask bit will
then be ignored. Therefore, use of the hexadecimal mask is only a temporary
measure until a new Postfix or OpenSSL release provides a better solution.
TTLLSS mmaannaaggeerr ssppeecciiffiicc sseettttiinnggss
The security of cryptographic software such as TLS depends critically on the

View File

@ -1,4 +1,4 @@
# $NetBSD: main.cf,v 1.4 2013/01/06 13:58:24 tron Exp $
# $NetBSD: main.cf,v 1.5 2014/07/06 19:45:50 tron Exp $
#
# Global Postfix configuration file. This file lists only a subset
# of all parameters. For the syntax, and for a complete parameter
@ -7,7 +7,7 @@
# For common configuration examples, see BASIC_CONFIGURATION_README
# and STANDARD_CONFIGURATION_README. To find these documents, use
# the command "postconf html_directory readme_directory", or go to
# http://www.postfix.org/.
# http://www.postfix.org/BASIC_CONFIGURATION_README.html etc.
#
# For best results, change no more than 2-3 parameters at a time,
# and test if Postfix still works after every change.

View File

@ -1,8 +1,9 @@
# $NetBSD: master.cf,v 1.6 2013/09/25 19:12:34 tron Exp $
# $NetBSD: master.cf,v 1.7 2014/07/06 19:45:50 tron Exp $
#
#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
@ -23,7 +24,8 @@
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
# -o smtpd_recipient_restrictions=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
#smtps inet n - n - - smtpd
# -o syslog_name=postfix/smtps
@ -33,7 +35,8 @@
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
# -o smtpd_recipient_restrictions=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
#628 inet n - n - - qmqpd
pickup unix n - n 60 1 pickup

View File

@ -1,4 +1,4 @@
# $NetBSD: postfix-files,v 1.4 2013/01/02 19:18:30 tron Exp $
# $NetBSD: postfix-files,v 1.5 2014/07/06 19:45:50 tron Exp $
#
# Commented out entries mean files not installed under NetBSD.
#
@ -167,10 +167,12 @@ $manpage_directory/man5/cidr_table.5:f:root:-:644
$manpage_directory/man5/generics.5:f:root:-:644:o
$manpage_directory/man5/generic.5:f:root:-:644
$manpage_directory/man5/header_checks.5:f:root:-:644
#$manpage_directory/man5/ldap_table.5:f:root:-:644
$manpage_directory/man5/ldap_table.5:f:root:-:644
#$manpage_directory/man5/lmdb_table.5:f:root:-:644
$manpage_directory/man5/master.5:f:root:-:644
$manpage_directory/man5/memcache_table.5:f:root:-:644
#$manpage_directory/man5/mysql_table.5:f:root:-:644
$manpage_directory/man5/socketmap_table.5:f:root:-:644
$manpage_directory/man5/sqlite_table.5:f:root:-:644
$manpage_directory/man5/nisplus_table.5:f:root:-:644
$manpage_directory/man5/pcre_table.5:f:root:-:644
@ -260,11 +262,13 @@ $readme_directory/DEBUG_README:f:root:-:644
$readme_directory/DSN_README:f:root:-:644
$readme_directory/ETRN_README:f:root:-:644
$readme_directory/FILTER_README:f:root:-:644
$readme_directory/FORWARD_SECRECY_README:f:root:-:644
$readme_directory/HOSTING_README:f:root:-:644:o
#$readme_directory/INSTALL:f:root:-:644
$readme_directory/IPV6_README:f:root:-:644
$readme_directory/LDAP_README:f:root:-:644
#$readme_directory/LINUX_README:f:root:-:644
#$readme_directory/LMDB_README:f:root:-:644
$readme_directory/LOCAL_RECIPIENT_README:f:root:-:644
$readme_directory/MACOSX_README:f:root:-:644:o
$readme_directory/MAILDROP_README:f:root:-:644
@ -316,10 +320,12 @@ $html_directory/DEBUG_README.html:f:root:-:644
$html_directory/DSN_README.html:f:root:-:644
$html_directory/ETRN_README.html:f:root:-:644
$html_directory/FILTER_README.html:f:root:-:644
$html_directory/FORWARD_SECRECY_README.html:f:root:-:644
#$html_directory/INSTALL.html:f:root:-:644
$html_directory/IPV6_README.html:f:root:-:644
$html_directory/LDAP_README.html:f:root:-:644
#$html_directory/LINUX_README.html:f:root:-:644
#$html_directory/LMDB_README.html:f:root:-:644
$html_directory/LOCAL_RECIPIENT_README.html:f:root:-:644
$html_directory/MAILDROP_README.html:f:root:-:644
$html_directory/MILTER_README.html:f:root:-:644

View File

@ -333,7 +333,7 @@ in forged email. </p>
<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> = hash:/etc/postfix/sender_access
<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sender_access
<a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> = 550
# Postfix 2.6 and later.
# <a href="postconf.5.html#unverified_sender_defer_code">unverified_sender_defer_code</a> = 250
@ -341,7 +341,7 @@ in forged email. </p>
# Default setting for Postfix 2.7 and later.
# Note 1: Be sure to read the "<a href="#caching">Caching</a>" section below!
# Note 2: Avoid hash files here. Use btree instead.
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = btree:/var/db/postfix/verify
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="DATABASE_README.html#types">btree</a>:/var/db/postfix/verify
/etc/postfix/sender_access:
# Don't do this when you handle lots of email.
@ -378,7 +378,7 @@ you can see what mail would be blocked: </p>
<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> =
<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>
...
<a href="postconf.5.html#check_sender_access">check_sender_access</a> hash:/etc/postfix/sender_access
<a href="postconf.5.html#check_sender_access">check_sender_access</a> <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sender_access
<a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a>
<a href="postconf.5.html#warn_if_reject">warn_if_reject</a> <a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a>
...
@ -388,7 +388,7 @@ you can see what mail would be blocked: </p>
# Default setting for Postfix 2.7 and later.
# Note 1: Be sure to read the "<a href="#caching">Caching</a>" section below!
# Note 2: Avoid hash files here. Use btree instead.
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = btree:/var/db/postfix/verify
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="DATABASE_README.html#types">btree</a>:/var/db/postfix/verify
</pre>
</blockquote>
@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
<blockquote>
<pre>
# Example 1: Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
# Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = btree:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="DATABASE_README.html#types">btree</a>:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
# Shared persistent cache (requires Postfix 2.9 or later).
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="proxymap.8.html">proxy</a>:btree:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
# Example 2: Shared persistent <a href="lmdb_table.5.html">lmdb</a>: cache (Postfix 2.11 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="lmdb_table.5.html">lmdb</a>:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
# <a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
# Shared memory cache (requires Postfix 2.9 or later).
# See <a href="memcache_table.5.html">memcache_table(5)</a> for details.
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/verify-memcache.cf
# Example 3: Shared persistent <a href="DATABASE_README.html#types">btree</a>: cache (Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="proxymap.8.html">proxy</a>:<a href="DATABASE_README.html#types">btree</a>:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
# <a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
# Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances.
# See <a href="memcache_table.5.html">memcache_table(5)</a> for details.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/verify-memcache.cf
<a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
# Example 5: Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#address_verify_map">address_verify_map</a> =
</pre>
</blockquote>

View File

@ -229,21 +229,25 @@ $ make
<p> and so on. In some cases, optimization is turned off automatically. </p>
<h3>4.3 - Building with optional extensions</h3>
<h3>4.3 - Building with optional features</h3>
By default, Postfix builds as a mail system with relatively few
bells and whistles. Support for third-party databases etc.
must be configured when Postfix is compiled. The following documents describe how to build Postfix with support for extensions:
must be configured when Postfix is compiled. The following documents
describe how to build Postfix with support for optional features:
<blockquote>
<table border="1">
<tr> <th>Postfix extension </th> <th>Document </th> <th>Availability</th>
<tr> <th>Optional feature </th> <th>Document </th> <th>Availability</th>
</tr>
<tr> <td> Berkeley DB database</td> <td><a href="DB_README.html">DB_README</a></td> <td> Postfix
1.0 </td> </tr>
<tr> <td> LMDB database</td> <td><a href="LMDB_README.html">LMDB_README</a></td> <td> Postfix
2.11 </td> </tr>
<tr> <td> LDAP database</td> <td><a href="LDAP_README.html">LDAP_README</a></td> <td> Postfix
1.0 </td> </tr>
@ -306,6 +310,9 @@ default</th> </tr>
<tr> <td>DEF_CONFIG_DIR</td> <td><a href="postconf.5.html#config_directory">config_directory</a></td>
<td>/etc/postfix</td> </tr>
<tr> <td>DEF_DB_TYPE</td> <td><a href="postconf.5.html#default_database_type">default_database_type</a></td>
<td>hash</td> </tr>
<tr> <td>DEF_DAEMON_DIR</td> <td><a href="postconf.5.html#daemon_directory">daemon_directory</a></td>
<td>/usr/libexec/postfix</td> </tr>
@ -372,7 +379,9 @@ off Postfix features at compile time:</td> </tr>
<tr> <td> </td> <td> -DNO_DB </td> <td> Do not build with Berkeley
DB support. By default, Berkeley DB support is compiled in on
platforms that are known to support this feature. </td> </tr>
platforms that are known to support this feature. If you override
this, then you probably should also override DEF_DB_TYPE as described
in section 4.4. </td> </tr>
<tr> <td> </td> <td> -DNO_DEVPOLL </td> <td> Do not build with
Solaris <tt>/dev/poll</tt> support. By default, <tt>/dev/poll</tt>
@ -395,7 +404,11 @@ support is compiled in on platforms that are known to support it.
</td> </tr>
<tr> <td> </td> <td> -DNO_NIS </td> <td> Do not build with NIS or
NISPLUS support. NIS is not available on some recent Linux or Solaris
NISPLUS support. NIS is not available on some recent Linux
distributions. </td> </tr>
<tr> <td> </td> <td> -DNO_NISPLUS </td> <td> Do not build with
NISPLUS support. NISPLUS is not available on some recent Solaris
distributions. </td> </tr>
<tr> <td> </td> <td> -DNO_PCRE </td> <td> Do not build with PCRE

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,10 @@
# are known to support it.
# .IP \fB-DNO_NIS\fR
# Do not build with NIS or NISPLUS support. Support for NIS
# is unavailable on some recent Linux and Solaris distributions.
# is unavailable on some recent Linux distributions.
# .IP \fB-DNO_NISPLUS\fR
# Do not build with NISPLUS support. Support for NISPLUS
# is unavailable on some recent Solaris distributions.
# .IP \fB-DNO_PCRE\fR
# Do not build with PCRE support.
# By default, PCRE support is compiled in when the \fBpcre-config\fR
@ -155,6 +158,8 @@ case "$SYSTEM.$RELEASE" in
;;
FreeBSD.9*) SYSTYPE=FREEBSD9
;;
DragonFly.*) SYSTYPE=DRAGONFLY
;;
OpenBSD.2*) SYSTYPE=OPENBSD2
;;
OpenBSD.3*) SYSTYPE=OPENBSD3
@ -175,6 +180,8 @@ case "$SYSTEM.$RELEASE" in
;;
NetBSD.5*) SYSTYPE=NETBSD5
;;
NetBSD.6*) SYSTYPE=NETBSD6
;;
BSD/OS.2*) SYSTYPE=BSDI2
;;
BSD/OS.3*) SYSTYPE=BSDI3
@ -194,7 +201,7 @@ case "$SYSTEM.$RELEASE" in
;;
SunOS.5*) SYSTYPE=SUNOS5
RANLIB=echo
SYSLIBS="-lresolv -lsocket -lnsl"
SYSLIBS="-lresolv -lsocket -lnsl -ldl"
# Stock awk breaks with >10 files.
test -x /usr/xpg4/bin/awk && AWK=/usr/xpg4/bin/awk
# Solaris 2.5 added usleep(), POSIX regexp, POSIX getpwnam/uid_r
@ -210,6 +217,10 @@ case "$SYSTEM.$RELEASE" in
case $RELEASE in
5.[0-8]|5.[0-8].*) CCARGS="$CCARGS -DNO_CLOSEFROM -DNO_DEV_URANDOM -DNO_FUTIMESAT -DSTREAM_CONNECTIONS";;
esac
# Somewhere NISPLUS went away.
case $RELEASE in
5.[0-9][0-9]*) CCARGS="$CCARGS -DNO_NISPLUS";;
esac
# Work around broken str*casecmp(). Do it all here instead
# of having half the solution in the sys_defs.h file.
CCARGS="$CCARGS -Dstrcasecmp=fix_strcasecmp \
@ -274,12 +285,14 @@ case "$SYSTEM.$RELEASE" in
Linux.1*) SYSTYPE=LINUX1
case "$CCARGS" in
*-DNO_DB*) ;;
*-DHAS_DB*) ;;
*) SYSLIBS="-ldb";;
esac
;;
Linux.2*) SYSTYPE=LINUX2
case "$CCARGS" in
*-DNO_DB*) ;;
*-DHAS_DB*) ;;
*) if [ -f /usr/include/db.h ]
then
: we are all set
@ -317,12 +330,12 @@ case "$SYSTEM.$RELEASE" in
# Workaround for retarded libc
2.6.*)
if [ `expr "X$CCARGS" : "X.*-DNO_EPOLL"` -gt 0 ]
then
:
elif [ ! -e /usr/include/sys/epoll.h ]
then
echo CCARGS="$CCARGS -DNO_EPOLL"
else
then
:
elif [ ! -e /usr/include/sys/epoll.h ]
then
echo CCARGS="$CCARGS -DNO_EPOLL"
else
trap 'rm -f makedefs.test makedefs.test.[co]' 1 2 3 15
cat >makedefs.test.c <<'EOF'
#include <sys/types.h>
@ -352,6 +365,7 @@ EOF
Linux.3*) SYSTYPE=LINUX3
case "$CCARGS" in
*-DNO_DB*) ;;
*-DHAS_DB*) ;;
*) if [ -f /usr/include/db.h ]
then
: we are all set
@ -380,7 +394,7 @@ EOF
done
;;
GNU.0*|GNU/kFreeBSD.[567]*)
SYSTYPE=GNU0
SYSTYPE=GNU0
case "$CCARGS" in
*-DNO_DB*) ;;
*) if [ -f /usr/include/db.h ]
@ -461,7 +475,7 @@ ReliantUNIX-?.5.43) SYSTYPE=ReliantUnix543
case $RELEASE in
1.[0-3]) AWK=gawk;;
*) AWK=awk
SYSLIBS=-flat_namespace;;
SYSLIBS="$SYSLIBS -flat_namespace";;
esac
# Darwin 7 adds IPv6 support, BIND_8_COMPAT, NO_NETINFO
case $RELEASE in
@ -477,64 +491,16 @@ ReliantUNIX-?.5.43) SYSTYPE=ReliantUnix543
?.*) CCARGS="$CCARGS -DRESOLVE_H_NEEDS_NAMESER8_COMPAT_H";;
*) CCARGS="$CCARGS -DRESOLVE_H_NEEDS_ARPA_NAMESER_COMPAT_H";;
esac
# kqueue and/or poll are broken up to and including MacOS X 10.5
CCARGS="$CCARGS -DNO_KQUEUE"
# # Darwin 8.11.1 has kqueue support, but let's play safe
# case $RELEASE in
# [1-8].*) CCARGS="$CCARGS -DNO_KQUEUE";;
# *) trap 'rm -f makedefs.test makedefs.test.[co]' 1 2 3 15
# cat >makedefs.test.c <<'EOF'
#/* Adapted from libevent. */
#
##include <sys/types.h>
##include <sys/event.h>
##include <sys/time.h>
##include <string.h>
##include <stdlib.h>
##include <stdio.h>
#
##ifndef EV_SET
##define EV_SET(kp, id, fi, fl, ffl, da, ud) do { \
# struct kevent *__kp = (kp); \
# __kp->ident = (id); \
# __kp->filter = (fi); \
# __kp->flags = (fl); \
# __kp->fflags = (ffl); \
# __kp->data = (da); \
# __kp->udata = (ud); \
# } while(0)
##endif
#
#int main(int argc, char **argv)
#{
# int kq;
# struct kevent test_change;
# struct kevent test_result;
#
# if ((kq = kqueue()) < 0) {
# perror("kqueue");
# exit(1);
# }
##define TEST_FD (-1)
#
# EV_SET(&test_change, TEST_FD, EVFILT_READ, EV_ADD, 0, 0, 0);
# if (kevent(kq,
# &test_change, sizeof(test_change) / sizeof(struct kevent),
# &test_result, sizeof(test_result) / sizeof(struct kevent),
# (struct timespec *) 0) != 1 ||
# test_result.ident != TEST_FD ||
# test_result.flags != EV_ERROR) {
# fprintf(stderr, "Error: kevent reports errors incorrectly\n");
# exit(1);
# }
# exit(0);
#}
#EOF
# $CC -o makedefs.test makedefs.test.c || exit 1
# ./makedefs.test 2>/dev/null ||
# CCARGS="$CCARGS -DNO_KQUEUE"
# rm -f makedefs.test makedefs.test.[co];;
# esac
# Darwin 12.x (MacOS X 10.8.x), maybe earlier, needs libresolv.
case $RELEASE in
?.*|1[0-1].*) ;;
*) SYSLIBS="$SYSLIBS -lresolv";;
esac
# kqueue and/or poll are broken in MacOS X 10.5 (Darwin 9).
# kqueue works in Mac OS X 10.8 (Darwin 12).
case $RELEASE in
?.*|1[0-1].*) CCARGS="$CCARGS -DNO_KQUEUE";;
esac
;;
dcosx.1*) SYSTYPE=DCOSX1
RANLIB=echo
@ -564,7 +530,7 @@ esac
#
case "$CCARGS" in
*-DNO_SIGSETJMP*) ;;
*) trap 'rm -f makedefs.test makedefs.test.[co]' 1 2 3 15
*) trap 'rm -f makedefs.test makedefs.test.[co]' 1 2 3 15
cat >makedefs.test.c <<'EOF'
#include <setjmp.h>
#include <stdlib.h>
@ -630,7 +596,7 @@ esac
case "$CCARGS" in
*-DHAS_PCRE*) ;;
*-DNO_PCRE*) ;;
*) pcre_cflags=`(pcre-config --cflags) 2>/dev/null` &&
*) pcre_cflags=`(pcre-config --cflags) 2>/dev/null` &&
pcre_libs=`(pcre-config --libs) 2>/dev/null` && {
CCARGS="$CCARGS -DHAS_PCRE $pcre_cflags"
AUXLIBS="$AUXLIBS $pcre_libs"
@ -649,7 +615,7 @@ case "$CC" in
"gcc version 2.8"*) : ${OPT=};;
esac;;
*CC) error "Don't use CC. That's the C++ compiler";;
*) : ${OPT='-O'};;
*) : ${OPT='-O'};;
esac
#
# "gcc -W" 3.4.2 no longer reports functions that fail to return a
@ -672,6 +638,9 @@ export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
# needed before the code stabilizes.
#CCARGS="$CCARGS -DNONPROD"
# Workaround: prepend Postfix include files before other include files.
CCARGS="-I. -I../../include $CCARGS"
sed 's/ / /g' <<EOF
SYSTYPE = $SYSTYPE
AR = $AR

File diff suppressed because it is too large Load Diff

View File

@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
<blockquote>
<pre>
# Example 1: Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
/etc/postfix/main.cf:
# Default setting for Postfix 2.7 and later.
# Note: avoid hash files here. Use btree instead.
address_verify_map = btree:$data_directory/verify_cache
# Shared persistent cache (requires Postfix 2.9 or later).
address_verify_map = proxy:btree:$data_directory/verify_cache
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
# Example 2: Shared persistent lmdb: cache (Postfix 2.11 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/main.cf:
address_verify_map = lmdb:$data_directory/verify_cache
# address_verify_cache_cleanup_interval = 0
# Shared memory cache (requires Postfix 2.9 or later).
# See memcache_table(5) for details.
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances except
# for one instance that will be responsible for cache cleanup.
/etc/postfix/main.cf:
address_verify_map = proxy:btree:$data_directory/verify_cache
# address_verify_cache_cleanup_interval = 0
# Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
# Disable automatic cache cleanup in all Postfix instances.
# See memcache_table(5) for details.
/etc/postfix/main.cf:
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
address_verify_cache_cleanup_interval = 0
# Example 5: Default setting for Postfix 2.6 and earlier.
# This uses non-persistent storage only.
/etc/postfix/main.cf:
address_verify_map =
</pre>
</blockquote>

View File

@ -229,21 +229,25 @@ $ make
<p> and so on. In some cases, optimization is turned off automatically. </p>
<h3>4.3 - Building with optional extensions</h3>
<h3>4.3 - Building with optional features</h3>
By default, Postfix builds as a mail system with relatively few
bells and whistles. Support for third-party databases etc.
must be configured when Postfix is compiled. The following documents describe how to build Postfix with support for extensions:
must be configured when Postfix is compiled. The following documents
describe how to build Postfix with support for optional features:
<blockquote>
<table border="1">
<tr> <th>Postfix extension </th> <th>Document </th> <th>Availability</th>
<tr> <th>Optional feature </th> <th>Document </th> <th>Availability</th>
</tr>
<tr> <td> Berkeley DB database</td> <td>DB_README</td> <td> Postfix
1.0 </td> </tr>
<tr> <td> LMDB database</td> <td>LMDB_README</td> <td> Postfix
2.11 </td> </tr>
<tr> <td> LDAP database</td> <td>LDAP_README</td> <td> Postfix
1.0 </td> </tr>
@ -306,6 +310,9 @@ default</th> </tr>
<tr> <td>DEF_CONFIG_DIR</td> <td>config_directory</td>
<td>/etc/postfix</td> </tr>
<tr> <td>DEF_DB_TYPE</td> <td>default_database_type</td>
<td>hash</td> </tr>
<tr> <td>DEF_DAEMON_DIR</td> <td>daemon_directory</td>
<td>/usr/libexec/postfix</td> </tr>
@ -372,7 +379,9 @@ off Postfix features at compile time:</td> </tr>
<tr> <td> </td> <td> -DNO_DB </td> <td> Do not build with Berkeley
DB support. By default, Berkeley DB support is compiled in on
platforms that are known to support this feature. </td> </tr>
platforms that are known to support this feature. If you override
this, then you probably should also override DEF_DB_TYPE as described
in section 4.4. </td> </tr>
<tr> <td> </td> <td> -DNO_DEVPOLL </td> <td> Do not build with
Solaris <tt>/dev/poll</tt> support. By default, <tt>/dev/poll</tt>
@ -395,7 +404,11 @@ support is compiled in on platforms that are known to support it.
</td> </tr>
<tr> <td> </td> <td> -DNO_NIS </td> <td> Do not build with NIS or
NISPLUS support. NIS is not available on some recent Linux or Solaris
NISPLUS support. NIS is not available on some recent Linux
distributions. </td> </tr>
<tr> <td> </td> <td> -DNO_NISPLUS </td> <td> Do not build with
NISPLUS support. NISPLUS is not available on some recent Solaris
distributions. </td> </tr>
<tr> <td> </td> <td> -DNO_PCRE </td> <td> Do not build with PCRE

View File

@ -32,7 +32,7 @@ Postfix. </p>
<p> Transport Layer Security (TLS, formerly called SSL) provides
certificate-based authentication and encrypted sessions. An
encrypted session protects the information that is transmitted with
SMTP mail or with SASL authentication.
SMTP mail or with SASL authentication. </p>
<blockquote> <p> <a name="client_tls_obs"></a> <a
name="client_tls_harden"></a> NOTE: This document describes a TLS
@ -163,16 +163,16 @@ private key must not be encrypted, meaning: the key must be accessible
without a password. The certificate and private key may be in the same
file, in which case the certificate file should be owned by "root" and
not be readable by any other user. If the key is stored separately,
this applies to the key file only, and the certificate file may be
"world-readable". </p>
this access restriction applies to the key file only, and the
certificate file may be "world-readable". </p>
<p> Public Internet MX hosts without certificates signed by a "reputable"
CA must generate, and be prepared to present to most clients, a
self-signed or private-CA signed certificate. The remote SMTP client
will generally not be
able to authenticate the self-signed certificate, but unless the
client is running Postfix or
similar software, it will still insist on a server certificate. </p>
<p> Public Internet MX hosts without certificates signed by a
well-known public CA must still generate, and be prepared to present
to most clients, a self-signed or private-CA signed certificate.
The remote SMTP client will generally not be able to verify the
self-signed certificate, but unless the client is running Postfix
or similar software, it will only negotiate TLS ciphersuites that
require a server certificate. </p>
<p> For servers that are <b>not</b> public Internet MX hosts, Postfix
supports configurations with no certificates. This entails the
@ -188,23 +188,37 @@ SMTP server configurations will not accidentally run with no
certificates. </p>
<p> RSA, DSA and ECDSA (Postfix &ge; 2.6) certificates are supported.
Typically you will
only have RSA certificates issued by a commercial CA. In addition,
the tools supplied with OpenSSL will by default issue RSA certificates.
You can configure all three at the same time, in which case the cipher used
determines which certificate is presented. For Netscape and OpenSSL
clients without special cipher choices, the RSA certificate is
preferred. </p>
Most sites only have RSA certificates. You can configure all three
at the same time, in which case the ciphersuite negotiated with the
remote SMTP client determines which certificate is used. If your
DNS zone is signed, and you want to publish RFC 6698 TLSA records,
these must match any of the configured certificates. Since the
best practice is to publish "3 1 1" certificate associations, create
a separate TLSA record for each public-key certificate digest. </p>
<p> To enable a remote SMTP client to verify the Postfix SMTP server
certificate, the issuing CA certificates must be made available to the
client. You should include the required certificates in the server
certificate file, the server certificate first, then the issuing
CA(s) (bottom-up order). </p>
<h4> Creating the server certificate file </h4>
<p> Example: the certificate for "server.example.com" was issued by
"intermediate CA" which itself has a certificate issued by "root
CA". Create the server.pem file with: </p>
<p> To verify the Postfix SMTP server certificate, the remote SMTP
client must receive the issuing CA certificates via the TLS handshake
or via public-key infrastructure. This means that the Postfix server
public-key certificate file must include the server certificate
first, then the issuing CA(s) (bottom-up order). The Postfix SMTP
server certificate must be usable as SSL server certificate and
hence pass the "<tt>openssl verify -purpose sslserver ...</tt>" test.
</p>
<p> The examples that follow show how to create a server certificate
file. We assume that the certificate for "server.example.com" was
issued by "intermediate CA" which itself has a certificate issued
by "root CA". </p>
<ul>
<li> <p> With legacy public CA trust verification, you can omit the
root certificate from the "server.pem" certificate file. If the
client trusts the root CA, it will already have a local copy of the
root CA certificate. Omitting the root CA certificate reduces the
size of the server TLS handshake. </p>
<blockquote>
<pre>
@ -212,18 +226,56 @@ CA". Create the server.pem file with: </p>
</pre>
</blockquote>
<p> A Postfix SMTP server certificate supplied here must be usable
as SSL server certificate and hence pass the "openssl verify -purpose
sslserver ..." test. </p>
<li> <p> If you publish RFC 6698 TLSA "2 0 1" or "2 1 1" records to
specify root CA certificate digests, you must include the corresponding
root CA certificates in the "server.pem" certificate file. See the
documentation of the tls_dane_trust_anchor_digest_enable main.cf
parameter. </p>
<p> A client that trusts the root CA has a local copy of the root
CA certificate, so it is not necessary to include the root CA
certificate here. Leaving it out of the "server.pem" file reduces
the overhead of the TLS exchange. </p>
<blockquote>
<pre>
% <b>cat server_cert.pem intermediate_CA.pem root.pem &gt; server.pem</b>
</pre>
</blockquote>
<p> Remote SMTP clients will be able to use the TLSA record you
publish (which only contains the certificate digest) only if they
have access to the corresponding certificate. Failure to verify
certificates per the server's published TLSA records will typically
cause the SMTP client to defer mail delivery. The foregoing also
applies to "2 0 2" and "2 1 2" TLSA records or any other digest of
a CA certificate, but it is expected that SHA256 will be by far the
most common digest for TLSA. </p>
<p> As a best practice, publish either "3 0 1" or "3 1 1" TLSA
associations that specify the SHA256 digest of the server certificate
public key with the alias-expanded hostname of each STARTTLS capable
SMTP server. These continue to work when a certificate is renewed
with the same public/private key pair. </p>
</ul>
<p> For instructions on how to compute the digest of a certificate
or its public key for use in TLSA records, see the documentation of
the smtpd_tls_fingerprint_digest main.cf parameter. </p>
<p> When a new key or certificate is generated, an additional TLSA
record with the new digest must be published in advance of the
actual deployment of the new key or certificate on the server. You
must allow sufficient time for any TLSA RRsets with only the old
digest to expire from DNS caches. The safest practice is to wait
until the DNSSEC signature on the previous TLSA RRset expires, and
only then switch the server to use new keys published in the updated
TLSA RRset. Once the new certificate trust chain and private key
are in effect, the DNS should be updated once again to remove the
old digest from the TLSA RRset. </p>
<p> If you want the Postfix SMTP server to accept remote SMTP client
certificates issued by these CAs, append the root certificate to
$smtpd_tls_CAfile or install it in the $smtpd_tls_CApath directory. </p>
certificates issued by one or more root CAs, append the root
certificate to $smtpd_tls_CAfile or install it in the $smtpd_tls_CApath
directory. </p>
<h4> Configuring the server certificate and key files </h4>
<p> RSA key and certificate examples: </p>
@ -332,16 +384,15 @@ logging level. </p>
<tr> <th> Level </th> <th> Postfix 2.9 and later</th> <th> Earlier
releases. </th> </tr>
<tr> <td valign="top"> 0 </td> <td valign="top"> Log only a summary
<tr> <td valign="top"> 0 </td> <td valign="top" colspan="2"> Disable
logging of TLS activity. </td> </tr>
<tr> <td valign="top"> 1 </td> <td valign="top"> Log only a summary
message on TLS handshake completion &mdash; no logging of client
certificate trust-chain verification errors if client certificate
verification is not required. </td> <td valign="top"> Disable logging
of TLS activity.</td> </tr>
<tr> <td valign="top"> 1 </td> <td valign="top"> Also log trust-chain
verification errors and peer certificate summary information. </td>
<td valign="top"> Also log TLS handshake and certificate information.
</td> </tr>
verification is not required. </td> <td valign="top"> Log the summary
message, peer certificate summary information and unconditionally log
trust-chain verification errors. </td> </tr>
<tr> <td valign="top"> 2 </td> <td valign="top" colspan="2"> Also
log levels during TLS negotiation. </td> </tr>
@ -545,12 +596,24 @@ In order to change this behavior, set
<h3><a name="server_tls_cache">Server-side TLS session cache</a> </h3>
<p> The Postfix SMTP server and the remote SMTP client negotiate
a session, which takes some computer time and network bandwidth.
By default, this session information is cached only in the smtpd(8)
process actually using this session and is lost when the process
terminates. To share the session information between multiple
smtpd(8) processes, a persistent session cache can be used. You
<p> The Postfix SMTP server and the remote SMTP client negotiate a
session, which takes some computer time and network bandwidth. SSL
protocol versions other than SSLv2 support resumption of cached
sessions. Not only is this more CPU and bandwidth efficient, it
also reduces latency as only one network round-trip is used to
resume a session while it takes two round-trips to create a session
from scratch. </p>
<p> Since Postfix uses multiple smtpd(8) service processes, an
in-memory cache is not sufficient for session re-use. Clients store
at most one cached session per server and are very unlikely to
repeatedly connect to the same server process. Thus session caching
in the Postfix SMTP server generally requires a shared cache (an
alternative available with Postfix &ge; 2.11 is described below).
</p>
<p> To share the session information between multiple
smtpd(8) processes, a session cache database is used. You
can specify any database type that can store objects of several
kbytes and that supports the sequence operator. DBM databases are
not suitable because they can only store small objects. The cache
@ -558,6 +621,24 @@ is maintained by the tlsmgr(8) process, so there is no problem with
concurrent access. Session caching is highly recommended, because
the cost of repeatedly negotiating TLS session keys is high.</p>
<p> Starting with Postfix 2.11, linked with a compatible OpenSSL
library (at least 0.9.8h, preferably 1.0.0 or later) the Postfix
SMTP server supports RFC 5077 TLS session resumption without
server-side state when the remote SMTP client also supports RFC
5077. The session is encrypted by the server in a <i>session
ticket</i> returned to client for storage. When a client sends a
valid session ticket, the server decrypts it and resumes the session,
provided neither the ticket nor the session have expired. This
makes it possible to resume cached sessions without allocating space
for a shared database on the server. This feature can be disabled
by setting the session cache timeout to zero, otherwise the timeout
must be at least 2 minutes and at most 100 days. </p>
<p> Note, session tickets can only be negotiated if the client
disables SSLv2 and does not use the legacy SSLv2 compatible HELLO
message. This is true by default with the Postfix &ge; 2.6 SMTP
client. </p>
<p> Example: </p>
<blockquote>
@ -587,9 +668,13 @@ recommends a maximum of 24 hours. </p>
</pre>
</blockquote>
<p> As of Postfix 2.11 this setting cannot exceed 100 days. If set
&le; 0, session caching is disabled. If set to a positive value
less than 2 minutes, the minimum value of 2 minutes is used instead. </p>
<p> When the Postfix SMTP server does not save TLS sessions to an
external cache database, client-side session caching is unlikely
to be useful. To prevent such wastage, the Postfix SMTP server can
to be useful. To reduce waste of client resources, the Postfix SMTP server can
be configured to not issue TLS session ids. By default the Postfix
SMTP server always issues TLS session ids. This works around known
interoperability issues with some MUAs, and prevents possible
@ -768,8 +853,8 @@ certificates</a> that use <b>only</b> the anonymous ciphers. This is
enabled by explicitly setting "smtpd_tls_cert_file = none"
and not specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. </p>
<p> Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade
ciphers: </p>
<p> Example, MSA that requires TLSv1 or higher, not SSLv2 or SSLv3,
with high grade ciphers: </p>
<blockquote>
<pre>
@ -779,69 +864,45 @@ ciphers: </p>
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5
smtpd_tls_security_level = encrypt
# Preferred form with Postfix &ge; 2.5:
# Preferred syntax with Postfix &ge; 2.5:
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
# Alternative form.
# Legacy syntax:
smtpd_tls_mandatory_protocols = TLSv1
</pre>
</blockquote>
<p> If you want to take advantage of ciphers with ephemeral Diffie-Hellman
(EDH) key exchange (this offers "forward-secrecy"), DH parameters are
needed. Instead of using the built-in DH parameters for both 1024-bit
(non-export ciphers) and 512-bit (export ciphers), it is better to
generate your own parameters, since otherwise it would "pay" for a
possible attacker to start a brute force attack against parameters that
are used by everybody. Postfix defaults to compiled-in parameters
that are shared by all Postfix users who don't generate their own
settings. </p>
<p> To generate your own set of DH parameters, use: </p>
<blockquote>
<pre>
% <b>openssl gendh -out /etc/postfix/dh_512.pem -2 512</b>
% <b>openssl gendh -out /etc/postfix/dh_1024.pem -2 1024</b>
</pre>
</blockquote>
<p> Support for elliptic curve cryptography is available with Postfix
2.6 and OpenSSL 1.0.0 or later. To enable ephemeral elliptic curve
Diffie-Hellman (EECDH) key-exchange, set "smtpd_tls_eecdh_grade =
strong" or "smtpd_tls_eecdh_grade = ultra". The "ultra" setting is
substantially more CPU intensive, and "strong" is sufficiently
secure for most situations. </p>
<p> Examples: </p>
<blockquote>
<pre>
/etc/postfix/main.cf:
smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
# Postfix &ge; 2.6:
smtpd_tls_eecdh_grade = strong
</pre>
</blockquote>
<p> If you want to take maximal advantage of ciphers that offer <a
href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
started</a> section of <a
href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
full document conveniently presents all information about Postfix
"perfect" forward secrecy support in one place: what forward secrecy
is, how to tweak settings, and what you can expect to see when
Postfix uses ciphers with forward secrecy. </p>
<p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later
allows TLS servers to preempt the TLS client's cipher preference list.
allows TLS servers to preempt the TLS client's cipher-suite preference list.
This is possible only with SSLv3 and later, as in SSLv2 the client
chooses the cipher from a list supplied by the server. </p>
chooses the cipher-suite from a list supplied by the server. </p>
<p> By default, the OpenSSL server selects the client's most preferred
cipher that the server supports. With SSLv3 and later, the server
may choose its own most preferred cipher that is supported (offered)
cipher-suite that the server supports. With SSLv3 and later, the server
may choose its own most preferred cipher-suite that is supported (offered)
by the client. Setting "tls_preempt_cipherlist = yes" enables server
cipher preferences. The default OpenSSL behavior applies with
cipher-suite preferences. The default OpenSSL behavior applies with
"tls_preempt_cipherlist = no". </p>
<p> While server cipher selection may in some cases lead to a more secure
or performant cipher choice, there is some risk of interoperability
issues. In the past, some SSL clients have listed lower priority ciphers
that they did not implement correctly. If the server chooses a cipher
that the client prefers less, it may select a cipher whose client
implementation is flawed. </p>
<p> While server cipher-suite selection may in some cases lead to
a more secure or performant cipher-suite choice, there is some risk
of interoperability issues. In the past, some SSL clients have
listed lower priority ciphers that they did not implement correctly.
If the server chooses a cipher that the client prefers less, it may
select a cipher whose client implementation is flawed. Most notably
Windows 2003 Microsoft Exchange servers have flawed implementations
of DES-CBC3-SHA, which OpenSSL considers stronger than RC4-SHA.
Enabling server cipher-suite selection may create interoperability
issues with Windows 2003 Microsoft Exchange clients. </p>
<h3><a name="server_misc"> Miscellaneous server controls</a> </h3>
@ -872,15 +933,48 @@ an OpenSSL library that could be vulnerable. </p>
<pre>
/etc/postfix/main.cf:
tls_disable_workarounds = 0xFFFFFFFF
tls_disable_workarounds = CVE-2010-4180, LEGACY_SERVER_CONNECT
tls_disable_workarounds = CVE-2010-4180
</pre>
</blockquote>
<p> Note: Disabling LEGACY_SERVER_CONNECT is not wise at this
time, lots of servers are still unpatched and Postfix is <a
href="http://www.postfix.org/wip.html#tls-renegotiation">not
significantly vulnerable</a> to the renegotiation issue in the TLS
protocol. </p>
<p> With Postfix &ge; 2.11, the tls_ssl_options parameter specifies
a list or bit-mask of OpenSSL options to enable. Specify one or
more of the named options below, or a hexadecimal bitmask of options
found in the ssl.h file corresponding to the run-time OpenSSL
library. While it may be reasonable to turn off all bug workarounds
(see above), it is not a good idea to attempt to turn on all features.
</p>
<dl>
<dt><b>LEGACY_SERVER_CONNECT</b></dt> <dd>See SSL_CTX_set_options(3).</dd>
<dt><b>NO_TICKET</b></dt> <dd>See SSL_CTX_set_options(3).</dd>
<dt><b>NO_COMPRESSION</b></dt> <dd>Disable SSL compression even if
supported by the OpenSSL library. Compression is CPU-intensive,
and compression before encryption does not always improve security. </dd>
</dl>
<p> Example: </p>
<blockquote>
<pre>
/etc/postfix/main.cf:
tls_ssl_options = no_ticket, no_compression
</pre>
</blockquote>
<p> You should only enable features via the hexadecimal mask when
the need to control the feature is critical (to deal with a new
vulnerability or a serious interoperability problem). Postfix DOES
NOT promise backwards compatible behavior with respect to the mask
bits. A feature enabled via the mask in one release may be enabled
by other means in a later release, and the mask bit will then be
ignored. Therefore, use of the hexadecimal mask is only a temporary
measure until a new Postfix or OpenSSL release provides a better
solution. </p>
<h2> <a name="client_tls">SMTP Client specific settings</a> </h2>
@ -927,6 +1021,10 @@ in more detail in the sections that follow.</p>
<dd><a href="#client_tls_may">Opportunistic TLS.</a></dd>
<dt><b>encrypt</b></dt>
<dd><a href="#client_tls_encrypt">Mandatory TLS encryption.</a>
<dt><b>dane</b></dt>
<dd><a href="#client_tls_dane">Opportunistic DANE TLS.</a>
<dt><b>dane-only</b></dt>
<dd><a href="#client_tls_dane">Mandatory DANE TLS.</a>
<dt><b>fingerprint</b></dt>
<dd><a href="#client_tls_fprint">Certificate fingerprint verification.</a>
<dt><b>verify</b></dt>
@ -1111,16 +1209,229 @@ just in case the transport table entries are not specified consistently. </p>
</pre>
</blockquote>
<h4><a name="client_tls_dane">DANE TLS authentication.</a> </h4>
<p> The Postfix SMTP client supports two TLS security levels based
on RFC6698 DANE TLSA records. The opportunistic "dane" level and
the mandatory "dane-only" level. </p>
<p> The "dane" level is a stronger form of <a
href="#client_tls_may">opportunistic</a> TLS that is resistant to
man in the middle and downgrade attacks when the destination domain
uses DNSSEC to publish DANE TLSA records for its MX hosts. If a
remote SMTP server has "usable" (see RFC 6698) DANE TLSA records,
the server connection will be authenticated. When DANE authentication
fails, there is no fallback to unauthenticated or plaintext delivery. </p>
<p> If TLSA records are published for a given remote SMTP server
(implying TLS support), but are all "unusable" due to unsupported
parameters or malformed data, the Postfix SMTP client will use <a
href="#client_tls_encrypt">mandatory</a> unauthenticated TLS.
Otherwise, when no TLSA records are published, the Postfix SMTP
client behavior is the same as with <a href="#client_tls_may">may</a>. </p>
<p> TLSA records must be published in DNSSEC validated DNS zones.
Any TLSA records in DNS zones not protected via DNSSEC are ignored.
The Postfix SMTP client will not look for TLSA records associated
with MX hosts whose "A" or "AAAA" records lie in an "insecure" DNS
zone. Such lookups have been observed to cause interoperability
issues with poorly implemented DNS servers, and are in any case not
expected to ever yield "secure" results, since that would require
a very unlikely DLV DNS trust anchor configured between the host
record and the associated "_25._tcp" child TLSA record. </p>
<p> The "dane-only" level is a form of <a
href="#client_tls_secure">secure-channel</a> TLS based on the DANE PKI.
If "usable" TLSA records are present these are used to authenticate the
remote SMTP server. Otherwise, or when server certificate verification
fails, delivery via the server in question tempfails. </p>
<p> At both security levels, the TLS policy for the destination is
obtained via TLSA records validated with DNSSEC. For TLSA policy
to be in effect, the destination domain's containing DNS zone must
be signed and the Postfix SMTP client's operating system must be
configured to send its DNS queries to a recursive DNS nameserver
that is able to validate the signed records. Each MX host's DNS
zone needs to also be signed, and needs to publish DANE TLSA (RFC 6698)
records that specify how that MX host's TLS certificate is to be
verified. </p>
<p> TLSA records do not preempt the normal SMTP MX host
selection algorithm, if some MX hosts support TLSA and others do
not, TLS security will vary from delivery to delivery. It is up
to the domain owner to configure their MX hosts and their DNS
sensibly. To configure the Postfix SMTP client for DNSSEC lookups
see the documentation for the smtp_dns_support_level main.cf
parameter. The tls_dane_trust_anchor_digest_enable main.cf parameter
controls support for trust-anchor digest TLSA records. The
tls_dane_digests and tls_dane_digest_agility parameters control
the list of supported digests and digest downgrade attack resistance.
</p>
<p> DANE for SMTP MTAs deviates in some details from the baseline
DANE protocol in RFC 6698. Most notably, it is not expected that
SMTP MTAs can reasonably include every public CA that a remote SMTP
server's administrator may believe to be well-known. Nor is there
an interactive user to "click OK" when authentication fails. </p>
<p> Therefore, certificate usages "0" and "1" from RFC 6698 which
are intended to "constrain" existing PKI trust, are not supported.
TLSA records with usage "0" are treated as "unusable". TLSA records
with usage "1" are instead treated as "trust assertions" and mapped
to usage "3". Specifically, with certificate usage "1", Postfix
will not require the remote SMTP server's certificate to be trusted
with respect to any locally defined public CAs, it is the domain
owner's responsibility to ensure that the certificate associations
in their TLSA records are appropriate to authenticate their SMTP
servers. </p>
<p> The Postfix SMTP client supports only certificate usages "2"
and "3" (with "1" treated as though it were "3"). See
tls_dane_trust_anchor_digest_enable for usage "2" usability
considerations. Support for certificate usage "1" is an experiment,
it may be withdrawn in the future. Server operators SHOULD NOT
publish TLSA records with usage "1". </p>
<p> When usable TLSA records are obtained for the remote SMTP server
the Postfix SMTP client sends the SNI TLS extension in its SSL
client hello message. This may help the remote SMTP server live
up to its promise to provide a certificate that matches its TLSA
records. </p>
<p> For purposes of protocol and cipher selection, the "dane"
security level is treated like a "mandatory" TLS security level,
and weak ciphers and protocols are disabled. Since DANE authenticates
server certificates the "aNULL" cipher-suites are transparently
excluded at this level, no need to configure this manually. RFC
6698 (DANE) TLS authentication is available with Postfix 2.11 and
later. </p>
<p> When a DANE TLSA record specifies a trust-anchor (TA) certificate
(that is an issuing CA), the strategy used to verify the peername
of the server certificate is unconditionally "nexthop, hostname".
Both the nexthop domain and the hostname obtained from the
DNSSEC-validated MX lookup are safe from forgery and the server
certificate must contain at least one of these names. </p>
<p> When a DANE TLSA record specifies an end-entity (EE) certificate,
(that is the actual server certificate), as with the fingerprint
security level below, no name checks or certificate expiration checks
are applied. The server certificate (or its public key) either matches
the DANE record or not. Server administrators should publish such
EE records in preference to all other types. </p>
<p> The pre-requisites for DANE support in the Postfix SMTP client are: </p>
<ul>
<li> A <i>compile-time</i> OpenSSL library that supports the TLS SNI
extension and "SHA-2" message digests.
<li> A <i>compile-time</i> DNS resolver library that supports DNSSEC.
Postfix binaries built on an older system will not support DNSSEC even
if deployed on a system with an updated resolver library.
<li> The "smtp_dns_support_level" must be set to "dnssec".
<li> The "smtp_host_lookup" parameter must include "dns".
<li> A DNSSEC-validating recursive resolver (see note below).
</ul>
<p> The above client pre-requisites do not apply to the Postfix SMTP server.
It will support DANE provided it supports TLSv1 and its TLSA records are
published in a DNSSEC signed zone. To receive DANE secured mail for multiple
domains, use the same hostname to add the server to each domain's MX
records. There are no plans to implement SNI in the Postfix SMTP server. </p>
<p> Note: The Postfix SMTP client's internal stub DNS resolver is
DNSSEC-aware, but it does not itself validate DNSSEC records, rather
it delegates DNSSEC validation to the operating system's configured
recursive DNS nameserver. The Postfix DNS client relies on a secure
channel to the resolver's cache for DNSSEC integrity, but does not
support TSIG to protect the transmission channel between itself and
the nameserver. Therefore, it is strongly recommended (DANE security
guarantee void otherwise) that each MTA run a local DNSSEC-validating
recursive resolver ("unbound" from nlnetlabs.nl is a reasonable
choice) listening on the loopback interface, and that the system
be configured to use <i>only</i> this local nameserver. The local
nameserver may forward queries to an upstream recursive resolver
on another host if desired. </p>
<p> Note: When the operating system's recursive nameserver is not
local, enabling EDNS0 expanded DNS packet sizes and turning on the
DNSSEC "DO" bit in the DNS request and/or the new DNSSEC-specific
records returned in the nameserver's replies may cause problems
with older or buggy firewall and DNS server implementations.
Therefore, Postfix does not enable DNSSEC by default. Since MX
lookups happen before the security level is determined, DANE support
is disabled for all destinations unless you set "smtp_dns_support_level
= dnssec". To enable DNSSEC lookups selectively, define a new
dedicated transport with a "-o smtp_dns_support_level=dnssec"
override in master.cf and route selected domains to that transport.
If DNSSEC proves to be sufficiently reliable for these domains, you
can enable it for all destinations by changing the global
smtp_dns_support_level in main.cf. </p>
<p><b>Example</b>: "dane" security for selected destinations, with
opportunistic TLS by default. This is the recommended configuration
for early adopters. <p>
<ul>
<li> <p> The "example.com" destination uses DANE, but if TLSA records
are not present or are unusable, mail is deferred. </p>
<li> <p> The "example.org" destination uses DANE if possible, but if no TLSA
records are found opportunistic TLS is used. </p>
</ul>
<blockquote>
<pre>
main.cf:
indexed = ${default_database_type}:${config_directory}/
#
# default: Opportunistic TLS with no DNSSEC lookups.
#
smtp_tls_security_level = may
smtp_dns_support_level = enabled
#
# Per-destination TLS policy
#
smtp_tls_policy_maps = ${indexed}tls_policy
#
# default_transport = smtp, but some destinations are special:
#
transport_maps = ${indexed}transport
</pre>
</blockquote>
<blockquote>
<pre>
transport:
example.com dane
example.org dane
</pre>
</blockquote>
<blockquote>
<pre>
tls_policy:
example.com dane-only
</pre>
</blockquote>
<blockquote>
<pre>
master.cf:
dane unix - - n - - smtp
-o smtp_dns_support_level=dnssec
-o smtp_tls_security_level=dane
</pre>
</blockquote>
<h4><a name="client_tls_fprint"> Certificate fingerprint verification </a> </h4>
<p> Certificate fingerprint verification is available with Postfix
2.5 and later. At this security level ("smtp_tls_security_level =
fingerprint"), no trusted certificate authorities are used or
required. The certificate trust chain, expiration date, ... are
not checked. Instead, the smtp_tls_fingerprint_cert_match parameter
or the "match" attribute in the <a href="#client_tls_policy">policy</a>
table lists the remote SMTP server certificate fingerprint or
public key fingerprint (Postfix 2.9 and later). </p>
<p> At the <i>fingerprint</i> security level, no trusted certificate
authorities are used or required. The certificate trust chain,
expiration date, etc., are not checked. Instead, the
smtp_tls_fingerprint_cert_match parameter or the "match" attribute
in the <a href="#client_tls_policy">policy</a> table lists the
remote SMTP server certificate fingerprint or public key fingerprint.
Certificate fingerprint verification is available with Postfix 2.5
and later, public-key fingerprint support is available with Postfix
2.9 and later. </p>
<p> If certificate fingerprints are exchanged securely, this is the
strongest, and least scalable security level. The administrator needs
@ -1217,7 +1528,7 @@ to Postfix 2.9.6 or later. </p>
<h4><a name="client_tls_verify"> Mandatory server certificate verification </a> </h4>
<p> At the "verify" TLS security level, messages are sent only over
<p> At the <i>verify</i> TLS security level, messages are sent only over
TLS encrypted sessions if the remote SMTP server certificate is
valid (not
expired or revoked, and signed by a trusted certificate authority)
@ -1239,6 +1550,19 @@ DNS names are specified, the certificate CommonName is checked.
If you want mandatory encryption without server certificate
verification, see <a href="#client_tls_encrypt">above</a>. </p>
<p> With Postfix &ge; 2.11 the "smtp_tls_trust_anchor_file" parameter
or more typically the corresponding per-destination "tafile" attribute
optionally modifies trust chain verification. If the parameter is
not empty the root CAs in CAfile and CApath are no longer trusted.
Rather, the Postfix SMTP client will only trust certificate-chains
signed by one of the trust-anchors contained in the chosen files.
The specified trust-anchor certificates and public keys are not
subject to expiration, and need not be (self-signed) root CAs. They
may, if desired, be intermediate certificates. Therefore, these
certificates also may be found "in the middle" of the trust chain
presented by the remote SMTP server, and any untrusted issuing
parent certificates will be ignored. </p>
<p> Despite the potential for eliminating "man-in-the-middle" and other
attacks, mandatory certificate trust chain and subject name verification
is not viable as a default Internet mail delivery policy. Most MX hosts
@ -1300,6 +1624,19 @@ specified, the CommonName is checked. If you want mandatory encryption
without server certificate verification, see <a
href="#client_tls_encrypt">above</a>. </p>
<p> With Postfix &ge; 2.11 the "smtp_tls_trust_anchor_file" parameter
or more typically the corresponding per-destination "tafile" attribute
optionally modifies trust chain verification. If the parameter is
not empty the root CAs in CAfile and CApath are no longer trusted.
Rather, the Postfix SMTP client will only trust certificate-chains
signed by one of the trust-anchors contained in the chosen files.
The specified trust-anchor certificates and public keys are not
subject to expiration, and need not be (self-signed) root CAs. They
may, if desired, be intermediate certificates. Therefore, these
certificates also may be found "in the middle" of the trust chain
presented by the remote SMTP server, and any untrusted issuing
parent certificates will be ignored. </p>
<p> Despite the potential for eliminating "man-in-the-middle" and other
attacks, mandatory secure server certificate verification is not
viable as a default Internet mail delivery policy. Most MX hosts
@ -1412,16 +1749,15 @@ logging level. </p>
<tr> <th> Level </th> <th> Postfix 2.9 and later</th> <th> Earlier
releases. </th> </tr>
<tr> <td valign="top"> 0 </td> <td valign="top"> Log only a summary
message on TLS handshake completion &mdash; no logging of remote
SMTP server certificate trust-chain verification errors if server
certificate verification is not required. </td> <td valign="top">
Disable logging of TLS activity.</td> </tr>
<tr> <td valign="top"> 0 </td> <td valign="top" colspan="2"> Disable
logging of TLS activity. </td> </tr>
<tr> <td valign="top"> 1 </td> <td valign="top"> Also log remote
SMTP server trust-chain verification errors and peer certificate
summary information. </td> <td valign="top"> Also log TLS handshake
and certificate information. </td> </tr>
<tr> <td valign="top"> 1 </td> <td valign="top"> Log only a summary
message on TLS handshake completion &mdash; no logging of remote SMTP
server certificate trust-chain verification errors if server certificate
verification is not required. </td> <td valign="top"> Log the summary
message and unconditionally log trust-chain verification errors.
</td> </tr>
<tr> <td valign="top"> 2 </td> <td valign="top" colspan="2"> Also
log levels during TLS negotiation. </td> </tr>
@ -1636,6 +1972,10 @@ recommends a maximum of 24 hours. </p>
</pre>
</blockquote>
<p> As of Postfix 2.11 this setting cannot exceed 100 days. If set
&le; 0, session caching is disabled. If set to a positive value
less than 2 minutes, the minimum value of 2 minutes is used instead. </p>
<h3><a name="client_tls_limits"> Client TLS limitations </a>
</h3>
@ -1686,14 +2026,22 @@ server has a greater opportunity to mandate client security policy when
it is a dedicated MSA that only handles outbound mail from trusted clients,
below we focus on the client security policy. </p>
<p> On the SMTP client, there are further complications. When delivering
mail to a given domain, in contrast to HTTPS, one rarely uses the domain
name directly as the target host of the SMTP session. More typically,
one uses MX lookups - these are usually unauthenticated - to obtain the domain's SMTP server
hostname(s). When, as is current practice, the client verifies the
insecurely obtained MX hostname, it is subject to a DNS man-in-the-middle
<p> On the SMTP client, there are further complications. When
delivering mail to a given domain, in contrast to HTTPS, one rarely
uses the domain name directly as the target host of the SMTP session.
More typically, one uses MX lookups &mdash; these are usually
unauthenticated &mdash; to obtain the domain's SMTP server hostname(s).
When, as is current practice, the client verifies the insecurely
obtained MX hostname, it is subject to a DNS man-in-the-middle
attack. </p>
<p> Adoption of DNSSEC and RFC6698 (DANE) may gradually (as domains
implement DNSSEC and publish TLSA records for their MX hosts) address
the DNS man-in-the-middle risk and provide scalable key management
for SMTP with TLS. Postfix &ge; 2.11 supports the new <a
href="#client_tls_dane">dane</a> and <a href="#client_tls_dane">dane-only</a>
security levels that take advantage of these standards. </p>
<p> If clients instead attempted to verify the recipient domain name,
an SMTP server for multiple domains would need to
list all its email domain names in its certificate, and generate a
@ -1789,6 +2137,26 @@ main.cf smtp_tls_mandatory_ciphers parameter, and the optional
"exclude" attribute (Postfix &ge; 2.6) overrides the main.cf
smtp_tls_mandatory_exclude_ciphers parameter. </dd>
<dt><b>dane</b></dt> <dd><a href="#client_tls_dane">Opportunistic DANE TLS</a>.
The TLS policy for the destination is obtained via TLSA records in
DNSSEC. If no TLSA records are found, the effective security level
used is <a href="#client_tls_may">may</a>. If TLSA records are
found, but none are usable, the effective security level is <a
href="#client_tls_encrypt">encrypt</a>. When usable TLSA records
are obtained for the remote SMTP server, SSLv2 is automatically
disabled (see smtp_tls_mandatory_protocols), and the server certificate
must match the TLSA records. RFC 6698 (DANE) TLS authentication
and DNSSEC support is available with Postfix 2.11 and later. </dd>
<dt><b>dane-only</b></dt> <dd><a href="#client_tls_dane">Mandatory DANE TLS</a>.
The TLS policy for the destination is obtained via TLSA records in
DNSSEC. If no TLSA records are found, or none are usable, no
connection is made to the server. When usable TLSA records are
obtained for the remote SMTP server, SSLv2 is automatically disabled
(see smtp_tls_mandatory_protocols), and the server certificate must
match the TLSA records. RFC 6698 (DANE) TLS authentication and
DNSSEC support is available with Postfix 2.11 and later. </dd>
<dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate
fingerprint verification.</a> Available with Postfix 2.5 and
later. At this security level, there are no trusted certificate
@ -1806,12 +2174,16 @@ digits. </dd>
<dt><b>verify</b></dt> <dd><a href="#client_tls_verify">Mandatory
server certificate verification</a>. Mail is delivered only if the
TLS handshake
succeeds, if the remote SMTP server certificate can be validated (not
expired or revoked, and signed by a trusted certificate authority), and
if the server certificate name matches the optional "match" attribute (or
the main.cf smtp_tls_verify_cert_match parameter value when no optional
"match" attribute is specified). </dd>
TLS handshake succeeds, if the remote SMTP server certificate can
be validated (not expired or revoked, and signed by a trusted
certificate authority), and if the server certificate name matches
the optional "match" attribute (or the main.cf smtp_tls_verify_cert_match
parameter value when no optional "match" attribute is specified).
With Postfix &ge; 2.11 the "tafile" attribute optionally modifies
trust chain verification in the same manner as the
"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute
may be specified multiple times to load multiple trust-anchor
files. </dd>
<dt><b>secure</b></dt> <dd><a href="#client_tls_secure">Secure certificate
verification.</a> Mail is delivered only if the TLS handshake succeeds,
@ -1819,7 +2191,11 @@ if the remote SMTP server certificate can be validated (not expired
or revoked, and signed by a trusted certificate authority), and if the
server certificate name matches the optional "match" attribute (or the
main.cf smtp_tls_secure_cert_match parameter value when no optional
"match" attribute is specified). </dd>
"match" attribute is specified). With Postfix &ge; 2.11 the "tafile"
attribute optionally modifies trust chain verification in the same manner
as the "smtp_tls_trust_anchor_file" parameter. The "tafile" attribute
may be specified multiple times to load multiple trust-anchor
files. </dd>
</dl>
@ -1869,9 +2245,8 @@ Example:
/etc/postfix/tls_policy:
example.edu none
example.mil may
example.gov encrypt protocols=SSLv3:TLSv1 ciphers=high
example.com verify
match=hostname:dot-nexthop protocols=SSLv3:TLSv1 ciphers=high
example.gov encrypt ciphers=high
example.com verify match=hostname:dot-nexthop ciphers=high
example.net secure
.example.net secure match=.example.net:example.net
[mail.example.org]:587 secure match=nexthop
@ -1985,7 +2360,7 @@ the SSL/TLS protocols used with opportunistic TLS. </p>
smtp_tls_exclude_ciphers = aNULL
# Preferred form with Postfix &ge; 2.5:
smtp_tls_mandatory_protocols = !SSLv2
# Alternative form.
# Legacy form for Postfix &lt; 2.5:
smtp_tls_mandatory_protocols = SSLv3, TLSv1
# Also available with Postfix &ge; 2.6:
smtp_tls_ciphers = export
@ -2084,6 +2459,64 @@ defers delivery if no alternative server is available. </p>
</pre>
</blockquote>
<p> With Postfix 2.8 and later, the tls_disable_workarounds parameter
specifies a list or bit-mask of OpenSSL bug work-arounds to disable. This
may be necessary if one of the work-arounds enabled by default in
OpenSSL proves to pose a security risk, or introduces an unexpected
interoperability issue. Some bug work-arounds known to be problematic
are disabled in the default value of the parameter when linked with
an OpenSSL library that could be vulnerable. </p>
<p> Example: </p>
<blockquote>
<pre>
/etc/postfix/main.cf:
tls_disable_workarounds = 0xFFFFFFFF
tls_disable_workarounds = CVE-2010-4180, LEGACY_SERVER_CONNECT
</pre>
</blockquote>
<p> Note: Disabling LEGACY_SERVER_CONNECT is not wise at this
time, lots of servers are still unpatched and Postfix is <a
href="http://www.postfix.org/wip.html#tls-renegotiation">not
significantly vulnerable</a> to the renegotiation issue in the TLS
protocol. </p>
<p> With Postfix &ge; 2.11, the tls_ssl_options parameter specifies
a list or bit-mask of OpenSSL options to enable. Specify one or
more of the named options below, or a hexadecimal bitmask of options
found in the ssl.h file corresponding to the run-time OpenSSL
library. While it may be reasonable to turn off all bug workarounds
(see above), it is not a good idea to attempt to turn on all features.
</p>
<p> A future version of OpenSSL may by default no longer allow
connections to servers that don't support secure renegotiation.
Since the exposure for SMTP is minimal, and some SMTP servers may
remain unpatched, you can add LEGACY_SERVER_CONNECT to the
options to restore the more permissive default of current OpenSSL
releases. </p>
<p> Example: </p>
<blockquote>
<pre>
/etc/postfix/main.cf:
tls_ssl_options = NO_TICKET, NO_COMPRESSION, LEGACY_SERVER_CONNECT
</pre>
</blockquote>
<p> You should only enable features via the hexadecimal mask when
the need to control the feature is critical (to deal with a new
vulnerability or a serious interoperability problem). Postfix DOES
NOT promise backwards compatible behavior with respect to the mask
bits. A feature enabled via the mask in one release may be enabled
by other means in a later release, and the mask bit will then be
ignored. Therefore, use of the hexadecimal mask is only a temporary
measure until a new Postfix or OpenSSL release provides a better
solution. </p>
<h2><a name="tlsmgr_controls"> TLS manager specific settings </a> </h2>
<p> The security of cryptographic software such as TLS depends

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: cleanup.h,v 1.5 2013/01/02 19:18:33 tron Exp $ */
/* $NetBSD: cleanup.h,v 1.6 2014/07/06 19:45:50 tron Exp $ */
/*++
/* NAME
@ -116,6 +116,7 @@ typedef struct CLEANUP_STATE {
VSTRING *milter_err_text; /* milter call-back reply */
HBC_CHECKS *milter_hbc_checks; /* Milter header checks */
VSTRING *milter_hbc_reply; /* Milter header checks reply */
VSTRING *milter_orcpt_buf; /* add_rcpt_par() orcpt */
/*
* Support for Milter body replacement requests.

View File

@ -1,4 +1,4 @@
/* $NetBSD: dns_lookup.c,v 1.2 2012/07/05 17:40:11 christos Exp $ */
/* $NetBSD: dns_lookup.c,v 1.3 2014/07/06 19:45:50 tron Exp $ */
/*++
/* NAME
@ -33,6 +33,37 @@
/* VSTRING *why;
/* int lflags;
/* unsigned *ltype;
/* AUXILIARY FUNCTIONS
/* int dns_lookup_r(name, type, rflags, list, fqdn, why, rcode)
/* const char *name;
/* unsigned type;
/* unsigned rflags;
/* DNS_RR **list;
/* VSTRING *fqdn;
/* VSTRING *why;
/* int *rcode;
/*
/* int dns_lookup_rl(name, rflags, list, fqdn, why, rcode, lflags,
/* ltype, ...)
/* const char *name;
/* unsigned rflags;
/* DNS_RR **list;
/* VSTRING *fqdn;
/* VSTRING *why;
/* int *rcode;
/* int lflags;
/* unsigned ltype;
/*
/* int dns_lookup_rv(name, rflags, list, fqdn, why, rcode, lflags,
/* ltype)
/* const char *name;
/* unsigned rflags;
/* DNS_RR **list;
/* VSTRING *fqdn;
/* VSTRING *why;
/* int *rcode;
/* int lflags;
/* unsigned *ltype;
/* DESCRIPTION
/* dns_lookup() looks up DNS resource records. When requested to
/* look up data other than type CNAME, it will follow a limited
@ -44,6 +75,9 @@
/*
/* dns_lookup_l() and dns_lookup_v() allow the user to specify
/* a list of resource types.
/*
/* dns_lookup_r(), dns_lookup_rl() and dns_lookup_rv() provide
/* additional information.
/* INPUTS
/* .ad
/* .fi
@ -62,6 +96,10 @@
/* Search local domain and parent domains.
/* .IP RES_DEFNAMES
/* Append local domain to unqualified names.
/* .IP RES_USE_DNSSEC
/* Request DNSSEC validation. This flag is silently ignored
/* when the system stub resolver API, resolver(3), does not
/* implement DNSSEC.
/* .RE
/* .IP lflags
/* Multi-type request control for dns_lookup_l() and dns_lookup_v().
@ -93,6 +131,9 @@
/* name found for \fIname\fR.
/* .IP why
/* A null pointer, or storage for the reason for failure.
/* .IP rcode
/* Pointer to storage for the reply RCODE value. This gives
/* more detailed information than DNS_FAIL, DNS_RETRY, etc.
/* DIAGNOSTICS
/* dns_lookup() returns one of the following codes and sets the
/* \fIwhy\fR argument accordingly:
@ -159,11 +200,13 @@
* Structure to keep track of things while decoding a name server reply.
*/
#define DEF_DNS_REPLY_SIZE 4096 /* in case we're using TCP */
#define MAX_DNS_REPLY_SIZE 32768 /* in case we're using TCP */
#define MAX_DNS_REPLY_SIZE 65536 /* in case we're using TCP */
typedef struct DNS_REPLY {
unsigned char *buf; /* raw reply data */
size_t buf_len; /* reply buffer length */
int rcode; /* unfiltered reply code */
int dnssec_ad; /* DNSSEC AD bit */
int query_count; /* number of queries */
int answer_count; /* number of answers */
unsigned char *query_start; /* start of query data */
@ -229,11 +272,26 @@ static int dns_query(const char *name, int type, int flags,
* Set search options: debugging, parent domain search, append local
* domain. Do not allow the user to control other features.
*/
#define USER_FLAGS (RES_DEBUG | RES_DNSRCH | RES_DEFNAMES)
#define USER_FLAGS (RES_DEBUG | RES_DNSRCH | RES_DEFNAMES | RES_USE_DNSSEC)
if ((flags & USER_FLAGS) != flags)
msg_panic("dns_query: bad flags: %d", flags);
saved_options = (res.options & USER_FLAGS);
/*
* Set extra options that aren't exposed to the application.
*/
#define XTRA_FLAGS (RES_USE_EDNS0)
if (flags & RES_USE_DNSSEC)
flags |= RES_USE_EDNS0;
/*
* Save and restore resolver options that we overwrite, to avoid
* surprising behavior in other code that also invokes the resolver.
*/
#define SAVE_FLAGS (USER_FLAGS | XTRA_FLAGS)
saved_options = (res.options & SAVE_FLAGS);
/*
* Perform the lookup. Claim that the information cannot be found if and
@ -245,6 +303,8 @@ static int dns_query(const char *name, int type, int flags,
len = res_nsearch(&res, name, C_IN, type, reply->buf, reply->buf_len);
res.options &= ~flags;
res.options |= saved_options;
reply_header = (HEADER *) reply->buf;
reply->rcode = reply_header->rcode;
if (len < 0) {
if (why)
vstring_sprintf(why, "Host or domain name not found. "
@ -266,7 +326,6 @@ static int dns_query(const char *name, int type, int flags,
if (msg_verbose)
msg_info("dns_query: %s (%s): OK", name, dns_strtype(type));
reply_header = (HEADER *) reply->buf;
if (reply_header->tc == 0 || reply->buf_len >= MAX_DNS_REPLY_SIZE)
break;
reply->buf = (unsigned char *)
@ -285,8 +344,13 @@ static int dns_query(const char *name, int type, int flags,
/*
* Initialize the reply structure. Some structure members are filled on
* the fly while the reply is being parsed.
* the fly while the reply is being parsed. Coerce AD bit to boolean.
*/
#if RES_USE_DNSSEC != 0
reply->dnssec_ad = (flags & RES_USE_DNSSEC) ? !!reply_header->ad : 0;
#else
reply->dnssec_ad = 0;
#endif
reply->end = reply->buf + len;
reply->query_start = reply->buf + sizeof(HEADER);
reply->answer_start = 0;
@ -387,6 +451,7 @@ static int dns_get_rr(DNS_RR **list, const char *orig_name, DNS_REPLY *reply,
DNS_FIXED *fixed)
{
char temp[DNS_NAME_LEN];
char *tempbuf = temp;
ssize_t data_len;
unsigned pref = 0;
unsigned char *src;
@ -402,6 +467,7 @@ static int dns_get_rr(DNS_RR **list, const char *orig_name, DNS_REPLY *reply,
msg_panic("dns_get_rr: don't know how to extract resource type %s",
dns_strtype(fixed->type));
case T_CNAME:
case T_DNAME:
case T_MB:
case T_MG:
case T_MR:
@ -445,6 +511,11 @@ static int dns_get_rr(DNS_RR **list, const char *orig_name, DNS_REPLY *reply,
data_len = fixed->length;
break;
#endif
/*
* We impose the same length limit here as for DNS names. However,
* see T_TLSA discussion below.
*/
case T_TXT:
data_len = MIN2(pos[0] + 1, MIN2(fixed->length + 1, sizeof(temp)));
for (src = pos + 1, dst = (unsigned char *) (temp);
@ -454,9 +525,24 @@ static int dns_get_rr(DNS_RR **list, const char *orig_name, DNS_REPLY *reply,
}
*dst = 0;
break;
/*
* For a full certificate, fixed->length may be longer than
* sizeof(tmpbuf) == DNS_NAME_LEN. Since we don't need a decode
* buffer, just copy the raw data into the rr.
*
* XXX Reject replies with bogus length < 3.
*
* XXX What about enforcing a sane upper bound? The RFC 1035 hard
* protocol limit is the RRDATA length limit of 65535.
*/
case T_TLSA:
data_len = fixed->length;
tempbuf = (char *) pos;
break;
}
*list = dns_rr_create(orig_name, rr_name, fixed->type, fixed->class,
fixed->ttl, pref, temp, data_len);
fixed->ttl, pref, tempbuf, data_len);
return (DNS_OK);
}
@ -477,7 +563,8 @@ static int dns_get_alias(DNS_REPLY *reply, unsigned char *pos,
/* dns_get_answer - extract answers from name server reply */
static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
DNS_RR **rrlist, VSTRING *fqdn, char *cname, int c_len)
DNS_RR **rrlist, VSTRING *fqdn, char *cname, int c_len,
int *maybe_secure)
{
char rr_name[DNS_NAME_LEN];
unsigned char *pos;
@ -553,6 +640,7 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
if ((status = dns_get_rr(&rr, orig_name, reply, pos, rr_name,
&fixed)) == DNS_OK) {
resource_found++;
rr->dnssec_valid = *maybe_secure ? reply->dnssec_ad : 0;
*rrlist = dns_rr_append(*rrlist, rr);
} else if (not_found_status != DNS_RETRY)
not_found_status = status;
@ -563,6 +651,8 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
if (cname && c_len > 0)
if ((status = dns_get_alias(reply, pos, &fixed, cname, c_len)) != DNS_OK)
CORRUPT(status);
if (!reply->dnssec_ad)
*maybe_secure = 0;
}
pos += fixed.length;
}
@ -579,16 +669,18 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
return (not_found_status);
}
/* dns_lookup - DNS lookup user interface */
/* dns_lookup_r - DNS lookup user interface */
int dns_lookup(const char *name, unsigned type, unsigned flags,
DNS_RR **rrlist, VSTRING *fqdn, VSTRING *why)
int dns_lookup_r(const char *name, unsigned type, unsigned flags,
DNS_RR **rrlist, VSTRING *fqdn, VSTRING *why,
int *rcode)
{
char cname[DNS_NAME_LEN];
int c_len = sizeof(cname);
static DNS_REPLY reply;
int count;
int status;
int maybe_secure = 1; /* Query name presumed secure */
const char *orig_name = name;
/*
@ -624,7 +716,10 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
/*
* Perform the DNS lookup, and pre-parse the name server reply.
*/
if ((status = dns_query(name, type, flags, &reply, why)) != DNS_OK)
status = dns_query(name, type, flags, &reply, why);
if (rcode)
*rcode = reply.rcode;
if (status != DNS_OK)
return (status);
/*
@ -632,7 +727,7 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
* information just in case the requested data is not found.
*/
status = dns_get_answer(orig_name, &reply, type, rrlist, fqdn,
cname, c_len);
cname, c_len, &maybe_secure);
switch (status) {
default:
if (why)
@ -645,6 +740,16 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
case DNS_RECURSE:
if (msg_verbose)
msg_info("dns_lookup: %s aliased to %s", name, cname);
#if RES_USE_DNSSEC
/*
* Once an intermediate CNAME reply is not validated, all
* consequent RRs are deemed not validated, so we don't ask for
* further DNSSEC replies.
*/
if (maybe_secure == 0)
flags &= ~RES_USE_DNSSEC;
#endif
name = cname;
}
}
@ -654,10 +759,11 @@ int dns_lookup(const char *name, unsigned type, unsigned flags,
return (DNS_NOTFOUND);
}
/* dns_lookup_l - DNS lookup interface with types list */
/* dns_lookup_rl - DNS lookup interface with types list */
int dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist,
VSTRING *fqdn, VSTRING *why, int lflags,...)
int dns_lookup_rl(const char *name, unsigned flags, DNS_RR **rrlist,
VSTRING *fqdn, VSTRING *why, int *rcode,
int lflags,...)
{
va_list ap;
unsigned type;
@ -673,8 +779,8 @@ int dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist,
if (msg_verbose)
msg_info("lookup %s type %s flags %d",
name, dns_strtype(type), flags);
status = dns_lookup(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
fqdn, why);
status = dns_lookup_r(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
fqdn, why, rcode);
if (status == DNS_OK) {
non_err = 1;
if (rrlist)
@ -693,11 +799,11 @@ int dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist,
return (non_err ? DNS_OK : soft_err ? DNS_RETRY : status);
}
/* dns_lookup_v - DNS lookup interface with types vector */
/* dns_lookup_rv - DNS lookup interface with types vector */
int dns_lookup_v(const char *name, unsigned flags, DNS_RR **rrlist,
VSTRING *fqdn, VSTRING *why, int lflags,
unsigned *types)
int dns_lookup_rv(const char *name, unsigned flags, DNS_RR **rrlist,
VSTRING *fqdn, VSTRING *why, int *rcode,
int lflags, unsigned *types)
{
unsigned type;
int status = DNS_NOTFOUND;
@ -711,8 +817,8 @@ int dns_lookup_v(const char *name, unsigned flags, DNS_RR **rrlist,
if (msg_verbose)
msg_info("lookup %s type %s flags %d",
name, dns_strtype(type), flags);
status = dns_lookup(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
fqdn, why);
status = dns_lookup_r(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
fqdn, why, rcode);
if (status == DNS_OK) {
non_err = 1;
if (rrlist)

View File

@ -1,4 +1,4 @@
/* $NetBSD: mail_params.h,v 1.11 2013/09/25 19:12:35 tron Exp $ */
/* $NetBSD: mail_params.h,v 1.12 2014/07/06 19:45:50 tron Exp $ */
#ifndef _MAIL_PARAMS_H_INCLUDED_
#define _MAIL_PARAMS_H_INCLUDED_
@ -208,6 +208,16 @@ extern char *var_fallback_relay;
#define DEF_DISABLE_DNS 0
extern bool var_disable_dns;
#define SMTP_DNS_SUPPORT_DISABLED "disabled"
#define SMTP_DNS_SUPPORT_ENABLED "enabled"
#define SMTP_DNS_SUPPORT_DNSSEC "dnssec"
#define VAR_SMTP_DNS_SUPPORT "smtp_dns_support_level"
#define DEF_SMTP_DNS_SUPPORT ""
#define VAR_LMTP_DNS_SUPPORT "lmtp_dns_support_level"
#define DEF_LMTP_DNS_SUPPORT ""
extern char *var_smtp_dns_support;
#define SMTP_HOST_LOOKUP_DNS "dns"
#define SMTP_HOST_LOOKUP_NATIVE "native"
@ -627,13 +637,20 @@ extern bool var_exp_own_alias;
extern bool var_stat_home_dir;
/*
* Queue manager: maximal size of the duplicate expansion filter. By
* Cleanup server: maximal size of the duplicate expansion filter. By
* default, we do graceful degradation with huge mailing lists.
*/
#define VAR_DUP_FILTER_LIMIT "duplicate_filter_limit"
#define DEF_DUP_FILTER_LIMIT 1000
extern int var_dup_filter_limit;
/*
* Transport Layer Security (TLS) protocol support.
*/
#define VAR_TLS_MGR_SERVICE "tlsmgr_service_name"
#define DEF_TLS_MGR_SERVICE "tlsmgr"
extern char *var_tls_mgr_service;
#define VAR_TLS_APPEND_DEF_CA "tls_append_default_CA"
#define DEF_TLS_APPEND_DEF_CA 0 /* Postfix < 2.8 BC break */
extern bool var_tls_append_def_CA;
@ -949,6 +966,12 @@ extern char *var_bestmx_transp;
#define DEF_LMTP_CACHE_CONNT "2s"
extern int var_smtp_cache_conn;
#define VAR_SMTP_REUSE_COUNT "smtp_connection_reuse_count_limit"
#define DEF_SMTP_REUSE_COUNT 0
#define VAR_LMTP_REUSE_COUNT "lmtp_connection_reuse_count_limit"
#define DEF_LMTP_REUSE_COUNT 0
extern int var_smtp_reuse_count;
#define VAR_SMTP_REUSE_TIME "smtp_connection_reuse_time_limit"
#define DEF_SMTP_REUSE_TIME "300s"
#define VAR_LMTP_REUSE_TIME "lmtp_connection_reuse_time_limit"
@ -1306,6 +1329,7 @@ extern bool var_smtpd_tls_received_header;
#define DEF_SMTPD_TLS_SCACHE_DB ""
extern char *var_smtpd_tls_scache_db;
#define MAX_SMTPD_TLS_SCACHETIME 8640000
#define VAR_SMTPD_TLS_SCACHTIME "smtpd_tls_session_cache_timeout"
#define DEF_SMTPD_TLS_SCACHTIME "3600s"
extern int var_smtpd_tls_scache_timeout;
@ -1432,6 +1456,12 @@ extern char *var_smtp_tls_mand_excl;
#define DEF_LMTP_TLS_FPT_DGST "md5"
extern char *var_smtp_tls_fpt_dgst;
#define VAR_SMTP_TLS_TAFILE "smtp_tls_trust_anchor_file"
#define DEF_SMTP_TLS_TAFILE ""
#define VAR_LMTP_TLS_TAFILE "lmtp_tls_trust_anchor_file"
#define DEF_LMTP_TLS_TAFILE ""
extern char *var_smtp_tls_tafile;
#define VAR_SMTP_TLS_LOGLEVEL "smtp_tls_loglevel"
#define DEF_SMTP_TLS_LOGLEVEL "0"
#define VAR_LMTP_TLS_LOGLEVEL "lmtp_tls_loglevel"
@ -1452,8 +1482,10 @@ extern bool var_smtp_tls_note_starttls_offer;
extern char *var_smtp_tls_scache_db;
extern char *var_lmtp_tls_scache_db;
#define MAX_SMTP_TLS_SCACHETIME 8640000
#define VAR_SMTP_TLS_SCACHTIME "smtp_tls_session_cache_timeout"
#define DEF_SMTP_TLS_SCACHTIME "3600s"
#define MAX_LMTP_TLS_SCACHETIME 8640000
#define VAR_LMTP_TLS_SCACHTIME "lmtp_tls_session_cache_timeout"
#define DEF_LMTP_TLS_SCACHTIME "3600s"
extern int var_smtp_tls_scache_timeout;
@ -1505,6 +1537,12 @@ extern char *var_smtp_tls_fpt_cmatch;
#define DEF_LMTP_TLS_BLK_EARLY_MAIL_REPLY 0
extern bool var_smtp_tls_blk_early_mail_reply;
#define VAR_SMTP_TLS_FORCE_TLSA "smtp_tls_force_insecure_host_tlsa_lookup"
#define DEF_SMTP_TLS_FORCE_TLSA 0
#define VAR_LMTP_TLS_FORCE_TLSA "lmtp_tls_force_insecure_host_tlsa_lookup"
#define DEF_LMTP_TLS_FORCE_TLSA 0
extern bool var_smtp_tls_force_tlsa;
/*
* SASL authentication support, SMTP server side.
*/
@ -1524,6 +1562,10 @@ extern char *var_smtpd_sasl_opts;
#define DEF_SMTPD_SASL_PATH "smtpd"
extern char *var_smtpd_sasl_path;
#define VAR_SMTPD_SASL_SERVICE "smtpd_sasl_service"
#define DEF_SMTPD_SASL_SERVICE "smtp"
extern char *var_smtpd_sasl_service;
#define VAR_CYRUS_CONF_PATH "cyrus_sasl_config_path"
#define DEF_CYRUS_CONF_PATH ""
extern char *var_cyrus_conf_path;
@ -1555,6 +1597,8 @@ extern char *var_smtpd_snd_auth_maps;
#define REJECT_SENDER_LOGIN_MISMATCH "reject_sender_login_mismatch"
#define REJECT_AUTH_SENDER_LOGIN_MISMATCH \
"reject_authenticated_sender_login_mismatch"
#define REJECT_KNOWN_SENDER_LOGIN_MISMATCH \
"reject_known_sender_login_mismatch"
#define REJECT_UNAUTH_SENDER_LOGIN_MISMATCH \
"reject_unauthenticated_sender_login_mismatch"
@ -2146,6 +2190,7 @@ extern int var_map_defer_code;
#define CHECK_CLIENT_ACL "check_client_access"
#define CHECK_REVERSE_CLIENT_ACL "check_reverse_client_hostname_access"
#define CHECK_CCERT_ACL "check_ccert_access"
#define CHECK_SASL_ACL "check_sasl_access"
#define CHECK_HELO_ACL "check_helo_access"
#define CHECK_SENDER_ACL "check_sender_access"
#define CHECK_RECIP_ACL "check_recipient_access"
@ -2730,6 +2775,13 @@ extern int var_db_create_buf;
#define DEF_DB_READ_BUF (128 *1024)
extern int var_db_read_buf;
/*
* OpenLDAP LMDB settings.
*/
#define VAR_LMDB_MAP_SIZE "lmdb_map_size"
#define DEF_LMDB_MAP_SIZE (16 * 1024 *1024)
extern long var_lmdb_map_size;
/*
* Named queue file attributes.
*/
@ -3029,6 +3081,10 @@ extern char *var_tls_eecdh_ultra;
#define DEF_TLS_PREEMPT_CLIST 0
extern bool var_tls_preempt_clist;
#define VAR_TLS_MULTI_WILDCARD "tls_wildcard_matches_multiple_labels"
#define DEF_TLS_MULTI_WILDCARD 1
extern bool var_tls_multi_wildcard;
/* The tweak for CVE-2010-4180 is needed in some versions prior to 1.0.1 */
/* The tweak for CVE-2005-2969 is needed in some versions prior to 1.0.0 */
#if defined(USE_TLS) && (OPENSSL_VERSION_NUMBER < 0x1000100fL)
@ -3045,10 +3101,40 @@ extern bool var_tls_preempt_clist;
#define DEF_TLS_BUG_TWEAKS TLS_BUG_TWEAKS
extern char *var_tls_bug_tweaks;
#define VAR_TLS_SSL_OPTIONS "tls_ssl_options"
#define DEF_TLS_SSL_OPTIONS ""
extern char *var_tls_ssl_options;
#define VAR_TLS_BC_PKEY_FPRINT "tls_legacy_public_key_fingerprints"
#define DEF_TLS_BC_PKEY_FPRINT 0
extern bool var_tls_bc_pkey_fprint;
/*
* Ordered list of DANE digest algorithms.
*/
#define TLS_DANE_AGILITY_OFF "off"
#define TLS_DANE_AGILITY_ON "on"
#define TLS_DANE_AGILITY_MAYBE "maybe"
#define VAR_TLS_DANE_AGILITY "tls_dane_digest_agility"
#define DEF_TLS_DANE_AGILITY TLS_DANE_AGILITY_ON
extern char *var_tls_dane_agility;
/*
* Ordered list of DANE digest algorithms.
*/
#define VAR_TLS_DANE_DIGESTS "tls_dane_digests"
#define DEF_TLS_DANE_DIGESTS "sha512 sha256"
extern char *var_tls_dane_digests;
/*
* External interface for enabling trust-anchor digests, which are risky
* when the corresponding certificate is missing from the peer chain (this
* can't happen with the leaf certificate).
*/
#define VAR_TLS_DANE_TAA_DGST "tls_dane_trust_anchor_digest_enable"
#define DEF_TLS_DANE_TAA_DGST 1
extern bool var_tls_dane_taa_dgst;
/*
* Sendmail-style mail filter support.
*/
@ -3339,6 +3425,10 @@ extern char *var_psc_dnsbl_sites;
#define DEF_PSC_DNSBL_THRESH 1
extern int var_psc_dnsbl_thresh;
#define VAR_PSC_DNSBL_WTHRESH "postscreen_dnsbl_whitelist_threshold"
#define DEF_PSC_DNSBL_WTHRESH 0
extern int var_psc_dnsbl_wthresh;
#define VAR_PSC_DNSBL_ENABLE "postscreen_dnsbl_enable"
#define DEF_PSC_DNSBL_ENABLE 0
extern char *var_psc_dnsbl_enable;
@ -3463,8 +3553,10 @@ extern char *var_psc_acl;
#define DEF_PSC_WLIST_IF "static:all"
extern char *var_psc_wlist_if;
#define NOPROXY_PROTO_NAME ""
#define VAR_PSC_UPROXY_PROTO "postscreen_upstream_proxy_protocol"
#define DEF_PSC_UPROXY_PROTO ""
#define DEF_PSC_UPROXY_PROTO NOPROXY_PROTO_NAME
extern char *var_psc_uproxy_proto;
#define VAR_PSC_UPROXY_TMOUT "postscreen_upstream_proxy_timeout"
@ -3594,14 +3686,6 @@ extern char *var_tlsp_tls_loglevel;
#define DEF_TLSP_TLS_RECHEAD "$" VAR_SMTPD_TLS_RECHEAD
extern bool var_tlsp_tls_received_header;
#define VAR_TLSP_TLS_SCACHE_DB "tlsproxy_tls_session_cache_database"
#define DEF_TLSP_TLS_SCACHE_DB "$" VAR_SMTPD_TLS_SCACHE_DB
extern char *var_tlsp_tls_scache_db;
#define VAR_TLSP_TLS_SCACHTIME "tlsproxy_tls_session_cache_timeout"
#define DEF_TLSP_TLS_SCACHTIME "$" VAR_SMTPD_TLS_SCACHTIME
extern int var_tlsp_tls_scache_timeout;
#define VAR_TLSP_TLS_SET_SESSID "tlsproxy_tls_always_issue_session_ids"
#define DEF_TLSP_TLS_SET_SESSID "$" VAR_SMTPD_TLS_SET_SESSID
extern bool var_tlsp_tls_set_sessid;

View File

@ -1,4 +1,4 @@
/* $NetBSD: postconf_master.c,v 1.2 2013/11/14 01:39:26 christos Exp $ */
/* $NetBSD: postconf_master.c,v 1.3 2014/07/06 19:45:50 tron Exp $ */
/*++
/* NAME
@ -8,24 +8,82 @@
/* SYNOPSIS
/* #include <postconf.h>
/*
/* const char daemon_options_expecting_value[];
/* const char pcf_daemon_options_expecting_value[];
/*
/* void read_master(fail_on_open)
/* void pcf_read_master(fail_on_open)
/* int fail_on_open;
/*
/* void show_master(fp, mode, filters)
/* void pcf_show_master_entries(fp, mode, service_filters)
/* VSTREAM *fp;
/* int mode;
/* char **filters;
/* DESCRIPTION
/* read_master() reads entries from master.cf into memory.
/* char **service_filters;
/*
/* show_master() writes the entries in the master.cf file
/* void pcf_show_master_fields(fp, mode, n_filters, field_filters)
/* VSTREAM *fp;
/* int mode;
/* int n_filters;
/* char **field_filters;
/*
/* void pcf_edit_master_field(masterp, field, new_value)
/* PCF_MASTER_ENT *masterp;
/* int field;
/* const char *new_value;
/*
/* void pcf_show_master_params(fp, mode, argc, **param_filters)
/* VSTREAM *fp;
/* int mode;
/* int argc;
/* char **param_filters;
/*
/* void pcf_edit_master_param(masterp, mode, param_name, param_value)
/* PCF_MASTER_ENT *masterp;
/* int mode;
/* const char *param_name;
/* const char *param_value;
/* AUXILIARY FUNCTIONS
/* const char *pcf_parse_master_entry(masterp, buf)
/* PCF_MASTER_ENT *masterp;
/* const char *buf;
/*
/* void pcf_print_master_entry(fp, mode, masterp)
/* VSTREAM *fp;
/* int mode;
/* PCF_MASTER_ENT *masterp;
/*
/* void pcf_free_master_entry(masterp)
/* PCF_MASTER_ENT *masterp;
/* DESCRIPTION
/* pcf_read_master() reads entries from master.cf into memory.
/*
/* pcf_show_master_entries() writes the entries in the master.cf
/* file to the specified stream.
/*
/* pcf_show_master_fields() writes name/type/field=value records
/* to the specified stream.
/*
/* daemon_options_expecting_value[] is an array of master.cf
/* pcf_edit_master_field() updates the value of a single-column
/* or multi-column attribute.
/*
/* pcf_show_master_params() writes name/type/parameter=value
/* records to the specified stream.
/*
/* pcf_edit_master_param() updates, removes or adds the named
/* parameter in a master.cf entry (the remove request ignores
/* the parameter value).
/*
/* pcf_daemon_options_expecting_value[] is an array of master.cf
/* daemon command-line options that expect an option value.
/*
/* pcf_parse_master_entry() parses a (perhaps multi-line)
/* string that contains a complete master.cf entry, and
/* normalizes daemon command-line options to simplify further
/* handling.
/*
/* pcf_print_master_entry() prints a parsed master.cf entry.
/*
/* pcf_free_master_entry() returns storage to the heap that
/* was allocated by pcf_parse_master_entry().
/*
/* Arguments
/* .IP fail_on_open
/* Specify FAIL_ON_OPEN if open failure is a fatal error,
@ -33,12 +91,38 @@
/* .IP fp
/* Output stream.
/* .IP mode
/* If the FOLD_LINE flag is set, show_master() wraps long
/* output lines.
/* .IP filters
/* A list of zero or more expressions in master_service(3)
/* format. If no list is specified, show_master() outputs
/* all master.cf entries in the specified order.
/* Bit-wise OR of flags. Flags other than the following are
/* ignored.
/* .RS
/* .IP PCF_FOLD_LINE
/* Wrap long output lines.
/* .IP PCF_SHOW_EVAL
/* Expand $name in parameter values.
/* .IP PCF_EDIT_EXCL
/* Request that pcf_edit_master_param() removes the parameter.
/* .RE
/* .IP n_filters
/* The number of command-line filters.
/* .IP field_filters
/* A list of zero or more service field patterns (name/type/field).
/* The output is formatted as "name/type/field = value". If
/* no filters are specified, pcf_show_master_fields() outputs
/* the fields of all master.cf entries in the specified order.
/* .IP param_filters
/* A list of zero or more service parameter patterns
/* (name/type/parameter). The output is formatted as
/* "name/type/parameter = value". If no filters are specified,
/* pcf_show_master_params() outputs the parameters of all
/* master.cf entries in sorted order.
/* .IP service_filters
/* A list of zero or more service patterns (name or name/type).
/* If no filters are specified, pcf_show_master_entries()
/* outputs all master.cf entries in the specified order.
/* .IP field
/* Index into parsed master.cf entry.
/* .IP new_value
/* Replacement value for the specified field. It is split in
/* whitespace in case of a multi-field attribute.
/* DIAGNOSTICS
/* Problems are reported to the standard error stream.
/* LICENSE
@ -56,6 +140,8 @@
#include <sys_defs.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
/* Utility library. */
@ -66,23 +152,51 @@
#include <vstream.h>
#include <readlline.h>
#include <stringops.h>
#include <split_at.h>
/* Global library. */
#include <mail_params.h>
#include <match_service.h>
/* Master library. */
#include <master_proto.h>
/* Application-specific. */
#include <postconf.h>
const char daemon_options_expecting_value[] = "o";
const char pcf_daemon_options_expecting_value[] = "o";
/*
* Data structure to capture a command-line service field filter.
*/
typedef struct {
int match_count; /* hit count */
const char *raw_text; /* full pattern text */
ARGV *service_pattern; /* parsed service name, type, ... */
int field_pattern; /* parsed field pattern */
const char *param_pattern; /* parameter pattern */
} PCF_MASTER_FLD_REQ;
/*
* Valid inputs.
*/
static const char *pcf_valid_master_types[] = {
MASTER_XPORT_NAME_UNIX,
MASTER_XPORT_NAME_FIFO,
MASTER_XPORT_NAME_INET,
MASTER_XPORT_NAME_PASS,
0,
};
static const char pcf_valid_bool_types[] = "yn-";
#define STR(x) vstring_str(x)
/* normalize_options - bring options into canonical form */
/* pcf_normalize_options - bring options into canonical form */
static void normalize_options(ARGV *argv)
static void pcf_normalize_options(ARGV *argv)
{
int field;
char *arg;
@ -92,14 +206,14 @@ static void normalize_options(ARGV *argv)
/*
* Normalize options to simplify later processing.
*/
for (field = PC_MASTER_MIN_FIELDS; argv->argv[field] != 0; field++) {
for (field = PCF_MASTER_MIN_FIELDS; argv->argv[field] != 0; field++) {
arg = argv->argv[field];
if (arg[0] != '-' || strcmp(arg, "--") == 0)
break;
for (cp = arg + 1; *cp; cp++) {
if (strchr(daemon_options_expecting_value, *cp) != 0
if (strchr(pcf_daemon_options_expecting_value, *cp) != 0
&& cp > arg + 1) {
/* Split "-stuffo" into "-stuff" and "-o". */
/* Split "-stuffozz" into "-stuff" and "-ozz". */
junk = concatenate("-", cp, (char *) 0);
argv_insert_one(argv, field + 1, junk);
myfree(junk);
@ -107,7 +221,7 @@ static void normalize_options(ARGV *argv)
break;
}
}
if (strchr(daemon_options_expecting_value, arg[1]) == 0)
if (strchr(pcf_daemon_options_expecting_value, arg[1]) == 0)
/* Option requires no value. */
continue;
if (arg[2] != 0) {
@ -122,9 +236,80 @@ static void normalize_options(ARGV *argv)
}
}
/* parse_master_line - parse one master line */
/* pcf_fix_fatal - fix multiline text before release */
static const char *parse_master_line(PC_MASTER_ENT *masterp, const char *buf)
static NORETURN PRINTFLIKE(1, 2) pcf_fix_fatal(const char *fmt,...)
{
VSTRING *buf = vstring_alloc(100);
va_list ap;
/*
* Replace newline with whitespace.
*/
va_start(ap, fmt);
vstring_vsprintf(buf, fmt, ap);
va_end(ap);
translit(STR(buf), "\n", " ");
msg_fatal("%s", STR(buf));
/* NOTREACHED */
}
/* pcf_check_master_entry - sanity check master.cf entry */
static void pcf_check_master_entry(ARGV *argv, const char *raw_text)
{
const char **cpp;
char *cp;
int len;
int field;
cp = argv->argv[PCF_MASTER_FLD_TYPE];
for (cpp = pcf_valid_master_types; /* see below */ ; cpp++) {
if (*cpp == 0)
pcf_fix_fatal("invalid " PCF_MASTER_NAME_TYPE " field \"%s\" in \"%s\"",
cp, raw_text);
if (strcmp(*cpp, cp) == 0)
break;
}
for (field = PCF_MASTER_FLD_PRIVATE; field <= PCF_MASTER_FLD_CHROOT; field++) {
cp = argv->argv[field];
if (cp[1] != 0 || strchr(pcf_valid_bool_types, *cp) == 0)
pcf_fix_fatal("invalid %s field \%s\" in \"%s\"",
pcf_str_field_pattern(field), cp, raw_text);
}
cp = argv->argv[PCF_MASTER_FLD_WAKEUP];
len = strlen(cp);
if (len > 0 && cp[len - 1] == '?')
len--;
if (!(cp[0] == '-' && len == 1) && strspn(cp, "0123456789") != len)
pcf_fix_fatal("invalid " PCF_MASTER_NAME_WAKEUP " field \%s\" in \"%s\"",
cp, raw_text);
cp = argv->argv[PCF_MASTER_FLD_MAXPROC];
if (strcmp("-", cp) != 0 && cp[strspn(cp, "0123456789")] != 0)
pcf_fix_fatal("invalid " PCF_MASTER_NAME_MAXPROC " field \%s\" in \"%s\"",
cp, raw_text);
}
/* pcf_free_master_entry - destroy parsed entry */
void pcf_free_master_entry(PCF_MASTER_ENT *masterp)
{
/* XX Fixme: allocation/deallocation asymmetry. */
myfree(masterp->name_space);
argv_free(masterp->argv);
if (masterp->valid_names)
htable_free(masterp->valid_names, myfree);
if (masterp->all_params)
dict_free(masterp->all_params);
myfree((char *) masterp);
}
/* pcf_parse_master_entry - parse one master line */
const char *pcf_parse_master_entry(PCF_MASTER_ENT *masterp, const char *buf)
{
ARGV *argv;
@ -136,28 +321,29 @@ static const char *parse_master_line(PC_MASTER_ENT *masterp, const char *buf)
* The postconf command needs to show default fields as "-", and needs to
* know about all service names so that it can generate service-dependent
* parameter names (transport-dependent etc.).
*
* XXX Do per-field sanity checks.
*/
#define MASTER_BLANKS " \t\r\n" /* XXX */
argv = argv_split(buf, MASTER_BLANKS);
if (argv->argc < PC_MASTER_MIN_FIELDS) {
argv_free(argv);
argv = argv_split(buf, PCF_MASTER_BLANKS);
if (argv->argc < PCF_MASTER_MIN_FIELDS) {
argv_free(argv); /* Coverity 201311 */
return ("bad field count");
}
normalize_options(argv);
pcf_check_master_entry(argv, buf);
pcf_normalize_options(argv);
masterp->name_space =
concatenate(argv->argv[0], ".", argv->argv[1], (char *) 0);
concatenate(argv->argv[0], PCF_NAMESP_SEP_STR, argv->argv[1], (char *) 0);
masterp->argv = argv;
masterp->valid_names = 0;
masterp->all_params = 0;
return (0);
}
/* read_master - read and digest the master.cf file */
/* pcf_read_master - read and digest the master.cf file */
void read_master(int fail_on_open_error)
void pcf_read_master(int fail_on_open_error)
{
const char *myname = "read_master";
const char *myname = "pcf_read_master";
char *path;
VSTRING *buf;
VSTREAM *fp;
@ -168,20 +354,20 @@ void read_master(int fail_on_open_error)
/*
* Sanity check.
*/
if (master_table != 0)
if (pcf_master_table != 0)
msg_panic("%s: master table is already initialized", myname);
/*
* Get the location of master.cf.
*/
if (var_config_dir == 0)
set_config_dir();
pcf_set_config_dir();
path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
/*
* Initialize the in-memory master table.
*/
master_table = (PC_MASTER_ENT *) mymalloc(sizeof(*master_table));
pcf_master_table = (PCF_MASTER_ENT *) mymalloc(sizeof(*pcf_master_table));
/*
* Skip blank lines and comment lines. Degrade gracefully if master.cf is
@ -194,10 +380,10 @@ void read_master(int fail_on_open_error)
} else {
buf = vstring_alloc(100);
while (readlline(buf, fp, &line_count) != 0) {
master_table = (PC_MASTER_ENT *) myrealloc((char *) master_table,
(entry_count + 2) * sizeof(*master_table));
if ((err = parse_master_line(master_table + entry_count,
STR(buf))) != 0)
pcf_master_table = (PCF_MASTER_ENT *) myrealloc((char *) pcf_master_table,
(entry_count + 2) * sizeof(*pcf_master_table));
if ((err = pcf_parse_master_entry(pcf_master_table + entry_count,
STR(buf))) != 0)
msg_fatal("file %s: line %d: %s", path, line_count, err);
entry_count += 1;
}
@ -208,13 +394,13 @@ void read_master(int fail_on_open_error)
/*
* Null-terminate the master table and clean up.
*/
master_table[entry_count].argv = 0;
pcf_master_table[entry_count].argv = 0;
myfree(path);
}
/* print_master_line - print one master line */
/* pcf_print_master_entry - print one master line */
static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
void pcf_print_master_entry(VSTREAM *fp, int mode, PCF_MASTER_ENT *masterp)
{
char **argv = masterp->argv->argv;
const char *arg;
@ -243,7 +429,7 @@ static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
* Show the standard fields at their preferred column position. Use at
* least one-space column separation.
*/
for (line_len = 0, field = 0; field < PC_MASTER_MIN_FIELDS; field++) {
for (line_len = 0, field = 0; field < PCF_MASTER_MIN_FIELDS; field++) {
arg = argv[field];
if (line_len > 0) {
do {
@ -270,26 +456,29 @@ static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
*/
if (arg[0] != '-' || strcmp(arg, "--") == 0) {
in_daemon_options = 0;
if ((mode & FOLD_LINE)
&& line_len > column_goal[PC_MASTER_MIN_FIELDS - 1]) {
#if 0
if (mode & PCF_FOLD_LINE)
/* Force line wrap. */
line_len = LINE_LIMIT;
}
line_len = PCF_LINE_LIMIT;
#endif
}
/*
* Special processing for options that require a value.
*/
else if (strchr(daemon_options_expecting_value, arg[1]) != 0
else if (strchr(pcf_daemon_options_expecting_value, arg[1]) != 0
&& (aval = argv[field + 1]) != 0) {
/* Force line wrap before option with value. */
line_len = PCF_LINE_LIMIT;
/*
* Optionally, expand $name in parameter value.
*/
if (strcmp(arg, "-o") == 0
&& (mode & SHOW_EVAL) != 0)
aval = expand_parameter_value((VSTRING *) 0, mode,
aval, masterp);
&& (mode & PCF_SHOW_EVAL) != 0)
aval = pcf_expand_parameter_value((VSTRING *) 0, mode,
aval, masterp);
/*
* Keep option and value on the same line.
@ -301,13 +490,13 @@ static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
/*
* Insert a line break when the next item won't fit.
*/
if (line_len > INDENT_LEN) {
if ((mode & FOLD_LINE) == 0
|| line_len + 1 + arg_len < LINE_LIMIT) {
if (line_len > PCF_INDENT_LEN) {
if ((mode & PCF_FOLD_LINE) == 0
|| line_len + 1 + arg_len < PCF_LINE_LIMIT) {
ADD_SPACE;
} else {
vstream_fputs("\n" INDENT_TEXT, fp);
line_len = INDENT_LEN;
vstream_fputs("\n" PCF_INDENT_TEXT, fp);
line_len = PCF_INDENT_LEN;
}
}
ADD_TEXT(arg, strlen(arg));
@ -315,36 +504,500 @@ static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
ADD_SPACE;
ADD_TEXT(aval, strlen(aval));
field += 1;
/* Force line wrap after option with value. */
line_len = PCF_LINE_LIMIT;
}
}
vstream_fputs("\n", fp);
if (msg_verbose)
vstream_fflush(fp);
}
/* show_master - show master.cf entries */
/* pcf_show_master_entries - show master.cf entries */
void show_master(VSTREAM *fp, int mode, char **filters)
void pcf_show_master_entries(VSTREAM *fp, int mode, int argc, char **argv)
{
PC_MASTER_ENT *masterp;
ARGV *service_filter = 0;
PCF_MASTER_ENT *masterp;
PCF_MASTER_FLD_REQ *field_reqs;
PCF_MASTER_FLD_REQ *req;
/*
* Initialize the service filter.
* Parse the filter expressions.
*/
if (filters[0])
service_filter = match_service_init_argv(filters);
if (argc > 0) {
field_reqs = (PCF_MASTER_FLD_REQ *)
mymalloc(sizeof(*field_reqs) * argc);
for (req = field_reqs; req < field_reqs + argc; req++) {
req->match_count = 0;
req->raw_text = *argv++;
req->service_pattern =
pcf_parse_service_pattern(req->raw_text, 1, 2);
if (req->service_pattern == 0)
msg_fatal("-M option requires service_name[/type]");
}
}
/*
* Iterate over the master table.
*/
for (masterp = master_table; masterp->argv != 0; masterp++)
if ((service_filter == 0
|| match_service_match(service_filter, masterp->name_space))
&& ((mode & SHOW_NONDEF) == 0 || masterp->all_params != 0))
print_master_line(fp, mode, masterp);
for (masterp = pcf_master_table; masterp->argv != 0; masterp++) {
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (PCF_MATCH_SERVICE_PATTERN(req->service_pattern,
masterp->argv->argv[0],
masterp->argv->argv[1])) {
req->match_count++;
pcf_print_master_entry(fp, mode, masterp);
}
}
} else {
pcf_print_master_entry(fp, mode, masterp);
}
}
/*
* Cleanup.
*/
if (service_filter != 0)
argv_free(service_filter);
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (req->match_count == 0)
msg_warn("unmatched request: \"%s\"", req->raw_text);
argv_free(req->service_pattern);
}
myfree((char *) field_reqs);
}
}
/* pcf_print_master_field - scaffolding */
static void pcf_print_master_field(VSTREAM *fp, int mode,
PCF_MASTER_ENT *masterp,
int field)
{
char **argv = masterp->argv->argv;
const char *arg;
const char *aval;
int arg_len;
int line_len;
int in_daemon_options;
/*
* Show the field value, or the first value in the case of a multi-column
* field.
*/
#define ADD_CHAR(ch) ADD_TEXT((ch), 1)
line_len = 0;
if ((mode & PCF_HIDE_NAME) == 0) {
ADD_TEXT(argv[0], strlen(argv[0]));
ADD_CHAR(PCF_NAMESP_SEP_STR);
ADD_TEXT(argv[1], strlen(argv[1]));
ADD_CHAR(PCF_NAMESP_SEP_STR);
ADD_TEXT(pcf_str_field_pattern(field), strlen(pcf_str_field_pattern(field)));
ADD_TEXT(" = ", 3);
if (line_len + strlen(argv[field]) > PCF_LINE_LIMIT) {
vstream_fputs("\n" PCF_INDENT_TEXT, fp);
line_len = PCF_INDENT_LEN;
}
}
ADD_TEXT(argv[field], strlen(argv[field]));
/*
* Format the daemon command-line options and non-option arguments. Here,
* we have no data-dependent preference for column positions, but we do
* have argument grouping preferences.
*/
if (field == PCF_MASTER_FLD_CMD) {
in_daemon_options = 1;
for (field += 1; (arg = argv[field]) != 0; field++) {
arg_len = strlen(arg);
aval = 0;
if (in_daemon_options) {
/*
* We make no special case for generic options (-v -D)
* options.
*/
if (arg[0] != '-' || strcmp(arg, "--") == 0) {
in_daemon_options = 0;
} else if (strchr(pcf_daemon_options_expecting_value, arg[1]) != 0
&& (aval = argv[field + 1]) != 0) {
/* Force line break before option with value. */
line_len = PCF_LINE_LIMIT;
/*
* Optionally, expand $name in parameter value.
*/
if (strcmp(arg, "-o") == 0
&& (mode & PCF_SHOW_EVAL) != 0)
aval = pcf_expand_parameter_value((VSTRING *) 0, mode,
aval, masterp);
/*
* Keep option and value on the same line.
*/
arg_len += strlen(aval) + 1;
}
}
/*
* Insert a line break when the next item won't fit.
*/
if (line_len > PCF_INDENT_LEN) {
if ((mode & PCF_FOLD_LINE) == 0
|| line_len + 1 + arg_len < PCF_LINE_LIMIT) {
ADD_SPACE;
} else {
vstream_fputs("\n" PCF_INDENT_TEXT, fp);
line_len = PCF_INDENT_LEN;
}
}
ADD_TEXT(arg, strlen(arg));
if (aval) {
ADD_SPACE;
ADD_TEXT(aval, strlen(aval));
field += 1;
/* Force line break after option with value. */
line_len = PCF_LINE_LIMIT;
}
}
}
vstream_fputs("\n", fp);
if (msg_verbose)
vstream_fflush(fp);
}
/* pcf_show_master_fields - show master.cf fields */
void pcf_show_master_fields(VSTREAM *fp, int mode, int argc, char **argv)
{
const char *myname = "pcf_show_master_fields";
PCF_MASTER_ENT *masterp;
PCF_MASTER_FLD_REQ *field_reqs;
PCF_MASTER_FLD_REQ *req;
int field;
/*
* Parse the filter expressions.
*/
if (argc > 0) {
field_reqs = (PCF_MASTER_FLD_REQ *)
mymalloc(sizeof(*field_reqs) * argc);
for (req = field_reqs; req < field_reqs + argc; req++) {
req->match_count = 0;
req->raw_text = *argv++;
req->service_pattern =
pcf_parse_service_pattern(req->raw_text, 1, 3);
if (req->service_pattern == 0)
msg_fatal("-F option requires service_name[/type[/field]]");
field = req->field_pattern =
pcf_parse_field_pattern(req->service_pattern->argv[2]);
if (pcf_is_magic_field_pattern(field) == 0
&& (field < 0 || field > PCF_MASTER_FLD_CMD))
msg_panic("%s: bad attribute field index: %d",
myname, field);
}
}
/*
* Iterate over the master table.
*/
for (masterp = pcf_master_table; masterp->argv != 0; masterp++) {
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (PCF_MATCH_SERVICE_PATTERN(req->service_pattern,
masterp->argv->argv[0],
masterp->argv->argv[1])) {
req->match_count++;
field = req->field_pattern;
if (pcf_is_magic_field_pattern(field)) {
for (field = 0; field <= PCF_MASTER_FLD_CMD; field++)
pcf_print_master_field(fp, mode, masterp, field);
} else {
pcf_print_master_field(fp, mode, masterp, field);
}
}
}
} else {
for (field = 0; field <= PCF_MASTER_FLD_CMD; field++)
pcf_print_master_field(fp, mode, masterp, field);
}
}
/*
* Cleanup.
*/
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (req->match_count == 0)
msg_warn("unmatched request: \"%s\"", req->raw_text);
argv_free(req->service_pattern);
}
myfree((char *) field_reqs);
}
}
/* pcf_edit_master_field - replace master.cf field value. */
void pcf_edit_master_field(PCF_MASTER_ENT *masterp, int field,
const char *new_value)
{
/*
* Replace multi-column attribute.
*/
if (field == PCF_MASTER_FLD_CMD) {
argv_truncate(masterp->argv, PCF_MASTER_FLD_CMD);
argv_split_append(masterp->argv, new_value, PCF_MASTER_BLANKS);
}
/*
* Replace single-column attribute.
*/
else {
argv_replace_one(masterp->argv, field, new_value);
}
/*
* Do per-field sanity checks.
*/
pcf_check_master_entry(masterp->argv, new_value);
}
/* pcf_print_master_param - scaffolding */
static void pcf_print_master_param(VSTREAM *fp, int mode,
PCF_MASTER_ENT *masterp,
const char *param_name,
const char *param_value)
{
if ((mode & PCF_SHOW_EVAL) != 0)
param_value = pcf_expand_parameter_value((VSTRING *) 0, mode,
param_value, masterp);
if ((mode & PCF_HIDE_NAME) == 0) {
pcf_print_line(fp, mode, "%s%c%s = %s\n",
masterp->name_space, PCF_NAMESP_SEP_CH,
param_name, param_value);
} else {
pcf_print_line(fp, mode, "%s\n", param_value);
}
if (msg_verbose)
vstream_fflush(fp);
}
/* pcf_sort_argv_cb - sort argv call-back */
static int pcf_sort_argv_cb(const void *a, const void *b)
{
return (strcmp(*(char **) a, *(char **) b));
}
/* pcf_show_master_any_param - show any parameter in master.cf service entry */
static void pcf_show_master_any_param(VSTREAM *fp, int mode,
PCF_MASTER_ENT *masterp)
{
const char *myname = "pcf_show_master_any_param";
ARGV *argv = argv_alloc(10);
DICT *dict = masterp->all_params;
const char *param_name;
const char *param_value;
int param_count = 0;
int how;
char **cpp;
/*
* Print parameters in sorted order. The number of parameters per
* master.cf entry is small, so we optmiize for code simplicity and don't
* worry about the cost of double lookup.
*/
/* Look up the parameter names and ignore the values. */
for (how = DICT_SEQ_FUN_FIRST;
dict->sequence(dict, how, &param_name, &param_value) == 0;
how = DICT_SEQ_FUN_NEXT) {
argv_add(argv, param_name, ARGV_END);
param_count++;
}
/* Print the parameters in sorted order. */
qsort(argv->argv, param_count, sizeof(argv->argv[0]), pcf_sort_argv_cb);
for (cpp = argv->argv; (param_name = *cpp) != 0; cpp++) {
if ((param_value = dict_get(dict, param_name)) == 0)
msg_panic("%s: parameter name not found: %s", myname, param_name);
pcf_print_master_param(fp, mode, masterp, param_name, param_value);
}
/*
* Clean up.
*/
argv_free(argv);
}
/* pcf_show_master_params - show master.cf params */
void pcf_show_master_params(VSTREAM *fp, int mode, int argc, char **argv)
{
PCF_MASTER_ENT *masterp;
PCF_MASTER_FLD_REQ *field_reqs;
PCF_MASTER_FLD_REQ *req;
DICT *dict;
const char *param_value;
/*
* Parse the filter expressions.
*/
if (argc > 0) {
field_reqs = (PCF_MASTER_FLD_REQ *)
mymalloc(sizeof(*field_reqs) * argc);
for (req = field_reqs; req < field_reqs + argc; req++) {
req->match_count = 0;
req->raw_text = *argv++;
req->service_pattern =
pcf_parse_service_pattern(req->raw_text, 1, 3);
if (req->service_pattern == 0)
msg_fatal("-P option requires service_name[/type[/parameter]]");
req->param_pattern = req->service_pattern->argv[2];
}
}
/*
* Iterate over the master table.
*/
for (masterp = pcf_master_table; masterp->argv != 0; masterp++) {
if ((dict = masterp->all_params) != 0) {
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (PCF_MATCH_SERVICE_PATTERN(req->service_pattern,
masterp->argv->argv[0],
masterp->argv->argv[1])) {
if (PCF_IS_MAGIC_PARAM_PATTERN(req->param_pattern)) {
pcf_show_master_any_param(fp, mode, masterp);
req->match_count += 1;
} else if ((param_value = dict_get(dict,
req->param_pattern)) != 0) {
pcf_print_master_param(fp, mode, masterp,
req->param_pattern,
param_value);
req->match_count += 1;
}
}
}
} else {
pcf_show_master_any_param(fp, mode, masterp);
}
}
}
/*
* Cleanup.
*/
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (req->match_count == 0)
msg_warn("unmatched request: \"%s\"", req->raw_text);
argv_free(req->service_pattern);
}
myfree((char *) field_reqs);
}
}
/* pcf_edit_master_param - update, add or remove -o parameter=value */
void pcf_edit_master_param(PCF_MASTER_ENT *masterp, int mode,
const char *param_name,
const char *param_value)
{
const char *myname = "pcf_edit_master_param";
ARGV *argv = masterp->argv;
const char *arg;
const char *aval;
int param_match = 0;
int name_len = strlen(param_name);
int field;
for (field = PCF_MASTER_MIN_FIELDS; argv->argv[field] != 0; field++) {
arg = argv->argv[field];
/*
* Stop at the first non-option argument or end-of-list.
*/
if (arg[0] != '-' || strcmp(arg, "--") == 0) {
break;
}
/*
* Zoom in on command-line options with a value.
*/
else if (strchr(pcf_daemon_options_expecting_value, arg[1]) != 0
&& (aval = argv->argv[field + 1]) != 0) {
/*
* Zoom in on "-o parameter=value".
*/
if (strcmp(arg, "-o") == 0) {
if (strncmp(aval, param_name, name_len) == 0
&& aval[name_len] == '=') {
param_match = 1;
switch (mode & (PCF_EDIT_CONF | PCF_EDIT_EXCL)) {
/*
* Update parameter=value.
*/
case PCF_EDIT_CONF:
aval = concatenate(param_name, "=",
param_value, (char *) 0);
argv_replace_one(argv, field + 1, aval);
myfree((char *) aval);
if (masterp->all_params)
dict_put(masterp->all_params, param_name, param_value);
/* XXX Update parameter "used/defined" status. */
break;
/*
* Delete parameter=value.
*/
case PCF_EDIT_EXCL:
argv_delete(argv, field, 2);
if (masterp->all_params)
dict_del(masterp->all_params, param_name);
/* XXX Update parameter "used/defined" status. */
field -= 2;
break;
default:
msg_panic("%s: unexpected mode: %d", myname, mode);
}
}
}
/*
* Skip over the command-line option value.
*/
field += 1;
}
}
/*
* Add unmatched parameter.
*/
if ((mode & PCF_EDIT_CONF) && param_match == 0) {
/* XXX Generalize: argv_insert(argv, where, list...) */
argv_insert_one(argv, field, "-o");
aval = concatenate(param_name, "=",
param_value, (char *) 0);
argv_insert_one(argv, field + 1, aval);
if (masterp->all_params)
dict_put(masterp->all_params, param_name, param_value);
/* XXX May affect parameter "used/defined" status. */
myfree((char *) aval);
param_match = 1;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtp.c,v 1.7 2013/09/25 19:12:35 tron Exp $ */
/* $NetBSD: smtp.c,v 1.8 2014/07/06 19:45:50 tron Exp $ */
/*++
/* NAME
@ -63,7 +63,7 @@
/* \fIpathname\fR. If the process runs chrooted, an absolute pathname
/* is interpreted relative to the Postfix queue directory.
/* .IP \fBinet\fR:\fIhostname\fR
/* .IP \fBinet\fB:\fIhostname\fR:\fIport\fR
/* .IP \fBinet\fR:\fIhostname\fR:\fIport\fR
/* .IP \fBinet\fR:[\fIaddress\fR]
/* .IP \fBinet\fR:[\fIaddress\fR]:\fIport\fR
/* Connect to the specified TCP port on the specified local or
@ -171,9 +171,7 @@
/* A mechanism to transform replies from remote SMTP servers one
/* line at a time.
/* .IP "\fBsmtp_skip_5xx_greeting (yes)\fR"
/* Skip remote SMTP servers that greet with a 5XX status code (go away,
/* do
/* not try again later).
/* Skip remote SMTP servers that greet with a 5XX status code.
/* .IP "\fBsmtp_skip_quit_response (yes)\fR"
/* Do not wait for the response to the SMTP QUIT command.
/* .PP
@ -251,6 +249,10 @@
/* .IP "\fBsmtp_send_dummy_mail_auth (no)\fR"
/* Whether or not to append the "AUTH=<>" option to the MAIL
/* FROM command in SASL-authenticated SMTP sessions.
/* .PP
/* Available in Postfix version 2.11 and later:
/* .IP "\fBsmtp_dns_support_level (empty)\fR"
/* Level of DNS support in the Postfix SMTP client.
/* MIME PROCESSING CONTROLS
/* .ad
/* .fi
@ -378,8 +380,7 @@
/* The verification depth for remote SMTP server certificates.
/* .IP "\fBsmtp_tls_secure_cert_match (nexthop, dot-nexthop)\fR"
/* How the Postfix SMTP client verifies the server certificate
/* peername for the
/* "secure" TLS security level.
/* peername for the "secure" TLS security level.
/* .IP "\fBsmtp_tls_session_cache_database (empty)\fR"
/* Name of the file containing the optional Postfix SMTP client
/* TLS session cache.
@ -442,6 +443,18 @@
/* Available in Postfix version 2.8 and later:
/* .IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR"
/* List or bit-mask of OpenSSL bug work-arounds to disable.
/* .PP
/* Available in Postfix version 2.11 and later:
/* .IP "\fBsmtp_tls_trust_anchor_file (empty)\fR"
/* Zero or more PEM-format files with trust-anchor certificates
/* and/or public keys.
/* .IP "\fBsmtp_tls_force_insecure_host_tlsa_lookup (no)\fR"
/* Lookup the associated DANE TLSA RRset even when a hostname is
/* not an alias and its address records lie in an unsigned zone.
/* .IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR"
/* RFC 6698 trust-anchor digest support in the Postfix TLS library.
/* .IP "\fBtlsmgr_service_name (tlsmgr)\fR"
/* The name of the \fBtlsmgr\fR(8) service entry in master.cf.
/* OBSOLETE STARTTLS CONTROLS
/* .ad
/* .fi
@ -547,6 +560,12 @@
/* time limit per read or write system call, to a time limit to send
/* or receive a complete record (an SMTP command line, SMTP response
/* line, SMTP message content line, or TLS protocol message).
/* .PP
/* Available in Postfix version 2.11 and later:
/* .IP "\fBsmtp_connection_reuse_count_limit (0)\fR"
/* When SMTP connection caching is enabled, the number of times
/* that an SMTP session may be reused before it is closed, or zero (no
/* limit).
/* TROUBLE SHOOTING CONTROLS
/* .ad
/* .fi
@ -628,8 +647,8 @@
/* .IP "\fBlmtp_lhlo_name ($myhostname)\fR"
/* The hostname to send in the LMTP LHLO command.
/* .IP "\fBsmtp_host_lookup (dns)\fR"
/* What mechanisms the Postfix SMTP client uses to look up a host's IP
/* address.
/* What mechanisms the Postfix SMTP client uses to look up a host's
/* IP address.
/* .IP "\fBsmtp_randomize_addresses (yes)\fR"
/* Randomize the order of equal-preference MX host addresses.
/* .IP "\fBsyslog_facility (mail)\fR"
@ -791,6 +810,7 @@ int var_smtp_mxaddr_limit;
int var_smtp_mxsess_limit;
int var_smtp_cache_conn;
int var_smtp_reuse_time;
int var_smtp_reuse_count;
char *var_smtp_cache_dest;
char *var_scache_service; /* You can now leave this here. */
bool var_smtp_cache_demand;
@ -826,11 +846,13 @@ int var_smtp_tls_scert_vd;
char *var_smtp_tls_vfy_cmatch;
char *var_smtp_tls_fpt_cmatch;
char *var_smtp_tls_fpt_dgst;
char *var_smtp_tls_tafile;
char *var_smtp_tls_proto;
char *var_smtp_tls_ciph;
char *var_smtp_tls_eccert_file;
char *var_smtp_tls_eckey_file;
bool var_smtp_tls_blk_early_mail_reply;
bool var_smtp_tls_force_tlsa;
#endif
@ -850,6 +872,7 @@ char *var_smtp_body_chks;
char *var_smtp_resp_filter;
bool var_lmtp_assume_final;
char *var_smtp_dns_res_opt;
char *var_smtp_dns_support;
bool var_smtp_rec_deadline;
bool var_smtp_dummy_mail_auth;
@ -861,7 +884,9 @@ bool var_smtp_sasl_auth_soft_bounce;
/*
* Global variables.
*/
int smtp_mode;
int smtp_host_lookup_mask;
int smtp_dns_support;
STRING_LIST *smtp_cache_dest;
SCACHE *smtp_scache;
MAPS *smtp_ehlo_dis_maps;
@ -975,18 +1000,39 @@ static void post_init(char *unused_name, char **unused_argv)
SMTP_DNS_RES_OPT_DNSRCH, RES_DNSRCH,
0,
};
static const NAME_CODE dns_support[] = {
SMTP_DNS_SUPPORT_DISABLED, SMTP_DNS_DISABLED,
SMTP_DNS_SUPPORT_ENABLED, SMTP_DNS_ENABLED,
#if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
SMTP_DNS_SUPPORT_DNSSEC, SMTP_DNS_DNSSEC,
#endif
0, SMTP_DNS_INVALID,
};
if (*var_smtp_dns_support == 0) {
/* Backwards compatible empty setting */
smtp_dns_support =
var_disable_dns ? SMTP_DNS_DISABLED : SMTP_DNS_ENABLED;
} else {
smtp_dns_support =
name_code(dns_support, NAME_CODE_FLAG_NONE, var_smtp_dns_support);
if (smtp_dns_support == SMTP_DNS_INVALID)
msg_fatal("invalid %s: \"%s\"", SMTP_X(DNS_SUPPORT),
var_smtp_dns_support);
var_disable_dns = (smtp_dns_support == SMTP_DNS_DISABLED);
}
/*
* Select hostname lookup mechanisms.
*/
if (var_disable_dns)
if (smtp_dns_support == SMTP_DNS_DISABLED)
smtp_host_lookup_mask = SMTP_HOST_FLAG_NATIVE;
else
smtp_host_lookup_mask = name_mask(VAR_SMTP_HOST_LOOKUP, lookup_masks,
var_smtp_host_lookup);
smtp_host_lookup_mask =
name_mask(SMTP_X(HOST_LOOKUP), lookup_masks, var_smtp_host_lookup);
if (msg_verbose)
msg_info("host name lookup methods: %s",
str_name_mask(VAR_SMTP_HOST_LOOKUP, lookup_masks,
str_name_mask(SMTP_X(HOST_LOOKUP), lookup_masks,
smtp_host_lookup_mask));
/*
@ -1005,7 +1051,7 @@ static void post_init(char *unused_name, char **unused_argv)
/*
* Select DNS query flags.
*/
smtp_dns_res_opt = name_mask(VAR_SMTP_DNS_RES_OPT, dns_res_opt_masks,
smtp_dns_res_opt = name_mask(SMTP_X(DNS_RES_OPT), dns_res_opt_masks,
var_smtp_dns_res_opt);
}
@ -1034,7 +1080,7 @@ static void pre_init(char *unused_name, char **unused_argv)
smtp_sasl_initialize();
#else
msg_warn("%s is true, but SASL support is not compiled in",
VAR_SMTP_SASL_ENABLE);
SMTP_X(SASL_ENABLE));
#endif
if (*var_smtp_tls_level != 0)
@ -1042,10 +1088,12 @@ static void pre_init(char *unused_name, char **unused_argv)
switch (tls_level_lookup(var_smtp_tls_level)) {
case TLS_LEV_SECURE:
case TLS_LEV_VERIFY:
case TLS_LEV_DANE_ONLY:
case TLS_LEV_FPRINT:
case TLS_LEV_ENCRYPT:
var_smtp_use_tls = var_smtp_enforce_tls = 1;
break;
case TLS_LEV_DANE:
case TLS_LEV_MAY:
var_smtp_use_tls = 1;
var_smtp_enforce_tls = 0;
@ -1067,7 +1115,6 @@ static void pre_init(char *unused_name, char **unused_argv)
if (use_tls || var_smtp_tls_per_site[0] || var_smtp_tls_policy[0]) {
#ifdef USE_TLS
TLS_CLIENT_INIT_PROPS props;
int using_smtp = (strcmp(var_procname, "smtp") == 0);
/*
* We get stronger type safety and a cleaner interface by combining
@ -1078,12 +1125,10 @@ static void pre_init(char *unused_name, char **unused_argv)
*/
smtp_tls_ctx =
TLS_CLIENT_INIT(&props,
log_param = using_smtp ?
VAR_SMTP_TLS_LOGLEVEL : VAR_LMTP_TLS_LOGLEVEL,
log_param = SMTP_X(TLS_LOGLEVEL),
log_level = var_smtp_tls_loglevel,
verifydepth = var_smtp_tls_scert_vd,
cache_type = using_smtp ?
TLS_MGR_SCACHE_SMTP : TLS_MGR_SCACHE_LMTP,
cache_type = X_SMTP(TLS_MGR_SCACHE),
cert_file = var_smtp_tls_cert_file,
key_file = var_smtp_tls_key_file,
dcert_file = var_smtp_tls_dcert_file,
@ -1092,7 +1137,7 @@ static void pre_init(char *unused_name, char **unused_argv)
eckey_file = var_smtp_tls_eckey_file,
CAfile = var_smtp_tls_CAfile,
CApath = var_smtp_tls_CApath,
fpt_dgst = var_smtp_tls_fpt_dgst);
mdalg = var_smtp_tls_fpt_dgst);
smtp_tls_list_init();
#else
msg_warn("TLS has been selected, but TLS support is not compiled in");
@ -1114,7 +1159,7 @@ static void pre_init(char *unused_name, char **unused_argv)
* EHLO keyword filter.
*/
if (*var_smtp_ehlo_dis_maps)
smtp_ehlo_dis_maps = maps_create(VAR_SMTP_EHLO_DIS_MAPS,
smtp_ehlo_dis_maps = maps_create(SMTP_X(EHLO_DIS_MAPS),
var_smtp_ehlo_dis_maps,
DICT_FLAG_LOCK);
@ -1122,7 +1167,7 @@ static void pre_init(char *unused_name, char **unused_argv)
* PIX bug workarounds.
*/
if (*var_smtp_pix_bug_maps)
smtp_pix_bug_maps = maps_create(VAR_SMTP_PIX_BUG_MAPS,
smtp_pix_bug_maps = maps_create(SMTP_X(PIX_BUG_MAPS),
var_smtp_pix_bug_maps,
DICT_FLAG_LOCK);
@ -1134,19 +1179,19 @@ static void pre_init(char *unused_name, char **unused_argv)
ext_prop_mask(VAR_PROP_EXTENSION, var_prop_extension);
if (*var_smtp_generic_maps)
smtp_generic_maps =
maps_create(VAR_SMTP_GENERIC_MAPS, var_smtp_generic_maps,
maps_create(SMTP_X(GENERIC_MAPS), var_smtp_generic_maps,
DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
/*
* Header/body checks.
*/
smtp_header_checks = hbc_header_checks_create(
VAR_SMTP_HEAD_CHKS, var_smtp_head_chks,
VAR_SMTP_MIME_CHKS, var_smtp_mime_chks,
VAR_SMTP_NEST_CHKS, var_smtp_nest_chks,
SMTP_X(HEAD_CHKS), var_smtp_head_chks,
SMTP_X(MIME_CHKS), var_smtp_mime_chks,
SMTP_X(NEST_CHKS), var_smtp_nest_chks,
smtp_hbc_callbacks);
smtp_body_checks = hbc_body_checks_create(
VAR_SMTP_BODY_CHKS, var_smtp_body_chks,
SMTP_X(BODY_CHKS), var_smtp_body_chks,
smtp_hbc_callbacks);
/*
@ -1164,7 +1209,7 @@ static void pre_init(char *unused_name, char **unused_argv)
smtp_addr_pref = name_code(addr_pref_map, NAME_CODE_FLAG_NONE,
var_smtp_addr_pref);
if (smtp_addr_pref < 0)
msg_fatal("bad %s value: %s", VAR_SMTP_ADDR_PREF, var_smtp_addr_pref);
msg_fatal("bad %s value: %s", SMTP_X(ADDR_PREF), var_smtp_addr_pref);
}
}
@ -1186,9 +1231,10 @@ MAIL_VERSION_STAMP_DECLARE;
int main(int argc, char **argv)
{
char *sane_procname;
#include "smtp_params.c"
#include "lmtp_params.c"
int smtp_mode;
/*
* Fingerprint executables and core dumps.
@ -1197,8 +1243,19 @@ int main(int argc, char **argv)
/*
* XXX At this point, var_procname etc. are not initialized.
*
* The process name, "smtp" or "lmtp", determines the protocol, the DSN
* server reply type, SASL service information lookup, and more. Prepare
* for the possibility there may be another personality.
*/
smtp_mode = (strcmp(sane_basename((VSTRING *) 0, argv[0]), "smtp") == 0);
sane_procname = sane_basename((VSTRING *) 0, argv[0]);
if (strcmp(sane_procname, "smtp") == 0)
smtp_mode = 1;
else if (strcmp(sane_procname, "lmtp") == 0)
smtp_mode = 0;
else
msg_fatal("unexpected process name \"%s\" - "
"specify \"smtp\" or \"lmtp\"", var_procname);
/*
* Initialize with the LMTP or SMTP parameter name space.

View File

@ -1,4 +1,4 @@
/* $NetBSD: smtpd.c,v 1.10 2013/09/25 19:12:35 tron Exp $ */
/* $NetBSD: smtpd.c,v 1.11 2014/07/06 19:45:50 tron Exp $ */
/*++
/* NAME
@ -92,10 +92,6 @@
/* not contain RFC 822 style comments or phrases.
/* .PP
/* Available in Postfix version 2.1 and later:
/* .IP "\fBresolve_null_domain (no)\fR"
/* Resolve an address that ends in the "@" null domain as if the
/* local hostname were specified, instead of rejecting the address as
/* invalid.
/* .IP "\fBsmtpd_reject_unlisted_sender (no)\fR"
/* Request that the Postfix SMTP server rejects mail from unknown
/* sender addresses, even when no explicit reject_unlisted_sender
@ -136,7 +132,8 @@
/* .PP
/* Available in Postfix version 2.9 and later:
/* .IP "\fBsmtpd_per_record_deadline (normal: no, overload: yes)\fR"
/* Change the behavior of the smtpd_timeout time limit, from a
/* Change the behavior of the smtpd_timeout and smtpd_starttls_timeout
/* time limits, from a
/* time limit per read or write system call, to a time limit to send
/* or receive a complete record (an SMTP command line, SMTP response
/* line, SMTP message content line, or TLS protocol message).
@ -320,6 +317,11 @@
/* .IP "\fBcyrus_sasl_config_path (empty)\fR"
/* Search path for Cyrus SASL application configuration files,
/* currently used only to locate the $smtpd_sasl_path.conf file.
/* .PP
/* Available in Postfix version 2.11 and later:
/* .IP "\fBsmtpd_sasl_service (smtp)\fR"
/* The service name that is passed to the SASL plug-in that is
/* selected with \fBsmtpd_sasl_type\fR and \fBsmtpd_sasl_path\fR.
/* STARTTLS SUPPORT CONTROLS
/* .ad
/* .fi
@ -364,10 +366,10 @@
/* File with the Postfix SMTP server DSA certificate in PEM format.
/* .IP "\fBsmtpd_tls_dh1024_param_file (empty)\fR"
/* File with DH parameters that the Postfix SMTP server should
/* use with EDH ciphers.
/* use with non-export EDH ciphers.
/* .IP "\fBsmtpd_tls_dh512_param_file (empty)\fR"
/* File with DH parameters that the Postfix SMTP server should
/* use with EDH ciphers.
/* use with export-grade EDH ciphers.
/* .IP "\fBsmtpd_tls_dkey_file ($smtpd_tls_dcert_file)\fR"
/* File with the Postfix SMTP server DSA private key in PEM format.
/* .IP "\fBsmtpd_tls_key_file ($smtpd_tls_cert_file)\fR"
@ -391,12 +393,6 @@
/* .IP "\fBsmtpd_tls_req_ccert (no)\fR"
/* With mandatory TLS encryption, require a trusted remote SMTP client
/* certificate in order to allow TLS connections to proceed.
/* .IP "\fBsmtpd_tls_session_cache_database (empty)\fR"
/* Name of the file containing the optional Postfix SMTP server
/* TLS session cache.
/* .IP "\fBsmtpd_tls_session_cache_timeout (3600s)\fR"
/* The expiration time of Postfix SMTP server TLS session cache
/* information.
/* .IP "\fBsmtpd_tls_wrappermode (no)\fR"
/* Run the Postfix SMTP server in the non-standard "wrapper" mode,
/* instead of using the STARTTLS command.
@ -453,6 +449,10 @@
/* order.
/* .IP "\fBtls_disable_workarounds (see 'postconf -d' output)\fR"
/* List or bit-mask of OpenSSL bug work-arounds to disable.
/* .PP
/* Available in Postfix version 2.11 and later:
/* .IP "\fBtlsmgr_service_name (tlsmgr)\fR"
/* The name of the \fBtlsmgr\fR(8) service entry in master.cf.
/* OBSOLETE STARTTLS CONTROLS
/* .ad
/* .fi
@ -531,7 +531,8 @@
/* Available in Postfix version 2.10 and later:
/* .IP "\fBsmtpd_log_access_permit_actions (empty)\fR"
/* Enable logging of the named "permit" actions in SMTP server
/* access lists.
/* access lists (by default, the SMTP server logs "reject" actions but
/* not "permit" actions).
/* KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS
/* .ad
/* .fi
@ -667,7 +668,8 @@
/* .PP
/* Available in Postfix version 2.9 and later:
/* .IP "\fBsmtpd_per_record_deadline (normal: no, overload: yes)\fR"
/* Change the behavior of the smtpd_timeout time limit, from a
/* Change the behavior of the smtpd_timeout and smtpd_starttls_timeout
/* time limits, from a
/* time limit per read or write system call, to a time limit to send
/* or receive a complete record (an SMTP command line, SMTP response
/* line, SMTP message content line, or TLS protocol message).
@ -784,7 +786,7 @@
/* applies in the context of the SMTP END-OF-DATA command.
/* .PP
/* Available in Postfix version 2.10 and later:
/* .IP "\fBsmtpd_relay_restrictions (permit_mynetworks, reject_unauth_destination)\fR"
/* .IP "\fBsmtpd_relay_restrictions (permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination)\fR"
/* Access restrictions for mail relay control that the Postfix
/* SMTP server applies in the context of the RCPT TO command, before
/* smtpd_recipient_restrictions.
@ -957,7 +959,9 @@
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
/* The location of the Postfix top-level queue directory.
/* .IP "\fBrecipient_delimiter (empty)\fR"
/* The separator between user names and address extensions (user+foo).
/* The set of characters that can separate a user name from its
/* extension (example: user+foo), or a .forward file name from its
/* extension (example: .forward+foo).
/* .IP "\fBsmtpd_banner ($myhostname ESMTP $mail_name)\fR"
/* The text that follows the 220 status code in the SMTP greeting
/* banner.
@ -1182,6 +1186,7 @@ bool var_smtpd_sasl_enable;
bool var_smtpd_sasl_auth_hdr;
char *var_smtpd_sasl_opts;
char *var_smtpd_sasl_path;
char *var_smtpd_sasl_service;
char *var_cyrus_conf_path;
char *var_smtpd_sasl_realm;
char *var_smtpd_sasl_exceptions_networks;
@ -1264,7 +1269,6 @@ char *var_smtpd_tls_loglevel;
char *var_smtpd_tls_mand_proto;
bool var_smtpd_tls_received_header;
bool var_smtpd_tls_req_ccert;
int var_smtpd_tls_scache_timeout;
bool var_smtpd_tls_set_sessid;
char *var_smtpd_tls_fpt_dgst;
char *var_smtpd_tls_ciph;
@ -1847,7 +1851,7 @@ static int mail_open_stream(SMTPD_STATE *state)
if (smtpd_proxy_create(state, smtpd_proxy_opts, var_smtpd_proxy_filt,
var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo,
state->proxy_mail) != 0) {
smtpd_chat_reply(state, "%s", STR(state->proxy->buffer));
smtpd_chat_reply(state, "%s", STR(state->proxy->reply));
smtpd_proxy_free(state);
return (-1);
}
@ -2690,7 +2694,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
proxy = state->proxy;
if (proxy != 0 && proxy->cmd(state, SMTPD_PROX_WANT_OK,
"%s", STR(state->buffer)) != 0) {
smtpd_chat_reply(state, "%s", STR(proxy->buffer));
smtpd_chat_reply(state, "%s", STR(proxy->reply));
return (-1);
}
@ -2939,7 +2943,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
proxy = state->proxy;
if (proxy != 0 && proxy->cmd(state, SMTPD_PROX_WANT_MORE,
"%s", STR(state->buffer)) != 0) {
smtpd_chat_reply(state, "%s", STR(proxy->buffer));
smtpd_chat_reply(state, "%s", STR(proxy->reply));
return (-1);
}
@ -3149,7 +3153,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
if (state->err == CLEANUP_STAT_OK) {
(void) proxy->cmd(state, SMTPD_PROX_WANT_ANY, ".");
if (state->err == CLEANUP_STAT_OK &&
*STR(proxy->buffer) != '2')
*STR(proxy->reply) != '2')
state->err = CLEANUP_STAT_CONT;
}
}
@ -3238,7 +3242,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
state->error_mask = 0;
state->junk_cmds = 0;
if (proxy)
smtpd_chat_reply(state, "%s", STR(proxy->buffer));
smtpd_chat_reply(state, "%s", STR(proxy->reply));
else
smtpd_chat_reply(state,
"250 2.0.0 Ok: queued as %s", state->queue_id);
@ -3274,7 +3278,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
state->error_mask |= MAIL_ERROR_POLICY;
detail = cleanup_stat_detail(CLEANUP_STAT_CONT);
if (proxy) {
smtpd_chat_reply(state, "%s", STR(proxy->buffer));
smtpd_chat_reply(state, "%s", STR(proxy->reply));
} else if (why && LEN(why) > 0) {
/* Allow address-specific DSN status in header/body_checks. */
smtpd_chat_reply(state, "%d %s", detail->smtp, STR(why));
@ -3289,7 +3293,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
detail->smtp, detail->dsn, detail->text);
} else if ((state->err & CLEANUP_STAT_PROXY) != 0) {
state->error_mask |= MAIL_ERROR_SOFTWARE;
smtpd_chat_reply(state, "%s", STR(proxy->buffer));
smtpd_chat_reply(state, "%s", STR(proxy->reply));
} else {
state->error_mask |= MAIL_ERROR_SOFTWARE;
detail = cleanup_stat_detail(CLEANUP_STAT_BAD);
@ -3303,7 +3307,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
if (proxy)
msg_info("proxy-%s: %s: %s;%s",
(state->err == CLEANUP_STAT_OK) ? "accept" : "reject",
state->where, STR(proxy->buffer), smtpd_whatsup(state));
state->where, STR(proxy->reply), smtpd_whatsup(state));
/*
* Cleanup. The client may send another MAIL command.
@ -3373,6 +3377,7 @@ static int noop_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
{
const char *err = 0;
int rate;
/*
* The SMTP standard (RFC 821) disallows unquoted special characters in
@ -3403,17 +3408,38 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
smtpd_chat_reply(state, "502 5.5.1 VRFY command is disabled");
return (-1);
}
if (argc < 2) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 5.5.4 Syntax: VRFY address");
return (-1);
}
/*
* XXX The client event count/rate control must be consistent in its use
* of client address information in connect and disconnect events. For
* now we exclude xclient authorized hosts from event count/rate control.
*/
if (SMTPD_STAND_ALONE(state) == 0
&& !xclient_allowed
&& anvil_clnt
&& var_smtpd_crcpt_limit > 0
&& !namadr_list_match(hogger_list, state->name, state->addr)
&& anvil_clnt_rcpt(anvil_clnt, state->service, state->addr,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_crcpt_limit) {
state->error_mask |= MAIL_ERROR_POLICY;
msg_warn("Recipient address rate limit exceeded: %d from %s for service %s",
rate, state->namaddr, state->service);
smtpd_chat_reply(state, "450 4.7.1 Error: too many recipients from %s",
state->addr);
return (-1);
}
if (smtpd_milters != 0 && (err = milter_other_event(smtpd_milters)) != 0
&& (err[0] == '5' || err[0] == '4')) {
state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if (argc < 2) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 5.5.4 Syntax: VRFY address");
return (-1);
}
if (argc > 2)
collapse_args(argc - 1, argv + 1);
if (extract_addr(state, argv + 1, REJECT_EMPTY_ADDR, SLOPPY) != 0) {
@ -4208,7 +4234,7 @@ static void smtpd_start_tls(SMTPD_STATE *state)
namaddr = state->namaddr,
cipher_grade = cipher_grade,
cipher_exclusions = STR(cipher_exclusions),
fpt_dgst = var_smtpd_tls_fpt_dgst);
mdalg = var_smtpd_tls_fpt_dgst);
#endif /* USE_TLSPROXY */
@ -4348,14 +4374,14 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
state->port, var_smtpd_tmout);
if (state->tlsproxy == 0) {
state->error_mask |= MAIL_ERROR_SOFTWARE;
/* RFC 4954 Section 6. */
/* RFC 3207 Section 4. */
smtpd_chat_reply(state, "454 4.7.0 TLS not available due to local problem");
return (-1);
}
#else /* USE_TLSPROXY */
if (smtpd_tls_ctx == 0) {
state->error_mask |= MAIL_ERROR_SOFTWARE;
/* RFC 4954 Section 6. */
/* RFC 3207 Section 4. */
smtpd_chat_reply(state, "454 4.7.0 TLS not available due to local problem");
return (-1);
}
@ -5130,8 +5156,6 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
log_level = var_smtpd_tls_loglevel,
verifydepth = var_smtpd_tls_ccert_vd,
cache_type = TLS_MGR_SCACHE_SMTPD,
scache_timeout
= var_smtpd_tls_scache_timeout,
set_sessid = var_smtpd_tls_set_sessid,
cert_file = cert_file,
key_file = var_smtpd_tls_key_file,
@ -5150,7 +5174,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
var_smtpd_tls_mand_proto :
var_smtpd_tls_proto,
ask_ccert = ask_client_cert,
fpt_dgst = var_smtpd_tls_fpt_dgst);
mdalg = var_smtpd_tls_fpt_dgst);
else
msg_warn("No server certs available. TLS won't be enabled");
#endif /* USE_TLSPROXY */
@ -5304,7 +5328,6 @@ int main(int argc, char **argv)
VAR_SMTPD_POLICY_TTL, DEF_SMTPD_POLICY_TTL, &var_smtpd_policy_ttl, 1, 0,
#ifdef USE_TLS
VAR_SMTPD_STARTTLS_TMOUT, DEF_SMTPD_STARTTLS_TMOUT, &var_smtpd_starttls_tmout, 1, 0,
VAR_SMTPD_TLS_SCACHTIME, DEF_SMTPD_TLS_SCACHTIME, &var_smtpd_tls_scache_timeout, 0, 0,
#endif
VAR_MILT_CONN_TIME, DEF_MILT_CONN_TIME, &var_milt_conn_time, 1, 0,
VAR_MILT_CMD_TIME, DEF_MILT_CMD_TIME, &var_milt_cmd_time, 1, 0,
@ -5367,6 +5390,7 @@ int main(int argc, char **argv)
VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 0, 0,
VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts, 0, 0,
VAR_SMTPD_SASL_PATH, DEF_SMTPD_SASL_PATH, &var_smtpd_sasl_path, 1, 0,
VAR_SMTPD_SASL_SERVICE, DEF_SMTPD_SASL_SERVICE, &var_smtpd_sasl_service, 1, 0,
VAR_CYRUS_CONF_PATH, DEF_CYRUS_CONF_PATH, &var_cyrus_conf_path, 0, 0,
VAR_SMTPD_SASL_REALM, DEF_SMTPD_SASL_REALM, &var_smtpd_sasl_realm, 0, 0,
VAR_SMTPD_SASL_EXCEPTIONS_NETWORKS, DEF_SMTPD_SASL_EXCEPTIONS_NETWORKS, &var_smtpd_sasl_exceptions_networks, 0, 0,

View File

@ -1,4 +1,4 @@
/* $NetBSD: tls_client.c,v 1.8 2013/09/25 19:12:35 tron Exp $ */
/* $NetBSD: tls_client.c,v 1.9 2014/07/06 19:45:50 tron Exp $ */
/*++
/* NAME
@ -93,7 +93,7 @@
/* .IP TLScontext->issuer_CN
/* Extracted CommonName of the issuer, or zero-length string if the
/* information could not be extracted.
/* .IP TLScontext->peer_fingerprint
/* .IP TLScontext->peer_cert_fprint
/* At the fingerprint security level, if the peer presented a certificate
/* the fingerprint of the certificate.
/* .PP
@ -170,7 +170,7 @@ static SSL_SESSION *load_clnt_session(TLS_SESS_STATE *TLScontext)
* Prepare the query.
*/
if (TLScontext->log_mask & TLS_LOG_CACHE)
/* serverid already contains namaddrport information */
/* serverid contains transport:addr:port information */
msg_info("looking for session %s in %s cache",
TLScontext->serverid, TLScontext->cache_type);
@ -192,7 +192,7 @@ static SSL_SESSION *load_clnt_session(TLS_SESS_STATE *TLScontext)
session = tls_session_activate(STR(session_data), LEN(session_data));
if (session) {
if (TLScontext->log_mask & TLS_LOG_CACHE)
/* serverid already contains namaddrport information */
/* serverid contains transport:addr:port information */
msg_info("reloaded session %s from %s cache",
TLScontext->serverid, TLScontext->cache_type);
}
@ -232,25 +232,10 @@ static int new_client_session_cb(SSL *ssl, SSL_SESSION *session)
myname);
if (TLScontext->log_mask & TLS_LOG_CACHE)
/* serverid already contains namaddrport information */
/* serverid contains transport:addr:port information */
msg_info("save session %s to %s cache",
TLScontext->serverid, TLScontext->cache_type);
#if (OPENSSL_VERSION_NUMBER < 0x00906011L) || (OPENSSL_VERSION_NUMBER == 0x00907000L)
/*
* Ugly Hack: OpenSSL before 0.9.6a does not store the verify result in
* sessions for the client side. We modify the session directly which is
* version specific, but this bug is version specific, too.
*
* READ: 0-09-06-01-1 = 0-9-6-a-beta1: all versions before beta1 have this
* bug, it has been fixed during development of 0.9.6a. The development
* version of 0.9.7 can have this bug, too. It has been fixed on
* 2000/11/29.
*/
session->verify_result = SSL_get_verify_result(TLScontext->con);
#endif
/*
* Passivate and save the session object. Errors are non-fatal, since
* caching is only an optimization.
@ -280,7 +265,7 @@ static void uncache_session(SSL_CTX *ctx, TLS_SESS_STATE *TLScontext)
return;
if (TLScontext->log_mask & TLS_LOG_CACHE)
/* serverid already contains namaddrport information */
/* serverid contains transport:addr:port information */
msg_info("remove session %s from client cache", TLScontext->serverid);
tls_mgr_delete(TLScontext->cache_type, TLScontext->serverid);
@ -292,10 +277,9 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
{
long off = 0;
int cachable;
int scache_timeout;
SSL_CTX *client_ctx;
TLS_APPL_STATE *app_ctx;
const EVP_MD *md_alg;
unsigned int md_len;
int log_mask;
/*
@ -337,40 +321,12 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
}
}
/*
* Register SHA-2 digests, if implemented and not already registered.
* Improves interoperability with clients and servers that prematurely
* deploy SHA-2 certificates.
*/
#if defined(LN_sha256) && defined(NID_sha256) && !defined(OPENSSL_NO_SHA256)
if (!EVP_get_digestbyname(LN_sha224))
EVP_add_digest(EVP_sha224());
if (!EVP_get_digestbyname(LN_sha256))
EVP_add_digest(EVP_sha256());
#endif
#if defined(LN_sha512) && defined(NID_sha512) && !defined(OPENSSL_NO_SHA512)
if (!EVP_get_digestbyname(LN_sha384))
EVP_add_digest(EVP_sha384());
if (!EVP_get_digestbyname(LN_sha512))
EVP_add_digest(EVP_sha512());
#endif
/*
* If the administrator specifies an unsupported digest algorithm, fail
* now, rather than in the middle of a TLS handshake.
*/
if ((md_alg = EVP_get_digestbyname(props->fpt_dgst)) == 0) {
msg_warn("Digest algorithm \"%s\" not found: disabling TLS support",
props->fpt_dgst);
return (0);
}
/*
* Sanity check: Newer shared libraries may use larger digests.
*/
if ((md_len = EVP_MD_size(md_alg)) > EVP_MAX_MD_SIZE) {
msg_warn("Digest algorithm \"%s\" output size %u too large:"
" disabling TLS support", props->fpt_dgst, md_len);
if (!tls_validate_digest(props->mdalg)) {
msg_warn("disabling TLS support");
return (0);
}
@ -492,7 +448,10 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
* sessions from the external cache, so we must delete them directly (not
* via a callback).
*/
if (tls_mgr_policy(props->cache_type, &cachable) != TLS_MGR_STAT_OK)
if (tls_mgr_policy(props->cache_type, &cachable,
&scache_timeout) != TLS_MGR_STAT_OK)
scache_timeout = 0;
if (scache_timeout <= 0)
cachable = 0;
/*
@ -531,69 +490,82 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
SSL_SESS_CACHE_NO_INTERNAL_STORE |
SSL_SESS_CACHE_NO_AUTO_CLEAR);
SSL_CTX_sess_set_new_cb(client_ctx, new_client_session_cb);
/*
* OpenSSL ignores timed-out sessions. We need to set the internal
* cache timeout at least as high as the external cache timeout. This
* applies even if no internal cache is used. We set the session to
* twice the cache lifetime. This way a session always lasts longer
* than its lifetime in the cache.
*/
SSL_CTX_set_timeout(client_ctx, 2 * scache_timeout);
}
return (app_ctx);
}
/* match_hostname - match hostname against pattern */
/* match_servername - match servername against pattern */
static int match_hostname(const char *peerid,
const TLS_CLIENT_START_PROPS *props)
static int match_servername(const char *certid,
const TLS_CLIENT_START_PROPS *props)
{
const ARGV *cmatch_argv;
const char *nexthop = props->nexthop;
const char *hname = props->host;
const char *pattern;
const char *pattern_left;
int sub;
const char *domain;
const char *parent;
int match_subdomain;
int i;
int idlen;
int patlen;
int domlen;
if ((cmatch_argv = props->matchargv) == 0)
return 0;
/*
* Match the peerid against each pattern until we find a match.
* Match the certid against each pattern until we find a match.
*/
for (i = 0; i < cmatch_argv->argc; ++i) {
sub = 0;
match_subdomain = 0;
if (!strcasecmp(cmatch_argv->argv[i], "nexthop"))
pattern = nexthop;
domain = nexthop;
else if (!strcasecmp(cmatch_argv->argv[i], "hostname"))
pattern = hname;
domain = hname;
else if (!strcasecmp(cmatch_argv->argv[i], "dot-nexthop")) {
pattern = nexthop;
sub = 1;
domain = nexthop;
match_subdomain = 1;
} else {
pattern = cmatch_argv->argv[i];
if (*pattern == '.' && pattern[1] != '\0') {
++pattern;
sub = 1;
domain = cmatch_argv->argv[i];
if (*domain == '.' && domain[1] != '\0') {
++domain;
match_subdomain = 1;
}
}
/*
* Sub-domain match: peerid is any sub-domain of pattern.
* Sub-domain match: certid is any sub-domain of hostname.
*/
if (sub) {
if ((idlen = strlen(peerid)) > (patlen = strlen(pattern)) + 1
&& peerid[idlen - patlen - 1] == '.'
&& !strcasecmp(peerid + (idlen - patlen), pattern))
if (match_subdomain) {
if ((idlen = strlen(certid)) > (domlen = strlen(domain)) + 1
&& certid[idlen - domlen - 1] == '.'
&& !strcasecmp(certid + (idlen - domlen), domain))
return (1);
else
continue;
}
/*
* Exact match and initial "*" match. The initial "*" in a peerid
* matches exactly one hostname component, under the condition that
* the peerid contains multiple hostname components.
* Exact match and initial "*" match. The initial "*" in a certid
* matches one (if var_tls_multi_label is false) or more hostname
* components under the condition that the certid contains multiple
* hostname components.
*/
if (!strcasecmp(peerid, pattern)
|| (peerid[0] == '*' && peerid[1] == '.' && peerid[2] != 0
&& (pattern_left = strchr(pattern, '.')) != 0
&& strcasecmp(pattern_left + 1, peerid + 2) == 0))
if (!strcasecmp(certid, domain)
|| (certid[0] == '*' && certid[1] == '.' && certid[2] != 0
&& (parent = strchr(domain, '.')) != 0
&& (idlen = strlen(certid + 1)) <= (domlen = strlen(parent))
&& strcasecmp(var_tls_multi_wildcard == 0 ? parent :
parent + domlen - idlen,
certid + 1) == 0))
return (1);
}
return (0);
@ -613,8 +585,7 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
int verbose;
const char *dnsname;
const GENERAL_NAME *gn;
STACK_OF(GENERAL_NAME) * gens;
general_name_stack_t *gens;
/*
* On exit both peer_CN and issuer_CN should be set.
@ -627,7 +598,13 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
if (TLS_CERT_IS_TRUSTED(TLScontext) && props->tls_level >= TLS_LEV_VERIFY)
/*
* With fingerprint or dane we may already be done. Otherwise, verify the
* peername if using traditional PKI or DANE with trust-anchors.
*/
if (!TLS_CERT_IS_MATCHED(TLScontext)
&& TLS_CERT_IS_TRUSTED(TLScontext)
&& TLS_MUST_TRUST(props->tls_level))
verify_peername = 1;
/* Force cert processing so we can log the data? */
@ -678,7 +655,7 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
TLScontext->peer_status |= TLS_CERT_FLAG_ALTNAME;
dnsname = tls_dns_name(gn, TLScontext);
if (dnsname && *dnsname) {
if ((dnsname_match = match_hostname(dnsname, props)) != 0)
if ((dnsname_match = match_servername(dnsname, props)) != 0)
matched++;
/* Keep the first matched name. */
if (TLScontext->peer_CN
@ -712,7 +689,7 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
if (TLScontext->peer_CN == 0) {
TLScontext->peer_CN = tls_peer_CN(peercert, TLScontext);
if (*TLScontext->peer_CN)
matched = match_hostname(TLScontext->peer_CN, props);
matched = match_servername(TLScontext->peer_CN, props);
if (verify_peername && matched)
TLScontext->peer_status |= TLS_CERT_FLAG_MATCHED;
if (verbose)
@ -732,16 +709,19 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
TLScontext->peer_CN = tls_peer_CN(peercert, TLScontext);
/*
* Give them a clue. Problems with trust chain verification were logged
* when the session was first negotiated, before the session was stored
* Give them a clue. Problems with trust chain verification are logged
* when the session is first negotiated, before the session is stored
* into the cache. We don't want mystery failures, so log the fact the
* real problem is to be found in the past.
*/
if (TLScontext->session_reused
&& !TLS_CERT_IS_TRUSTED(TLScontext)
&& (TLScontext->log_mask & TLS_LOG_UNTRUSTED))
msg_info("%s: re-using session with untrusted certificate, "
"look for details earlier in the log", props->namaddr);
if (!TLS_CERT_IS_TRUSTED(TLScontext)
&& (TLScontext->log_mask & TLS_LOG_UNTRUSTED)) {
if (TLScontext->session_reused == 0)
tls_log_verify_error(TLScontext);
else
msg_info("%s: re-using session with untrusted certificate, "
"look for details earlier in the log", props->namaddr);
}
}
/* verify_extract_print - extract and verify peer fingerprint */
@ -749,25 +729,22 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
static void verify_extract_print(TLS_SESS_STATE *TLScontext, X509 *peercert,
const TLS_CLIENT_START_PROPS *props)
{
char **cpp;
/* Non-null by contract */
TLScontext->peer_fingerprint = tls_fingerprint(peercert, props->fpt_dgst);
TLScontext->peer_pkey_fprint = tls_pkey_fprint(peercert, props->fpt_dgst);
TLScontext->peer_cert_fprint = tls_cert_fprint(peercert, props->mdalg);
TLScontext->peer_pkey_fprint = tls_pkey_fprint(peercert, props->mdalg);
/*
* Compare the fingerprint against each acceptable value, ignoring
* upper/lower case differences.
* Whether the level is "dane" or "fingerprint" when the peer certificate
* is matched without resorting to a separate CA, we set both the trusted
* and matched bits. This simplifies logic in smtp_proto.c where "dane"
* must be trusted and matched, since some "dane" TLSA RRsets do use CAs.
*
* This also suppresses spurious logging of the peer certificate as
* untrusted in verify_extract_name().
*/
if (props->tls_level == TLS_LEV_FPRINT) {
for (cpp = props->matchargv->argv; *cpp; ++cpp) {
if (strcasecmp(TLScontext->peer_fingerprint, *cpp) == 0
|| strcasecmp(TLScontext->peer_pkey_fprint, *cpp) == 0) {
TLScontext->peer_status |= TLS_CERT_FLAG_MATCHED;
break;
}
}
}
if (TLS_DANE_HASEE(props->dane)
&& tls_dane_match(TLScontext, TLS_DANE_EE, peercert, 0))
TLScontext->peer_status |=
TLS_CERT_FLAG_TRUSTED | TLS_CERT_FLAG_MATCHED;
}
/*
@ -780,19 +757,21 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
int sts;
int protomask;
const char *cipher_list;
SSL_SESSION *session;
const SSL_CIPHER *cipher;
SSL_SESSION *session = 0;
SSL_CIPHER_const SSL_CIPHER *cipher;
X509 *peercert;
TLS_SESS_STATE *TLScontext;
TLS_APPL_STATE *app_ctx = props->ctx;
VSTRING *myserverid;
char *myserverid;
int log_mask = app_ctx->log_mask;
/*
* When certificate verification is required, log trust chain validation
* errors even when disabled by default for opportunistic sessions.
* errors even when disabled by default for opportunistic sessions. For
* "dane" this only applies when using trust-anchor associations.
*/
if (props->tls_level >= TLS_LEV_VERIFY)
if (TLS_MUST_TRUST(props->tls_level)
&& (props->tls_level != TLS_LEV_DANE || TLS_DANE_HASTA(props->dane)))
log_mask |= TLS_LOG_UNTRUSTED;
if (log_mask & TLS_LOG_VERBOSE)
@ -801,19 +780,8 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
/*
* First make sure we have valid protocol and cipher parameters
*
* The cipherlist will be applied to the global SSL context, where it can be
* repeatedly reset if necessary, but the protocol restrictions will be
* is applied to the SSL connection, because protocol restrictions in the
* global context cannot be cleared.
*/
/*
* OpenSSL will ignore cached sessions that use the wrong protocol. So we
* do not need to filter out cached sessions with the "wrong" protocol,
* rather OpenSSL will simply negotiate a new session.
*
* Still, we salt the session lookup key with the protocol list, so that
* sessions found in the cache are always acceptable.
* Per-session protocol restrictions must be applied to the SSL connection,
* as restrictions in the global context cannot be cleared.
*/
protomask = tls_protocol_mask(props->protocols);
if (protomask == TLS_PROTOCOL_INVALID) {
@ -822,35 +790,51 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
props->namaddr, props->protocols);
return (0);
}
myserverid = vstring_alloc(100);
vstring_sprintf_append(myserverid, "%s&p=%d", props->serverid, protomask);
/* The DANE level requires SSLv3 or later, not SSLv2. */
if (props->tls_level == TLS_LEV_DANE)
protomask |= TLS_PROTOCOL_SSLv2;
/*
* Per session cipher selection for sessions with mandatory encryption
*
* By the time a TLS client is negotiating ciphers it has already offered to
* re-use a session, it is too late to renege on the offer. So we must
* not attempt to re-use sessions whose ciphers are too weak. We salt the
* session lookup key with the cipher list, so that sessions found in the
* cache are always acceptable.
* The cipherlist is applied to the global SSL context, since it is likely
* to stay the same between connections, so we make use of a 1-element
* cache to return the same result for identical inputs.
*/
cipher_list = tls_set_ciphers(app_ctx, "TLS", props->cipher_grade,
props->cipher_exclusions);
if (cipher_list == 0) {
msg_warn("%s: %s: aborting TLS session",
props->namaddr, vstring_str(app_ctx->why));
vstring_free(myserverid);
return (0);
}
if (log_mask & TLS_LOG_VERBOSE)
msg_info("%s: TLS cipher list \"%s\"", props->namaddr, cipher_list);
vstring_sprintf_append(myserverid, "&c=%s", cipher_list);
/*
* Finally, salt the session key with the OpenSSL library version,
* (run-time, rather than compile-time, just in case that matters).
* OpenSSL will ignore cached sessions that use the wrong protocol. So we
* do not need to filter out cached sessions with the "wrong" protocol,
* rather OpenSSL will simply negotiate a new session.
*
* We salt the session lookup key with the protocol list, so that sessions
* found in the cache are plausibly acceptable.
*
* By the time a TLS client is negotiating ciphers it has already offered to
* re-use a session, it is too late to renege on the offer. So we must
* not attempt to re-use sessions whose ciphers are too weak. We salt the
* session lookup key with the cipher list, so that sessions found in the
* cache are always acceptable.
*
* With DANE, (more generally any TLScontext where we specified explicit
* trust-anchor or end-entity certificates) the verification status of
* the SSL session depends on the specified list. Since we verify the
* certificate only during the initial handshake, we must segregate
* sessions with different TA lists. Note, that TA re-verification is
* not possible with cached sessions, since these don't hold the complete
* peer trust chain. Therefore, we compute a digest of the sorted TA
* parameters and append it to the serverid.
*/
vstring_sprintf_append(myserverid, "&l=%ld", (long) SSLeay());
myserverid = tls_serverid_digest(props, protomask, cipher_list);
/*
* Allocate a new TLScontext for the new connection and get an SSL
@ -863,8 +847,12 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
TLScontext = tls_alloc_sess_context(log_mask, props->namaddr);
TLScontext->cache_type = app_ctx->cache_type;
TLScontext->serverid = vstring_export(myserverid);
TLScontext->serverid = myserverid;
TLScontext->stream = props->stream;
TLScontext->mdalg = props->mdalg;
/* Alias DANE digest info from props */
TLScontext->dane = props->dane;
if ((TLScontext->con = SSL_new(app_ctx->ssl_ctx)) == NULL) {
msg_warn("Could not allocate 'TLScontext->con' with SSL_new()");
@ -883,12 +871,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
* Apply session protocol restrictions.
*/
if (protomask != 0)
SSL_set_options(TLScontext->con,
((protomask & TLS_PROTOCOL_TLSv1) ? SSL_OP_NO_TLSv1 : 0L)
| ((protomask & TLS_PROTOCOL_TLSv1_1) ? SSL_OP_NO_TLSv1_1 : 0L)
| ((protomask & TLS_PROTOCOL_TLSv1_2) ? SSL_OP_NO_TLSv1_2 : 0L)
| ((protomask & TLS_PROTOCOL_SSLv3) ? SSL_OP_NO_SSLv3 : 0L)
| ((protomask & TLS_PROTOCOL_SSLv2) ? SSL_OP_NO_SSLv2 : 0L));
SSL_set_options(TLScontext->con, TLS_SSL_OP_PROTOMASK(protomask));
/*
* XXX To avoid memory leaks we must always call SSL_SESSION_free() after
@ -900,24 +883,38 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
if (session) {
SSL_set_session(TLScontext->con, session);
SSL_SESSION_free(session); /* 200411 */
#if (OPENSSL_VERSION_NUMBER < 0x00906011L) || (OPENSSL_VERSION_NUMBER == 0x00907000L)
/*
* Ugly Hack: OpenSSL before 0.9.6a does not store the verify
* result in sessions for the client side. We modify the session
* directly which is version specific, but this bug is version
* specific, too.
*
* READ: 0-09-06-01-1 = 0-9-6-a-beta1: all versions before beta1
* have this bug, it has been fixed during development of 0.9.6a.
* The development version of 0.9.7 can have this bug, too. It
* has been fixed on 2000/11/29.
*/
SSL_set_verify_result(TLScontext->con, session->verify_result);
#endif
}
}
#ifdef TLSEXT_MAXLEN_host_name
if (props->tls_level == TLS_LEV_DANE
&& strlen(props->host) <= TLSEXT_MAXLEN_host_name) {
/*
* With DANE sessions, send an SNI hint. We don't care whether the
* server reports finding a matching certificate or not, so no
* callback is required to process the server response. Our use of
* SNI is limited to giving servers that are (mis)configured to use
* SNI the best opportunity to find the certificate they promised via
* the associated TLSA RRs. (Generally, server administrators should
* avoid SNI, and there are no plans to support SNI in the Postfix
* SMTP server).
*
* Since the hostname is DNSSEC-validated, it must be a DNS FQDN and
* thererefore valid for use with SNI. Failure to set a valid SNI
* hostname is a memory allocation error, and thus transient. Since
* we must not cache the session if we failed to send the SNI name,
* we have little choice but to abort.
*/
if (!SSL_set_tlsext_host_name(TLScontext->con, props->host)) {
msg_warn("%s: error setting SNI hostname to: %s", props->namaddr,
props->host);
tls_free_context(TLScontext);
return (0);
}
if (log_mask & TLS_LOG_DEBUG)
msg_info("%s: SNI hostname: %s", props->namaddr, props->host);
}
#endif
/*
* Before really starting anything, try to seed the PRNG a little bit
@ -962,6 +959,8 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
if (log_mask & TLS_LOG_TLSPKTS)
BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
tls_dane_set_callback(app_ctx->ssl_ctx, TLScontext);
/*
* Start TLS negotiations. This process is a black box that invokes our
* call-backs for certificate verification.
@ -1006,23 +1005,25 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
/*
* Peer name or fingerprint verification as requested.
* Unconditionally set peer_CN, issuer_CN and peer_fingerprint.
* Unconditionally set peer_CN, issuer_CN and peer_cert_fprint. Check
* fingerprint first, and avoid logging verified as untrusted in the
* call to verify_extract_name().
*/
verify_extract_name(TLScontext, peercert, props);
verify_extract_print(TLScontext, peercert, props);
verify_extract_name(TLScontext, peercert, props);
if (TLScontext->log_mask &
(TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
msg_info("%s: subject_CN=%s, issuer_CN=%s, "
"fingerprint=%s, pkey_fingerprint=%s", props->namaddr,
TLScontext->peer_CN, TLScontext->issuer_CN,
TLScontext->peer_fingerprint,
TLScontext->peer_cert_fprint,
TLScontext->peer_pkey_fprint);
X509_free(peercert);
} else {
TLScontext->issuer_CN = mystrdup("");
TLScontext->peer_CN = mystrdup("");
TLScontext->peer_fingerprint = mystrdup("");
TLScontext->peer_cert_fprint = mystrdup("");
TLScontext->peer_pkey_fprint = mystrdup("");
}
@ -1046,7 +1047,9 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
*/
if (log_mask & TLS_LOG_SUMMARY)
msg_info("%s TLS connection established to %s: %s with cipher %s "
"(%d/%d bits)", TLS_CERT_IS_MATCHED(TLScontext) ? "Verified" :
"(%d/%d bits)",
!TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" :
TLS_CERT_IS_MATCHED(TLScontext) ? "Verified" :
TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted",
props->namaddr, TLScontext->protocol, TLScontext->cipher_name,
TLScontext->cipher_usebits, TLScontext->cipher_algbits);

View File

@ -1,4 +1,4 @@
/* $NetBSD: tls_server.c,v 1.7 2013/09/25 19:12:35 tron Exp $ */
/* $NetBSD: tls_server.c,v 1.8 2014/07/06 19:45:50 tron Exp $ */
/*++
/* NAME
@ -72,7 +72,7 @@
/* .IP TLScontext->issuer_CN
/* Extracted CommonName of the issuer, or zero-length string
/* when information could not be extracted.
/* .IP TLScontext->peer_fingerprint
/* .IP TLScontext->peer_cert_fprint
/* Fingerprint of the certificate, or zero-length string when no peer
/* certificate is available.
/* .PP
@ -185,8 +185,8 @@ static SSL_SESSION *get_server_session_cb(SSL *ssl, unsigned char *session_id,
do { \
buf = vstring_alloc(2 * (len + strlen(service))); \
hex_encode(buf, (char *) (id), (len)); \
vstring_sprintf_append(buf, "&s=%s", (service)); \
vstring_sprintf_append(buf, "&l=%ld", (long) SSLeay()); \
vstring_sprintf_append(buf, "&s=%s", (service)); \
vstring_sprintf_append(buf, "&l=%ld", (long) SSLeay()); \
} while (0)
@ -278,6 +278,53 @@ static int new_server_session_cb(SSL *ssl, SSL_SESSION *session)
return (1);
}
#define NOENGINE ((ENGINE *) 0)
#define TLS_TKT_NOKEYS -1 /* No keys for encryption */
#define TLS_TKT_STALE 0 /* No matching keys for decryption */
#define TLS_TKT_ACCEPT 1 /* Ticket decryptable and re-usable */
#define TLS_TKT_REISSUE 2 /* Ticket decryptable, not re-usable */
/* ticket_cb - configure tls session ticket encrypt/decrypt context */
#if defined(SSL_OP_NO_TICKET) \
&& !defined(OPENSSL_NO_TLSEXT) \
&& OPENSSL_VERSION_NUMBER >= 0x0090808fL
static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
EVP_CIPHER_CTX * ctx, HMAC_CTX * hctx, int create)
{
static const EVP_MD *sha256;
static const EVP_CIPHER *aes128;
TLS_TICKET_KEY *key;
TLS_SESS_STATE *TLScontext = SSL_get_ex_data(con, TLScontext_index);
int timeout = ((int) SSL_CTX_get_timeout(SSL_get_SSL_CTX(con))) / 2;
if ((!sha256 && (sha256 = EVP_sha256()) == 0)
|| (!aes128 && (aes128 = EVP_aes_128_cbc()) == 0)
|| (key = tls_mgr_key(create ? 0 : name, timeout)) == 0
|| (create && RAND_bytes(iv, TLS_TICKET_IVLEN) <= 0))
return (create ? TLS_TKT_NOKEYS : TLS_TKT_STALE);
HMAC_Init_ex(hctx, key->hmac, TLS_TICKET_MACLEN, sha256, NOENGINE);
if (create) {
EVP_EncryptInit_ex(ctx, aes128, NOENGINE, key->bits, iv);
memcpy((char *) name, (char *) key->name, TLS_TICKET_NAMELEN);
if (TLScontext->log_mask & TLS_LOG_CACHE)
msg_info("%s: Issuing session ticket, key expiration: %ld",
TLScontext->namaddr, (long) key->tout);
} else {
EVP_DecryptInit_ex(ctx, aes128, NOENGINE, key->bits, iv);
if (TLScontext->log_mask & TLS_LOG_CACHE)
msg_info("%s: Decrypting session ticket, key expiration: %ld",
TLScontext->namaddr, (long) key->tout);
}
TLScontext->ticketed = 1;
return (TLS_TKT_ACCEPT);
}
#endif
/* tls_server_init - initialize the server-side TLS engine */
TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
@ -286,10 +333,10 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
long off = 0;
int verify_flags = SSL_VERIFY_NONE;
int cachable;
int scache_timeout;
int ticketable = 0;
int protomask;
TLS_APPL_STATE *app_ctx;
const EVP_MD *md_alg;
unsigned int md_len;
int log_mask;
/*
@ -342,40 +389,12 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
}
}
/*
* Register SHA-2 digests, if implemented and not already registered.
* Improves interoperability with clients and servers that prematurely
* deploy SHA-2 certificates.
*/
#if defined(LN_sha256) && defined(NID_sha256) && !defined(OPENSSL_NO_SHA256)
if (!EVP_get_digestbyname(LN_sha224))
EVP_add_digest(EVP_sha224());
if (!EVP_get_digestbyname(LN_sha256))
EVP_add_digest(EVP_sha256());
#endif
#if defined(LN_sha512) && defined(NID_sha512) && !defined(OPENSSL_NO_SHA512)
if (!EVP_get_digestbyname(LN_sha384))
EVP_add_digest(EVP_sha384());
if (!EVP_get_digestbyname(LN_sha512))
EVP_add_digest(EVP_sha512());
#endif
/*
* If the administrator specifies an unsupported digest algorithm, fail
* now, rather than in the middle of a TLS handshake.
*/
if ((md_alg = EVP_get_digestbyname(props->fpt_dgst)) == 0) {
msg_warn("Digest algorithm \"%s\" not found: disabling TLS support",
props->fpt_dgst);
return (0);
}
/*
* Sanity check: Newer shared libraries may use larger digests.
*/
if ((md_len = EVP_MD_size(md_alg)) > EVP_MAX_MD_SIZE) {
msg_warn("Digest algorithm \"%s\" output size %u too large:"
" disabling TLS support", props->fpt_dgst, md_len);
if (!tls_validate_digest(props->mdalg)) {
msg_warn("disabling TLS support");
return (0);
}
@ -412,13 +431,42 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
*/
SSL_CTX_set_verify_depth(server_ctx, props->verifydepth + 1);
/*
* The session cache is implemented by the tlsmgr(8) server.
*
* XXX 200502 Surprise: when OpenSSL purges an entry from the in-memory
* cache, it also attempts to purge the entry from the on-disk cache.
* This is undesirable, especially when we set the in-memory cache size
* to 1. For this reason we don't allow OpenSSL to purge on-disk cache
* entries, and leave it up to the tlsmgr process instead. Found by
* Victor Duchovni.
*/
if (tls_mgr_policy(props->cache_type, &cachable,
&scache_timeout) != TLS_MGR_STAT_OK)
scache_timeout = 0;
if (scache_timeout <= 0)
cachable = 0;
/*
* Protocol work-arounds, OpenSSL version dependent.
*/
#ifdef SSL_OP_NO_TICKET
off |= SSL_OP_NO_TICKET;
#endif
off |= tls_bug_bits();
/*
* Add SSL_OP_NO_TICKET when the timeout is zero or library support is
* incomplete. The SSL_CTX_set_tlsext_ticket_key_cb feature was added in
* OpenSSL 0.9.8h, while SSL_NO_TICKET was added in 0.9.8f.
*/
#ifdef SSL_OP_NO_TICKET
#if !defined(OPENSSL_NO_TLSEXT) && OPENSSL_VERSION_NUMBER >= 0x0090808fL
ticketable = (scache_timeout > 0 && !(off & SSL_OP_NO_TICKET));
if (ticketable)
SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, ticket_cb);
#endif
if (!ticketable)
off |= SSL_OP_NO_TICKET;
#endif
SSL_CTX_set_options(server_ctx, off);
/*
@ -432,8 +480,6 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
| ((protomask & TLS_PROTOCOL_SSLv3) ? SSL_OP_NO_SSLv3 : 0L)
| ((protomask & TLS_PROTOCOL_SSLv2) ? SSL_OP_NO_SSLv2 : 0L));
#if OPENSSL_VERSION_NUMBER >= 0x0090700fL
/*
* Some sites may want to give the client less rope. On the other hand,
* this could trigger inter-operability issues, the client should not
@ -445,7 +491,6 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
*/
if (var_tls_preempt_clist)
SSL_CTX_set_options(server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif
/*
* Set the call-back routine to debug handshake progress.
@ -556,21 +601,7 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
*/
app_ctx = tls_alloc_app_context(server_ctx, log_mask);
/*
* The session cache is implemented by the tlsmgr(8) server.
*
* XXX 200502 Surprise: when OpenSSL purges an entry from the in-memory
* cache, it also attempts to purge the entry from the on-disk cache.
* This is undesirable, especially when we set the in-memory cache size
* to 1. For this reason we don't allow OpenSSL to purge on-disk cache
* entries, and leave it up to the tlsmgr process instead. Found by
* Victor Duchovni.
*/
if (tls_mgr_policy(props->cache_type, &cachable) != TLS_MGR_STAT_OK)
cachable = 0;
if (cachable || props->set_sessid) {
if (cachable || ticketable || props->set_sessid) {
/*
* Initialize the session cache.
@ -607,9 +638,14 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
/*
* OpenSSL ignores timed-out sessions. We need to set the internal
* cache timeout at least as high as the external cache timeout. This
* applies even if no internal cache is used.
* applies even if no internal cache is used. We set the session
* lifetime to twice the cache lifetime, which is also the issuing
* and retired key validation lifetime of session tickets keys. This
* way a session always lasts longer than the server's ability to
* decrypt its session ticket. Otherwise, a bug in OpenSSL may fail
* to re-issue tickets when sessions decrypt, but are expired.
*/
SSL_CTX_set_timeout(server_ctx, props->scache_timeout);
SSL_CTX_set_timeout(server_ctx, 2 * scache_timeout);
} else {
/*
@ -666,9 +702,8 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props)
TLScontext->serverid = mystrdup(props->serverid);
TLScontext->am_server = 1;
TLScontext->fpt_dgst = mystrdup(props->fpt_dgst);
TLScontext->stream = props->stream;
TLScontext->mdalg = props->mdalg;
ERR_clear_error();
if ((TLScontext->con = (SSL *) SSL_new(app_ctx->ssl_ctx)) == 0) {
@ -764,7 +799,7 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props)
TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
{
const SSL_CIPHER *cipher;
SSL_CIPHER_const SSL_CIPHER *cipher;
X509 *peer;
char buf[CCERT_BUFSIZ];
@ -778,7 +813,8 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
*/
TLScontext->session_reused = SSL_session_reused(TLScontext->con);
if ((TLScontext->log_mask & TLS_LOG_CACHE) && TLScontext->session_reused)
msg_info("%s: Reusing old session", TLScontext->namaddr);
msg_info("%s: Reusing old session%s", TLScontext->namaddr,
TLScontext->ticketed ? " (RFC 5077 session ticket)" : "");
/*
* Let's see whether a peer certificate is available and what is the
@ -800,24 +836,23 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
}
TLScontext->peer_CN = tls_peer_CN(peer, TLScontext);
TLScontext->issuer_CN = tls_issuer_CN(peer, TLScontext);
TLScontext->peer_fingerprint =
tls_fingerprint(peer, TLScontext->fpt_dgst);
TLScontext->peer_pkey_fprint =
tls_pkey_fprint(peer, TLScontext->fpt_dgst);
TLScontext->peer_cert_fprint = tls_cert_fprint(peer, TLScontext->mdalg);
TLScontext->peer_pkey_fprint = tls_pkey_fprint(peer, TLScontext->mdalg);
if (TLScontext->log_mask & (TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) {
msg_info("%s: subject_CN=%s, issuer=%s, fingerprint=%s"
", pkey_fingerprint=%s",
TLScontext->namaddr,
TLScontext->peer_CN, TLScontext->issuer_CN,
TLScontext->peer_fingerprint,
TLScontext->peer_cert_fprint,
TLScontext->peer_pkey_fprint);
}
X509_free(peer);
} else {
TLScontext->peer_CN = mystrdup("");
TLScontext->issuer_CN = mystrdup("");
TLScontext->peer_fingerprint = mystrdup("");
TLScontext->peer_cert_fprint = mystrdup("");
TLScontext->peer_pkey_fprint = mystrdup("");
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: dict_sockmap.c,v 1.3 2013/11/14 02:27:29 christos Exp $ */
/* $NetBSD: dict_sockmap.c,v 1.4 2014/07/06 19:45:50 tron Exp $ */
/*++
/* NAME
@ -311,36 +311,44 @@ static void dict_sockmap_close(DICT *dict)
DICT *dict_sockmap_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_SOCKMAP *dp;
char *saved_name;
char *saved_name = 0;
char *sockmap;
DICT_SOCKMAP_REFC_HANDLE *ref_handle;
HTABLE_INFO *client_info;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_SOCKMAP_OPEN_RETURN(d) { \
DICT *__d = (d); \
if (saved_name != 0) \
myfree(saved_name); \
return (__d); \
} while (0)
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_SOCKMAP, mapname));
DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_SOCKMAP, mapname));
if (dict_flags & DICT_FLAG_NO_UNAUTH)
return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s:%s map is not allowed for security-sensitive data",
DICT_TYPE_SOCKMAP, mapname));
DICT_TYPE_SOCKMAP, mapname));
/*
* Separate the socketmap name from the socketmap server name.
*/
saved_name = mystrdup(mapname);
if ((sockmap = split_at_right(saved_name, ':')) == 0) {
myfree(saved_name);
return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s requires server:socketmap argument",
DICT_TYPE_SOCKMAP));
}
if ((sockmap = split_at_right(saved_name, ':')) == 0)
DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s requires server:socketmap argument",
DICT_TYPE_SOCKMAP));
/*
* Use one reference-counted client handle for all socketmaps with the
@ -374,10 +382,5 @@ DICT *dict_sockmap_open(const char *mapname, int open_flags, int dict_flags)
/* Don't look up parent domains or network superblocks. */
dp->dict.flags = dict_flags | DICT_FLAG_PATTERN;
/*
* Clean up.
*/
myfree(saved_name);
return (DICT_DEBUG (&dp->dict));
DICT_SOCKMAP_OPEN_RETURN(DICT_DEBUG (&dp->dict));
}

View File

@ -1,138 +0,0 @@
/* $NetBSD: read_wait.c,v 1.1.1.2 2010/06/17 18:07:15 tron Exp $ */
/*++
/* NAME
/* read_wait 3
/* SUMMARY
/* wait until descriptor becomes readable
/* SYNOPSIS
/* #include <iostuff.h>
/*
/* int read_wait(fd, timeout)
/* int fd;
/* int timeout;
/* DESCRIPTION
/* read_wait() blocks the current process until the specified file
/* descriptor becomes readable, or until the deadline is exceeded.
/*
/* Arguments:
/* .IP fd
/* File descriptor in the range 0..FD_SETSIZE (on systems that
/* need to use select(2)).
/* .IP timeout
/* If positive, deadline in seconds. A zero value effects a poll.
/* A negative value means wait until something happens.
/* DIAGNOSTICS
/* Panic: interface violation. All system call errors are fatal.
/*
/* A zero result means success. When the specified deadline is
/* exceeded, read_wait() returns -1 and sets errno to ETIMEDOUT.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#ifdef USE_SYSV_POLL
#include <poll.h>
#endif
#ifdef USE_SYS_SELECT_H
#include <sys/select.h>
#endif
/* Utility library. */
#include <msg.h>
#include <iostuff.h>
/* read_wait - block with timeout until file descriptor is readable */
int read_wait(int fd, int timeout)
{
#ifndef USE_SYSV_POLL
fd_set read_fds;
fd_set except_fds;
struct timeval tv;
struct timeval *tp;
/*
* Sanity checks.
*/
if (FD_SETSIZE <= fd)
msg_panic("descriptor %d does not fit FD_SETSIZE %d", fd, FD_SETSIZE);
/*
* Use select() so we do not depend on alarm() and on signal() handlers.
* Restart the select when interrupted by some signal. Some select()
* implementations reduce the time to wait when interrupted, which is
* exactly what we want.
*/
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
FD_ZERO(&except_fds);
FD_SET(fd, &except_fds);
if (timeout >= 0) {
tv.tv_usec = 0;
tv.tv_sec = timeout;
tp = &tv;
} else {
tp = 0;
}
for (;;) {
switch (select(fd + 1, &read_fds, (fd_set *) 0, &except_fds, tp)) {
case -1:
if (errno != EINTR)
msg_fatal("select: %m");
continue;
case 0:
errno = ETIMEDOUT;
return (-1);
default:
return (0);
}
}
#else
/*
* System-V poll() is optimal for polling a few descriptors.
*/
struct pollfd pollfd;
#define WAIT_FOR_EVENT (-1)
pollfd.fd = fd;
pollfd.events = POLLIN;
for (;;) {
switch (poll(&pollfd, 1, timeout < 0 ?
WAIT_FOR_EVENT : timeout * 1000)) {
case -1:
if (errno != EINTR)
msg_fatal("poll: %m");
continue;
case 0:
errno = ETIMEDOUT;
return (-1);
default:
if (pollfd.revents & POLLNVAL)
msg_fatal("poll: %m");
return (0);
}
}
#endif
}

View File

@ -1,121 +0,0 @@
/* $NetBSD: readable.c,v 1.1.1.1 2009/06/23 10:09:00 tron Exp $ */
/*++
/* NAME
/* readable 3
/* SUMMARY
/* test if descriptor is readable
/* SYNOPSIS
/* #include <iostuff.h>
/*
/* int readable(fd)
/* int fd;
/* DESCRIPTION
/* readable() asks the kernel if the specified file descriptor
/* is readable, i.e. a read operation would not block.
/*
/* Arguments:
/* .IP fd
/* File descriptor in the range 0..FD_SETSIZE.
/* DIAGNOSTICS
/* All system call errors are fatal.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#ifdef USE_SYSV_POLL
#include <poll.h>
#endif
#ifdef USE_SYS_SELECT_H
#include <sys/select.h>
#endif
/* Utility library. */
#include <msg.h>
#include <iostuff.h>
/* readable - see if file descriptor is readable */
int readable(int fd)
{
#ifndef USE_SYSV_POLL
struct timeval tv;
fd_set read_fds;
fd_set except_fds;
/*
* Sanity checks.
*/
if (fd >= FD_SETSIZE)
msg_fatal("fd %d does not fit in FD_SETSIZE", fd);
/*
* Initialize.
*/
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
FD_ZERO(&except_fds);
FD_SET(fd, &except_fds);
tv.tv_sec = 0;
tv.tv_usec = 0;
/*
* Loop until we have an authoritative answer.
*/
for (;;) {
switch (select(fd + 1, &read_fds, (fd_set *) 0, &except_fds, &tv)) {
case -1:
if (errno != EINTR)
msg_fatal("select: %m");
continue;
default:
return (FD_ISSET(fd, &read_fds));
case 0:
return (0);
}
}
#else
/*
* System-V poll() is optimal for polling a few descriptors.
*/
struct pollfd pollfd;
#define DONT_WAIT_FOR_EVENT 0
pollfd.fd = fd;
pollfd.events = POLLIN;
for (;;) {
switch (poll(&pollfd, 1, DONT_WAIT_FOR_EVENT)) {
case -1:
if (errno != EINTR)
msg_fatal("poll: %m");
continue;
case 0:
return (0);
default:
if (pollfd.revents & POLLNVAL)
msg_fatal("poll: %m");
return (1);
}
}
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_defs.h,v 1.6 2013/09/25 19:12:35 tron Exp $ */
/* $NetBSD: sys_defs.h,v 1.7 2014/07/06 19:45:51 tron Exp $ */
#ifndef _SYS_DEFS_H_INCLUDED_
#define _SYS_DEFS_H_INCLUDED_
@ -32,8 +32,8 @@
|| defined(OPENBSD2) || defined(OPENBSD3) || defined(OPENBSD4) \
|| defined(OPENBSD5) \
|| defined(NETBSD1) || defined(NETBSD2) || defined(NETBSD3) \
|| defined(NETBSD4) \
|| defined(EKKOBSD1)
|| defined(NETBSD4) || defined(NETBSD5) || defined(NETBSD6) \
|| defined(EKKOBSD1) || defined(DRAGONFLY)
#define SUPPORTED
#include <sys/types.h>
#include <sys/param.h>
@ -48,15 +48,15 @@
#define HAS_FSYNC
#define HAS_DB
#define HAS_SA_LEN
#define DEF_DB_TYPE "hash"
#define NATIVE_DB_TYPE "hash"
#if (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 104250000)
#define ALIAS_DB_MAP "hash:/etc/mail/aliases" /* sendmail 8.10 */
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases" /* sendmail 8.10 */
#endif
#if (defined(OpenBSD) && OpenBSD >= 200006)
#define ALIAS_DB_MAP "hash:/etc/mail/aliases" /* OpenBSD 2.7 */
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases" /* OpenBSD 2.7 */
#endif
#ifndef ALIAS_DB_MAP
#define ALIAS_DB_MAP "hash:/etc/aliases"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin"
@ -167,9 +167,19 @@
#define HAS_FUTIMES
#endif
#if defined(__DragonFly__)
#define HAS_DEV_URANDOM
#define HAS_ISSETUGID
#define HAS_FUTIMES
#define SOCKADDR_SIZE socklen_t
#define SOCKOPT_SIZE socklen_t
#define HAS_DUPLEX_PIPE
#endif
#if (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105000000) \
|| (defined(__FreeBSD__) && __FreeBSD__ >= 4) \
|| (defined(OpenBSD) && OpenBSD >= 200003) \
|| defined(__DragonFly__) \
|| defined(USAGI_LIBINET6)
#ifndef NO_IPV6
# define HAS_IPV6
@ -178,14 +188,16 @@
#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300000) \
|| (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 103000000) \
|| (defined(OpenBSD) && OpenBSD >= 199700) /* OpenBSD 2.0?? */
|| (defined(OpenBSD) && OpenBSD >= 199700) /* OpenBSD 2.0?? */ \
|| defined(__DragonFly__)
# define USE_SYSV_POLL
#endif
#ifndef NO_KQUEUE
# if (defined(__FreeBSD_version) && __FreeBSD_version >= 410000) \
|| (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 200000000) \
|| (defined(OpenBSD) && OpenBSD >= 200105) /* OpenBSD 2.9 */
|| (defined(OpenBSD) && OpenBSD >= 200105) /* OpenBSD 2.9 */ \
|| defined(__DragonFly__)
# define EVENTS_STYLE EVENTS_STYLE_KQUEUE
# endif
#endif
@ -217,8 +229,8 @@
#define HAS_FSYNC
#define HAS_DB
#define HAS_SA_LEN
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
#define NATIVE_DB_TYPE "hash"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin"
#define USE_STATFS
@ -244,8 +256,9 @@
#define SOCKOPT_SIZE socklen_t
#ifndef NO_KQUEUE
# define EVENTS_STYLE EVENTS_STYLE_KQUEUE
# define USE_SYSV_POLL
# define USE_SYSV_POLL_THEN_SELECT
#endif
#define USE_MAX_FILES_PER_PROC
#ifndef NO_POSIX_GETPW_R
# define HAVE_POSIX_GETPW_R
#endif
@ -276,12 +289,12 @@
#define HAS_FSYNC
/* might be set by makedef */
#ifdef HAS_DB
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
#define NATIVE_DB_TYPE "hash"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#else
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#endif
extern int optind;
extern char *optarg;
@ -325,8 +338,8 @@ extern int h_errno;
#define HAS_FSYNC
#define HAVE_BASENAME
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/var/adm/sendmail/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/var/adm/sendmail/aliases"
extern int optind; /* XXX use <getopt.h> */
extern char *optarg; /* XXX use <getopt.h> */
extern int opterr; /* XXX use <getopt.h> */
@ -372,8 +385,8 @@ extern int opterr; /* XXX use <getopt.h> */
#define DEF_MAILBOX_LOCK "flock, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
extern int optind;
extern char *optarg;
extern int opterr;
@ -418,11 +431,13 @@ extern int opterr;
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
#ifndef NO_NIS
#define HAS_NIS
#ifndef NO_NISPLUS
#define HAS_NISPLUS
#endif /* NO_NISPLUS */
#endif
#define USE_SYS_SOCKIO_H /* Solaris 2.5, changed sys/ioctl.h */
#define GETTIMEOFDAY(t) gettimeofday(t)
@ -495,8 +510,8 @@ extern int opterr;
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
@ -526,8 +541,8 @@ extern int opterr;
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
#ifndef NO_NIS
#define HAS_NIS */
#endif
@ -569,8 +584,8 @@ extern int opterr;
#define USE_SYS_SELECT_H
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
@ -623,8 +638,8 @@ extern int opterr;
#define USE_SYS_SELECT_H
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
@ -669,8 +684,8 @@ extern int initgroups(const char *, int);
#define USE_SYS_SELECT_H
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
@ -711,8 +726,8 @@ extern int initgroups(const char *, int);
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
@ -755,8 +770,8 @@ extern int initgroups(const char *, int);
#define DEF_MAILBOX_LOCK "fcntl, dotlock" /* RedHat >= 4.x */
#define HAS_FSYNC
#define HAS_DB
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
#define NATIVE_DB_TYPE "hash"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
@ -832,8 +847,8 @@ extern int initgroups(const char *, int);
#define DEF_MAILBOX_LOCK "dotlock" /* verified RedHat 3.03 */
#define HAS_FSYNC
#define HAS_DB
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
#define NATIVE_DB_TYPE "hash"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
@ -866,8 +881,8 @@ extern int initgroups(const char *, int);
#define DEF_MAILBOX_LOCK "fcntl, dotlock" /* RedHat >= 4.x */
#define HAS_FSYNC
#define HAS_DB
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
#define NATIVE_DB_TYPE "hash"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
@ -932,8 +947,8 @@ extern int initgroups(const char *, int);
#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
#define ROOT_PATH "/usr/bin:/sbin:/usr/sbin"
#define MISSING_SETENV
#ifndef NO_NIS
@ -971,8 +986,8 @@ extern int h_errno; /* <netdb.h> imports too much stuff */
#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
#define ROOT_PATH "/usr/bin:/sbin:/usr/sbin"
#define MISSING_SETENV
#ifndef NO_NIS
@ -1016,8 +1031,8 @@ extern int h_errno; /* <netdb.h> imports too much stuff */
#define MISSING_SETENV
#define MISSING_RLIMIT_FSIZE
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/usr/lib/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/usr/lib/aliases"
#define ROOT_PATH "/bin:/usr/bin:/etc"
#define _PATH_BSHELL "/bin/sh"
#define _PATH_MAILDIR "/usr/mail"
@ -1076,7 +1091,7 @@ extern int h_errno;
#define _PATH_DEFPATH "/bin:/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/bin:/usr/bin:/usr/ucb"
#define ROOT_PATH "/bin:/usr/bin:/usr/etc:/usr/ucb"
#define DEF_DB_TYPE "dbm"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP "netinfo:/aliases"
#include <libc.h>
#define MISSING_POSIX_S_IS
@ -1131,7 +1146,7 @@ typedef unsigned short mode_t;
#define _PATH_DEFPATH "/bin:/usr/bin:/usr/ucb"
#define _PATH_STDPATH "/bin:/usr/bin:/usr/ucb"
#define ROOT_PATH "/bin:/usr/bin:/usr/etc:/usr/ucb"
#define DEF_DB_TYPE "dbm"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP "netinfo:/aliases"
#include <libc.h>
#define MISSING_POSIX_S_IS
@ -1168,8 +1183,8 @@ typedef unsigned short mode_t;
#define FIONREAD_IN_SYS_FILIO_H
#define USE_SYS_SOCKIO_H
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/var/adm/sendmail/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/var/adm/sendmail/aliases"
extern int optind; /* XXX use <getopt.h> */
extern char *optarg; /* XXX use <getopt.h> */
extern int opterr; /* XXX use <getopt.h> */
@ -1198,8 +1213,8 @@ extern int opterr; /* XXX use <getopt.h> */
#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
#define NATIVE_DB_TYPE "hash"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
/* Uncomment the following line if you have NIS package installed */
/* #define HAS_NIS */
#define USE_SYS_SOCKIO_H
@ -1231,8 +1246,8 @@ extern int h_errno;
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define NATIVE_DB_TYPE "dbm"
#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
#define DBM_NO_TRAILING_NULL
#ifndef NO_NIS
#define HAS_NIS
@ -1292,6 +1307,10 @@ extern int h_errno;
#endif
#endif
#ifndef DEF_DB_TYPE
#define DEF_DB_TYPE NATIVE_DB_TYPE
#endif
#define CAST_CHAR_PTR_TO_INT(cptr) ((int) (long) (cptr))
#define CAST_INT_TO_CHAR_PTR(ival) ((char *) (long) (ival))
@ -1372,8 +1391,14 @@ extern int inet_pton(int, const char *, void *);
#define EVENTS_STYLE_DEVPOLL 3 /* Solaris /dev/poll */
#define EVENTS_STYLE_EPOLL 4 /* Linux epoll */
#if !defined(USE_SYSV_POLL) && (EVENTS_STYLE != EVENTS_STYLE_SELECT)
#error "need USE_SYSV_POLL with EVENTS_STYLE != EVENTS_STYLE_SELECT"
/*
* We use poll() for read/write time limit enforcement on modern systems. We
* use select() on historical systems without poll() support. And on systems
* where poll() is not implemented for some file handle types, we try to use
* select() as a fall-back solution (MacOS X needs this).
*/
#if !defined(USE_SYSV_POLL) && !defined(USE_SYSV_POLL_THEN_SELECT)
#define USE_BSD_SELECT
#endif
/*

View File

@ -1,121 +0,0 @@
/* $NetBSD: writable.c,v 1.1.1.1 2009/06/23 10:09:01 tron Exp $ */
/*++
/* NAME
/* writable 3
/* SUMMARY
/* test if descriptor is writable
/* SYNOPSIS
/* #include <iostuff.h>
/*
/* int writable(fd)
/* int fd;
/* DESCRIPTION
/* writable() asks the kernel if the specified file descriptor
/* is writable, i.e. a write operation would not block.
/*
/* Arguments:
/* .IP fd
/* File descriptor in the range 0..FD_SETSIZE.
/* DIAGNOSTICS
/* All system call errors are fatal.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#ifdef USE_SYSV_POLL
#include <poll.h>
#endif
#ifdef USE_SYS_SELECT_H
#include <sys/select.h>
#endif
/* Utility library. */
#include <msg.h>
#include <iostuff.h>
/* writable - see if file descriptor is writable */
int writable(int fd)
{
#ifndef USE_SYSV_POLL
struct timeval tv;
fd_set write_fds;
fd_set except_fds;
/*
* Sanity checks.
*/
if (fd >= FD_SETSIZE)
msg_fatal("fd %d does not fit in FD_SETSIZE", fd);
/*
* Initialize.
*/
FD_ZERO(&write_fds);
FD_SET(fd, &write_fds);
FD_ZERO(&except_fds);
FD_SET(fd, &except_fds);
tv.tv_sec = 0;
tv.tv_usec = 0;
/*
* Loop until we have an authoritative answer.
*/
for (;;) {
switch (select(fd + 1, (fd_set *) 0, &write_fds, &except_fds, &tv)) {
case -1:
if (errno != EINTR)
msg_fatal("select: %m");
continue;
default:
return (FD_ISSET(fd, &write_fds));
case 0:
return (0);
}
}
#else
/*
* System-V poll() is optimal for polling a few descriptors.
*/
struct pollfd pollfd;
#define DONT_WAIT_FOR_EVENT 0
pollfd.fd = fd;
pollfd.events = POLLOUT;
for (;;) {
switch (poll(&pollfd, 1, DONT_WAIT_FOR_EVENT)) {
case -1:
if (errno != EINTR)
msg_fatal("poll: %m");
continue;
case 0:
return (0);
default:
if (pollfd.revents & POLLNVAL)
msg_fatal("poll: %m");
return (1);
}
}
#endif
}

View File

@ -1,137 +0,0 @@
/* $NetBSD: write_wait.c,v 1.1.1.1 2009/06/23 10:09:01 tron Exp $ */
/*++
/* NAME
/* write_wait 3
/* SUMMARY
/* wait until descriptor becomes writable
/* SYNOPSIS
/* #include <iostuff.h>
/*
/* int write_wait(fd, timeout)
/* int fd;
/* int timeout;
/* DESCRIPTION
/* write_wait() blocks the current process until the specified file
/* descriptor becomes writable, or until the deadline is exceeded.
/*
/* Arguments:
/* .IP fd
/* File descriptor in the range 0..FD_SETSIZE.
/* .IP timeout
/* If positive, deadline in seconds. A zero value effects a poll.
/* A negative value means wait until something happens.
/* DIAGNOSTICS
/* Panic: interface violation. All system call errors are fatal.
/*
/* A zero result means success. When the specified deadline is
/* exceeded, write_wait() returns -1 and sets errno to ETIMEDOUT.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#ifdef USE_SYSV_POLL
#include <poll.h>
#endif
#ifdef USE_SYS_SELECT_H
#include <sys/select.h>
#endif
/* Utility library. */
#include <msg.h>
#include <iostuff.h>
/* write_wait - block with timeout until file descriptor is writable */
int write_wait(int fd, int timeout)
{
#ifndef USE_SYSV_POLL
fd_set write_fds;
fd_set except_fds;
struct timeval tv;
struct timeval *tp;
/*
* Sanity checks.
*/
if (FD_SETSIZE <= fd)
msg_panic("descriptor %d does not fit FD_SETSIZE %d", fd, FD_SETSIZE);
/*
* Guard the write() with select() so we do not depend on alarm() and on
* signal() handlers. Restart the select when interrupted by some signal.
* Some select() implementations may reduce the time to wait when
* interrupted, which is exactly what we want.
*/
FD_ZERO(&write_fds);
FD_SET(fd, &write_fds);
FD_ZERO(&except_fds);
FD_SET(fd, &except_fds);
if (timeout >= 0) {
tv.tv_usec = 0;
tv.tv_sec = timeout;
tp = &tv;
} else {
tp = 0;
}
for (;;) {
switch (select(fd + 1, (fd_set *) 0, &write_fds, &except_fds, tp)) {
case -1:
if (errno != EINTR)
msg_fatal("select: %m");
continue;
case 0:
errno = ETIMEDOUT;
return (-1);
default:
return (0);
}
}
#else
/*
* System-V poll() is optimal for polling a few descriptors.
*/
struct pollfd pollfd;
#define WAIT_FOR_EVENT (-1)
pollfd.fd = fd;
pollfd.events = POLLOUT;
for (;;) {
switch (poll(&pollfd, 1, timeout < 0 ?
WAIT_FOR_EVENT : timeout * 1000)) {
case -1:
if (errno != EINTR)
msg_fatal("poll: %m");
continue;
case 0:
errno = ETIMEDOUT;
return (-1);
default:
if (pollfd.revents & POLLNVAL)
msg_fatal("poll: %m");
return (0);
}
}
#endif
}