mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-22 18:07:41 +00:00
postfix-2.11-20131228
This commit is contained in:
parent
35467ac47f
commit
6ff1c3ac62
3
postfix/.indent.pro
vendored
3
postfix/.indent.pro
vendored
@ -64,6 +64,9 @@
|
|||||||
-TDELTA_TIME
|
-TDELTA_TIME
|
||||||
-TDICT
|
-TDICT
|
||||||
-TDICT_CACHE
|
-TDICT_CACHE
|
||||||
|
-TDICT_CACHE_SREQ
|
||||||
|
-TDICT_CACHE_SREQ_INFO
|
||||||
|
-TDICT_CACHE_TEST
|
||||||
-TDICT_CDBM
|
-TDICT_CDBM
|
||||||
-TDICT_CDBQ
|
-TDICT_CDBQ
|
||||||
-TDICT_CIDR
|
-TDICT_CIDR
|
||||||
|
@ -19409,8 +19409,8 @@ Apologies for any names omitted.
|
|||||||
20131219
|
20131219
|
||||||
|
|
||||||
Cleanup: renamed postconf(1) internal identifiers according
|
Cleanup: renamed postconf(1) internal identifiers according
|
||||||
to a consistent scheme, to avoid name future name conflicts
|
to a consistent scheme, to avoid future name conflicts as
|
||||||
as Postfix evolves. This is a no-feature change. Files:
|
Postfix evolves. This is a no-feature change. Files:
|
||||||
postconf/*.[hc], postconf/extract.awk.
|
postconf/*.[hc], postconf/extract.awk.
|
||||||
|
|
||||||
Documentation: linearized the order of exposition in
|
Documentation: linearized the order of exposition in
|
||||||
@ -19440,3 +19440,32 @@ Apologies for any names omitted.
|
|||||||
|
|
||||||
Documentation: added section on how to verify that forward
|
Documentation: added section on how to verify that forward
|
||||||
secrecy works. File: proto/FORWARD_SECRECY_README.html.
|
secrecy works. File: proto/FORWARD_SECRECY_README.html.
|
||||||
|
|
||||||
|
20131222
|
||||||
|
|
||||||
|
Documentation: forward secrecy, with feedback from Adam
|
||||||
|
Shostack. Viktor Dukhovni and Wietse Venema. File:
|
||||||
|
proto/FORWARD_SECRECY_README.html.
|
||||||
|
|
||||||
|
20131224
|
||||||
|
|
||||||
|
Feature: smtpd_sasl_service (until now, this was hard-coded
|
||||||
|
internally as "smtp"). On request by Michal (sksoft.cz).
|
||||||
|
Files: global/mail_params.h, proto/postconf.proto,
|
||||||
|
mantools/postlink, smtpd/smtpd.c, smtpd/smtpd_sasl_glue.c.
|
||||||
|
|
||||||
|
Documentation: updated example to Dovecot version 2 syntax.
|
||||||
|
File: proto/SASL_README/html.
|
||||||
|
|
||||||
|
20131228
|
||||||
|
|
||||||
|
Cleanup: DANE support: test script. Viktor Dukhovni. File
|
||||||
|
tls/tls_dane.sh.
|
||||||
|
|
||||||
|
LMDB will not be supported in the stable Postfix 2.11 release.
|
||||||
|
|
||||||
|
Debugging: test driver to speed up LMDB debugging and stress
|
||||||
|
testing. Shockingly, LMDB terminates the postcreen daemon
|
||||||
|
without logfile record. Fixing this will require changes
|
||||||
|
in LMDB or changes in the way Postfix can use LMDB. File:
|
||||||
|
util/dict_cache.c.
|
||||||
|
@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
WWaarrnniinngg
|
||||||
|
|
||||||
|
Forward secrecy does not protect against active attacks such as forged DNS
|
||||||
|
replies or forged TLS server certificates. If such attacks are a concern, then
|
||||||
|
the SMTP client will need to authenticate the remote SMTP server in a
|
||||||
|
sufficiently-secure manner. For example, by the fingerprint of the public key
|
||||||
|
or certificate. Conventional PKI relies on many trusted parties and is easily
|
||||||
|
subverted by a state-funded adversary.
|
||||||
|
|
||||||
BBaacckkggrroouunndd
|
BBaacckkggrroouunndd
|
||||||
|
|
||||||
Postfix supports forward secrecy of TLS network communication since version
|
Postfix supports forward secrecy of TLS network communication since version
|
||||||
@ -34,18 +43,15 @@ cost constraints on the efficacy of bulk surveillance, recovering all past
|
|||||||
traffic is generally infeasible, and even recovery of individual sessions may
|
traffic is generally infeasible, and even recovery of individual sessions may
|
||||||
be infeasible given a sufficiently-strong key agreement method.
|
be infeasible given a sufficiently-strong key agreement method.
|
||||||
|
|
||||||
Forward secrecy protects network communication in the absence of active
|
|
||||||
attacks, i.e. no forged DNS replies, and no forged TLS server certificates. If
|
|
||||||
active attacks are a concern, then you will need to authenticate the remote
|
|
||||||
SMTP server in a secure manner. For example, by the fingerprint of the public
|
|
||||||
key or certificate. Conventional PKI relies on too many trusted parties.
|
|
||||||
|
|
||||||
Topics covered in this document:
|
Topics covered in this document:
|
||||||
|
|
||||||
* Forward Secrecy in TLS
|
* Forward Secrecy in TLS
|
||||||
* Forward Secrecy in the Postfix SMTP Server
|
* Forward Secrecy in the Postfix SMTP Server
|
||||||
* Forward Secrecy in the Postfix SMTP Client
|
* Forward Secrecy in the Postfix SMTP Client
|
||||||
* How do I know that it works?
|
* Getting started, quick and dirty
|
||||||
|
* How can I see that a connection has forward secrecy?
|
||||||
|
* What ciphers provide forward secrecy?
|
||||||
|
* What do "Anonymous", "Untrusted", etc. in Postfix logging mean?
|
||||||
* Credits
|
* Credits
|
||||||
|
|
||||||
And last but not least, for the impatient:
|
And last but not least, for the impatient:
|
||||||
@ -71,18 +77,19 @@ not compromised by future disclosure of long-term authentication keys.
|
|||||||
|
|
||||||
The key-exchange algorithms used for forward secrecy require the TLS server to
|
The key-exchange algorithms used for forward secrecy require the TLS server to
|
||||||
designate appropriate "parameters" consisting of a mathematical "group" and an
|
designate appropriate "parameters" consisting of a mathematical "group" and an
|
||||||
element of that group called a "generator". There are two flavors of "groups"
|
element of that group called a "generator". Presently, there are two flavors of
|
||||||
that work with PFS:
|
"groups" that work with PFS:
|
||||||
|
|
||||||
* Prime field groups. The server needs to be configured with a suitably large
|
* PPrriimmee--ffiieelldd ggrroouuppss ((EEDDHH)):: The server needs to be configured with a
|
||||||
prime and a corresponding "generator".
|
suitably-large prime and a corresponding "generator". The acronym for
|
||||||
* Elliptic curve groups. The server needs to be configured with a "named
|
forward secrecy over prime fields is EDH or Ephemeral Diffie-Hellman
|
||||||
curve". These offer better security at lower computational cost than prime
|
(sometimes also abbreviated as DHE).
|
||||||
field groups, but are not as widely implemented.
|
|
||||||
|
|
||||||
The acronym for forward secrecy over prime fields is EDH or Ephemeral Diffie-
|
* EElllliippttiicc--ccuurrvvee ggrroouuppss ((EEEECCDDHH)):: The server needs to be configured with a
|
||||||
Hellman (sometimes also abbreviated as DHE). The acronym for the elliptic curve
|
"named curve". These offer better security at lower computational cost than
|
||||||
version is EECDH which is short for Ephemeral Elliptic Curve Diffie-Hellman.
|
prime field groups, but are not as widely implemented. The acronym for the
|
||||||
|
elliptic curve version is EECDH which is short for Ephemeral Elliptic Curve
|
||||||
|
Diffie-Hellman.
|
||||||
|
|
||||||
It is not essential to know what these are, but one does need to know that
|
It is not essential to know what these are, but one does need to know that
|
||||||
OpenSSL only supports EECDH as of version 1.0.0. Thus the configuration
|
OpenSSL only supports EECDH as of version 1.0.0. Thus the configuration
|
||||||
@ -155,7 +162,7 @@ supported. The OpenSSL code for making this possible is not yet released as of
|
|||||||
late 2013 (it is available only in OpenSSL development snapshots).
|
late 2013 (it is available only in OpenSSL development snapshots).
|
||||||
|
|
||||||
At some point Postfix will need to adjust to the new API for setting the
|
At some point Postfix will need to adjust to the new API for setting the
|
||||||
elliptic curve options. Fortunately, when EECDH support was added to Postfix,
|
elliptic-curve options. Fortunately, when EECDH support was added to Postfix,
|
||||||
it introduced a layer of indirection:
|
it introduced a layer of indirection:
|
||||||
|
|
||||||
smtpd_tls_eecdh_grade = strong | ultra
|
smtpd_tls_eecdh_grade = strong | ultra
|
||||||
@ -172,10 +179,12 @@ main.cf.
|
|||||||
FFoorrwwaarrdd SSeeccrreeccyy iinn tthhee PPoossttffiixx SSMMTTPP CClliieenntt
|
FFoorrwwaarrdd SSeeccrreeccyy iinn tthhee PPoossttffiixx SSMMTTPP CClliieenntt
|
||||||
|
|
||||||
The Postfix >= 2.2 SMTP client supports forward secrecy in its default
|
The Postfix >= 2.2 SMTP client supports forward secrecy in its default
|
||||||
configuration. If the remote SMTP server supports cipher suites with forward
|
configuration. No configuration changes are needed besides turning on elliptic-
|
||||||
secrecy (and does not override the SMTP client cipher preference), then the
|
curve support with Postfix 2.6 and 2.7 (see the quick-start section). If the
|
||||||
traffic between the server and client will resist decryption even if the
|
remote SMTP server supports cipher suites with forward secrecy (and does not
|
||||||
server's long-term authentication keys are later compromised.
|
override the SMTP client's cipher preference), then the traffic between the
|
||||||
|
server and client will resist decryption even if the server's long-term
|
||||||
|
authentication keys are later compromised.
|
||||||
|
|
||||||
The default Postfix SMTP client cipher lists are correctly ordered to prefer
|
The default Postfix SMTP client cipher lists are correctly ordered to prefer
|
||||||
EECDH and EDH cipher suites ahead of similar cipher suites that don't implement
|
EECDH and EDH cipher suites ahead of similar cipher suites that don't implement
|
||||||
@ -189,8 +198,22 @@ a case-by-case basis via the TLS policy table.
|
|||||||
|
|
||||||
GGeettttiinngg ssttaarrtteedd,, qquuiicckk aanndd ddiirrttyy
|
GGeettttiinngg ssttaarrtteedd,, qquuiicckk aanndd ddiirrttyy
|
||||||
|
|
||||||
At least one time as root (prime group generation can take a few seconds to a
|
* Postfix 2.6 and 2.7: Enable elliptic-curve support. This is the default
|
||||||
few minutes):
|
with Postfix >= 2.8.
|
||||||
|
|
||||||
|
/etc/postfix/main.cf:
|
||||||
|
# Postfix 2.6 or 2.7 only. This is default with Postfix 2.8 and
|
||||||
|
later.
|
||||||
|
smtpd_tls_eecdh_grade = strong
|
||||||
|
|
||||||
|
* Optionally generate non-default EDH parameters for improved security
|
||||||
|
against pre-computation attacks and for compatibility with Debian-patched
|
||||||
|
EXIM SMTP clients (these require a minimum 2048-bit length for the non-
|
||||||
|
export prime). The parameter files are not secret, after all these
|
||||||
|
parameters are sent to all SMTP clients in the clear. Mode 0644 is fine.
|
||||||
|
|
||||||
|
Execute as root (prime group generation can take a few seconds to a few
|
||||||
|
minutes):
|
||||||
|
|
||||||
# cd /etc/postfix
|
# cd /etc/postfix
|
||||||
# openssl dhparam -out dh512.tmp 512 && mv dh512.tmp dh512.pem
|
# openssl dhparam -out dh512.tmp 512 && mv dh512.tmp dh512.pem
|
||||||
@ -198,23 +221,18 @@ few minutes):
|
|||||||
# openssl dhparam -out dh2048.tmp 2048 && mv dh2048.tmp dh2048.pem
|
# openssl dhparam -out dh2048.tmp 2048 && mv dh2048.tmp dh2048.pem
|
||||||
# chmod 644 dh512.pem dh1024.pem dh2048.pem
|
# chmod 644 dh512.pem dh1024.pem dh2048.pem
|
||||||
|
|
||||||
Note: greater security against "pre-computation" attacks against EDH can be
|
You can improve security against pre-computation attacks further by
|
||||||
obtained by periodically regenerating the EDH parameters as above (an hourly or
|
regenerating the EDH parameters periodically (an hourly or daily cron job
|
||||||
daily cron job running as root can automate this task). The parameter files are
|
running as root can automate this task).
|
||||||
not secret, after all these are sent to all SMTP clients in the clear. Mode
|
|
||||||
0644 is fine.
|
|
||||||
|
|
||||||
Once the parameters are in place, update main.cf as follows:
|
Once the parameters are in place, update main.cf as follows:
|
||||||
|
|
||||||
/etc/postfix/main.cf:
|
/etc/postfix/main.cf:
|
||||||
# Postfix >= 2.6
|
|
||||||
smtpd_tls_eecdh_grade = strong
|
|
||||||
# All versions of Postfix:
|
|
||||||
smtpd_tls_dh1024_param_file = ${config_directory}/dh2048.pem
|
smtpd_tls_dh1024_param_file = ${config_directory}/dh2048.pem
|
||||||
smtpd_tls_dh512_param_file = ${config_directory}/dh512.pem
|
smtpd_tls_dh512_param_file = ${config_directory}/dh512.pem
|
||||||
|
|
||||||
If some of your MSA clients don't support 2048-bit EDH, you may need to adjust
|
If some of your MSA clients don't support 2048-bit EDH, you may need to
|
||||||
the submission entry in master.cf accordingly:
|
adjust the submission entry in master.cf accordingly:
|
||||||
|
|
||||||
/etc/postfix/master.cf:
|
/etc/postfix/master.cf:
|
||||||
submission inet n - n - - smtpd
|
submission inet n - n - - smtpd
|
||||||
@ -225,32 +243,51 @@ the submission entry in master.cf accordingly:
|
|||||||
-o smtpd_sasl_auth_enable=yes
|
-o smtpd_sasl_auth_enable=yes
|
||||||
...
|
...
|
||||||
|
|
||||||
HHooww ddoo II kknnooww tthhaatt iitt wwoorrkkss??
|
HHooww ccaann II sseeee tthhaatt aa ccoonnnneeccttiioonn hhaass ffoorrwwaarrdd sseeccrreeccyy??
|
||||||
|
|
||||||
Postfix reports TLS connection information in several ways:
|
Postfix can be configured to report information about the negotiated cipher,
|
||||||
|
the corresponding key lengths, and the remote peer certificate or public-key
|
||||||
|
verification status.
|
||||||
|
|
||||||
* With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1", the Postfix SMTP
|
* With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1", the Postfix SMTP
|
||||||
client and server will log information about, among others, the remote peer
|
client and server will log TLS connection information to the maillog file.
|
||||||
certificate or public-key verification status, the negotiated cipher, and
|
The general logfile format is:
|
||||||
key lengths. The general logfile format is:
|
|
||||||
|
|
||||||
postfix/smtp[xxx]: Trusted TLS connection established to
|
postfix/smtp[process-id]: Untrusted TLS connection established
|
||||||
host.example.com[192.168.0.2]:25: TLSv1 with cipher XXX (YYY/ZZZ bits)
|
to host.example.com[192.168.0.2]:25: TLSv1 with cipher cipher-name
|
||||||
|
(actual-key-size/raw-key-size bits)
|
||||||
|
|
||||||
postfix/smtpd[xxx]: Untrusted TLS connection established from
|
postfix/smtpd[process-id]: Anonymous TLS connection established
|
||||||
host.example.com[192.168.0.2]: TLSv1 with cipher XXX (YYY/ZZZ bits)
|
from host.example.com[192.168.0.2]: TLSv1 with cipher cipher-name
|
||||||
|
(actual-key-size/raw-key-size bits)
|
||||||
|
|
||||||
* With "smtpd_tls_received_header = yes", the Postfix SMTP server will record
|
* With "smtpd_tls_received_header = yes", the Postfix SMTP server will record
|
||||||
similar information in the Received: header in the form of comments (text
|
TLS connection information in the Received: header in the form of comments
|
||||||
inside parentheses). The general format is:
|
(text inside parentheses). The general format depends on the
|
||||||
|
smtpd_tls_ask_ccert setting:
|
||||||
|
|
||||||
Received: from host.example.com (host.example.com [192.168.0.2])
|
Received: from host.example.com (host.example.com [192.168.0.2])
|
||||||
(using TLSv1 with cipher XXX (YYY/ZZZ bits))
|
(using TLSv1 with cipher cipher-name
|
||||||
(Client CN "host.example.com", Issuer "Wietse Venema" (not
|
(actual-key-size/raw-key-size bits))
|
||||||
|
(Client CN "host.example.com", Issuer "John Doe" (not
|
||||||
verified))
|
verified))
|
||||||
|
|
||||||
|
Received: from host.example.com (host.example.com [192.168.0.2])
|
||||||
|
(using TLSv1 with cipher cipher-name
|
||||||
|
(actual-key-size/raw-key-size bits))
|
||||||
|
(No client certificate requested)
|
||||||
|
|
||||||
|
The next sections will explain what cipher-name, key-size, and peer
|
||||||
|
verification status information to expect.
|
||||||
|
|
||||||
|
WWhhaatt cciipphheerrss pprroovviiddee ffoorrwwaarrdd sseeccrreeccyy??
|
||||||
|
|
||||||
There are dozens of ciphers that support forward secrecy. What follows is the
|
There are dozens of ciphers that support forward secrecy. What follows is the
|
||||||
beginning of a list of 51 ciphers available with OpenSSL 1.0.1e:
|
beginning of a list of 51 ciphers available with OpenSSL 1.0.1e. The list is
|
||||||
|
sorted in the default Postfix preference order. It excludes null ciphers that
|
||||||
|
only authenticate and don't encrypt, together with export and low-grade ciphers
|
||||||
|
whose encryption is too weak to offer meaningful secrecy. The first column
|
||||||
|
shows the cipher name, and the second shows the key exchange method.
|
||||||
|
|
||||||
$ openssl ciphers -v \
|
$ openssl ciphers -v \
|
||||||
'aNULL:-aNULL:kEECDH:kEDH:+RC4:!eNULL:!EXPORT:!LOW:@STRENGTH' |
|
'aNULL:-aNULL:kEECDH:kEDH:+RC4:!eNULL:!EXPORT:!LOW:@STRENGTH' |
|
||||||
@ -271,6 +308,81 @@ beginning of a list of 51 ciphers available with OpenSSL 1.0.1e:
|
|||||||
DHE-RSA-AES256-SHA256 Kx=DH
|
DHE-RSA-AES256-SHA256 Kx=DH
|
||||||
...
|
...
|
||||||
|
|
||||||
|
To date, all ciphers that support forward secrecy have one of five values for
|
||||||
|
the first component of their OpenSSL name: "AECDH", "ECDHE", "ADH", "EDH" or
|
||||||
|
"DHE". Ciphers that don't implement forward secrecy have names that don't start
|
||||||
|
with one of these prefixes. This pattern is likely to persist until some new
|
||||||
|
key-exchange mechanism is invented that also supports forward secrecy.
|
||||||
|
|
||||||
|
The actual key length and raw algorithm key length are generally the same with
|
||||||
|
non-export ciphers, but may they differ for the legacy export ciphers where the
|
||||||
|
actual key is artificially shortened.
|
||||||
|
|
||||||
|
WWhhaatt ddoo ""AAnnoonnyymmoouuss"",, ""UUnnttrruusstteedd"",, eettcc.. iinn PPoossttffiixx llooggggiinngg mmeeaann??
|
||||||
|
|
||||||
|
The verification levels below are subject to man-in-the-middle attacks to
|
||||||
|
different degrees. If such attacks are a concern, then the SMTP client will
|
||||||
|
need to authenticate the remote SMTP server in a sufficiently-secure manner.
|
||||||
|
For example, by the fingerprint of the public key or certificate. Remember that
|
||||||
|
conventional PKI relies on many trusted parties and is easily subverted by a
|
||||||
|
state-funded adversary.
|
||||||
|
|
||||||
|
AAnnoonnyymmoouuss (no peer certificate)
|
||||||
|
PPoossttffiixx SSMMTTPP cclliieenntt:: With opportunistic TLS (the "may" security level) the
|
||||||
|
Postfix SMTP client does not verify any information in the peer
|
||||||
|
certificate. In this case it enables and prefers anonymous cipher suites in
|
||||||
|
which the remote SMTP server does not present a certificate (these ciphers
|
||||||
|
offer forward secrecy of necessity). When the remote SMTP server also
|
||||||
|
supports anonymous TLS, and agrees to such a cipher suite, the verification
|
||||||
|
status will be logged as "Anonymous".
|
||||||
|
|
||||||
|
PPoossttffiixx SSMMTTPP sseerrvveerr:: This is by far most common, as client certificates are
|
||||||
|
optional, and the Postfix SMTP server does not request client certificates
|
||||||
|
by default (see smtpd_tls_ask_ccert). Even when client certificates are
|
||||||
|
requested, the remote SMTP client might not send a certificate. Unlike the
|
||||||
|
Postfix SMTP client, the Postfix SMTP server "anonymous" verification
|
||||||
|
status does not imply that the cipher suite is anonymous, which corresponds
|
||||||
|
to the server not sending a certificate.
|
||||||
|
|
||||||
|
UUnnttrruusstteedd (peer certificate not signed by trusted CA)
|
||||||
|
PPoossttffiixx SSMMTTPP cclliieenntt:: The remote SMTP server presented a certificate, but
|
||||||
|
the Postfix SMTP client was unable to check the issuing CA signature. With
|
||||||
|
opportunistic TLS this is common with remote SMTP servers that don't
|
||||||
|
support anonymous cipher suites.
|
||||||
|
|
||||||
|
PPoossttffiixx SSMMTTPP sseerrvveerr:: The remote SMTP client presented a certificate, but
|
||||||
|
the Postfix SMTP server was unable to check the issuing CA signature. This
|
||||||
|
can happen when the server is configured to request client certificates
|
||||||
|
(see smtpd_tls_ask_ccert).
|
||||||
|
|
||||||
|
TTrruusstteedd (peer certificate signed by trusted CA, unverified peer name)
|
||||||
|
PPoossttffiixx SSMMTTPP cclliieenntt:: The remote SMTP server's certificate was signed by a
|
||||||
|
CA that the Postfix SMTP client trusts, but either the client was not
|
||||||
|
configured to verify the destination server name against the certificate,
|
||||||
|
or the server certificate did not contain any matching names. This is
|
||||||
|
common with opportunistic TLS (smtp_tls_security_level is "may" or else
|
||||||
|
"dane" with no usable TLSA DNS records) when the Postfix SMTP client's
|
||||||
|
trusted CAs can verify the authenticity of the remote SMTP server's
|
||||||
|
certificate, but the client is not configured or unable to verify the
|
||||||
|
server name.
|
||||||
|
|
||||||
|
PPoossttffiixx SSMMTTPP sseerrvveerr:: The remote SMTP client certificate was signed by a CA
|
||||||
|
that the Postfix SMTP server trusts. The Postfix SMTP server never verifies
|
||||||
|
the remote SMTP client name against the names in the certificate. Since the
|
||||||
|
client chooses to connect to the server, the Postfix SMTP server has no
|
||||||
|
expectation of a particular client hostname.
|
||||||
|
|
||||||
|
VVeerriiffiieedd (peer certificate signed by trusted CA, verified peer name)
|
||||||
|
PPoossttffiixx SSMMTTPP cclliieenntt:: The remote SMTP server's certificate was signed by a
|
||||||
|
CA that the Postfix SMTP client trusts, and it matches one of the expected
|
||||||
|
server names. This implies that the Postfix SMTP client enforced
|
||||||
|
verification for the destination server name, otherwise the verification
|
||||||
|
status would have been just "Trusted".
|
||||||
|
|
||||||
|
PPoossttffiixx SSMMTTPP sseerrvveerr:: The status is never "Verified", as the Postfix SMTP
|
||||||
|
server never verifies the remote SMTP client name against the names in the
|
||||||
|
certificate.
|
||||||
|
|
||||||
CCrreeddiittss
|
CCrreeddiittss
|
||||||
|
|
||||||
* TLS support for Postfix was originally developed by Lutz Jänicke at Cottbus
|
* TLS support for Postfix was originally developed by Lutz Jänicke at Cottbus
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
X
|
||||||
|
|
||||||
PPoossttffiixx SSAASSLL HHoowwttoo
|
PPoossttffiixx SSAASSLL HHoowwttoo
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -109,71 +111,30 @@ configure and operate the Dovecot authentication server.
|
|||||||
PPoossttffiixx ttoo DDoovveeccoott SSAASSLL ccoommmmuunniiccaattiioonn
|
PPoossttffiixx ttoo DDoovveeccoott SSAASSLL ccoommmmuunniiccaattiioonn
|
||||||
|
|
||||||
Communication between the Postfix SMTP server and Dovecot SASL happens over a
|
Communication between the Postfix SMTP server and Dovecot SASL happens over a
|
||||||
UNIX-domain socket or over a TCP socket. Dovecot 1 supports UNIX-domain socket
|
UNIX-domain socket or over a TCP socket. We will be using a UNIX-domain socket
|
||||||
communication only.
|
for better privacy.
|
||||||
|
|
||||||
UUNNIIXX--ddoommaaiinn ssoocckkeett ccoommmmuunniiccaattiioonn
|
The following fragment for Dovecot version 2 assumes that the Postfix queue is
|
||||||
|
under /var/spool/postfix/.
|
||||||
|
|
||||||
The socket pathname and the list of mechanisms offered to Postfix need to be
|
1 conf.d/10-master.conf:
|
||||||
specified on the Dovecot server side in dovecot.conf.
|
|
||||||
|
|
||||||
The following example assumes that the Postfix queue is under /var/spool/
|
|
||||||
postfix/.
|
|
||||||
|
|
||||||
Note: the example uses Dovecot 1 syntax, See http://www.dovecot.org/ for newer
|
|
||||||
syntax.
|
|
||||||
|
|
||||||
1 /etc/dovecot.conf:
|
|
||||||
2 auth default {
|
|
||||||
3 mechanisms = plain login
|
|
||||||
4 passdb pam {
|
|
||||||
5 }
|
|
||||||
6 userdb passwd {
|
|
||||||
7 }
|
|
||||||
8 socket listen {
|
|
||||||
9 client {
|
|
||||||
10 path = /var/spool/postfix/private/auth
|
|
||||||
11 mode = 0660
|
|
||||||
12 user = postfix
|
|
||||||
13 group = postfix
|
|
||||||
14 }
|
|
||||||
15 }
|
|
||||||
16 }
|
|
||||||
|
|
||||||
Line 3 provides plain and login as mechanisms for the Postfix SMTP server, line
|
|
||||||
10 places the Dovecot SASL socket in /var/spool/postfix/private/auth, and lines
|
|
||||||
11-13 limit read+write permissions to user and group postfix only.
|
|
||||||
|
|
||||||
Proceed with the section "Enabling SASL authentication and authorization in the
|
|
||||||
Postfix SMTP server" to turn on and use SASL in the Postfix SMTP server.
|
|
||||||
|
|
||||||
TTCCPP ssoocckkeett ccoommmmuunniiccaattiioonn
|
|
||||||
|
|
||||||
The TCP port and the list of mechanisms offered to Postfix need to be specified
|
|
||||||
on the Dovecot server side in 10-auth.conf and 10-master.conf.
|
|
||||||
|
|
||||||
The following examples assume that Postfix should communicate with Dovecot on
|
|
||||||
TCP port 12345.
|
|
||||||
|
|
||||||
Note: the examples use Dovecot 1 syntax, See http://www.dovecot.org/ for newer
|
|
||||||
syntax.
|
|
||||||
|
|
||||||
1 /etc/dovecot/conf.d/10-auth.conf:
|
|
||||||
2 auth_mechanisms = plain login
|
|
||||||
|
|
||||||
Line 2 provides plain and login as mechanisms for the Postfix SMTP server.
|
|
||||||
|
|
||||||
1 /etc/dovecot/conf.d/10-master.conf:
|
|
||||||
2 service auth {
|
2 service auth {
|
||||||
3 unix_listener auth-userdb {
|
3 ...
|
||||||
4 }
|
4 unix_listener /var/spool/postfix/private/auth {
|
||||||
5 inet_listener {
|
5 mode = 0660
|
||||||
6 port = 12345
|
6 # Assuming the default Postfix user and group
|
||||||
7 }
|
7 user = postfix
|
||||||
8 }
|
8 group = postfix
|
||||||
|
9 }
|
||||||
|
10 ...
|
||||||
|
11 }
|
||||||
|
12
|
||||||
|
13 conf.d/10-auth.conf
|
||||||
|
14 auth_mechanisms = plain login
|
||||||
|
|
||||||
Line 5 creates a new TCP socket and line 6 specifies port 12345 where Dovecot
|
Line 4 places the Dovecot SASL socket in /var/spool/postfix/private/auth, lines
|
||||||
SASL should wait for Postfix authentication requests.
|
5-8 limit read+write permissions to user and group postfix only, and line 14
|
||||||
|
provides plain and login as mechanisms for the Postfix SMTP server.
|
||||||
|
|
||||||
Proceed with the section "Enabling SASL authentication and authorization in the
|
Proceed with the section "Enabling SASL authentication and authorization in the
|
||||||
Postfix SMTP server" to turn on and use SASL in the Postfix SMTP server.
|
Postfix SMTP server" to turn on and use SASL in the Postfix SMTP server.
|
||||||
|
@ -4,6 +4,10 @@ Wish list:
|
|||||||
independent from the DNS and native routines for host
|
independent from the DNS and native routines for host
|
||||||
name/address lookup.
|
name/address lookup.
|
||||||
|
|
||||||
|
Incorporate 3rd-party code such as dynamic_maps.
|
||||||
|
|
||||||
|
Support 3rd-party extension with /etc/postfix/postfix-files.d
|
||||||
|
|
||||||
Make been_here flag BH_FLAG_FOLD configurable for masochists.
|
Make been_here flag BH_FLAG_FOLD configurable for masochists.
|
||||||
|
|
||||||
Replace some redundant TLS_README sections with pointers
|
Replace some redundant TLS_README sections with pointers
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
# For common configuration examples, see BASIC_CONFIGURATION_README
|
# For common configuration examples, see BASIC_CONFIGURATION_README
|
||||||
# and STANDARD_CONFIGURATION_README. To find these documents, use
|
# and STANDARD_CONFIGURATION_README. To find these documents, use
|
||||||
# the command "postconf html_directory readme_directory", or go to
|
# 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,
|
# For best results, change no more than 2-3 parameters at a time,
|
||||||
# and test if Postfix still works after every change.
|
# and test if Postfix still works after every change.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Postfix master process configuration file. For details on the format
|
# 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.
|
# Do not forget to execute "postfix reload" after editing this file.
|
||||||
#
|
#
|
||||||
|
@ -19,6 +19,16 @@ TLS Forward Secrecy in Postfix
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
<h2> Warning </h2>
|
||||||
|
|
||||||
|
<p> Forward secrecy does not protect against active attacks such
|
||||||
|
as forged DNS replies or forged TLS server certificates. If such
|
||||||
|
attacks are a concern, then the SMTP client will need to authenticate
|
||||||
|
the remote SMTP server in a sufficiently-secure manner. For example,
|
||||||
|
by the fingerprint of the public key or certificate. Conventional
|
||||||
|
PKI relies on many trusted parties and is easily subverted by a
|
||||||
|
state-funded adversary. </p>
|
||||||
|
|
||||||
<h2> Background </h2>
|
<h2> Background </h2>
|
||||||
|
|
||||||
<p> Postfix supports forward secrecy of TLS network communication
|
<p> Postfix supports forward secrecy of TLS network communication
|
||||||
@ -55,13 +65,6 @@ all past traffic is generally infeasible, and even recovery of
|
|||||||
individual sessions may be infeasible given a sufficiently-strong
|
individual sessions may be infeasible given a sufficiently-strong
|
||||||
key agreement method. </p>
|
key agreement method. </p>
|
||||||
|
|
||||||
<p> Forward secrecy protects network communication in the absence
|
|
||||||
of active attacks, i.e. no forged DNS replies, and no forged TLS
|
|
||||||
server certificates. If active attacks are a concern, then you will
|
|
||||||
need to authenticate the remote SMTP server in a secure manner.
|
|
||||||
For example, by the fingerprint of the public key or certificate.
|
|
||||||
Conventional PKI relies on too many trusted parties. </p>
|
|
||||||
|
|
||||||
<p> Topics covered in this document: </p>
|
<p> Topics covered in this document: </p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@ -72,7 +75,14 @@ Conventional PKI relies on too many trusted parties. </p>
|
|||||||
|
|
||||||
<li><a href="#client_fs">Forward Secrecy in the Postfix SMTP Client</a>
|
<li><a href="#client_fs">Forward Secrecy in the Postfix SMTP Client</a>
|
||||||
|
|
||||||
<li><a href="#test">How do I know that it works?</a>
|
<li><a href="#quick-start">Getting started, quick and dirty</a>
|
||||||
|
|
||||||
|
<li><a href="#test">How can I see that a connection has forward secrecy?</a>
|
||||||
|
|
||||||
|
<li><a href="#ciphers"> What ciphers provide forward secrecy? </a>
|
||||||
|
|
||||||
|
<li><a href="#status"> What do "Anonymous", "Untrusted", etc. in
|
||||||
|
Postfix logging mean? </a>
|
||||||
|
|
||||||
<li><a href="#credits"> Credits </a>
|
<li><a href="#credits"> Credits </a>
|
||||||
|
|
||||||
@ -109,24 +119,24 @@ of long-term authentication keys. </p>
|
|||||||
<p> The key-exchange algorithms used for forward secrecy require
|
<p> The key-exchange algorithms used for forward secrecy require
|
||||||
the TLS server to designate appropriate "parameters" consisting of a
|
the TLS server to designate appropriate "parameters" consisting of a
|
||||||
mathematical "group" and an element of that group called a "generator".
|
mathematical "group" and an element of that group called a "generator".
|
||||||
There are two flavors of "groups" that work with PFS: </p>
|
Presently, there are two flavors of "groups" that work with PFS: </p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li> Prime field groups. The server needs to be configured with a
|
<li> <p> <b> Prime-field groups (EDH):</b> The server needs to be
|
||||||
suitably large prime and a corresponding "generator".
|
configured with a suitably-large prime and a corresponding "generator".
|
||||||
|
The acronym for forward secrecy over prime fields is EDH or Ephemeral
|
||||||
|
Diffie-Hellman (sometimes also abbreviated as DHE). </p>
|
||||||
|
|
||||||
<li> Elliptic curve groups. The server needs to be configured with
|
<li> <p> <b> Elliptic-curve groups (EECDH): </b> The server needs
|
||||||
a "named curve". These offer better security at lower computational
|
to be configured with a "named curve". These offer better security
|
||||||
cost than prime field groups, but are not as widely implemented.
|
at lower computational cost than prime field groups, but are not
|
||||||
|
as widely implemented. The acronym for the elliptic curve version
|
||||||
|
is EECDH which is short for Ephemeral Elliptic Curve Diffie-Hellman.
|
||||||
|
</p>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p> The acronym for forward secrecy over prime fields is EDH or
|
|
||||||
Ephemeral Diffie-Hellman (sometimes also abbreviated as DHE). The
|
|
||||||
acronym for the elliptic curve version is EECDH which is short for
|
|
||||||
Ephemeral Elliptic Curve Diffie-Hellman. </p>
|
|
||||||
|
|
||||||
<p> It is not essential to know what these are, but one does need
|
<p> It is not essential to know what these are, but one does need
|
||||||
to know that OpenSSL only supports EECDH as of version 1.0.0. Thus
|
to know that OpenSSL only supports EECDH as of version 1.0.0. Thus
|
||||||
the configuration parameters related to Elliptic Curve forward secrecy
|
the configuration parameters related to Elliptic Curve forward secrecy
|
||||||
@ -156,8 +166,6 @@ the <a href="postconf.5.html">main.cf</a> setting "<a href="postconf.5.html#tls_
|
|||||||
will likely cause interoperability issues with older Exchange servers
|
will likely cause interoperability issues with older Exchange servers
|
||||||
and is not recommended for now. </p>
|
and is not recommended for now. </p>
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3> EDH Server support </h3>
|
<h3> EDH Server support </h3>
|
||||||
|
|
||||||
<p> Postfix ≥ 2.2 support 1024-bit-prime EDH out of the box,
|
<p> Postfix ≥ 2.2 support 1024-bit-prime EDH out of the box,
|
||||||
@ -215,7 +223,7 @@ code for making this possible is not yet released as of late 2013
|
|||||||
(it is available only in OpenSSL development snapshots). </p>
|
(it is available only in OpenSSL development snapshots). </p>
|
||||||
|
|
||||||
<p> At some point Postfix will need to adjust to the new API for
|
<p> At some point Postfix will need to adjust to the new API for
|
||||||
setting the elliptic curve options. Fortunately, when EECDH support
|
setting the elliptic-curve options. Fortunately, when EECDH support
|
||||||
was added to Postfix, it introduced a layer of indirection: </p>
|
was added to Postfix, it introduced a layer of indirection: </p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
@ -237,19 +245,23 @@ more curves at the desired security level without any changes to
|
|||||||
<h2> <a name="client_fs">Forward Secrecy in the Postfix SMTP Client</a> </h2>
|
<h2> <a name="client_fs">Forward Secrecy in the Postfix SMTP Client</a> </h2>
|
||||||
|
|
||||||
<p> The Postfix ≥ 2.2 SMTP client supports forward secrecy in
|
<p> The Postfix ≥ 2.2 SMTP client supports forward secrecy in
|
||||||
its default configuration. If the remote SMTP server supports
|
its default configuration. No configuration changes are needed
|
||||||
cipher suites with forward secrecy (and does not override the SMTP
|
besides turning on elliptic-curve support with Postfix 2.6 and 2.7
|
||||||
client cipher preference), then the traffic between the server and
|
(see the <a href="#quick-start"> quick-start</a> section). If the
|
||||||
client will resist decryption even if the server's long-term
|
remote SMTP server supports cipher suites with forward secrecy (and
|
||||||
authentication keys are <i>later</i> compromised. </p>
|
does not override the SMTP client's cipher preference), then the
|
||||||
|
traffic between the server and client will resist decryption even
|
||||||
|
if the server's long-term authentication keys are <i>later</i>
|
||||||
|
compromised. </p>
|
||||||
|
|
||||||
<p> The default Postfix SMTP client cipher lists are correctly ordered
|
<p> The default Postfix SMTP client cipher lists are correctly
|
||||||
to prefer EECDH and EDH cipher suites ahead of similar cipher suites
|
ordered to prefer EECDH and EDH cipher suites ahead of similar
|
||||||
that don't implement forward secrecy. Administrators are strongly
|
cipher suites that don't implement forward secrecy. Administrators
|
||||||
discouraged from changing the cipher list definitions. It is likely
|
are strongly discouraged from changing the cipher list definitions.
|
||||||
safe to set "<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a> = medium" if you wish to disable the
|
It is likely safe to set "<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a> = medium" if you wish
|
||||||
obsolete "export" and "low" grade ciphers even with opportunistic
|
to disable the obsolete "export" and "low" grade ciphers even with
|
||||||
TLS. Setting a minimum strength does not change the preference
|
opportunistic TLS. Setting a minimum strength does not change the
|
||||||
|
preference
|
||||||
order. Note that strengths higher than "medium" exclude Exchange
|
order. Note that strengths higher than "medium" exclude Exchange
|
||||||
2003 and likely other widely used MTAs, thus "high" grade ciphers
|
2003 and likely other widely used MTAs, thus "high" grade ciphers
|
||||||
should only be used on a case-by-case basis via the <a
|
should only be used on a case-by-case basis via the <a
|
||||||
@ -257,7 +269,27 @@ href="TLS_README.html#client_tls_policy">TLS policy</a> table. </p>
|
|||||||
|
|
||||||
<h2><a name="quick-start">Getting started, quick and dirty</a></h2>
|
<h2><a name="quick-start">Getting started, quick and dirty</a></h2>
|
||||||
|
|
||||||
<p> At least one time as root (prime group generation can take a
|
<ul>
|
||||||
|
|
||||||
|
<li> <p> Postfix 2.6 and 2.7: Enable elliptic-curve support. This
|
||||||
|
is the default with Postfix ≥ 2.8.
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||||
|
# Postfix 2.6 or 2.7 only. This is default with Postfix 2.8 and later.
|
||||||
|
<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> = strong
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<li> <p> Optionally generate non-default EDH parameters for improved
|
||||||
|
security against pre-computation attacks and for compatibility with
|
||||||
|
Debian-patched EXIM SMTP clients (these require a minimum 2048-bit
|
||||||
|
length for the non-export prime). The parameter files are not
|
||||||
|
secret, after all these parameters are sent to all SMTP clients in
|
||||||
|
the clear. Mode 0644 is fine. </p>
|
||||||
|
|
||||||
|
<p> Execute as root (prime group generation can take a
|
||||||
few seconds to a few minutes): </p>
|
few seconds to a few minutes): </p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
@ -270,20 +302,15 @@ few seconds to a few minutes): </p>
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<p> Note: greater security against "pre-computation" attacks against
|
<p> You can improve security against pre-computation attacks further
|
||||||
EDH can be obtained by periodically regenerating the EDH parameters
|
by regenerating the EDH parameters periodically (an hourly or daily
|
||||||
as above (an hourly or daily cron job running as root can automate
|
cron job running as root can automate this task). </p>
|
||||||
this task). The parameter files are not secret, after all these are
|
|
||||||
sent to all SMTP clients in the clear. Mode 0644 is fine. </p>
|
|
||||||
|
|
||||||
<p> Once the parameters are in place, update <a href="postconf.5.html">main.cf</a> as follows: </p>
|
<p> Once the parameters are in place, update <a href="postconf.5.html">main.cf</a> as follows: </p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||||
# Postfix ≥ 2.6
|
|
||||||
<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> = strong
|
|
||||||
# All versions of Postfix:
|
|
||||||
<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> = ${<a href="postconf.5.html#config_directory">config_directory</a>}/dh2048.pem
|
<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> = ${<a href="postconf.5.html#config_directory">config_directory</a>}/dh2048.pem
|
||||||
<a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> = ${<a href="postconf.5.html#config_directory">config_directory</a>}/dh512.pem
|
<a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> = ${<a href="postconf.5.html#config_directory">config_directory</a>}/dh512.pem
|
||||||
</pre>
|
</pre>
|
||||||
@ -305,44 +332,67 @@ need to adjust the submission entry in <a href="master.5.html">master.cf</a> acc
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<h2><a name="test">How do I know that it works? </a> </h2>
|
</ul>
|
||||||
|
|
||||||
<p> Postfix reports TLS connection information in several ways: </p>
|
<h2><a name="test">How can I see that a connection has forward
|
||||||
|
secrecy? </a> </h2>
|
||||||
|
|
||||||
|
<p> Postfix can be configured to report information about the
|
||||||
|
negotiated cipher, the corresponding key lengths, and the remote
|
||||||
|
peer certificate or public-key verification status. </p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li> <p> With "<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> = 1" and "<a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> = 1",
|
<li> <p> With "<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> = 1" and "<a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> = 1",
|
||||||
the Postfix SMTP client and server will log information about, among
|
the Postfix SMTP client and server will log TLS connection information
|
||||||
others, the remote peer certificate or public-key verification
|
to the maillog file. The general logfile format is: </p>
|
||||||
status, the negotiated cipher, and key lengths. The general logfile
|
|
||||||
format is: </p>
|
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
postfix/smtp[xxx]: Trusted TLS connection established to host.example.com[192.168.0.2]:25: TLSv1 with cipher XXX (YYY/ZZZ bits)
|
postfix/smtp[<i>process-id</i>]: Untrusted TLS connection established
|
||||||
|
to host.example.com[192.168.0.2]:25: TLSv1 with cipher <i>cipher-name</i>
|
||||||
|
(<i>actual-key-size</i>/<i>raw-key-size</i> bits)
|
||||||
|
|
||||||
postfix/smtpd[xxx]: Untrusted TLS connection established from host.example.com[192.168.0.2]: TLSv1 with cipher XXX (YYY/ZZZ bits)
|
postfix/smtpd[<i>process-id</i>]: Anonymous TLS connection established
|
||||||
|
from host.example.com[192.168.0.2]: TLSv1 with cipher <i>cipher-name</i>
|
||||||
|
(<i>actual-key-size</i>/<i>raw-key-size</i> bits)
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<li> <p> With "<a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> = yes", the Postfix SMTP
|
<li> <p> With "<a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> = yes", the Postfix SMTP
|
||||||
server will record similar information in the Received: header in
|
server will record TLS connection information in the Received:
|
||||||
the form of comments (text inside parentheses). The general format
|
header in the form of comments (text inside parentheses). The general
|
||||||
is: </p>
|
format depends on the <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> setting:
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
Received: from host.example.com (host.example.com [192.168.0.2])
|
Received: from host.example.com (host.example.com [192.168.0.2])
|
||||||
(using TLSv1 with cipher XXX (YYY/ZZZ bits))
|
(using TLSv1 with cipher <i>cipher-name</i>
|
||||||
(Client CN "host.example.com", Issuer "Wietse Venema" (not verified))
|
(<i>actual-key-size</i>/<i>raw-key-size</i> bits))
|
||||||
|
(Client CN "host.example.com", Issuer "John Doe" (not verified))
|
||||||
|
|
||||||
|
Received: from host.example.com (host.example.com [192.168.0.2])
|
||||||
|
(using TLSv1 with cipher <i>cipher-name</i>
|
||||||
|
(<i>actual-key-size</i>/<i>raw-key-size</i> bits))
|
||||||
|
(No client certificate requested)
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p> The next sections will explain what <i>cipher-name</i>,
|
||||||
|
<i>key-size</i>, and peer verification status information to expect.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="ciphers"> What ciphers provide forward secrecy? </a> </h2>
|
||||||
|
|
||||||
<p> There are dozens of ciphers that support forward secrecy. What
|
<p> There are dozens of ciphers that support forward secrecy. What
|
||||||
follows is the beginning of a list of 51 ciphers available with
|
follows is the beginning of a list of 51 ciphers available with
|
||||||
OpenSSL 1.0.1e: </p>
|
OpenSSL 1.0.1e. The list is sorted in the default Postfix preference
|
||||||
|
order. It excludes null ciphers that only authenticate and don't
|
||||||
|
encrypt, together with export and low-grade ciphers whose encryption
|
||||||
|
is too weak to offer meaningful secrecy. The first column shows the
|
||||||
|
cipher name, and the second shows the key exchange method. </p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
@ -367,6 +417,112 @@ DHE-RSA-AES256-SHA256 Kx=DH
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
|
<p> To date, all ciphers that support forward secrecy have one of
|
||||||
|
five values for the first component of their OpenSSL name: "AECDH",
|
||||||
|
"ECDHE", "ADH", "EDH" or "DHE". Ciphers that don't implement forward
|
||||||
|
secrecy have names that don't start with one of these prefixes.
|
||||||
|
This pattern is likely to persist until some new key-exchange
|
||||||
|
mechanism is invented that also supports forward secrecy. </p>
|
||||||
|
|
||||||
|
<p> The actual key length and raw algorithm key length
|
||||||
|
are generally the same with non-export ciphers, but may they
|
||||||
|
differ for the legacy export ciphers where the actual key
|
||||||
|
is artificially shortened. </p>
|
||||||
|
|
||||||
|
<h2><a name="status"> What do "Anonymous", "Untrusted", etc. in
|
||||||
|
Postfix logging mean? </a> </h2>
|
||||||
|
|
||||||
|
<p> The verification levels below are subject to man-in-the-middle
|
||||||
|
attacks to different degrees. If such attacks are a concern, then
|
||||||
|
the SMTP client will need to authenticate the remote SMTP server
|
||||||
|
in a sufficiently-secure manner. For example, by the fingerprint
|
||||||
|
of the public key or certificate. Remember that conventional PKI
|
||||||
|
relies on many trusted parties and is easily subverted by a
|
||||||
|
state-funded adversary. </p>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
|
||||||
|
<dt><b>Anonymous</b> (no peer certificate)</dt>
|
||||||
|
|
||||||
|
<dd> <p> <b> Postfix SMTP client:</b> With opportunistic TLS (the "may" security level) the Postfix
|
||||||
|
SMTP client does not verify any information in the peer certificate.
|
||||||
|
In this case it enables and prefers anonymous cipher suites in which
|
||||||
|
the remote SMTP server does not present a certificate (these ciphers
|
||||||
|
offer forward secrecy of necessity). When the remote SMTP server
|
||||||
|
also supports anonymous TLS, and agrees to such a cipher suite, the
|
||||||
|
verification status will be logged as "Anonymous". </p> </dd>
|
||||||
|
|
||||||
|
<dd> <p> <b> Postfix SMTP server:</b> This is by far most common,
|
||||||
|
as client certificates are optional, and the Postfix SMTP server
|
||||||
|
does not request client certificates by default (see <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>).
|
||||||
|
Even when client certificates are requested, the remote SMTP client
|
||||||
|
might not send a certificate. Unlike the Postfix SMTP client, the
|
||||||
|
Postfix SMTP server "anonymous" verification status does not imply
|
||||||
|
that the cipher suite is anonymous, which corresponds to the
|
||||||
|
<i>server</i> not sending a certificate. </p> </dd>
|
||||||
|
|
||||||
|
<dt><b>Untrusted</b> (peer certificate not signed by trusted CA)</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP client:</b> The remote SMTP server presented
|
||||||
|
a certificate, but the Postfix SMTP client was unable to check the
|
||||||
|
issuing CA signature. With opportunistic TLS this is common with
|
||||||
|
remote SMTP servers that don't support anonymous cipher suites.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP server:</b> The remote SMTP client presented
|
||||||
|
a certificate, but the Postfix SMTP server was unable to check the
|
||||||
|
issuing CA signature. This can happen when the server is configured
|
||||||
|
to request client certificates (see <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>). </p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt><b>Trusted</b> (peer certificate signed by trusted CA, unverified
|
||||||
|
peer name)</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP client:</b> The remote SMTP server's certificate
|
||||||
|
was signed by a CA that the Postfix SMTP client trusts, but either
|
||||||
|
the client was not configured to verify the destination server name
|
||||||
|
against the certificate, or the server certificate did not contain
|
||||||
|
any matching names. This is common with opportunistic TLS
|
||||||
|
(<a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a> is "may" or else "dane" with no usable
|
||||||
|
TLSA DNS records) when the Postfix SMTP client's trusted CAs can
|
||||||
|
verify the authenticity of the remote SMTP server's certificate,
|
||||||
|
but the client is not configured or unable to verify the server
|
||||||
|
name. </p>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP server:</b> The remote SMTP client certificate
|
||||||
|
was signed by a CA that the Postfix SMTP server trusts. The Postfix
|
||||||
|
SMTP server never verifies the remote SMTP client name against the
|
||||||
|
names in the certificate. Since the client chooses to connect to
|
||||||
|
the server, the Postfix SMTP server has no expectation of a particular
|
||||||
|
client hostname. </p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt><b>Verified</b> (peer certificate signed by trusted CA, verified
|
||||||
|
peer name)</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP client:</b> The remote SMTP server's certificate
|
||||||
|
was signed by a CA that the Postfix SMTP client trusts, and it
|
||||||
|
matches one of the expected server names. This implies that the
|
||||||
|
Postfix SMTP client enforced verification for the destination server
|
||||||
|
name, otherwise the verification status would have been just
|
||||||
|
"Trusted". </p>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP server:</b> The status is never "Verified",
|
||||||
|
as the Postfix SMTP server never verifies the remote SMTP client
|
||||||
|
name against the names in the certificate. </p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
<h2><a name="credits">Credits </a> </h2>
|
<h2><a name="credits">Credits </a> </h2>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
|
X<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||||
"http://www.w3.org/TR/html4/loose.dtd">
|
"http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
@ -185,91 +185,36 @@ to configure and operate the Dovecot authentication server. </p>
|
|||||||
<h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4>
|
<h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4>
|
||||||
|
|
||||||
<p> Communication between the Postfix SMTP server and Dovecot SASL
|
<p> Communication between the Postfix SMTP server and Dovecot SASL
|
||||||
happens over a UNIX-domain socket or over a TCP socket. Dovecot 1
|
happens over a UNIX-domain socket or over a TCP socket. We will
|
||||||
supports UNIX-domain socket communication only. </p>
|
be using a UNIX-domain socket for better privacy. </p>
|
||||||
|
|
||||||
<h5>UNIX-domain socket communication</h5>
|
<p> The following fragment for Dovecot version 2 assumes that the
|
||||||
|
Postfix queue is under <code>/var/spool/postfix/</code>. </p>
|
||||||
<p> The socket
|
|
||||||
pathname and the list of mechanisms offered to Postfix need to be
|
|
||||||
specified on the Dovecot server side in <code>dovecot.conf</code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p> The following example assumes that the Postfix queue is under
|
|
||||||
<code>/var/spool/postfix/</code>. </p>
|
|
||||||
|
|
||||||
<p> Note: the example uses Dovecot 1 syntax, See <a href="http://www.dovecot.org/">http://www.dovecot.org/</a>
|
|
||||||
for newer syntax. </p>
|
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
1 /etc/dovecot.conf:
|
1 conf.d/10-master.conf:
|
||||||
2 auth default {
|
2 service auth {
|
||||||
3 mechanisms = plain login
|
3 ...
|
||||||
4 passdb pam {
|
4 unix_listener /var/spool/postfix/private/auth {
|
||||||
5 }
|
5 mode = 0660
|
||||||
6 userdb passwd {
|
6 # Assuming the default Postfix user and group
|
||||||
7 }
|
7 user = postfix
|
||||||
8 socket listen {
|
8 group = postfix
|
||||||
9 client {
|
9 }
|
||||||
10 path = /var/spool/postfix/private/auth
|
10 ...
|
||||||
11 mode = 0660
|
11 }
|
||||||
12 user = postfix
|
12
|
||||||
13 group = postfix
|
13 conf.d/10-auth.conf
|
||||||
14 }
|
14 auth_mechanisms = plain login
|
||||||
15 }
|
|
||||||
16 }
|
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<p> Line 3 provides <code>plain</code> and <code>login</code> as
|
<p> Line 4 places the Dovecot SASL socket in
|
||||||
mechanisms for the Postfix SMTP server, line 10 places the Dovecot
|
<code>/var/spool/postfix/private/auth</code>, lines 5-8 limit
|
||||||
SASL socket in <code>/var/spool/postfix/private/auth</code>, and
|
read+write permissions to user and group <code>postfix</code> only,
|
||||||
lines 11-13 limit read+write permissions to user and group
|
and line 14 provides <code>plain</code> and <code>login</code> as
|
||||||
<code>postfix</code> only. </p>
|
mechanisms for the Postfix SMTP server. </p>
|
||||||
|
|
||||||
<p> Proceed with the section "<a href="#server_sasl_enable">Enabling
|
|
||||||
SASL authentication and authorization in the Postfix SMTP server</a>"
|
|
||||||
to turn on and use SASL in the Postfix SMTP server. </p>
|
|
||||||
|
|
||||||
<h5>TCP socket communication</h5>
|
|
||||||
|
|
||||||
<p> The TCP port and the list of mechanisms offered to Postfix need
|
|
||||||
to be specified on the Dovecot server side in <code>10-auth.conf</code>
|
|
||||||
and <code>10-master.conf</code>. </p>
|
|
||||||
|
|
||||||
<p> The following examples assume that Postfix should communicate
|
|
||||||
with Dovecot on TCP port 12345. </p>
|
|
||||||
|
|
||||||
<p> Note: the examples use Dovecot 1 syntax, See <a href="http://www.dovecot.org/">http://www.dovecot.org/</a>
|
|
||||||
for newer syntax. </p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
1 /etc/dovecot/conf.d/10-auth.conf:
|
|
||||||
2 auth_mechanisms = plain login
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p> Line 2 provides plain and login as mechanisms for the Postfix
|
|
||||||
SMTP server. </p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
1 /etc/dovecot/conf.d/10-master.conf:
|
|
||||||
2 service auth {
|
|
||||||
3 unix_listener auth-userdb {
|
|
||||||
4 }
|
|
||||||
5 inet_listener {
|
|
||||||
6 port = 12345
|
|
||||||
7 }
|
|
||||||
8 }
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p> Line 5 creates a new TCP socket and line 6 specifies port 12345
|
|
||||||
where Dovecot SASL should wait for Postfix authentication requests.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p> Proceed with the section "<a href="#server_sasl_enable">Enabling
|
<p> Proceed with the section "<a href="#server_sasl_enable">Enabling
|
||||||
SASL authentication and authorization in the Postfix SMTP server</a>"
|
SASL authentication and authorization in the Postfix SMTP server</a>"
|
||||||
|
@ -14620,6 +14620,19 @@ Example:
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
</DD>
|
||||||
|
|
||||||
|
<DT><b><a name="smtpd_sasl_service">smtpd_sasl_service</a>
|
||||||
|
(default: smtp)</b></DT><DD>
|
||||||
|
|
||||||
|
<p> The service name that is passed to the SASL plug-in that is
|
||||||
|
selected with <b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b> and <b><a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a></b>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.11 and later. Prior
|
||||||
|
versions behave as if "<b>smtp</b>" is specified. </p>
|
||||||
|
|
||||||
|
|
||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<DT><b><a name="smtpd_sasl_tls_security_options">smtpd_sasl_tls_security_options</a>
|
<DT><b><a name="smtpd_sasl_tls_security_options">smtpd_sasl_tls_security_options</a>
|
||||||
|
@ -361,6 +361,12 @@ SMTPD(8) SMTPD(8)
|
|||||||
Search path for Cyrus SASL application configuration files, cur-
|
Search path for Cyrus SASL application configuration files, cur-
|
||||||
rently used only to locate the $<a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a>.conf file.
|
rently used only to locate the $<a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a>.conf file.
|
||||||
|
|
||||||
|
Available in Postfix version 2.11 and later:
|
||||||
|
|
||||||
|
<b>smtpd_sasl_service (smtp)</b>
|
||||||
|
The service name that is passed to the SASL plug-in that is
|
||||||
|
selected with <b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b> and <b><a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a></b>.
|
||||||
|
|
||||||
<b>STARTTLS SUPPORT CONTROLS</b>
|
<b>STARTTLS SUPPORT CONTROLS</b>
|
||||||
Detailed information about STARTTLS configuration may be found in the
|
Detailed information about STARTTLS configuration may be found in the
|
||||||
<a href="TLS_README.html">TLS_README</a> document.
|
<a href="TLS_README.html">TLS_README</a> document.
|
||||||
|
@ -9767,6 +9767,12 @@ smtpd_sasl_security_options = noanonymous, noplaintext
|
|||||||
.fi
|
.fi
|
||||||
.ad
|
.ad
|
||||||
.ft R
|
.ft R
|
||||||
|
.SH smtpd_sasl_service (default: smtp)
|
||||||
|
The service name that is passed to the SASL plug-in that is
|
||||||
|
selected with \fBsmtpd_sasl_type\fR and \fBsmtpd_sasl_path\fR.
|
||||||
|
.PP
|
||||||
|
This feature is available in Postfix 2.11 and later. Prior
|
||||||
|
versions behave as if "\fBsmtp\fR" is specified.
|
||||||
.SH smtpd_sasl_tls_security_options (default: $smtpd_sasl_security_options)
|
.SH smtpd_sasl_tls_security_options (default: $smtpd_sasl_security_options)
|
||||||
The SASL authentication security options that the Postfix SMTP
|
The SASL authentication security options that the Postfix SMTP
|
||||||
server uses for TLS encrypted SMTP sessions.
|
server uses for TLS encrypted SMTP sessions.
|
||||||
|
@ -347,6 +347,11 @@ Available in Postfix version 2.5 and later:
|
|||||||
.IP "\fBcyrus_sasl_config_path (empty)\fR"
|
.IP "\fBcyrus_sasl_config_path (empty)\fR"
|
||||||
Search path for Cyrus SASL application configuration files,
|
Search path for Cyrus SASL application configuration files,
|
||||||
currently used only to locate the $smtpd_sasl_path.conf file.
|
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.
|
||||||
.SH "STARTTLS SUPPORT CONTROLS"
|
.SH "STARTTLS SUPPORT CONTROLS"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
@ -19,6 +19,16 @@ TLS Forward Secrecy in Postfix
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
<h2> Warning </h2>
|
||||||
|
|
||||||
|
<p> Forward secrecy does not protect against active attacks such
|
||||||
|
as forged DNS replies or forged TLS server certificates. If such
|
||||||
|
attacks are a concern, then the SMTP client will need to authenticate
|
||||||
|
the remote SMTP server in a sufficiently-secure manner. For example,
|
||||||
|
by the fingerprint of the public key or certificate. Conventional
|
||||||
|
PKI relies on many trusted parties and is easily subverted by a
|
||||||
|
state-funded adversary. </p>
|
||||||
|
|
||||||
<h2> Background </h2>
|
<h2> Background </h2>
|
||||||
|
|
||||||
<p> Postfix supports forward secrecy of TLS network communication
|
<p> Postfix supports forward secrecy of TLS network communication
|
||||||
@ -55,13 +65,6 @@ all past traffic is generally infeasible, and even recovery of
|
|||||||
individual sessions may be infeasible given a sufficiently-strong
|
individual sessions may be infeasible given a sufficiently-strong
|
||||||
key agreement method. </p>
|
key agreement method. </p>
|
||||||
|
|
||||||
<p> Forward secrecy protects network communication in the absence
|
|
||||||
of active attacks, i.e. no forged DNS replies, and no forged TLS
|
|
||||||
server certificates. If active attacks are a concern, then you will
|
|
||||||
need to authenticate the remote SMTP server in a secure manner.
|
|
||||||
For example, by the fingerprint of the public key or certificate.
|
|
||||||
Conventional PKI relies on too many trusted parties. </p>
|
|
||||||
|
|
||||||
<p> Topics covered in this document: </p>
|
<p> Topics covered in this document: </p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@ -72,7 +75,14 @@ Conventional PKI relies on too many trusted parties. </p>
|
|||||||
|
|
||||||
<li><a href="#client_fs">Forward Secrecy in the Postfix SMTP Client</a>
|
<li><a href="#client_fs">Forward Secrecy in the Postfix SMTP Client</a>
|
||||||
|
|
||||||
<li><a href="#test">How do I know that it works?</a>
|
<li><a href="#quick-start">Getting started, quick and dirty</a>
|
||||||
|
|
||||||
|
<li><a href="#test">How can I see that a connection has forward secrecy?</a>
|
||||||
|
|
||||||
|
<li><a href="#ciphers"> What ciphers provide forward secrecy? </a>
|
||||||
|
|
||||||
|
<li><a href="#status"> What do "Anonymous", "Untrusted", etc. in
|
||||||
|
Postfix logging mean? </a>
|
||||||
|
|
||||||
<li><a href="#credits"> Credits </a>
|
<li><a href="#credits"> Credits </a>
|
||||||
|
|
||||||
@ -109,24 +119,24 @@ of long-term authentication keys. </p>
|
|||||||
<p> The key-exchange algorithms used for forward secrecy require
|
<p> The key-exchange algorithms used for forward secrecy require
|
||||||
the TLS server to designate appropriate "parameters" consisting of a
|
the TLS server to designate appropriate "parameters" consisting of a
|
||||||
mathematical "group" and an element of that group called a "generator".
|
mathematical "group" and an element of that group called a "generator".
|
||||||
There are two flavors of "groups" that work with PFS: </p>
|
Presently, there are two flavors of "groups" that work with PFS: </p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li> Prime field groups. The server needs to be configured with a
|
<li> <p> <b> Prime-field groups (EDH):</b> The server needs to be
|
||||||
suitably large prime and a corresponding "generator".
|
configured with a suitably-large prime and a corresponding "generator".
|
||||||
|
The acronym for forward secrecy over prime fields is EDH or Ephemeral
|
||||||
|
Diffie-Hellman (sometimes also abbreviated as DHE). </p>
|
||||||
|
|
||||||
<li> Elliptic curve groups. The server needs to be configured with
|
<li> <p> <b> Elliptic-curve groups (EECDH): </b> The server needs
|
||||||
a "named curve". These offer better security at lower computational
|
to be configured with a "named curve". These offer better security
|
||||||
cost than prime field groups, but are not as widely implemented.
|
at lower computational cost than prime field groups, but are not
|
||||||
|
as widely implemented. The acronym for the elliptic curve version
|
||||||
|
is EECDH which is short for Ephemeral Elliptic Curve Diffie-Hellman.
|
||||||
|
</p>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p> The acronym for forward secrecy over prime fields is EDH or
|
|
||||||
Ephemeral Diffie-Hellman (sometimes also abbreviated as DHE). The
|
|
||||||
acronym for the elliptic curve version is EECDH which is short for
|
|
||||||
Ephemeral Elliptic Curve Diffie-Hellman. </p>
|
|
||||||
|
|
||||||
<p> It is not essential to know what these are, but one does need
|
<p> It is not essential to know what these are, but one does need
|
||||||
to know that OpenSSL only supports EECDH as of version 1.0.0. Thus
|
to know that OpenSSL only supports EECDH as of version 1.0.0. Thus
|
||||||
the configuration parameters related to Elliptic Curve forward secrecy
|
the configuration parameters related to Elliptic Curve forward secrecy
|
||||||
@ -156,8 +166,6 @@ the main.cf setting "tls_preempt_cipherlist = yes". However, this
|
|||||||
will likely cause interoperability issues with older Exchange servers
|
will likely cause interoperability issues with older Exchange servers
|
||||||
and is not recommended for now. </p>
|
and is not recommended for now. </p>
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3> EDH Server support </h3>
|
<h3> EDH Server support </h3>
|
||||||
|
|
||||||
<p> Postfix ≥ 2.2 support 1024-bit-prime EDH out of the box,
|
<p> Postfix ≥ 2.2 support 1024-bit-prime EDH out of the box,
|
||||||
@ -215,7 +223,7 @@ code for making this possible is not yet released as of late 2013
|
|||||||
(it is available only in OpenSSL development snapshots). </p>
|
(it is available only in OpenSSL development snapshots). </p>
|
||||||
|
|
||||||
<p> At some point Postfix will need to adjust to the new API for
|
<p> At some point Postfix will need to adjust to the new API for
|
||||||
setting the elliptic curve options. Fortunately, when EECDH support
|
setting the elliptic-curve options. Fortunately, when EECDH support
|
||||||
was added to Postfix, it introduced a layer of indirection: </p>
|
was added to Postfix, it introduced a layer of indirection: </p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
@ -237,19 +245,23 @@ main.cf. </p>
|
|||||||
<h2> <a name="client_fs">Forward Secrecy in the Postfix SMTP Client</a> </h2>
|
<h2> <a name="client_fs">Forward Secrecy in the Postfix SMTP Client</a> </h2>
|
||||||
|
|
||||||
<p> The Postfix ≥ 2.2 SMTP client supports forward secrecy in
|
<p> The Postfix ≥ 2.2 SMTP client supports forward secrecy in
|
||||||
its default configuration. If the remote SMTP server supports
|
its default configuration. No configuration changes are needed
|
||||||
cipher suites with forward secrecy (and does not override the SMTP
|
besides turning on elliptic-curve support with Postfix 2.6 and 2.7
|
||||||
client cipher preference), then the traffic between the server and
|
(see the <a href="#quick-start"> quick-start</a> section). If the
|
||||||
client will resist decryption even if the server's long-term
|
remote SMTP server supports cipher suites with forward secrecy (and
|
||||||
authentication keys are <i>later</i> compromised. </p>
|
does not override the SMTP client's cipher preference), then the
|
||||||
|
traffic between the server and client will resist decryption even
|
||||||
|
if the server's long-term authentication keys are <i>later</i>
|
||||||
|
compromised. </p>
|
||||||
|
|
||||||
<p> The default Postfix SMTP client cipher lists are correctly ordered
|
<p> The default Postfix SMTP client cipher lists are correctly
|
||||||
to prefer EECDH and EDH cipher suites ahead of similar cipher suites
|
ordered to prefer EECDH and EDH cipher suites ahead of similar
|
||||||
that don't implement forward secrecy. Administrators are strongly
|
cipher suites that don't implement forward secrecy. Administrators
|
||||||
discouraged from changing the cipher list definitions. It is likely
|
are strongly discouraged from changing the cipher list definitions.
|
||||||
safe to set "smtp_tls_ciphers = medium" if you wish to disable the
|
It is likely safe to set "smtp_tls_ciphers = medium" if you wish
|
||||||
obsolete "export" and "low" grade ciphers even with opportunistic
|
to disable the obsolete "export" and "low" grade ciphers even with
|
||||||
TLS. Setting a minimum strength does not change the preference
|
opportunistic TLS. Setting a minimum strength does not change the
|
||||||
|
preference
|
||||||
order. Note that strengths higher than "medium" exclude Exchange
|
order. Note that strengths higher than "medium" exclude Exchange
|
||||||
2003 and likely other widely used MTAs, thus "high" grade ciphers
|
2003 and likely other widely used MTAs, thus "high" grade ciphers
|
||||||
should only be used on a case-by-case basis via the <a
|
should only be used on a case-by-case basis via the <a
|
||||||
@ -257,7 +269,27 @@ href="TLS_README.html#client_tls_policy">TLS policy</a> table. </p>
|
|||||||
|
|
||||||
<h2><a name="quick-start">Getting started, quick and dirty</a></h2>
|
<h2><a name="quick-start">Getting started, quick and dirty</a></h2>
|
||||||
|
|
||||||
<p> At least one time as root (prime group generation can take a
|
<ul>
|
||||||
|
|
||||||
|
<li> <p> Postfix 2.6 and 2.7: Enable elliptic-curve support. This
|
||||||
|
is the default with Postfix ≥ 2.8.
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
/etc/postfix/main.cf:
|
||||||
|
# Postfix 2.6 or 2.7 only. This is default with Postfix 2.8 and later.
|
||||||
|
smtpd_tls_eecdh_grade = strong
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<li> <p> Optionally generate non-default EDH parameters for improved
|
||||||
|
security against pre-computation attacks and for compatibility with
|
||||||
|
Debian-patched EXIM SMTP clients (these require a minimum 2048-bit
|
||||||
|
length for the non-export prime). The parameter files are not
|
||||||
|
secret, after all these parameters are sent to all SMTP clients in
|
||||||
|
the clear. Mode 0644 is fine. </p>
|
||||||
|
|
||||||
|
<p> Execute as root (prime group generation can take a
|
||||||
few seconds to a few minutes): </p>
|
few seconds to a few minutes): </p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
@ -270,20 +302,15 @@ few seconds to a few minutes): </p>
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<p> Note: greater security against "pre-computation" attacks against
|
<p> You can improve security against pre-computation attacks further
|
||||||
EDH can be obtained by periodically regenerating the EDH parameters
|
by regenerating the EDH parameters periodically (an hourly or daily
|
||||||
as above (an hourly or daily cron job running as root can automate
|
cron job running as root can automate this task). </p>
|
||||||
this task). The parameter files are not secret, after all these are
|
|
||||||
sent to all SMTP clients in the clear. Mode 0644 is fine. </p>
|
|
||||||
|
|
||||||
<p> Once the parameters are in place, update main.cf as follows: </p>
|
<p> Once the parameters are in place, update main.cf as follows: </p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
/etc/postfix/main.cf:
|
/etc/postfix/main.cf:
|
||||||
# Postfix ≥ 2.6
|
|
||||||
smtpd_tls_eecdh_grade = strong
|
|
||||||
# All versions of Postfix:
|
|
||||||
smtpd_tls_dh1024_param_file = ${config_directory}/dh2048.pem
|
smtpd_tls_dh1024_param_file = ${config_directory}/dh2048.pem
|
||||||
smtpd_tls_dh512_param_file = ${config_directory}/dh512.pem
|
smtpd_tls_dh512_param_file = ${config_directory}/dh512.pem
|
||||||
</pre>
|
</pre>
|
||||||
@ -305,44 +332,67 @@ need to adjust the submission entry in master.cf accordingly: </p>
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<h2><a name="test">How do I know that it works? </a> </h2>
|
</ul>
|
||||||
|
|
||||||
<p> Postfix reports TLS connection information in several ways: </p>
|
<h2><a name="test">How can I see that a connection has forward
|
||||||
|
secrecy? </a> </h2>
|
||||||
|
|
||||||
|
<p> Postfix can be configured to report information about the
|
||||||
|
negotiated cipher, the corresponding key lengths, and the remote
|
||||||
|
peer certificate or public-key verification status. </p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li> <p> With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1",
|
<li> <p> With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1",
|
||||||
the Postfix SMTP client and server will log information about, among
|
the Postfix SMTP client and server will log TLS connection information
|
||||||
others, the remote peer certificate or public-key verification
|
to the maillog file. The general logfile format is: </p>
|
||||||
status, the negotiated cipher, and key lengths. The general logfile
|
|
||||||
format is: </p>
|
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
postfix/smtp[xxx]: Trusted TLS connection established to host.example.com[192.168.0.2]:25: TLSv1 with cipher XXX (YYY/ZZZ bits)
|
postfix/smtp[<i>process-id</i>]: Untrusted TLS connection established
|
||||||
|
to host.example.com[192.168.0.2]:25: TLSv1 with cipher <i>cipher-name</i>
|
||||||
|
(<i>actual-key-size</i>/<i>raw-key-size</i> bits)
|
||||||
|
|
||||||
postfix/smtpd[xxx]: Untrusted TLS connection established from host.example.com[192.168.0.2]: TLSv1 with cipher XXX (YYY/ZZZ bits)
|
postfix/smtpd[<i>process-id</i>]: Anonymous TLS connection established
|
||||||
|
from host.example.com[192.168.0.2]: TLSv1 with cipher <i>cipher-name</i>
|
||||||
|
(<i>actual-key-size</i>/<i>raw-key-size</i> bits)
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<li> <p> With "smtpd_tls_received_header = yes", the Postfix SMTP
|
<li> <p> With "smtpd_tls_received_header = yes", the Postfix SMTP
|
||||||
server will record similar information in the Received: header in
|
server will record TLS connection information in the Received:
|
||||||
the form of comments (text inside parentheses). The general format
|
header in the form of comments (text inside parentheses). The general
|
||||||
is: </p>
|
format depends on the smtpd_tls_ask_ccert setting:
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
Received: from host.example.com (host.example.com [192.168.0.2])
|
Received: from host.example.com (host.example.com [192.168.0.2])
|
||||||
(using TLSv1 with cipher XXX (YYY/ZZZ bits))
|
(using TLSv1 with cipher <i>cipher-name</i>
|
||||||
(Client CN "host.example.com", Issuer "Wietse Venema" (not verified))
|
(<i>actual-key-size</i>/<i>raw-key-size</i> bits))
|
||||||
|
(Client CN "host.example.com", Issuer "John Doe" (not verified))
|
||||||
|
|
||||||
|
Received: from host.example.com (host.example.com [192.168.0.2])
|
||||||
|
(using TLSv1 with cipher <i>cipher-name</i>
|
||||||
|
(<i>actual-key-size</i>/<i>raw-key-size</i> bits))
|
||||||
|
(No client certificate requested)
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p> The next sections will explain what <i>cipher-name</i>,
|
||||||
|
<i>key-size</i>, and peer verification status information to expect.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2><a name="ciphers"> What ciphers provide forward secrecy? </a> </h2>
|
||||||
|
|
||||||
<p> There are dozens of ciphers that support forward secrecy. What
|
<p> There are dozens of ciphers that support forward secrecy. What
|
||||||
follows is the beginning of a list of 51 ciphers available with
|
follows is the beginning of a list of 51 ciphers available with
|
||||||
OpenSSL 1.0.1e: </p>
|
OpenSSL 1.0.1e. The list is sorted in the default Postfix preference
|
||||||
|
order. It excludes null ciphers that only authenticate and don't
|
||||||
|
encrypt, together with export and low-grade ciphers whose encryption
|
||||||
|
is too weak to offer meaningful secrecy. The first column shows the
|
||||||
|
cipher name, and the second shows the key exchange method. </p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
@ -367,6 +417,112 @@ DHE-RSA-AES256-SHA256 Kx=DH
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
|
<p> To date, all ciphers that support forward secrecy have one of
|
||||||
|
five values for the first component of their OpenSSL name: "AECDH",
|
||||||
|
"ECDHE", "ADH", "EDH" or "DHE". Ciphers that don't implement forward
|
||||||
|
secrecy have names that don't start with one of these prefixes.
|
||||||
|
This pattern is likely to persist until some new key-exchange
|
||||||
|
mechanism is invented that also supports forward secrecy. </p>
|
||||||
|
|
||||||
|
<p> The actual key length and raw algorithm key length
|
||||||
|
are generally the same with non-export ciphers, but may they
|
||||||
|
differ for the legacy export ciphers where the actual key
|
||||||
|
is artificially shortened. </p>
|
||||||
|
|
||||||
|
<h2><a name="status"> What do "Anonymous", "Untrusted", etc. in
|
||||||
|
Postfix logging mean? </a> </h2>
|
||||||
|
|
||||||
|
<p> The verification levels below are subject to man-in-the-middle
|
||||||
|
attacks to different degrees. If such attacks are a concern, then
|
||||||
|
the SMTP client will need to authenticate the remote SMTP server
|
||||||
|
in a sufficiently-secure manner. For example, by the fingerprint
|
||||||
|
of the public key or certificate. Remember that conventional PKI
|
||||||
|
relies on many trusted parties and is easily subverted by a
|
||||||
|
state-funded adversary. </p>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
|
||||||
|
<dt><b>Anonymous</b> (no peer certificate)</dt>
|
||||||
|
|
||||||
|
<dd> <p> <b> Postfix SMTP client:</b> With opportunistic TLS (the "may" security level) the Postfix
|
||||||
|
SMTP client does not verify any information in the peer certificate.
|
||||||
|
In this case it enables and prefers anonymous cipher suites in which
|
||||||
|
the remote SMTP server does not present a certificate (these ciphers
|
||||||
|
offer forward secrecy of necessity). When the remote SMTP server
|
||||||
|
also supports anonymous TLS, and agrees to such a cipher suite, the
|
||||||
|
verification status will be logged as "Anonymous". </p> </dd>
|
||||||
|
|
||||||
|
<dd> <p> <b> Postfix SMTP server:</b> This is by far most common,
|
||||||
|
as client certificates are optional, and the Postfix SMTP server
|
||||||
|
does not request client certificates by default (see smtpd_tls_ask_ccert).
|
||||||
|
Even when client certificates are requested, the remote SMTP client
|
||||||
|
might not send a certificate. Unlike the Postfix SMTP client, the
|
||||||
|
Postfix SMTP server "anonymous" verification status does not imply
|
||||||
|
that the cipher suite is anonymous, which corresponds to the
|
||||||
|
<i>server</i> not sending a certificate. </p> </dd>
|
||||||
|
|
||||||
|
<dt><b>Untrusted</b> (peer certificate not signed by trusted CA)</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP client:</b> The remote SMTP server presented
|
||||||
|
a certificate, but the Postfix SMTP client was unable to check the
|
||||||
|
issuing CA signature. With opportunistic TLS this is common with
|
||||||
|
remote SMTP servers that don't support anonymous cipher suites.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP server:</b> The remote SMTP client presented
|
||||||
|
a certificate, but the Postfix SMTP server was unable to check the
|
||||||
|
issuing CA signature. This can happen when the server is configured
|
||||||
|
to request client certificates (see smtpd_tls_ask_ccert). </p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt><b>Trusted</b> (peer certificate signed by trusted CA, unverified
|
||||||
|
peer name)</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP client:</b> The remote SMTP server's certificate
|
||||||
|
was signed by a CA that the Postfix SMTP client trusts, but either
|
||||||
|
the client was not configured to verify the destination server name
|
||||||
|
against the certificate, or the server certificate did not contain
|
||||||
|
any matching names. This is common with opportunistic TLS
|
||||||
|
(smtp_tls_security_level is "may" or else "dane" with no usable
|
||||||
|
TLSA DNS records) when the Postfix SMTP client's trusted CAs can
|
||||||
|
verify the authenticity of the remote SMTP server's certificate,
|
||||||
|
but the client is not configured or unable to verify the server
|
||||||
|
name. </p>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP server:</b> The remote SMTP client certificate
|
||||||
|
was signed by a CA that the Postfix SMTP server trusts. The Postfix
|
||||||
|
SMTP server never verifies the remote SMTP client name against the
|
||||||
|
names in the certificate. Since the client chooses to connect to
|
||||||
|
the server, the Postfix SMTP server has no expectation of a particular
|
||||||
|
client hostname. </p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt><b>Verified</b> (peer certificate signed by trusted CA, verified
|
||||||
|
peer name)</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP client:</b> The remote SMTP server's certificate
|
||||||
|
was signed by a CA that the Postfix SMTP client trusts, and it
|
||||||
|
matches one of the expected server names. This implies that the
|
||||||
|
Postfix SMTP client enforced verification for the destination server
|
||||||
|
name, otherwise the verification status would have been just
|
||||||
|
"Trusted". </p>
|
||||||
|
|
||||||
|
<p> <b> Postfix SMTP server:</b> The status is never "Verified",
|
||||||
|
as the Postfix SMTP server never verifies the remote SMTP client
|
||||||
|
name against the names in the certificate. </p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
<h2><a name="credits">Credits </a> </h2>
|
<h2><a name="credits">Credits </a> </h2>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -185,91 +185,36 @@ to configure and operate the Dovecot authentication server. </p>
|
|||||||
<h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4>
|
<h4><a name="server_dovecot_comm">Postfix to Dovecot SASL communication</a></h4>
|
||||||
|
|
||||||
<p> Communication between the Postfix SMTP server and Dovecot SASL
|
<p> Communication between the Postfix SMTP server and Dovecot SASL
|
||||||
happens over a UNIX-domain socket or over a TCP socket. Dovecot 1
|
happens over a UNIX-domain socket or over a TCP socket. We will
|
||||||
supports UNIX-domain socket communication only. </p>
|
be using a UNIX-domain socket for better privacy. </p>
|
||||||
|
|
||||||
<h5>UNIX-domain socket communication</h5>
|
<p> The following fragment for Dovecot version 2 assumes that the
|
||||||
|
Postfix queue is under <code>/var/spool/postfix/</code>. </p>
|
||||||
<p> The socket
|
|
||||||
pathname and the list of mechanisms offered to Postfix need to be
|
|
||||||
specified on the Dovecot server side in <code>dovecot.conf</code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p> The following example assumes that the Postfix queue is under
|
|
||||||
<code>/var/spool/postfix/</code>. </p>
|
|
||||||
|
|
||||||
<p> Note: the example uses Dovecot 1 syntax, See http://www.dovecot.org/
|
|
||||||
for newer syntax. </p>
|
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
1 /etc/dovecot.conf:
|
1 conf.d/10-master.conf:
|
||||||
2 auth default {
|
2 service auth {
|
||||||
3 mechanisms = plain login
|
3 ...
|
||||||
4 passdb pam {
|
4 unix_listener /var/spool/postfix/private/auth {
|
||||||
5 }
|
5 mode = 0660
|
||||||
6 userdb passwd {
|
6 # Assuming the default Postfix user and group
|
||||||
7 }
|
7 user = postfix
|
||||||
8 socket listen {
|
8 group = postfix
|
||||||
9 client {
|
9 }
|
||||||
10 path = /var/spool/postfix/private/auth
|
10 ...
|
||||||
11 mode = 0660
|
11 }
|
||||||
12 user = postfix
|
12
|
||||||
13 group = postfix
|
13 conf.d/10-auth.conf
|
||||||
14 }
|
14 auth_mechanisms = plain login
|
||||||
15 }
|
|
||||||
16 }
|
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<p> Line 3 provides <code>plain</code> and <code>login</code> as
|
<p> Line 4 places the Dovecot SASL socket in
|
||||||
mechanisms for the Postfix SMTP server, line 10 places the Dovecot
|
<code>/var/spool/postfix/private/auth</code>, lines 5-8 limit
|
||||||
SASL socket in <code>/var/spool/postfix/private/auth</code>, and
|
read+write permissions to user and group <code>postfix</code> only,
|
||||||
lines 11-13 limit read+write permissions to user and group
|
and line 14 provides <code>plain</code> and <code>login</code> as
|
||||||
<code>postfix</code> only. </p>
|
mechanisms for the Postfix SMTP server. </p>
|
||||||
|
|
||||||
<p> Proceed with the section "<a href="#server_sasl_enable">Enabling
|
|
||||||
SASL authentication and authorization in the Postfix SMTP server</a>"
|
|
||||||
to turn on and use SASL in the Postfix SMTP server. </p>
|
|
||||||
|
|
||||||
<h5>TCP socket communication</h5>
|
|
||||||
|
|
||||||
<p> The TCP port and the list of mechanisms offered to Postfix need
|
|
||||||
to be specified on the Dovecot server side in <code>10-auth.conf</code>
|
|
||||||
and <code>10-master.conf</code>. </p>
|
|
||||||
|
|
||||||
<p> The following examples assume that Postfix should communicate
|
|
||||||
with Dovecot on TCP port 12345. </p>
|
|
||||||
|
|
||||||
<p> Note: the examples use Dovecot 1 syntax, See http://www.dovecot.org/
|
|
||||||
for newer syntax. </p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
1 /etc/dovecot/conf.d/10-auth.conf:
|
|
||||||
2 auth_mechanisms = plain login
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p> Line 2 provides plain and login as mechanisms for the Postfix
|
|
||||||
SMTP server. </p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
1 /etc/dovecot/conf.d/10-master.conf:
|
|
||||||
2 service auth {
|
|
||||||
3 unix_listener auth-userdb {
|
|
||||||
4 }
|
|
||||||
5 inet_listener {
|
|
||||||
6 port = 12345
|
|
||||||
7 }
|
|
||||||
8 }
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p> Line 5 creates a new TCP socket and line 6 specifies port 12345
|
|
||||||
where Dovecot SASL should wait for Postfix authentication requests.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p> Proceed with the section "<a href="#server_sasl_enable">Enabling
|
<p> Proceed with the section "<a href="#server_sasl_enable">Enabling
|
||||||
SASL authentication and authorization in the Postfix SMTP server</a>"
|
SASL authentication and authorization in the Postfix SMTP server</a>"
|
||||||
|
@ -10389,6 +10389,15 @@ configuration file or rendezvous point. </p>
|
|||||||
<p> This feature is available in Postfix 2.3 and later. In earlier
|
<p> This feature is available in Postfix 2.3 and later. In earlier
|
||||||
releases it was called <b>smtpd_sasl_application_name</b>. </p>
|
releases it was called <b>smtpd_sasl_application_name</b>. </p>
|
||||||
|
|
||||||
|
%PARAM smtpd_sasl_service smtp
|
||||||
|
|
||||||
|
<p> The service name that is passed to the SASL plug-in that is
|
||||||
|
selected with <b>smtpd_sasl_type</b> and <b>smtpd_sasl_path</b>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p> This feature is available in Postfix 2.11 and later. Prior
|
||||||
|
versions behave as if "<b>smtp</b>" is specified. </p>
|
||||||
|
|
||||||
%PARAM cyrus_sasl_config_path
|
%PARAM cyrus_sasl_config_path
|
||||||
|
|
||||||
<p> Search path for Cyrus SASL application configuration files,
|
<p> Search path for Cyrus SASL application configuration files,
|
||||||
|
@ -1282,3 +1282,4 @@ XXX
|
|||||||
YYY
|
YYY
|
||||||
ZZZ
|
ZZZ
|
||||||
kEECDH
|
kEECDH
|
||||||
|
EXIM
|
||||||
|
@ -179,7 +179,7 @@
|
|||||||
#ifdef HAS_DB
|
#ifdef HAS_DB
|
||||||
#include <dict_db.h>
|
#include <dict_db.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAS_LMDB
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
#include <dict_lmdb.h>
|
#include <dict_lmdb.h>
|
||||||
#endif
|
#endif
|
||||||
#include <inet_proto.h>
|
#include <inet_proto.h>
|
||||||
@ -725,7 +725,7 @@ void mail_params_init()
|
|||||||
#ifdef HAS_DB
|
#ifdef HAS_DB
|
||||||
dict_db_cache_size = var_db_read_buf;
|
dict_db_cache_size = var_db_read_buf;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAS_LMDB
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
dict_lmdb_map_size = var_lmdb_map_size;
|
dict_lmdb_map_size = var_lmdb_map_size;
|
||||||
#endif
|
#endif
|
||||||
inet_windowsize = var_inet_windowsize;
|
inet_windowsize = var_inet_windowsize;
|
||||||
|
@ -1560,6 +1560,10 @@ extern char *var_smtpd_sasl_opts;
|
|||||||
#define DEF_SMTPD_SASL_PATH "smtpd"
|
#define DEF_SMTPD_SASL_PATH "smtpd"
|
||||||
extern char *var_smtpd_sasl_path;
|
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 VAR_CYRUS_CONF_PATH "cyrus_sasl_config_path"
|
||||||
#define DEF_CYRUS_CONF_PATH ""
|
#define DEF_CYRUS_CONF_PATH ""
|
||||||
extern char *var_cyrus_conf_path;
|
extern char *var_cyrus_conf_path;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20131221"
|
#define MAIL_RELEASE_DATE "20131228"
|
||||||
#define MAIL_VERSION_NUMBER "2.11"
|
#define MAIL_VERSION_NUMBER "2.11"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#include <myflock.h>
|
#include <myflock.h>
|
||||||
#include <warn_stat.h>
|
#include <warn_stat.h>
|
||||||
|
|
||||||
#ifdef HAS_LMDB
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
#ifdef PATH_LMDB_H
|
#ifdef PATH_LMDB_H
|
||||||
#include PATH_LMDB_H
|
#include PATH_LMDB_H
|
||||||
#else
|
#else
|
||||||
|
@ -102,7 +102,7 @@ static const MKMAP_OPEN_INFO mkmap_types[] = {
|
|||||||
DICT_TYPE_HASH, mkmap_hash_open,
|
DICT_TYPE_HASH, mkmap_hash_open,
|
||||||
DICT_TYPE_BTREE, mkmap_btree_open,
|
DICT_TYPE_BTREE, mkmap_btree_open,
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAS_LMDB
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
DICT_TYPE_LMDB, mkmap_lmdb_open,
|
DICT_TYPE_LMDB, mkmap_lmdb_open,
|
||||||
#endif
|
#endif
|
||||||
DICT_TYPE_FAIL, mkmap_fail_open,
|
DICT_TYPE_FAIL, mkmap_fail_open,
|
||||||
|
@ -315,6 +315,11 @@
|
|||||||
/* .IP "\fBcyrus_sasl_config_path (empty)\fR"
|
/* .IP "\fBcyrus_sasl_config_path (empty)\fR"
|
||||||
/* Search path for Cyrus SASL application configuration files,
|
/* Search path for Cyrus SASL application configuration files,
|
||||||
/* currently used only to locate the $smtpd_sasl_path.conf file.
|
/* 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
|
/* STARTTLS SUPPORT CONTROLS
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -1179,6 +1184,7 @@ bool var_smtpd_sasl_enable;
|
|||||||
bool var_smtpd_sasl_auth_hdr;
|
bool var_smtpd_sasl_auth_hdr;
|
||||||
char *var_smtpd_sasl_opts;
|
char *var_smtpd_sasl_opts;
|
||||||
char *var_smtpd_sasl_path;
|
char *var_smtpd_sasl_path;
|
||||||
|
char *var_smtpd_sasl_service;
|
||||||
char *var_cyrus_conf_path;
|
char *var_cyrus_conf_path;
|
||||||
char *var_smtpd_sasl_realm;
|
char *var_smtpd_sasl_realm;
|
||||||
char *var_smtpd_sasl_exceptions_networks;
|
char *var_smtpd_sasl_exceptions_networks;
|
||||||
@ -5382,6 +5388,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 0, 0,
|
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_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_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_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_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,
|
VAR_SMTPD_SASL_EXCEPTIONS_NETWORKS, DEF_SMTPD_SASL_EXCEPTIONS_NETWORKS, &var_smtpd_sasl_exceptions_networks, 0, 0,
|
||||||
|
@ -202,7 +202,6 @@ void smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name,
|
|||||||
/*
|
/*
|
||||||
* Set up a new server context for this connection.
|
* Set up a new server context for this connection.
|
||||||
*/
|
*/
|
||||||
#define SMTPD_SASL_SERVICE "smtp"
|
|
||||||
#ifdef USE_TLS
|
#ifdef USE_TLS
|
||||||
tls_flag = state->tls_context != 0;
|
tls_flag = state->tls_context != 0;
|
||||||
#else
|
#else
|
||||||
@ -218,7 +217,7 @@ void smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name,
|
|||||||
state->dest_addr : ""),
|
state->dest_addr : ""),
|
||||||
client_addr = ADDR_OR_EMPTY(state->addr,
|
client_addr = ADDR_OR_EMPTY(state->addr,
|
||||||
CLIENT_ADDR_UNKNOWN),
|
CLIENT_ADDR_UNKNOWN),
|
||||||
service = SMTPD_SASL_SERVICE,
|
service = var_smtpd_sasl_service,
|
||||||
user_realm = REALM_OR_NULL(var_smtpd_sasl_realm),
|
user_realm = REALM_OR_NULL(var_smtpd_sasl_realm),
|
||||||
security_options = sasl_opts_val,
|
security_options = sasl_opts_val,
|
||||||
tls_flag = tls_flag)) == 0)
|
tls_flag = tls_flag)) == 0)
|
||||||
|
@ -17,14 +17,19 @@ key() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req() {
|
req() {
|
||||||
|
local key=$1; shift
|
||||||
local cn=$1; shift
|
local cn=$1; shift
|
||||||
|
|
||||||
|
key "$key"
|
||||||
openssl req -new -sha256 -key "${key}.pem" 2>/dev/null \
|
openssl req -new -sha256 -key "${key}.pem" 2>/dev/null \
|
||||||
-config <(printf "[req]\n%s\n%s\n[dn]\nCN=%s\n" \
|
-config <(printf "[req]\n%s\n%s\n[dn]\nCN=%s\n" \
|
||||||
"prompt = no" "distinguished_name = dn" "${cn}")
|
"prompt = no" "distinguished_name = dn" "${cn}")
|
||||||
}
|
}
|
||||||
|
|
||||||
req_nocn() {
|
req_nocn() {
|
||||||
|
local key=$1; shift
|
||||||
|
|
||||||
|
key "$key"
|
||||||
openssl req -new -sha256 -subj / -key "${key}.pem" 2>/dev/null \
|
openssl req -new -sha256 -subj / -key "${key}.pem" 2>/dev/null \
|
||||||
-config <(printf "[req]\n%s\n[dn]\nCN_default =\n" \
|
-config <(printf "[req]\n%s\n[dn]\nCN_default =\n" \
|
||||||
"distinguished_name = dn")
|
"distinguished_name = dn")
|
||||||
@ -46,8 +51,7 @@ genroot() {
|
|||||||
local akid=$1; shift
|
local akid=$1; shift
|
||||||
|
|
||||||
exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = CA:true")
|
exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = CA:true")
|
||||||
key "$key"
|
req "$key" "$cn" |
|
||||||
req "$cn" |
|
|
||||||
cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days 30
|
cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days 30
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,8 +65,7 @@ genca() {
|
|||||||
local cakey=$1; shift
|
local cakey=$1; shift
|
||||||
|
|
||||||
exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = CA:true")
|
exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = CA:true")
|
||||||
key "$key"
|
req "$key" "$cn" |
|
||||||
req "$cn" |
|
|
||||||
cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
|
cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
|
||||||
-set_serial 2 -days 30 "$@"
|
-set_serial 2 -days 30 "$@"
|
||||||
}
|
}
|
||||||
@ -80,8 +83,7 @@ genee() {
|
|||||||
"basicConstraints = CA:false" \
|
"basicConstraints = CA:false" \
|
||||||
"extendedKeyUsage = serverAuth" \
|
"extendedKeyUsage = serverAuth" \
|
||||||
"subjectAltName = @alts" "DNS=${cn}")
|
"subjectAltName = @alts" "DNS=${cn}")
|
||||||
key "$key"
|
req "$key" "$cn" |
|
||||||
req "$cn" |
|
|
||||||
cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
|
cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
|
||||||
-set_serial 2 -days 30 "$@"
|
-set_serial 2 -days 30 "$@"
|
||||||
}
|
}
|
||||||
@ -97,8 +99,7 @@ genss() {
|
|||||||
"basicConstraints = CA:true" \
|
"basicConstraints = CA:true" \
|
||||||
"extendedKeyUsage = serverAuth" \
|
"extendedKeyUsage = serverAuth" \
|
||||||
"subjectAltName = @alts" "DNS=${cn}")
|
"subjectAltName = @alts" "DNS=${cn}")
|
||||||
key "$key"
|
req "$key" "$cn" |
|
||||||
req "$cn" |
|
|
||||||
cert "$cert" "$exts" -set_serial 1 -days 30 -signkey "${key}.pem" "$@"
|
cert "$cert" "$exts" -set_serial 1 -days 30 -signkey "${key}.pem" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,8 +107,7 @@ gennocn() {
|
|||||||
local key=$1; shift
|
local key=$1; shift
|
||||||
local cert=$1; shift
|
local cert=$1; shift
|
||||||
|
|
||||||
key "$key"
|
req_nocn "$key" |
|
||||||
req_nocn |
|
|
||||||
cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
|
cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
|
|||||||
unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
|
unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
|
||||||
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
|
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
|
||||||
valid_utf_8 ip_match base32_code msg_rate_delay netstring \
|
valid_utf_8 ip_match base32_code msg_rate_delay netstring \
|
||||||
vstream timecmp
|
vstream timecmp dict_cache
|
||||||
|
|
||||||
LIB_DIR = ../../lib
|
LIB_DIR = ../../lib
|
||||||
INC_DIR = ../../include
|
INC_DIR = ../../include
|
||||||
@ -460,6 +460,11 @@ timecmp: $(LIB)
|
|||||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||||
mv junk $@.o
|
mv junk $@.o
|
||||||
|
|
||||||
|
dict_cache: $(LIB)
|
||||||
|
mv $@.o junk
|
||||||
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||||
|
mv junk $@.o
|
||||||
|
|
||||||
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
|
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
|
||||||
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
|
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
|
||||||
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
|
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
|
||||||
|
@ -682,3 +682,437 @@ const char *dict_cache_name(DICT_CACHE *cp)
|
|||||||
*/
|
*/
|
||||||
return (cp->name);
|
return (cp->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test driver with support for interleaved access. First, enter a number of
|
||||||
|
* requests to look up, update or delete a sequence of cache entries, then
|
||||||
|
* interleave those sequences with the "run" command.
|
||||||
|
*/
|
||||||
|
#ifdef TEST
|
||||||
|
#include <msg_vstream.h>
|
||||||
|
#include <vstring_vstream.h>
|
||||||
|
#include <argv.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
|
||||||
|
#define DELIMS " "
|
||||||
|
#define USAGE "\n\tTo manage settings:" \
|
||||||
|
"\n\tverbose <level> (verbosity level)" \
|
||||||
|
"\n\telapsed <level> (0=don't show elapsed time)" \
|
||||||
|
"\n\tlmdb_map_size <limit> (initial LMDB size limit)" \
|
||||||
|
"\n\tcache <type>:<name> (switch to named database)" \
|
||||||
|
"\n\tstatus (show map size, cache, pending requests)" \
|
||||||
|
"\n\n\tTo manage pending requests:" \
|
||||||
|
"\n\treset (discard pending requests)" \
|
||||||
|
"\n\trun (execute pending requests in interleaved order)" \
|
||||||
|
"\n\n\tTo add a pending request:" \
|
||||||
|
"\n\tquery <key-prefix> <count> (negative to reverse order)" \
|
||||||
|
"\n\tupdate <key-prefix> <count> (negative to reverse order)" \
|
||||||
|
"\n\tdelete <key-prefix> <count> (negative to reverse order)" \
|
||||||
|
"\n\tpurge <key-prefix>" \
|
||||||
|
"\n\tcount <key-prefix>"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For realism, open the cache with the same flags as postscreen(8) and
|
||||||
|
* verify(8).
|
||||||
|
*/
|
||||||
|
#define DICT_CACHE_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | \
|
||||||
|
DICT_FLAG_OPEN_LOCK)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Storage for one request to access a sequence of cache entries.
|
||||||
|
*/
|
||||||
|
typedef struct DICT_CACHE_SREQ {
|
||||||
|
int flags; /* per-request: reverse, purge */
|
||||||
|
char *cmd; /* command for status report */
|
||||||
|
void (*action) (struct DICT_CACHE_SREQ *, DICT_CACHE *, VSTRING *);
|
||||||
|
char *prefix; /* key prefix */
|
||||||
|
int done; /* progress indicator */
|
||||||
|
int todo; /* number of entries to process */
|
||||||
|
int first_next; /* first/next */
|
||||||
|
} DICT_CACHE_SREQ;
|
||||||
|
|
||||||
|
#define DICT_CACHE_SREQ_FLAG_PURGE (1<<1) /* purge instead of count */
|
||||||
|
#define DICT_CACHE_SREQ_FLAG_REVERSE (1<<2) /* reverse instead of forward */
|
||||||
|
|
||||||
|
#define DICT_CACHE_SREQ_LIMIT 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All test requests combined.
|
||||||
|
*/
|
||||||
|
typedef struct DICT_CACHE_TEST {
|
||||||
|
int flags; /* exclusion flags */
|
||||||
|
int size; /* allocated slots */
|
||||||
|
int used; /* used slots */
|
||||||
|
DICT_CACHE_SREQ job_list[1]; /* actually, a bunch */
|
||||||
|
} DICT_CACHE_TEST;
|
||||||
|
|
||||||
|
#define DICT_CACHE_TEST_FLAG_ITER (1<<0) /* count or purge */
|
||||||
|
|
||||||
|
#define STR(x) vstring_str(x)
|
||||||
|
|
||||||
|
int show_elapsed = 1; /* show elapsed time */
|
||||||
|
|
||||||
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
|
extern size_t dict_lmdb_map_size; /* LMDB-specific */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* usage - command-line usage message */
|
||||||
|
|
||||||
|
static NORETURN usage(const char *progname)
|
||||||
|
{
|
||||||
|
msg_fatal("usage: %s (no argument)", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make_tagged_key - make tagged search key */
|
||||||
|
|
||||||
|
static void make_tagged_key(VSTRING *bp, DICT_CACHE_SREQ *cp)
|
||||||
|
{
|
||||||
|
if (cp->done < 0)
|
||||||
|
msg_panic("make_tagged_key: bad done count: %d", cp->done);
|
||||||
|
if (cp->todo < 1)
|
||||||
|
msg_panic("make_tagged_key: bad todo count: %d", cp->todo);
|
||||||
|
vstring_sprintf(bp, "%s-%d", cp->prefix,
|
||||||
|
(cp->flags & DICT_CACHE_SREQ_FLAG_REVERSE) ?
|
||||||
|
cp->todo - cp->done - 1 : cp->done);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create_requests - create request list */
|
||||||
|
|
||||||
|
static DICT_CACHE_TEST *create_requests(int count)
|
||||||
|
{
|
||||||
|
DICT_CACHE_TEST *tp;
|
||||||
|
DICT_CACHE_SREQ *cp;
|
||||||
|
|
||||||
|
tp = (DICT_CACHE_TEST *) mymalloc(sizeof(DICT_CACHE_TEST) +
|
||||||
|
(count - 1) *sizeof(DICT_CACHE_SREQ));
|
||||||
|
tp->flags = 0;
|
||||||
|
tp->size = count;
|
||||||
|
tp->used = 0;
|
||||||
|
for (cp = tp->job_list; cp < tp->job_list + count; cp++) {
|
||||||
|
cp->flags = 0;
|
||||||
|
cp->cmd = 0;
|
||||||
|
cp->action = 0;
|
||||||
|
cp->prefix = 0;
|
||||||
|
cp->todo = 0;
|
||||||
|
cp->first_next = DICT_SEQ_FUN_FIRST;
|
||||||
|
}
|
||||||
|
return (tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset_requests - reset request list */
|
||||||
|
|
||||||
|
static void reset_requests(DICT_CACHE_TEST *tp)
|
||||||
|
{
|
||||||
|
DICT_CACHE_SREQ *cp;
|
||||||
|
|
||||||
|
tp->flags = 0;
|
||||||
|
tp->used = 0;
|
||||||
|
for (cp = tp->job_list; cp < tp->job_list + tp->size; cp++) {
|
||||||
|
cp->flags = 0;
|
||||||
|
if (cp->cmd) {
|
||||||
|
myfree(cp->cmd);
|
||||||
|
cp->cmd = 0;
|
||||||
|
}
|
||||||
|
cp->action = 0;
|
||||||
|
if (cp->prefix) {
|
||||||
|
myfree(cp->prefix);
|
||||||
|
cp->prefix = 0;
|
||||||
|
}
|
||||||
|
cp->todo = 0;
|
||||||
|
cp->first_next = DICT_SEQ_FUN_FIRST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free_requests - destroy request list */
|
||||||
|
|
||||||
|
static void free_requests(DICT_CACHE_TEST *tp)
|
||||||
|
{
|
||||||
|
reset_requests(tp);
|
||||||
|
myfree((char *) tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* run_requests - execute pending requests in interleaved order */
|
||||||
|
|
||||||
|
static void run_requests(DICT_CACHE_TEST *tp, DICT_CACHE *dp, VSTRING *bp)
|
||||||
|
{
|
||||||
|
DICT_CACHE_SREQ *cp;
|
||||||
|
int todo;
|
||||||
|
struct timeval start;
|
||||||
|
struct timeval finish;
|
||||||
|
struct timeval elapsed;
|
||||||
|
|
||||||
|
if (dp == 0) {
|
||||||
|
msg_warn("no cache");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GETTIMEOFDAY(&start);
|
||||||
|
do {
|
||||||
|
todo = 0;
|
||||||
|
for (cp = tp->job_list; cp < tp->job_list + tp->used; cp++) {
|
||||||
|
if (cp->done < cp->todo) {
|
||||||
|
todo = 1;
|
||||||
|
cp->action(cp, dp, bp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (todo);
|
||||||
|
GETTIMEOFDAY(&finish);
|
||||||
|
timersub(&finish, &start, &elapsed);
|
||||||
|
if (show_elapsed)
|
||||||
|
vstream_printf("Elapsed: %g\n",
|
||||||
|
elapsed.tv_sec + elapsed.tv_usec / 1000000.0);
|
||||||
|
|
||||||
|
reset_requests(tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show_status - show settings and pending requests */
|
||||||
|
|
||||||
|
static void show_status(DICT_CACHE_TEST *tp, DICT_CACHE *dp)
|
||||||
|
{
|
||||||
|
DICT_CACHE_SREQ *cp;
|
||||||
|
|
||||||
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
|
vstream_printf("lmdb_map_size\t%ld\n", (long) dict_lmdb_map_size);
|
||||||
|
#endif
|
||||||
|
vstream_printf("cache\t%s\n", dp ? dp->name : "(none)");
|
||||||
|
|
||||||
|
vstream_printf("%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||||
|
"cmd", "dir", "prefix", "count", "done", "first/next");
|
||||||
|
|
||||||
|
for (cp = tp->job_list; cp < tp->job_list + tp->used; cp++)
|
||||||
|
if (cp->todo > 0)
|
||||||
|
vstream_printf("%s\t%s\t%s\t%d\t%d\t%d\n",
|
||||||
|
cp->cmd,
|
||||||
|
(cp->flags & DICT_CACHE_SREQ_FLAG_REVERSE) ?
|
||||||
|
"reverse" : "forward",
|
||||||
|
cp->prefix ? cp->prefix : "(null)", cp->todo,
|
||||||
|
cp->done, cp->first_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query_action - lookup cache entry */
|
||||||
|
|
||||||
|
static void query_action(DICT_CACHE_SREQ *cp, DICT_CACHE *dp, VSTRING *bp)
|
||||||
|
{
|
||||||
|
const char *lookup;
|
||||||
|
|
||||||
|
make_tagged_key(bp, cp);
|
||||||
|
if ((lookup = dict_cache_lookup(dp, STR(bp))) == 0) {
|
||||||
|
if (dp->error)
|
||||||
|
msg_warn("query_action: query failed: %s: %m", STR(bp));
|
||||||
|
else
|
||||||
|
msg_warn("query_action: query failed: %s", STR(bp));
|
||||||
|
} else if (strcmp(STR(bp), lookup) != 0) {
|
||||||
|
msg_warn("lookup result \"%s\" differs from key \"%s\"",
|
||||||
|
lookup, STR(bp));
|
||||||
|
}
|
||||||
|
cp->done += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update_action - update cache entry */
|
||||||
|
|
||||||
|
static void update_action(DICT_CACHE_SREQ *cp, DICT_CACHE *dp, VSTRING *bp)
|
||||||
|
{
|
||||||
|
make_tagged_key(bp, cp);
|
||||||
|
if (dict_cache_update(dp, STR(bp), STR(bp)) != 0) {
|
||||||
|
if (dp->error)
|
||||||
|
msg_warn("update_action: update failed: %s: %m", STR(bp));
|
||||||
|
else
|
||||||
|
msg_warn("update_action: update failed: %s", STR(bp));
|
||||||
|
}
|
||||||
|
cp->done += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete_action - delete cache entry */
|
||||||
|
|
||||||
|
static void delete_action(DICT_CACHE_SREQ *cp, DICT_CACHE *dp, VSTRING *bp)
|
||||||
|
{
|
||||||
|
make_tagged_key(bp, cp);
|
||||||
|
if (dict_cache_delete(dp, STR(bp)) != 0) {
|
||||||
|
if (dp->error)
|
||||||
|
msg_warn("delete_action: delete failed: %s: %m", STR(bp));
|
||||||
|
else
|
||||||
|
msg_warn("delete_action: delete failed: %s", STR(bp));
|
||||||
|
}
|
||||||
|
cp->done += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iter_action - iterate over cache and act on entries with given prefix */
|
||||||
|
|
||||||
|
static void iter_action(DICT_CACHE_SREQ *cp, DICT_CACHE *dp, VSTRING *bp)
|
||||||
|
{
|
||||||
|
const char *cache_key;
|
||||||
|
const char *cache_val;
|
||||||
|
const char *what;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (dict_cache_sequence(dp, cp->first_next, &cache_key, &cache_val) == 0) {
|
||||||
|
if (strcmp(cache_key, cache_val) != 0)
|
||||||
|
msg_warn("value \"%s\" differs from key \"%s\"",
|
||||||
|
cache_val, cache_key);
|
||||||
|
len = strlen(cp->prefix);
|
||||||
|
if (strncmp(cache_key, cp->prefix, len) == 0 && cache_key[len] == '-') {
|
||||||
|
cp->done += 1;
|
||||||
|
cp->todo = cp->done + 1; /* XXX */
|
||||||
|
if ((cp->flags & DICT_CACHE_SREQ_FLAG_PURGE)
|
||||||
|
&& dict_cache_delete(dp, cache_key) != 0) {
|
||||||
|
if (dp->error)
|
||||||
|
msg_warn("purge_action: delete failed: %s: %m", STR(bp));
|
||||||
|
else
|
||||||
|
msg_warn("purge_action: delete failed: %s", STR(bp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cp->first_next = DICT_SEQ_FUN_NEXT;
|
||||||
|
} else {
|
||||||
|
what = (cp->flags & DICT_CACHE_SREQ_FLAG_PURGE) ? "purge" : "count";
|
||||||
|
if (dp->error)
|
||||||
|
msg_warn("%s error after %d: %m", what, cp->done);
|
||||||
|
else
|
||||||
|
vstream_printf("prefix=%s %s=%d\n", cp->prefix, what, cp->done);
|
||||||
|
cp->todo = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table-driven support.
|
||||||
|
*/
|
||||||
|
typedef struct DICT_CACHE_SREQ_INFO {
|
||||||
|
const char *name;
|
||||||
|
int argc;
|
||||||
|
void (*action) (DICT_CACHE_SREQ *, DICT_CACHE *, VSTRING *);
|
||||||
|
int test_flags;
|
||||||
|
int req_flags;
|
||||||
|
} DICT_CACHE_SREQ_INFO;
|
||||||
|
|
||||||
|
static DICT_CACHE_SREQ_INFO req_info[] = {
|
||||||
|
{"query", 3, query_action},
|
||||||
|
{"update", 3, update_action},
|
||||||
|
{"delete", 3, delete_action},
|
||||||
|
{"count", 2, iter_action, DICT_CACHE_TEST_FLAG_ITER},
|
||||||
|
{"purge", 2, iter_action, DICT_CACHE_TEST_FLAG_ITER, DICT_CACHE_SREQ_FLAG_PURGE},
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* add_request - add a request to the list */
|
||||||
|
|
||||||
|
static void add_request(DICT_CACHE_TEST *tp, ARGV *argv)
|
||||||
|
{
|
||||||
|
DICT_CACHE_SREQ_INFO *rp;
|
||||||
|
DICT_CACHE_SREQ *cp;
|
||||||
|
int req_flags;
|
||||||
|
int count;
|
||||||
|
char *cmd = argv->argv[0];
|
||||||
|
char *prefix = (argv->argc > 1 ? argv->argv[1] : 0);
|
||||||
|
char *todo = (argv->argc > 2 ? argv->argv[2] : "1"); /* XXX */
|
||||||
|
|
||||||
|
if (tp->used >= tp->size) {
|
||||||
|
msg_warn("%s: request list is full", cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (rp = req_info; /* See below */ ; rp++) {
|
||||||
|
if (rp->name == 0) {
|
||||||
|
vstream_printf("usage: %s\n", USAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp(rp->name, argv->argv[0]) == 0
|
||||||
|
&& rp->argc == argv->argc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
req_flags = rp->req_flags;
|
||||||
|
if (todo[0] == '-') {
|
||||||
|
req_flags |= DICT_CACHE_SREQ_FLAG_REVERSE;
|
||||||
|
todo += 1;
|
||||||
|
}
|
||||||
|
if (!alldig(todo) || (count = atoi(todo)) == 0) {
|
||||||
|
msg_warn("%s: bad count: %s", cmd, todo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tp->flags & rp->test_flags) {
|
||||||
|
msg_warn("%s: command conflicts with other command", cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tp->flags |= rp->test_flags;
|
||||||
|
cp = tp->job_list + tp->used;
|
||||||
|
cp->cmd = mystrdup(cmd);
|
||||||
|
cp->action = rp->action;
|
||||||
|
if (prefix)
|
||||||
|
cp->prefix = mystrdup(prefix);
|
||||||
|
cp->done = 0;
|
||||||
|
cp->flags = req_flags;
|
||||||
|
cp->todo = count;
|
||||||
|
tp->used += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main - main program */
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
DICT_CACHE_TEST *test_job;
|
||||||
|
VSTRING *inbuf = vstring_alloc(100);
|
||||||
|
char *bufp;
|
||||||
|
ARGV *args;
|
||||||
|
DICT_CACHE *cache = 0;
|
||||||
|
int stdin_is_tty;
|
||||||
|
|
||||||
|
msg_vstream_init(argv[0], VSTREAM_ERR);
|
||||||
|
if (argc != 1)
|
||||||
|
usage(argv[0]);
|
||||||
|
|
||||||
|
|
||||||
|
test_job = create_requests(DICT_CACHE_SREQ_LIMIT);
|
||||||
|
|
||||||
|
stdin_is_tty = isatty(0);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (stdin_is_tty) {
|
||||||
|
vstream_printf("> ");
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
}
|
||||||
|
if (vstring_fgets_nonl(inbuf, VSTREAM_IN) == 0)
|
||||||
|
break;
|
||||||
|
bufp = vstring_str(inbuf);
|
||||||
|
if (!stdin_is_tty) {
|
||||||
|
vstream_printf("> %s\n", bufp);
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
}
|
||||||
|
if (*bufp == '#')
|
||||||
|
continue;
|
||||||
|
args = argv_split(bufp, DELIMS);
|
||||||
|
if (argc == 0) {
|
||||||
|
vstream_printf("usage: %s\n", USAGE);
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(args->argv[0], "verbose") == 0 && args->argc == 2) {
|
||||||
|
msg_verbose = atoi(args->argv[1]);
|
||||||
|
} else if (strcmp(args->argv[0], "elapsed") == 0 && args->argc == 2) {
|
||||||
|
show_elapsed = atoi(args->argv[1]);
|
||||||
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
|
} else if (strcmp(args->argv[0], "lmdb_map_size") == 0 && args->argc == 2) {
|
||||||
|
dict_lmdb_map_size = atol(args->argv[1]);
|
||||||
|
#endif
|
||||||
|
} else if (strcmp(args->argv[0], "cache") == 0 && args->argc == 2) {
|
||||||
|
if (cache)
|
||||||
|
dict_cache_close(cache);
|
||||||
|
cache = dict_cache_open(args->argv[1], O_CREAT | O_RDWR,
|
||||||
|
DICT_CACHE_OPEN_FLAGS);
|
||||||
|
} else if (strcmp(args->argv[0], "reset") == 0 && args->argc == 1) {
|
||||||
|
reset_requests(test_job);
|
||||||
|
} else if (strcmp(args->argv[0], "run") == 0 && args->argc == 1) {
|
||||||
|
run_requests(test_job, cache, inbuf);
|
||||||
|
} else if (strcmp(args->argv[0], "status") == 0 && args->argc == 1) {
|
||||||
|
show_status(test_job, cache);
|
||||||
|
} else {
|
||||||
|
add_request(test_job, args);
|
||||||
|
}
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
argv_free(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
vstring_free(inbuf);
|
||||||
|
free_requests(test_job);
|
||||||
|
if (cache)
|
||||||
|
dict_cache_close(cache);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
#include <sys_defs.h>
|
#include <sys_defs.h>
|
||||||
|
|
||||||
#ifdef HAS_LMDB
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ static const DICT_OPEN_INFO dict_open_info[] = {
|
|||||||
DICT_TYPE_HASH, dict_hash_open,
|
DICT_TYPE_HASH, dict_hash_open,
|
||||||
DICT_TYPE_BTREE, dict_btree_open,
|
DICT_TYPE_BTREE, dict_btree_open,
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAS_LMDB
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
DICT_TYPE_LMDB, dict_lmdb_open,
|
DICT_TYPE_LMDB, dict_lmdb_open,
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAS_NIS
|
#ifdef HAS_NIS
|
||||||
|
@ -187,7 +187,7 @@
|
|||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
#ifdef HAS_LMDB
|
#if defined(SNAPSHOT) && defined(HAS_LMDB)
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user